void InitOsc(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer BCSCTL1 |= XTS; // XT1 as high-frequency _BIC_SR(OSCOFF); // turn on XT1 oscillator do // wait in loop until crystal is stable IFG1 &= ~OFIFG; while (IFG1 & OFIFG); BCSCTL1 |= DIVA0; // ACLK = XT1 / 2 BCSCTL1 &= ~DIVA1; IE1 &= ~WDTIE; // disable WDT int. IFG1 &= ~WDTIFG; // clear WDT int. flag WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | WDTSSEL | WDTIS1; // use WDT as timer, flag each // 512 pulses from ACLK while (!(IFG1 & WDTIFG)); // count 1024 pulses from XT1 (until XT1's // amplitude is OK) IFG1 &= ~OFIFG; // clear osc. fault int. flag BCSCTL2 |= SELM0 | SELM1; // set XT1 as MCLK }
inline void initialize_cpu_12mhz() { /* Disable the FLL control loop */ _BIS_SR(SCG0); /* Set lowest possible DCOx, MODx */ UCSCTL0 = 0x0000; /* Select suitable range */ UCSCTL1 = DCORSEL_5; /* Set DCO Multiplier */ UCSCTL2 = FLLD_1 + 0x16E; _BIC_SR(SCG0); /* Worst-case settling time for the DCO when the DCO range bits have been changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx UG for optimization. 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle */ __delay_cycles(250000); /* Loop until XT1 & DCO stabilizes, use do-while to insure that body is executed at least once */ do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); /* Clear fault flags */ SFRIFG1 &= ~OFIFG; } while ((SFRIFG1 & OFIFG)); }
int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT // configure the CPU clock (MCLK) // to run from SMCLK: DCO @ 16MHz and SMCLK = DCO // If no DCO calibration => stop here by loop if(CALBC1_16MHZ==0xff) while(1) _NOP(); _BIC_SR(GIE); DCOCTL = 0; BCSCTL1= CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; clock_init(); uart_init(); motor_init(); protocols_init(); pwm_init(); // ---------- // **action** // ---------- _BIS_SR(GIE); FOREVER { // read input input_scanner(); // handle any pending state changes in motor motor_step(); // send status reports to pi reporter(); } }
void RTC_Clock_init(void) { P5OUT = 0x00; //P5DIR = 0x02; // If this is uncommented RTC doesn't work!!!!!!!!!!!!!!!!!! P5DIR register must be set to 0x00!!!!!! P5SEL = 0x03; // Enabled alternative functions _BIC_SR(OSCOFF); // Enable the LFXT1 crystal oscillator UCSCTL6 &= (~XTS); // Select Low-frequency mode. XCAP bits define the capacitance at the XIN and XOUT pins. UCSCTL6 |= (XCAP0); // Set XCAP0 UCSCTL6 |= (XCAP1); // Set XCAP1 // Then Qrystal Load Capacitance is: // (XCAP1=0),(XCAP0=0) -> 2pF (XCAP1=0),(XCAP0=1) -> 5.5pF // (XCAP1=1),(XCAP0=0) -> 8.5pF (XCAP1=1),(XCAP0=1) -> 12pF UCSCTL6 &= (~XT1OFF); // Turns on the XT1. // Loop until XT1,XT2 & DCO stabilizes do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag UCSCTL4 = ((SELA__XT1CLK | SELS__DCOCLKDIV) | SELM__DCOCLKDIV); // ACLK source: XT1CLK, SMCLK: DCOCLKDIV, MCLK: DCOCLKDIV SFRIFG1 &= (~OFIFG); // Oscillator fault interrupt flag SFRIE1 |= (OFIE); // Oscillator fault interrupt enable }
__interrupt void Port_1(void) { wdtCounter = 0; P1OUT |= 0x01; P1IFG &= ~0x08; _BIC_SR(LPM0_EXIT); }
/******************************************************************************* * @fn void setup_oscillator( void ) * @brief configures oscillator for 12MHz operation derived from 32.768kHz * low-frequency crystal driving ACLK. * ****************************************************************************/ void setup_oscillator( void ) { // --------------------------------------------------------------------- // Enable 32kHz ACLK P5SEL |= 0x03; // Select XIN, XOUT on P5.0 and P5.1 UCSCTL6 &= ~(XT1OFF + XT1DRIVE_3); // XT1 On, Lowest drive strength UCSCTL6 |= XCAP_3; // Internal load cap UCSCTL3 = SELA__XT1CLK; // Select XT1 as FLL reference UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV; // SMCLK == MCLK // --------------------------------------------------------------------- // Configure CPU clock for 12MHz _BIS_SR(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_5; // Select suitable range UCSCTL2 = FLLD_1 + 0x16E; // Set DCO Multiplier _BIC_SR(SCG0); // Enable the FLL control loop // Worst-case settling time for the DCO when the DCO range bits have been // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx // UG for optimization. // 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle __delay_cycles(250000); // CHANGE // Loop until XT1 & DCO stabilizes, use do-while to insure that // body is executed at least once do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); SFRIFG1 &= ~OFIFG; // Clear fault flags } while ((SFRIFG1 & OFIFG)); }
//______________________________________________________________________ int main() { WDTCTL = WDTPW + WDTHOLD; __use_cal_clk(MHZ); P1SEL = 0; P1DIR = 0; P1OUT = 0; P2SEL = 0; P2DIR = 0; P2OUT = 0; _BIC_SR(GIE); led_init(); led_off(); uart_init(); _BIS_SR(GIE); char buf[64], *at=buf; uint8_t c = 0; while (1) { if (c || uart_getc(&c)) { switch (c) { case '.': led_flip(); break; case '1': uart_puts(quick); uart_putc('\n'); say(quick); break; case '2': uart_puts(dave); uart_putc('\n'); say(dave); break; case '3': uart_puts(luke); uart_putc('\n'); say(luke); break; case '4': uart_puts(time); uart_putc('\n'); say(time); break; case '5': uart_puts(temp); uart_putc('\n'); say(temp); break; case '\r': // end of command uart_putc('\n'); *at = '\0'; at = buf; if (*at == '*') { speak(at+1); }//if else { if (*at == '!') setPitch(*(at+1)-'A'); else say(at); }//else uart_puts("\ndone\n"); break; default: *at++ = c; uart_putc(c); break; }//switch }//if c = 0; }//while }
__interrupt void PORT1_ISR(void) #endif { _BIC_SR(GIE); led_on(); uart_port1_isr(); P1IFG = 0x00; led_off(); _BIS_SR(GIE); }
void board_init( void ) { _BIC_SR( GIE ); /* Disable interrupts during initialization. */ WDTCTL = WDTPW | WDTHOLD; /* Stop WDT */ init_ports( ); init_button_led( ); init_rf( ); _BIS_SR( GIE ); /* Enable interrupts after initialization. */ }
__interrupt void Port6_isr(void) { uint8_t i; uint8_t pin; P6IFG &= P6IE; for(i = 0, pin = P6IFG; pin > 0; i++) { if(gpio6_isrs[i] != 0 && (pin & 0x01)) { gpio6_isrs[i](i); } pin >>= 1; } P6IFG = 0; _BIC_SR(LPM3_EXIT); }
/* * main.c */ int main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer P1DIR|=BIT6+BIT0; P1SEL|=BIT6+BIT0; TA0CCR0=12000; TA0CCR1=6000; TA0CCTL1|=OUTMOD_7; TA0CTL|=TASSEL_1+MC_1; _BIC_SR(LPM0_bits); }
/*=============================================================== * Timer_Kill : The purpose of this service is to kill the timer * * This is done by putting the timer counter to 0 * * This function return information about the timer status at the * moment it was called. * * if the timer was running it returns 0 * if the timer has already expired (event was already dispatched) * it returns 1. This info is useful for timed events in FSM * When event was already dispatched (we got too late) FSM has * can block the event. */ UINT Timer_Kill(void) { _BIC_SR(GIE); // Disable General interrupts ( do atomic !!!!!!!!!!!!!!!!!!!) if (timer){ //If timer <> 0 => timer is running timer=0; // Therefore Kill timer _BIS_SR(GIE); // Re Enable General interrupts return (0); //Timer was running } else _BIS_SR(GIE); // Re Enable General interrupts return(1); //Timer has already expired i.e. timer event has been dispatched }
void clock_init(void) { // UCSCTL1 = DCORSEL_5; // 0x0050 //UCSCTL1 = DCORSEL_1; // UCSCTL2 = 0x01F9; // UCSCTL3 = 0x0020; // UCSCTL4 = 0x0233; // UCSCTL5 = 0x0040; // UCSCTL6 = 0x0100; //Set DCO FLL reference = REFO UCS_clockSignalInit( __MSP430_BASEADDRESS_UCS_RF__, UCS_FLLREF, UCS_REFOCLK_SELECT, UCS_CLOCK_DIVIDER_1 ); //Set ACLK = REFO UCS_clockSignalInit( __MSP430_BASEADDRESS_UCS_RF__, UCS_ACLK, UCS_REFOCLK_SELECT, UCS_CLOCK_DIVIDER_1 ); //Set Ratio and Desired MCLK Frequency and initialize DCO // UCS_initFLLSettle( // __MSP430_BASEADDRESS_UCS_RF__, // 1000, // 1000 khz // 31 // 1000 kHz / 32.768 Khz (Crystal) // ); _BIS_SR(SCG0); // Disable the FLL control loop UCS_initFLLSettle( __MSP430_BASEADDRESS_UCS_RF__, target_clock_speed_kHz, // 10000 khz (uint16_t) ((target_clock_speed_kHz * 1000) / 32768) // 10000 kHz / 32.768 Khz = 305(Crystal) ); _BIC_SR(SCG0); // Enable the FLL control loop clock_speed = UCS_getSMCLK(__MSP430_BASEADDRESS_UCS_RF__); //unsigned long clockValueMCLK = UCS_getMCLK(__MSP430_BASEADDRESS_UCS_RF__); //unsigned long clockValueCLK = UCS_getACLK(__MSP430_BASEADDRESS_UCS_RF__); }
/** * setMCLK * * Config MCLK registers * * @param dcorsel CPU DCORSEL value * @param flln MCLK multiplier bits */ void __inline__ CC430CORE::setMCLK(uint16_t dcorsel, uint16_t flln) { /** * Configure CPU clock for 8MHz */ _BIS_SR(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = dcorsel; // Select suitable range UCSCTL2 = FLLD_1 + flln; // Set DCO Multiplier _BIC_SR(SCG0); // Enable the FLL control loop // Worst-case settling time for the DCO when the DCO range bits have been // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx // UG for optimization. // 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle //__delay_cycles(250000); delayClockCycles(0xFFFF); }
void init_devices(void) { //1. Stop errant interrupts until set up _BIC_SR(GIE); // Disable interrupts during initialization process //2. Init System Clock // By defaut the FLL stabilizes MCLK and SMCLK to 1.048576 MHz and fDCO = 2.097152 MHz. //3. Init Peripherals //RTC_Clock_init(); ports_init(); timer1_A3_init(); timer1_A3_Stop_Mode; //P3DIR |= BIT7; // Show SMCLK to P3.7 //P3SEL |= BIT7; _BIS_SR(GIE); // Global Interrupt enabled. Do this at the END of the initialization!!!!!!!! //all peripherals are now initialized }
void init_clock(void){ volatile unsigned int i; /* XTAL = LF crystal, ACLK = LFXT1/1, DCO Rset = 4, XT2 = ON */ BCSCTL1 = 0x04; /* Clear OSCOFF flag - start oscillator */ _BIC_SR( OSCOFF ); do{ /* Clear OSCFault flag */ IFG1 &= ~OFIFG; /* Wait for flag to set */ for( i = 255; i > 0; i-- ) ; } while(( IFG1 & OFIFG ) != 0); /* Set MCLK to XT2CLK and SMCLK to XT2CLK */ BCSCTL2 = 0x88; }
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DO NOT ALTER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv //****************************************************************************** // Call display_results after every generation // // returns TRUE when MAX_TIME is reached or switch is pressed // int display_results(void) { //LED_RED_ON; // turn red LED on generation++; // next generation lcd_mode(0); lcd_cursor(4, 1); lcd_printf("%d", generation); // only update when seconds changes if (seconds != old_seconds) { old_seconds = seconds; printf("/%d", seconds); lcd_cursor(145, 1); printf("%2d", generation / seconds); } // check for MAX_GENERATION or MAX_TIME exceeded if ((generation >= MAX_GENERATION) || (seconds >= MAX_TIME)) { long hSecs, hGensPerSec; _BIC_SR(GIE); lcd_cursor(4, 1); // output results lcd_printf("%d/%d", generation, seconds); lcd_cursor(145, 1); printf("%2d", generation / seconds); lcd_cursor(50, 80); hSecs = ((long)seconds * 100) + (((WDT_1SEC_CNT - WDT_sec_cnt) * 100) / WDT_1SEC_CNT); hGensPerSec = ((long)generation * 100 * 100) / hSecs; lcd_printf("\a\b\t%ld.%02ld", hGensPerSec / 100, hGensPerSec % 100); if (generation < MAX_TIME * 5) { lcd_cursor(30, 30); lcd_printf("\a\b\tTOO SLOW!"); } _BIS_SR(GIE); switches = 0; // clear any pending switches while (!switches); // wait for any switch } //LED_RED_OFF; // turn red LED off return switches; // return switch value } // end display_results
void sleep_ms(unsigned short delay) { _BIC_SR(GIE); /* Disable all interrupts so we can setup sleep */ /* Disable all interrupts */ P1IE = 0; P2IE = 0; /* Setup timer B, compare */ TBCCTL0 = CCIE; /* ACLK at 32768 Hz, this converts to ms */ /* 4096/125 = 32.768 */ TBCCR0 = (unsigned short) (((unsigned int) (delay) * 4096) / 125); /** * Setup timer B, with capture 0. * MC_1 - Count up to TBCCR0 * TBSSEL_1 - We use the ACLK as our clock * TBCLR - Reset the clock to TBR == 0 */ TBCTL = MC_1 + TBSSEL_1 + TBCLR; _BIS_SR(LPM3_bits + GIE); }
inline void sleep() { P1OUT &= ~RX_EN_PIN; // enable port interrupt for voltage supervisor P2IES = 0; P2IFG = 0; P2IE |= VOLTAGE_SV_PIN; P1IE = 0; P1IFG = 0; TACTL = 0; _BIC_SR(GIE); // temporarily disable GIE so we can sleep and enable interrupts // at the same time P2IE |= VOLTAGE_SV_PIN; // Enable Port 2 interrupt if (is_power_good()) P2IFG = VOLTAGE_SV_PIN; _BIS_SR(LPM4_bits | GIE); return; }
/** * Startup routine for 32kHz Cristal on LFXT1 * */ void LFXT_Start(uint16_t xtdrive) { //SetVCore(3); //UCSCTL6_L |= XT1DRIVE1_L+XT1DRIVE0_L; // Highest drive setting for XT1 startup /* Enable 32K ACLK */ P5SEL |= 0x03; /* Select XIN XOUT on P5.0 P5.1 */ UCSCTL6 &= ~XT1OFF; /* XT1 ON highest drive strenght */ UCSCTL6 |= XCAP_3; /* Internal load cap */ UCSCTL3 = SELA__XT1CLK; /* Select XT1 as FLL reference */ UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV; /* Set MCLK for 12MHz */ //__bis_SR_register(SCG0); /* Disable the FLL control loop */ _BIS_SR(SCG0); UCSCTL0 = 0x0000; /* Set lowest possible DCOx and MODx */ UCSCTL1 = DCORSEL_5; /* Select Divider range for 12MHz */ UCSCTL2 = FLLD_1 + 0x16E; /* Set DCO multiplier */ //__bic_SR_register(SCG0); /* Enable FLL control loop */ _BIC_SR(SCG0); __delay_cycles(250000); /* Loop until it stabilizes ensuring to perform at least once the instructions*/ do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); SFRIFG1 &= ~OFIFG; /* Clear fault flags */ } while ((SFRIFG1 & OFIFG)); /*while (SFRIFG1 & OFIFG) { // check OFIFG fault flag UCSCTL7 &= ~(DCOFFG+XT1LFOFFG+XT1HFOFFG+XT2OFFG); // Clear OSC flaut Flags fault flags SFRIFG1 &= ~OFIFG; // Clear OFIFG fault flag }*/ UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(xtdrive); // set Drive mode }
static void ISR_timer0_a1() { _BIC_SR(GIE); switch(TAIV) { case 0x02: clear_pin(PWM_PINS[current_servo]); if(current_servo == 0) { TA0CCR0 = last_period; } else { TA0CCR0 = norm_period; } break; default: break; } _BIS_SR_IRQ(GIE); }
void ISR_timer0_a0() { _BIC_SR(GIE); current_servo++; if(current_servo == NUM_SERVOS) { current_servo = 0; } set_pin(PWM_PINS[current_servo]); /* * If the control structure is not locked, go ahead and access it * (Also access if there was no busy query function specified) */ if(!servo_ctl_busy || !servo_ctl_busy()) { current_servo_pos = servo_ctl->pos[current_servo]; servo_ctl_buffer.pos[current_servo] = current_servo_pos; memcpy(&servo_ctl_buffer.baseband, &servo_ctl->baseband, 4); } else { current_servo_pos = servo_ctl_buffer.pos[current_servo]; } // Clamp servo position uint16_t maxband_diff = servo_ctl_buffer.maxband - servo_ctl_buffer.baseband; if(current_servo_pos > maxband_diff) current_servo_pos = maxband_diff; TA0CCR1 = servo_ctl_buffer.baseband + current_servo_pos; _BIS_SR_IRQ(GIE); }
//************************** SETUP TO RECEIVE ********************************* // note: port interrupt can also reset, but it doesn't call this function // because function call causes PUSH instructions prior to bit read // at beginning of interrupt, which screws up timing. so, remember // to change things in both places. static inline void setup_to_receive() { _BIC_SR(GIE); // temporarily disable GIE so we can sleep and enable interrupts // at the same time P1OUT |= RX_EN_PIN; delimiterNotFound = 0; // setup port interrupt on pin 1.2 P1SEL &= ~BIT2; //Disable TimerA2, so port interrupt can be used // Setup timer. It has to setup because there is no setup time after done with // port1 interrupt. TACTL = 0; TAR = 0; TACCR0 = 0xFFFF; // Set up TimerA0 register as Max TACCTL0 = 0; TACCTL1 = SCS + CAP; //Synchronize capture source and capture mode TACTL = TASSEL1 + MC1 + TAIE; // SMCLK and continuous mode and Timer_A // interrupt enabled. // initialize bits bits = 0; // initialize dest dest = destorig; // = &cmd[0] // clear R6 bits of word counter from prior communications to prevent dest++ // on 1st port interrupt asm("CLR R6"); P1IE = 0; P1IES &= ~RX_PIN; // Make positive edge for port interrupt to detect start of // delimiter P1IFG = 0; // Clear interrupt flag P1IE |= RX_PIN; // Enable Port1 interrupt _BIS_SR(LPM4_bits | GIE); return; }
// ************************************************************************************************* // @fn init_application // @brief Initialize the microcontroller. // @param none // @return none // ************************************************************************************************* void init_application(void) { volatile unsigned char *ptr; #ifndef EMU // --------------------------------------------------------------------- // Enable watchdog // Watchdog triggers after 16 seconds when not cleared #ifdef USE_WATCHDOG WDTCTL = WDTPW + WDTIS__512K + WDTSSEL__ACLK; #else WDTCTL = WDTPW + WDTHOLD; #endif // --------------------------------------------------------------------- // Configure PMM SetVCore(3); // Set global high power request enable PMMCTL0_H = 0xA5; PMMCTL0_L |= PMMHPMRE; PMMCTL0_H = 0x00; // --------------------------------------------------------------------- // Enable 32kHz ACLK P5SEL |= 0x03; // Select XIN, XOUT on P5.0 and P5.1 UCSCTL6 &= ~XT1OFF; // XT1 On, Highest drive strength UCSCTL6 |= XCAP_3; // Internal load cap UCSCTL3 = SELA__XT1CLK; // Select XT1 as FLL reference UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV; // --------------------------------------------------------------------- // Configure CPU clock for 12MHz _BIS_SR(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_5; // Select suitable range UCSCTL2 = FLLD_1 + 0x16E; // Set DCO Multiplier _BIC_SR(SCG0); // Enable the FLL control loop // Worst-case settling time for the DCO when the DCO range bits have been // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx // UG for optimization. // 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle __delay_cycles(250000); // Loop until XT1 & DCO stabilizes, use do-while to insure that // body is executed at least once do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); SFRIFG1 &= ~OFIFG; // Clear fault flags } while ((SFRIFG1 & OFIFG)); // --------------------------------------------------------------------- // Configure port mapping // Disable all interrupts __disable_interrupt(); // Get write-access to port mapping registers: PMAPPWD = 0x02D52; // Allow reconfiguration during runtime: PMAPCTL = PMAPRECFG; // P2.7 = TA0CCR1A or TA1CCR0A output (buzzer output) ptr = &P2MAP0; *(ptr+7) = PM_TA1CCR0A; P2OUT &= ~BIT7; P2DIR |= BIT7; // P1.5 = SPI MISO input ptr = &P1MAP0; *(ptr+5) = PM_UCA0SOMI; // P1.6 = SPI MOSI output *(ptr+6) = PM_UCA0SIMO; // P1.7 = SPI CLK output *(ptr+7) = PM_UCA0CLK; // Disable write-access to port mapping registers: PMAPPWD = 0; // Re-enable all interrupts __enable_interrupt(); #endif // --------------------------------------------------------------------- // Configure ports // --------------------------------------------------------------------- // Reset radio core radio_reset(); radio_powerdown(); // --------------------------------------------------------------------- // Init acceleration sensor as_init(); // --------------------------------------------------------------------- // Init LCD lcd_init(); // --------------------------------------------------------------------- // Init buttons init_buttons(); // --------------------------------------------------------------------- // Configure Timer0 for use by the clock and delay functions Timer0_Init(); // --------------------------------------------------------------------- // Init pressure sensor ps_init(); }
__interrupt void watchdog_timer(void) { _BIC_SR(GIE); // Disable interrupts if(count % 13 == 0) { switch(adc_channel) { case 0: ADC10CTL1 &= ~INCH_2; ADC10CTL1 = INCH_3; ADC10AE0 &= ~BIT2; ADC10AE0 |= BIT3; break; case 1: ADC10CTL1 &= ~INCH_3; ADC10CTL1 = INCH_1; ADC10AE0 &= ~BIT3; ADC10AE0 |= BIT1; break; case 2: ADC10CTL1 &= ~INCH_1; ADC10CTL1 |= INCH_2; ADC10AE0 &= ~BIT1; ADC10AE0 |= BIT2; break; } ADC10CTL0 |= ENC + ADC10SC; } if(count >= MAX) { P1OUT |= BIT7 + BIT4 + BIT5; // Turn on power to all outputs pwm1_off = 0; pwm2_off = 0; pwm3_off = 0; count = 0; // and reset count. } else// if(!(pwm1_off + pwm2_off + pwm3_off == 3)) { if( count > pwm1_val ) { P1OUT &= ~BIT7; // Turn off power to this output. pwm1_off = 1; } if(count >= pwm2_val) { P1OUT &= ~BIT4; pwm2_off = 1; } if(count > pwm3_val) { P1OUT &= ~BIT5; pwm3_off = 1; } } if(count % 19 == 0 ) { switch(adc_channel) { case 0: pwm1_val = (ADC10MEM); adc_channel = 1; break; case 1: pwm2_val = (ADC10MEM); adc_channel = 2; break; case 2: pwm3_val = (ADC10MEM); adc_channel = 0; break; } ADC10CTL0 &= ~(ENC + ADC10SC); } count++; _BIS_SR(GIE); // Reenable Interrupts. }
port1(void) { wdtCounter = 0; P1OUT |= 0x01; P1IFG &= ~0x08; _BIC_SR(LPM0_EXIT); }
void main(void) { // Disable Entire System // _BIS_SR(LPM4_bits); // Turn DCO to slowest clock (method from Errata sheet) DCOCTL = 0x00; // Set RSEL bits BCSCTL1 &= 0xF0; // 0b1111_0000 -> Clear out previous setting /*BCSCTL1 |= 0x00; // Place new setting for RSEL : 0b0000_xxxx DCOCTL |= 0x00; // Place new setting for DCO : 0bxxx0_0000*/ BCSCTL2 |= DIVM0; //Divide MCLK by 2 WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer // Turn OFF SMCLK and external Oscillator _BIS_SR(OSCOFF + SCG1); // Set P1.ALL to be Output ports P1OUT = 0x00; // 1111_1110 P1DIR = ~(0x01); P1SEL = 0x00; // Setup ACLK source to be from internal VLOCLK (~10 kHz) BCSCTL3 |= LFXT1S_2; // Setup ACLK to be dvided by 8 BCSCTL1 |= DIVA1 + DIVA0; // Sleep 20 ms // Initialize timerA0 //TACTL &= TACLR; CCTL0 = CCIE; // CCR0 interrupt enabled CCR0 = 900; // 10 khz source * 900 ms = 9,000 cycles TACTL = TACLR + TASSEL_1 + MC_1; // Source: ACLK, Mode: UP // Enter LPM3 Mode _BIC_SR(OSCOFF); _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupts // -- Wake up -- // // Turn OFF SMCLK and external Oscillator _BIS_SR(OSCOFF + SCG1); while (1) { // Generate 5.0 kHz tone -- Tone 1 for ( unsigned short i = 175 ; i != 0 ; i-- ) { // Toggle Pin ON P1OUT ^= 0x04; // Delay for 1/2 period of 2.5 kHz (10 cycles) //__delay_cycles(1); // Toggle Pin OFF P1OUT ^= 0x04; // Delay __delay_cycles(1); } /* // -- Toggle LED 1 (Red- // P1OUT ^= 0x20; // -- Toggle LED 2 (Green)/ P1OUT ^= 0x40; // -- Toggle LED 3 (Yellow)-- // P1OUT ^= 0x80; */ // Sleep LONG ms // Initialize timerA0 //TACTL &= TACLR; CCTL0 = CCIE; // CCR0 interrupt enabled CCR0 = 700; // 10 khz source * 900 ms = 9,000 cycles TACTL = TACLR + TASSEL_1 + MC_1; // Source: ACLK, Mode: UP // Enter LPM3 Mode _BIC_SR(OSCOFF); _BIS_SR(LPM3_bits + GIE); // Enter LPM3 w/ interrupts // -- Wake up -- // // Turn OFF SMCLK and external Oscillator _BIS_SR(OSCOFF + SCG1); } }
int main(void) { //if (!(P1IN&usbminus)) usbwait = 0; // no usb D- pullup, no bootloader // no pull-up, app present, run app if (!(P1IN&usbminus) && (*((char*) *((uint16_t*) 0xffbe)) != -1)) asm("br &0xffbe"); WDTCTL = WDTPW | WDTHOLD; // Stop watchdog P1OUT = 0; // Prepare Port 1 usbdir = ~(usbplus | usbminus); // USB lines are inputs //P1SEL |= BIT4; // SMCLK for measurements on P1.4 P1DIR |= BIT5; #ifdef USE_32768HZ_XTAL BCSCTL1 = DIVA_3 | 15; // ACLK / 8, Range 15 DCOCTL = 127; // ~15 MHz TACTL = TASSEL_2 | MC_2 | TACLR; // Continous up mode with clocking from SMCLK TACCTL0 = CM_1 | CCIS_1 | CAP | CCIE; // Setup CCR0 for capturing on rising edges of ACLK with enabled interrupts __eint(); #else P2SEL = 0; P2DIR = BIT6|BIT7; // indicator led P2OUT = 0; BCSCTL1 = 15; // Range 15 DCOCTL = 127; // ~15 MHz #endif __delay_cycles(2000000); // Allow some time to stabilize power uint8_t usbwait=12; usbies = 0; // Interrupt on rising edge of D+ because there is keep-alive signaling on // D- that would cause false syncs usbifg = 0; // No interrupt pending uint16_t addrStart=0, addrEnd=0, addrCurrent=0, addrSave=0; uint8_t initialized=0; uint16_t heartbeat = 0; uint8_t idx=0, inBuf[48]; uint8_t *buffUp=0; uint8_t next_time_flash_erase = 0; static uint16_t const USB_IDLE_DETECT_THRESHOLD = 16384; uint16_t usb_idle_detect_counter = 0; uint8_t usb_idle = 0; /* What is this usb idle thing ? We are in a bootloader, its aim is to receive via usb a new program to be flashed. But erasing and writing to flash takes quite a big time, and usb timing is tight. The usb protocol needs that response packets be sent within a certain time frame, and if the mcu misses that time frame, the host can consider the device as malfunctioning. The idea behind the usb idle thing is to delay operations that take time to a moment where we hope the mcu will not have any usb packet to answer. Specifically : 1. when the host side sends an address where flash must be erased, the host sleeps for a certain amount T of milliseconds before sending another command. Within T milliseconds, the mcu has time to answer remaining usb packets and erase the requested flash segment. 2. when the host side sends payload bytes (which are bytes of the program to be flashed), the mcu has no time to write them into flash and answer usb packets. It stores them in a small RAM buffer, and writes them to flash once the host sleeps a bit. Here, the host sends 32 bytes before sleeping and letting the mcu write those bytes to flash. To detect usb idle, we simply count how many "for-ever" loops we have done since last received usb packet, and beyond a threshold, we consider being in usb idle mode, that is to say : we consider the host will not send any other usb packet before we have finished with flashing and being able to handle a new usb packet. */ for (;;) // for-ever { // Detect USB idle if(initialized && !usb_idle) { usb_idle_detect_counter++; if(usb_idle_detect_counter > USB_IDLE_DETECT_THRESHOLD) usb_idle = 1; } if (!heartbeat++) { if (initialized) // usb reset from host occured { P2OUT ^= BIT6; }//if else { // no reset, run app if present //if (!usbwait && (*((char*) 0xc000) != -1)) { if (!usbwait && (*((char*) *((uint16_t*) 0xffbe)) != -1)) { _BIC_SR(GIE); TACTL = 0; P2DIR = P1DIR = 0; P2OUT = P1OUT = 0; asm("br &0xffbe"); } else { usbwait--; } } } unsigned n = 80; // Reset if both D+ and D- stay low for a while // 10 ms in SE0 is reset // Should this be done in the ISR somehow??? while (!initialized && !(usbin & (usbplus | usbminus))) { if (!--n) { CurrentAddress = 0; // Device has initial address of 0 NewAddress = 0; // addrCurrent = addrStart = addrEnd = 0; #ifndef USE_32768HZ_XTAL if (!initialized) { TACTL = TASSEL_2 | MC_2 | TACLR; // Continous up mode with clocking from SMCLK initialized = 1; //P2OUT |= BIT6; // debug use, led indicate we are trying sync n = 1000; // time to stabilize clock while (--n) { while (!(usbin&usbminus)); TACTL |= TACLR; while ((usbin&usbminus)); if (TAR < 15000) ++DCOCTL; else --DCOCTL; } usbie = usbplus; _BIS_SR(GIE); } #else usbie = usbplus; _BIS_SR(GIE); initialized = 1; #endif break; } } if(DataPacketBuffer[0]) // Check if the USB SIE has received a packet { uint8_t packet_size = *DataPacketBuffer; // we save packet_size here to avoid it being DataPacketBuffer[0] = 0; // overwritten by "fast" status packet that follows usb_idle_detect_counter = 0; usb_idle = 0; // At the end of the buffer is the PID of the preceding token packet // Check if it is a SETUP packet if(DataPacketBuffer[15] == USB_PID_SETUP) { // Handle the packet, get a response if((DataToTransmit = ProtocolSetupPacket(DataPacketBuffer))) { // Setup to send the response Data_PID_Toggle = USB_PID_DATA0; DataToTransmitOffset = 1; } else { // Send STALL PID if there is no response ReadyForTransmit = usb_packet_stall; } } else if (DataPacketBuffer[15] == USB_PID_OUT) // Check if it is an OUT packet { // will be getting stuffs here // incoming LL-PP-RI-(d0-d1-d2-d3-d4-d5)-C1-C2 // ex. 0a-4b-01-(00-4b-0e-8d-0d-4e)-56-fa // LL - length, ours are always 0a or 08 // PP - PID, should only be DATA0 or DATA1 (0xc3 or 0x4b) - 4b for us // RI - application level control byte - the HID report id. Here : // == 1, request flash write, start address / length follows // == 2, no special instruction, just carry data // d? - firmware data, each packet carries up to LL-4 bytes of data // for report id 1 : report count = 6, LL = 0a, data bytes = 6 // for report id 2 : report count = 4, LL = 08, data bytes = 4 // C? - packet checksum, application does not use these // uint8_t *cp = DataPacketBuffer+2; //if (*DataPacketBuffer == 0x0A && *cp == 0x01) if (packet_size == 0x0A) { // flash write request (report id 1) cp++; addrCurrent = addrStart = (*cp<<8) + *(cp+1); // get start address high bytes cp += 2; addrEnd = (*cp<<8) + *(cp+1); //______________ interrupt vector, don't do immediate flash write if (addrStart >= 0xff00) { buffUp = inBuf; } else { addrSave = addrEnd; buffUp = 0; idx = 0; next_time_flash_erase = 1; } } //else if (*DataPacketBuffer == 0x08 && *cp == 0x02) else if (packet_size == 0x08) { uint8_t c=0; // receive bytes (report id 2) cp++; // skip report id if (buffUp) // we are receiving interrupt vector bytes { for (c=0;c<4;c++) *((uint8_t *) buffUp++) = *cp++; addrCurrent += 4; } else { // we are receiving normal data for (c=0;c<4;c++) inBuf[c+idx] = *cp++; idx += 4; } } } // else if USB_PID_OUT //DataPacketBuffer[0] = 0; // Done with received packet, don't process again, allow USB SIE to receive the next packet } // if USB SIE has received a packet // Check if an outgoing packet needs chunking and the USB SIE // is ready for it if (DataToTransmit && !ReadyForTransmit) { PacketGenerator(); // Make a chunk with CRC } if (!ReadyForTransmitIrqIn) { // Check if the USB SIE is ready for an endpoint 1 packet /* IrqIn(IrqInSendPacketBuffer); // Build the packet CRC(IrqInSendPacketBuffer); // Append CRC ReadyForTransmitIrqIn = IrqInSendPacketBuffer; // Send it */ } // We have received interrupt vector address, and data bytes. // USB is idle which means we can write to flash if(usb_idle && buffUp && addrCurrent > addrStart && addrStart >= 0xff00) { //_____ we doing interrupt vector, so don't be interrupted uint16_t savIntr = *((uint16_t *) 0xffe4); uint16_t savReset = *((uint16_t *) 0xfffe); _BIC_SR(GIE); FCTL1 = FWKEY+ERASE; FCTL3 = FWKEY; *((uint8_t *) 0xff00) = 0; FCTL1 = FWKEY+WRT; uint8_t *dp = (uint8_t *) 0xffa0; uint8_t *vp = (uint8_t *) 0xffe0; uint8_t *cp = inBuf; uint8_t i=0x20; while (i--) *dp++ = *cp++; // write to flash backup copy *((uint16_t *) (inBuf+4)) = savIntr; // use bootloader's interrupt *((uint16_t *) (inBuf+30)) = savReset;// reset goes to bootloader i=0x20; cp = inBuf; while (i--) *vp++ = *cp++; // write to flash real vector *((uint16_t *) (0xff80)) = addrSave; // save application's end address *((uint16_t *) (0xffde)) = 0xaa55; // disable factory BSL buffUp = 0; FCTL1 = FWKEY; FCTL3 = FWKEY+LOCK; _BIS_SR(GIE); } // We have received addresses. USB is idle : erase flash. if(usb_idle && next_time_flash_erase) { FCTL2 = FWKEY+FSSEL0+(30); FCTL1 = FWKEY+ERASE; FCTL3 = FWKEY; *((uint8_t *) addrCurrent) = 0; FCTL1 = FWKEY+WRT; next_time_flash_erase = 0; } // We have received data bytes, and USB is idle : flash them. if(usb_idle && !buffUp && addrStart < 0xff00 && idx) { uint8_t c=0; for(c = 0; c < idx; c++) *((uint8_t *) addrCurrent++) = inBuf[c]; idx = 0; if (!(addrCurrent&0x01ff)) { //____ we are crossing 512byte/block boundary //____ erase and get ready for next block FCTL1 = FWKEY+ERASE; FCTL3 = FWKEY; *((uint8_t *) addrCurrent) = 0; FCTL1 = FWKEY+WRT; } } if(addrCurrent >= addrEnd && !buffUp) // !buffUp means that we have handled the interrupt vector in an usb idle time { //____ lockup flash, we are over. FCTL1 = FWKEY; FCTL3 = FWKEY+LOCK; addrCurrent = addrStart = addrEnd = 0; idx = 0; } }//for-ever }
void cc430_cpu_init(void) { volatile uint16_t i; volatile unsigned char *ptr; /* disable watchdog */ WDTCTL = WDTPW + WDTHOLD; // --------------------------------------------------------------------- // Enable 32kHz ACLK P5SEL |= 0x03; // Select XIN, XOUT on P5.0 and P5.1 UCSCTL6 &= ~XT1OFF; // XT1 On, Highest drive strength UCSCTL6 |= XCAP_3; // Internal load cap UCSCTL3 = SELA__XT1CLK; // Select XT1 as FLL reference UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV; // --------------------------------------------------------------------- // Configure CPU clock for 12MHz _BIS_SR(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_5; // Select suitable range UCSCTL2 = FLLD_1 + 0x16E; // Set DCO Multiplier _BIC_SR(SCG0); // Enable the FLL control loop // Worst-case settling time for the DCO when the DCO range bits have been // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx // UG for optimization. // 32 x 32 x 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle for (i = 0xFF; i > 0; i--); // Time for flag to set // Loop until XT1 & DCO stabilizes, use do-while to insure that // body is executed at least once do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); SFRIFG1 &= ~OFIFG; // Clear fault flags } while ((SFRIFG1 & OFIFG)); // Disable all interrupts __disable_interrupt(); // Get write-access to port mapping registers: PMAPPWD = 0x02D52; // Allow reconfiguration during runtime: PMAPCTL = PMAPRECFG; // P2.7 = TA0CCR1A or TA1CCR0A output (buzzer output) ptr = &P2MAP0; *(ptr + 7) = PM_TA1CCR0A; P2OUT &= ~BIT7; P2DIR |= BIT7; // P1.5 = SPI MISO input ptr = &P1MAP0; *(ptr + 5) = PM_UCA0SOMI; // P1.6 = SPI MOSI output *(ptr + 6) = PM_UCA0SIMO; // P1.7 = SPI CLK output *(ptr + 7) = PM_UCA0CLK; // Disable write-access to port mapping registers: PMAPPWD = 0; // Re-enable all interrupts irq_enable(); }
int main(void) { #if WITH_SD int r; #endif /* WITH_SD */ msp430_cpu_init(); watchdog_stop(); /* Platform-specific initialization. */ msb_ports_init(); adc_init(); clock_init(); rtimer_init(); sht11_init(); leds_init(); leds_on(LEDS_ALL); irq_init(); process_init(); /* serial interface */ rs232_set_input(serial_line_input_byte); rs232_init(); serial_line_init(); uart_lock(UART_MODE_RS232); uart_unlock(UART_MODE_RS232); #if WITH_UIP slip_arch_init(BAUD2UBR(115200)); #endif #if WITH_SD r = sd_initialize(); if(r < 0) { printf("Failed to initialize the SD driver: %s\n", sd_error_string(r)); } else { sd_offset_t capacity; printf("The SD driver was successfully initialized\n"); capacity = sd_get_capacity(); if(capacity < 0) { printf("Failed to get the SD card capacity: %s\n", sd_error_string(r)); } else { printf("SD card capacity: %u MB\n", (unsigned)(capacity / (1024UL * 1024))); } } #endif /* System services */ process_start(&etimer_process, NULL); ctimer_init(); node_id_restore(); init_net(); energest_init(); #if PROFILE_CONF_ON profile_init(); #endif /* PROFILE_CONF_ON */ leds_off(LEDS_ALL); printf(CONTIKI_VERSION_STRING " started. Node id %u, using %s.\n", node_id, rime_mac->name); autostart_start(autostart_processes); /* * This is the scheduler loop. */ ENERGEST_ON(ENERGEST_TYPE_CPU); while (1) { int r; #if PROFILE_CONF_ON profile_episode_start(); #endif /* PROFILE_CONF_ON */ do { /* Reset watchdog. */ watchdog_periodic(); r = process_run(); } while(r > 0); #if PROFILE_CONF_ON profile_episode_end(); #endif /* PROFILE_CONF_ON */ /* * Idle processing. */ int s = splhigh(); /* Disable interrupts. */ if (process_nevents() != 0) { splx(s); /* Re-enable interrupts. */ } else { static unsigned long irq_energest = 0; /* Re-enable interrupts and go to sleep atomically. */ ENERGEST_OFF(ENERGEST_TYPE_CPU); ENERGEST_ON(ENERGEST_TYPE_LPM); /* * We only want to measure the processing done in IRQs when we * are asleep, so we discard the processing time done when we * were awake. */ energest_type_set(ENERGEST_TYPE_IRQ, irq_energest); if (uart_edge) { _BIC_SR(LPM1_bits + GIE); } else { _BIS_SR(LPM1_bits + GIE); } /* * We get the current processing time for interrupts that was * done during the LPM and store it for next time around. */ dint(); irq_energest = energest_type_time(ENERGEST_TYPE_IRQ); eint(); ENERGEST_OFF(ENERGEST_TYPE_LPM); ENERGEST_ON(ENERGEST_TYPE_CPU); #if PROFILE_CONF_ON profile_clear_timestamps(); #endif /* PROFILE_CONF_ON */ } } return 0; }