Skip to main content

C

2015


2014


msp430 - (still on the) basics

·2 mins
I was incorrect on the last post when I said our blinking fizzbuzz would need to step down to the LPM1 in order to use the watchdog timer, other than using external crystal. The watchdog timer, like I’ve said on the last post, can be sourced from a low-powered internal oscillator (VLO) which actually still active at LPM3. // ... // Setup Watchdog timer with ACLK // sourced from VLO (LFXT1S_2) at ~12kHz // so it will trigger interrupt within // interval: // (32/12) * 250ms) ~= ~670ms BCSCTL1 |= DIVA_0; BCSCTL3 |= LFXT1S_2; // Disable watchdog for now WDTCTL = WDTPW | WDTHOLD; // .

msp430 - basics

·6 mins

It’s interesting that msp430 has low power mode (LPM) which enables the MCU to get into sleep mode and stay operating. There are 6 profiles for this: 5 low-power modes, and one active mode.

These modes related to which components get disabled, thus lowering power consumption. The components are: CPU, MCLK (Master Clock), SMCLK (Sub-System Master Clock), ACLK (Auxiliary Clock), DCO (Digitally Controlled Oscillator), and internal crystal oscillator. By default, after power-up, DCO is used as the source oscillator for MCLK and SMCLK, while ACLK is sourced from a low-frequency (~32kHz) additional watch-crystal (LFXT1), All the clocks is software selectable, and can use either DCO, additional crystal (LFXT1), or internal low-power oscillator (VLO), but ACLK is the only clock that can not be configured to use DCO as its source oscillator.

Now back to the operating modes, here is the list of profile for msp430

  • Active mode is the normal operation profile, all components is enabled and running.
  • LPM 0 has CPU and MCLK disabled
  • LPM 1 has CPU, MCLK, and DCO disabled. DCO only disabled if it’s not used in active mode.
  • LPM 2 has CPU, MCLK, and SMCLK disabled.
  • LPM 3 has CPU, MCLK, SMCLK, and DCO disabled.
  • LPM 4 has CPU, MCLK, SMCLK, ACLK, DCO, and internal crytal oscillator disabled.

So yes, LPM 4 is the deep sleep mode.

The low-power mode can be set to be interruptible. That is, by setting the interrupt-enable flag together with the LPM profile. We’ll see how to do that in a moment.

The usual first program for microcontroller is the grand LED-blinking code. And to do that naively is to XOR-ing the bit to the pin where the led is mounted, and add some delay/sleep for some cycles so it’s alternating between high and low currents.

#include <msp430.h> 

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer
    /* Set P1.0 direction to output */
    P1DIR |= BIT0;

    /* Set P1.0 output high */
    P1OUT |= BIT0;

    while (1) {
        /* Wait for 200000 cycles */
        __delay_cycles(200000);
        /* Toggle P1.0 output */
        P1OUT ^= BIT0;
    }

    return 0;
}

/* Adapted from http://simplyembedded.wordpress.com/tutorials/lesson3/
 */

Now you see the code above would require the MCU to run in active mode all the time, and for MSP430 to living up to its title, we can optimize the code so it can run with less power consumption (shame on me because I haven’t measure the actual power consumption yet). First let’s take a look at the first line inside our main block above. The default watchdog timer was set to do a h/w reset in every 32ms (or the default timer set, since it’s probably different), so we have to hold it, or more like killing it, since we wont have anything to do with the timer.

But hey, it’s a timer. Could we possibly use that as the timer for our blinking led, sure we could. The watchdog can be configured to interrupt the normal execution and move the PC (Program Counter) to the ISR (Interrupt Service Routine), and execute the code over there. This combined with the low-power mode can be used to eliminate the infinite loop above, just like this:

#include <msp430.h> 

int i;

int main(void) {
    /* Set Watchdog timer to interrupt in interval 32ms,
     * clocked from SMCLK. */
    WDTCTL = WDT_MDLY_32;
    IE1 |= WDTIE;

    /* Set P1.0 direction to output */
    P1DIR |= BIT0;

    /* Set P1.0 output high */
    P1OUT |= BIT0;

    i = 0;

    __bis_SR_register(LPM1_bits | GIE);
}


/* Watchdog Timer interrupt service routine */
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(WDT_VECTOR))) watchdog_timer (void)
#else
#error Compiler not supported!
#endif
{
    i++;
    if (i >= 25) {
        P1OUT ^= BIT0;                            /* Toggle P1.0 using exclusive-OR */
        i = 0;
    }
}

For now I wont mind with the extra flag checking over there, but in case you curious, it’s checking for the compiler version and will use the pragma and __interrupt void watchdog_timer(void) for TI or IAR C compiler, and will use a bit longer line void __attribute__ ((interrupt(WDT_VECTOR))) watchdog_timer (void) for gcc. Other than those compiler, throw error.

Now back to our topic. I said I will show you how to set an interruptible low-power mode, and that it is. With some addition, actually, we should add the Watchdog interrupt-enable flag to the register, then proceed to the LPM1 mode while standby for any interrupts registered.

We defined the ISR as watchdog_timer and since 32ms is a bit too fast, we multiply the counter by 25 so it will blinking with interval at roughly 800ms.

got the launchpad

·2 mins

Here’s the new toy. An evaluation board of the legendary MSP430 series. It comes with 2 MCUs the MSP430G2553, a spare MSP4302452, and an 32kHz crystal for external oscillator. I’ll be working with MSP430G2553 mainly because it has twice the memory of the latter, another reason is since MSP430G2553 has its own h/w UART support, but since the board could do soft emulation for the UART (need jumper switching and some emulation code though), I think I will tinkering with the latter too, that is after I comfortable with the UART setup.

2013


Code Tidbits: wrk pt.1

·9 mins

I have this plan to do some write up series related to programming and such, mostly as another form of practicing C systems programming. Just when I wondered about what topic I should write, I found this gem written by Will Glozer. So I think I can study the source code and write some little explanation here and there about the code, hence the tidbits. Feel free to critic and correct things if you find mistakes on this. It would be my honour.

I kinda like the source code for its simplicity and learn a lot from them. The library used from redis including zmalloc and ae. I will going into zmalloc, before that, lets see this aprintf first.