This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430FR4133: Timer A interrupt issues

Part Number: MSP430FR4133
Other Parts Discussed in Thread: MSP430WARE

Tool/software: Code Composer Studio

Hello all, 

I am trying to configure Timer A to feed the dog every millisecond. Feeding the dog isn't the issue, it seems I am struggling with the ISR. The majority of my code is unrelated to this task. If something seems to be missing just let me know. Since the SMCLK is at 8Hz, the clock should count up from 0 to 8000 (hex is 1F40), which should have a period of 1 millisecond. I have identified one of the issues in the MC bit in the TA0CTL register. I have attempted to write to the register three different ways in hopes of the labels being weird in the libraries. If I remove the MC bit flip, then the code works without the interrupt every triggering. If the MC bit is included then it never reaches main. 

int main(void)
{
char buffer[50];
SYSTEMinit();
while(1)
{
char buffer[30];
sprintf(buffer,"\n\r%d",i);
writeUART(buffer);
_delay_cycles(8000000);

}
}

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
i++;
}

void SYSTEMinit()
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
_BIS_SR(GIE);

//Timer configuration
TA0CCTL0 |= TACLR; //Clears clock
TA0CCR0 = 0x1F40; //0x1F40= 8000 which at 8 MHz is 1 ms
TA0CCTL0 |= CCIE; //Enables compare interrupt, puts timer A into compare mode
//TA0CTL |= TASSEL_2 | MC_1 | TAIE; // SMCLK, continuous mode
//TA0CTL |= TASSEL_2 + TAIE + MC0;
TA0CTL = 0x0212;

PM5CTL0 &= ~LOCKLPM5; //Lock Pins into place // disable FLL
CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source
CSCTL0 = 0; // clear DCO and MOD registers
CSCTL1 &= ~(DCORSEL_7); // Clear DCO frequency select bits first
CSCTL1 |= DCORSEL_3; // Set DCO = 8MHz
CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz
CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32kHz) as ACLK source, ACLK = 32768Hz
// default DCODIV as MCLK and SMCLK source
}

void UARTinit()
{
//STEP 1 Set UCSWRST Bit
UCA0CTLW0 |= UCSWRST; //Allows UART to be configured
//STEP 2 Initialize all relevant Registers
UCA0CTLW0 |= UCSSEL__SMCLK; //Choses SMCLK as clock source for UART
UCA0BR0 = 52; // 8000000/16/9600 CORRECT 9600 BAUD RATE
//UCA0BR1 = 0x00;
UCA0MCTLW = 0x4900 | UCOS16 | UCBRF_1;
//STEP 3 Configure Ports
P1SEL0 |= BIT0 + BIT1; // set 2-UART pin as Primary non I/O function
//STEP 4 SEt UCSWRST Bit
UCA0CTLW0 &= ~UCSWRST; // Initialize eUSCI
//STEP 5 ENABLE INTERUPTS
__enable_interrupt( );
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt

_delay_cycles(4000000);
writeUART("\n\rstart");
}

int writeUART(char* sentence)
{
int i;
for (i = 0; i < strlen(sentence); i++) {
while(!(UCA0IFG&UCTXIFG));
UCA0TXBUF = sentence[i];
}
return i;
}

Thank you in advance for your help.

