/* * XIOHV5.12 power sequence * Copyright (C) 2012 Avencall * Authors: * Jean Marc Ouvrard * Noe Rubinstein * Guillaume Knispel * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include "def.h" #include "hardware.h" static void InitPorts(void); static void GlobalInit(void); volatile u16 Timer1; volatile u16 SW1State; volatile u16 SW2State; #ifdef CAN_WAIT_TENSION //has to be coded on real board volatile u8 bV1P0 = true; volatile u8 bV1P2 = true; volatile u8 bV1P8_DDR = true; volatile u8 bV2P5 = true; volatile u8 bVCC3 = true; #define TENSION_EXPIRED (SW1State || Timer1 == 0) #define TENSION_WAIT(t) (t) #else #define TENSION_EXPIRED (SW1State) #define TENSION_WAIT(t) (Timer1 == 0) #endif #define STOP 10 #define WAIT_START 20 #define WAIT_ATX_OK 30 #define WAIT_V1P0 40 #define WAIT_V1P2 50 #define WAIT_V1P8 60 #define WAIT_RSMRST 70 #define CK410_VTT_GD 80 #define CPU_RUN 90 #define WAIT_STOP 100 int main(void) { u16 state; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset __disable_interrupt(); InitPorts(); GlobalInit(); __enable_interrupt(); state = WAIT_START; while (1) { switch (state) { case WAIT_START: if (SW1State > 30) // SW1 pressed for at least 30ms state = WAIT_START + 1; break; case WAIT_START + 1: // wait for release SW1 before real Start if (SW1State == 0) { SetBit(P4OUT, CMDPWR); // Start Atx Power Supply Timer1 = 2000; state = WAIT_ATX_OK; } break; case WAIT_ATX_OK: if (TENSION_EXPIRED) state = STOP; // if SW1 just pressed during power or ATX didn't set up // ATX power OK, stop if ((P4IN & ATX_PWROK) && TENSION_WAIT(bV2P5 && bVCC3)) { // atx power Ok & V2P5 Ok SetBit(P1DIR, V1P2_CORE_EN_N); // enable V1P2 (V1P2_CORE_EN_N go from // Hz to Out Low) Timer1 = 30; // set Timer1 @ 30 milli seconde to get V1P2 stable state = WAIT_V1P2; } break; case WAIT_V1P2: if (TENSION_EXPIRED) state = STOP; if (TENSION_WAIT(bV1P2)) { // Got V1P2 stable Timer1 = 30; // set Timer1 @ 30 milli seconde to get V1P8-DDR stable SetBit(P4OUT, V1P8_CMD); // enable V1P8-DDR state = WAIT_RSMRST; } break; case WAIT_RSMRST: if (SW1State) state = STOP; if (Timer1 < 20) { SetBit(P2DIR, IMCH_RSMRST_N); ClrBit(P2OUT, IMCH_RSMRST_N); state = WAIT_V1P8; } break; case WAIT_V1P8: if (TENSION_EXPIRED) state = STOP; if (TENSION_WAIT(bV1P8)) { ClrBit(P2OUT, CPU_VCCP_EN_N); // enable V1P0 Timer1 = 30; // set Timer1 @ 30 milli seconde to get V1P0 stable state = WAIT_V1P0; } break; case WAIT_V1P0: if (TENSION_EXPIRED) state = STOP; if (TENSION_WAIT(bV1P0)) { // Got V1P0 stable and all other supplies too SetBit(P3OUT, VRMPWRGD); ClrBit(P2OUT, GREEN_LED_N); // set GREEN_LED_N to show Power Seq Ok Timer1 = 3; // set Timer1 @ 3ms instead of 2 before assserted // CK410_PWR_GD_N Low state = CK410_VTT_GD; } break; case CK410_VTT_GD: if (Timer1 == 0) { SetBit(P2DIR, CK410_PWR_GD_N); // asssert CK410_PWR_GD_N As output ClrBit(P2OUT, CK410_PWR_GD_N); // asssert CK410_PWR_GD_N Low Timer1 = 300; // set Timer1 @ 300 ms before starting Tolapai state = CPU_RUN; } break; case CPU_RUN: if (SW1State) // if SW1 just pressed during power up go STOP state = STOP; if (Timer1 == 0) { SetBit(P2DIR, IMCH_PWRBTN_N); // Start Tolapai Timer1 = 200; // pour relācher le bouton comme un humain state = CPU_RUN + 1; } break; case CPU_RUN + 1: if (SW1State != 0) // if SW1 just pressed during power up go STOP state = STOP; if (Timer1 == 0) { ClrBit(P2DIR, IMCH_PWRBTN_N); // Release IMCH-PWRBTN-N signal after 200 // milli-secondes state = WAIT_STOP; } break; case WAIT_STOP: if (SW1State >= 6000) // Sw1 button press for more than 6 secondes state = STOP; break; case STOP: InitPorts(); Timer1 = 10000; // set Timer1 @ 10s before any other Power up ClrBit(P2OUT, RED_LED_N); // To show no restart is possible for now state = STOP + 1; break; case STOP + 1: InitPorts(); if (Timer1 == 0) { SetBit(P2OUT, RED_LED_N); // To show restart is possible now state = WAIT_START; } break; } } } #pragma vector = TIMERA1_VECTOR __interrupt void Timer_A(void) { if (!(P1IN & START_SW1_N)) SW1State++; else SW1State = 0; if (!(P1IN & RST_SW2_N)) SW2State++; else SW2State = 0; if (Timer1) Timer1--; } static void InitPorts(void) { /* DIR: direction: 0 input 1 output * SEL: function: 0 gpio * REN: resistor enabled * OUT: output when REN=0 and DIR=1 * 0 pull-down 1 pull-up if REN=1 * IES: Interrupt Edge Select * IE: Interrupt Enable */ P1DIR = P1DIR_INIT; P1SEL = P1SEL_INIT; P1REN = P1REN_INIT; P1OUT = P1OUT_INIT; P1IES = P1IES_INIT; P1IE = P1IE_INIT; P2OUT = P2OUT_INIT; P2SEL = P2SEL_INIT; P2REN = P2REN_INIT; P2DIR = P2DIR_INIT; P2IES = P2IES_INIT; P2IE = P2IE_INIT; P3OUT = P3OUT_INIT; P3SEL = P3SEL_INIT; P3DIR = P3DIR_INIT; P4OUT = P4OUT_INIT; P4SEL = P4SEL_INIT; P4DIR = P4DIR_INIT; P4REN = P4REN_INIT; } static void GlobalInit(void) { DCOCTL = CALDCO_12MHZ; BCSCTL1 = CALBC1_12MHZ; BCSCTL2 |= DIVS_3; // DIVS_3 => 1/8; SMCLK = 12/8 = 1.5Mhz // Set timer A so that Timer_A is called every 1.00266 ms (nominal) TACTL = TASSEL_2 + ID_3 + TACLR + TAIE + MC_1; // SMCLK + divise 8 + reset + // enable intterupt + UP // 188/187500.0 = 0.001002666666666666 TACCR0 = 188; }