AJ

  • Hello Austin,
    thank you for your interest in the MSP430.
    In general we recommend to use our code examples as a starting point. The other point is, when debugging a problem, to reduce the code to the absolute minimum.
    Our code examples are tested, and there should be a pretty similar code example available in the Resource Explorer of CCS, or you could look directly at the home page of the FR4133 for code examples. These code examples are tested, so you can start with a functional base and then step by step modify the code towards your needs.
    Please try the msp430fr413x_ta0_01.c and let us know, whether this is functional with your setup. Many thanks in advance.

    Best regards
    Peter
  • Hello Austin,
    I tried to modify the msp413x_ta_01.c with portion of your settings for the clock system. Please find here the code, which works perfectly. Maybe you can use it as a base for your tests.

    Best regards
    Peter
    #include <msp430.h>

    int main(void)
    {
    WDTCTL = WDTPW | WDTHOLD; // Stop WDT

    // Configure GPIO
    P1DIR |= BIT0; // P1.0 output
    P1OUT |= BIT0; // P1.0 high

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;

    CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source // 07/09/2018
    CSCTL0 = 0; // clear DCO and MOD registers // 07/09/2018
    CSCTL1 &= ~(DCORSEL_7); // Clear DCO frequency select bits // 07/09/2018
    // first
    CSCTL1 |= DCORSEL_3; // Set DCO = 8MHz // 07/09/2018
    CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz // 07/09/2018
    // 243d = 1111 0011b
    CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;
    // set default REFO(~32kHz) as ACLK // 07/09/2018
    // source, ACLK = 32768Hz
    // // default DCODIV as MCLK and SMCLK source

    TA0CCTL0 |= CCIE; // TACCR0 interrupt enabled
    //TA0CCR0 = 50000; // 07/09/2018
    TA0CCR0 = 0x1F40; // 0x1F40 = 8000 which at 8 MHz is // 07/09/2018
    // 1 ms
    TA0CTL |= TASSEL__SMCLK | MC__CONTINOUS; // SMCLK, continuous mode

    __bis_SR_register(LPM0_bits | GIE); // Enter LPM3 w/ interrupts
    __no_operation(); // For debugger
    }

    // Timer A0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A (void)
    #else
    #error Compiler not supported!
    #endif
    {
    P1OUT ^= BIT0; // 07/09/2018
    //TA0CCR0 += 50000; // Add Offset to TACCR0 // 07/09/2018
    }
  • Peter,

    When I copied your code and attempted to run it on my MSP430FR4133, it didn't work.

    1) Initially, I wasn't sure if I was unable to tell if the LED was toggling since it would happen once every milisecond, so I changed the line TA0CRR0 = 0xFFFF, which should should give a new rate of filling every .75 seconds give or take. Still no luck. CCS gives no error. The LED lights up initially when the code runs proven by it turning off briefly when the power reset button is hit.

    2)I tried adding a infinite loop at the end of main where it would toggle 1.0 every 8E6 clock sycles (aka 1 sec), however, that also didn't work. After commenting out one line at a time, I found out that the LPM0 | GIE line was to blame. Once I removed it, I could use the loop in main to toggle the LED. LPM3 as suggested by the comment similarly didn't work.

    3) Having removed the low power mode and global enable interrupts, I added _enable_interrupt(); in their stead. The interrupt still didn't trigger.

    As for your advice in the first comment, I have been unable to find the code you referred to, however, I did base my code off the following blog post. www.embeddedrelated.com/.../182.php It is for a separate device, but I thought I had done a decent job properly converting the code.

    I assume you tested your code on a device and saw the LED toggle yourself. I'm not sure what could cause the issue on my end. I created a new project for the FR4133. The device itself still functions properly with previous code.

    Best,
    Austin
  • It worked fine on my Launchpad, but the LED blink was indeed too fast to see by eye -- about 64K/8*2us -> ~60Hz. Changing CCR0 won't help. Instead, add something like:
    > TA0CTL |= ID_3; // SMCLK/8 gives 1MHz tick -> 8Hz blink
    in some appropriate spot.
    -----------------------
    The given program is designed to never come out of LPM, and so won't execute anything that follows -- good thing, since there isn't anything there. If you want to add code there you can either remove the LPM statement (as you did) or arrange for a wakeup of some sort.
  • Oh I forgot -- if you remove the LPM line you won't get the interrupt. Instead, edit it to say:
    > __bis_SR_register(GIE); // Enable interrupts
  • Hello Austin,

    which CCS version are you using? Is there already a Resource Explorer integrated?

    Finding the mentioned code example in the Resource Explorer works as follows:

    1. Launch the Resource Explorer in CCS, either by clicking the "Resource Explorer" tab, or by opening the pull-down menu View >> Resource Explorer.

    2. In the left window of the Resource Explorer you'll see 3 folders Device Documentation / Software / Development Tools, click on the Software Folder.

    3. This lists all the SW packages. Select MSP430Ware - v3.80.04.05 (latest version).

    4. In MSP430Ware you'll see again 3 sub-directories, Development Tools / Devices / Libraries. Click on the "Devices " folder.

    5. In the opened list select MSP430FR2XX_4XX. and select MSP430FR4133.

    6. There you have the possibility to open Peripheral Examples and Middleware, please select first one.

    7. Now you can select Register Level, and in this list you can find the mentioned msp430fr413x_ta0_01.c

    8. When you click on it, in the right upper corner of that window, the middle of the three icons allows you to import the code example. The nice thing about this is, it set's up everything in the correct way for the device and the respective project.

    I would recommend to try this, to ensure you're HW is ok, as this definitely should work. Once you have reached this point, we can take it from there.

    Best regards

    Peter

  • Austin,
    to address your point about not reaching the main:
    The philosophy of the given code example is, to remain in LPM, and just wake up for servicing the Timer interrupt, and go back to LPM0 again.
    In general, if you want to terminate the active LPMx by an interrupt, you need to terminate it at the end of the Interrupt Service Routine, by e.g. inserting this instruction

    __bic_SR_register_on_exit(LPM4_bits);// Exit LPM4 on reti

    There are instructions for all LPMs of this kind, but this one works for all LPMs, as it clears all the SR bits of all LPMs. What these instructions do, is to manipulate the stored SR status on the Stack, which will be used to restore the SR status after return from interrupt. That's why if not executing this instruction, the MSP430 device goes back to the LPMx, active at the time of the interrupt occurrence. With this instruction, the device remains active, and starts executing the code after the instruction, which activated the LPMx.

    Best regards
    Peter
  • Peter, 

    Thank you for the screenshots detailing how to find the code. It helped greatly. I tried loading the code directly from the resource explorer and it worked without an issue. I'm not sure what the issue was previously. As I said in the very first post, I wanted to drop the frequency of the timer down to less than 4 ms. I still don't understand why, but I accomplished this by changing the TA0CRR0 register, both in the interrupt and initialization. Overall, everything is working as desired now. Thank you so much.

    Best,

    Austin

    Bruce, 

    Thank you for letting me know it worked on your device and the input on enabling interrupts. 

    Thank you,

    Austin

**Attention** This is a public forum