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/TMS470MF03107: TMS430F249

Part Number: TMS470MF03107
Other Parts Discussed in Thread: MSP430F249

Tool/software: Code Composer Studio

Gentlemen,

TMS430F249 was not accepted in the Part Number field above???

I am attempting to set up Timer A0 as an up counter to 480 but the CPU never gets to the ISR. It traps to:

;******************************************************************************

;* ISR_TRAP.ASM -                                                             *

;*                                                                            *

;* Copyright (c) 2003 Texas Instruments Incorporated                          *

;* http://www.ti.com/                                                         *

;*                                                                            *

;*  Redistribution and  use in source  and binary forms, with  or without     *

;*  modification,  are permitted provided  that the  following conditions     *

;*  are met:                                                                  *

;*                                                                            *

;*     Redistributions  of source  code must  retain the  above copyright     *

;*     notice, this list of conditions and the following disclaimer.          *

;*                                                                            *

;*     Redistributions in binary form  must reproduce the above copyright     *

;*     notice, this  list of conditions  and the following  disclaimer in     *

;*     the  documentation  and/or   other  materials  provided  with  the     *

;*     distribution.                                                          *

;*                                                                            *

;*     Neither the  name of Texas Instruments Incorporated  nor the names     *

;*     of its  contributors may  be used to  endorse or  promote products     *

;*     derived  from   this  software  without   specific  prior  written     *

;*     permission.                                                            *

;*                                                                            *

;*  THIS SOFTWARE  IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS     *

;*  "AS IS"  AND ANY  EXPRESS OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT     *

;*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR     *

;*  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT     *

;*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,     *

;*  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL  DAMAGES  (INCLUDING, BUT  NOT     *

;*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     *

;*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY     *

;*  THEORY OF  LIABILITY, WHETHER IN CONTRACT, STRICT  LIABILITY, OR TORT     *

;*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE     *

;*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.      *

;*                                                                            *

;******************************************************************************

;-----------------------------------------------------------------------------

;-- default ISR handler if user does not supply

;-- simply puts device into lpm0

;-----------------------------------------------------------------------------

   .sect ".text:_isr:__TI_ISR_TRAP"

.align 2

.global __TI_ISR_TRAP

__TI_ISR_TRAP:

        BIS.W     #(0x0010),SR

        JMP __TI_ISR_TRAP

        NOP                     ; CPU40 Compatibility NOP

My setup:

  // Timer A0 Initialization.

  TACTL  = MC_0;         // Shut down Timer A0.

  TACTL  = TASSEL_1;     // Select ACLK as clock source and divide by 1.

  TACCR0 = 480;          // Set compare register for ~ 30 usec.

  TACTL |= TAIE;         // Timer A interrupt enable.

  TACTL |= MC_1;          // Set timer A to up counting mode.

My ISR:

/*********************************************************************************************

*  NAME: evTMR_A0_isr

*

*  DESCRIPTION: Timer A0 interrupt processor.

*    Read the next byte from the C3_PM.

*    SMBus_Buffer - each byte from the C3 is built bit by bit in this memory location.

*    The timer A0 interrupt flag is also cleared just prior to exit.

*

*********************************************************************************************/

#pragma vector = TIMERA0_VECTOR

__interrupt void evTMR_A0_isr(void)

{

  // Scope trigger

  P1OUT &= ~M_LED4;  // Turn  on M_LED4.

  if( C3_BYTE_READ == ( C3_BYTE_READ & SMBus_Flags ) ) {

    Port_Five_Snapshot = P5IN;  // Snapshot of SMBus comm port with the C3_PM Card.

    switch(C3_Byte_Rd_State) // *****  Beginning of C3 Byte Read State Machine  *****

    {

    case C3_Byte_Init:

      if( nM_SCL & ~Port_Five_Snapshot )  {  // If the clock line has gone low then...

        bit_position = 8;  // Initialze the bit counter.

        C3_Byte_Rd_State = C3_Byte_Wait1;

      }

      break;

    case C3_Byte_Wait1:

      if( nM_SCL & Port_Five_Snapshot )  {  // If valid data bit has been sent...

        if(nM_SDA & Port_Five_Snapshot)  { SMBus_Buffer |= 0x01; } // If SMBdata is a 1, OR a 1 into data byte LSB...

        else                             { SMBus_Buffer &= 0xFE; } // otherwise clear the LSB.

        bit_position--; // Decrement the bit count.

        C3_Byte_Rd_State = C3_Byte_Wait2;

      }

      break;

    case C3_Byte_Wait2:  // Wait here for the clock line to go low.

      if( nM_SCL & ~Port_Five_Snapshot )  {  

        if(bit_position > 0 ) {  // If there are more bits in the byte to collect then...

          SMBus_Buffer <<= 1;  // Shift the bit just received toward the MSbit.

          C3_Byte_Rd_State = C3_Byte_Wait1;  // Go read the next bit.

        }

        // Acknowledge receipt of the last data bit. Pull data line low.

        else{

      SMBdata_Clr_C3;

      C3_Byte_Rd_State = C3_Byte_Ack1; }

      }

      break;

    case C3_Byte_Ack1: // Wait for the SMBus clock to go high.

      if( nM_SCL & Port_Five_Snapshot )  {

        C3_Byte_Rd_State = C3_Byte_Ack2;

      }

      break;

    case C3_Byte_Ack2: // Wait for the SMBus clock to go low to complete the acknowledge.

      if( nM_SCL & ~Port_Five_Snapshot )  { // If clock has gone low, terminate acknowledge.

        SMBdata_Set_C3;                     // Release the SMBus data line to be pulled high.

        SMBus_Flags      &= ~C3_BYTE_READ;  // Shut down the C3 Card byte read state machine.

        C3_Byte_Rd_State = C3_Byte_Init;  // Rearm state machine.

      }

      break;

    } // Endcase C3 Card byte read.

  } // Endif C3_BYTE_READ

// ?????  TAIFG &= ~BIT0;       // Clear the interrupt flag.

  TA0R   =  0;          // Restart counter.

  // Scope trigger

  P1OUT |=  M_LED4;  // Turn off M_LED4.

}

Please advise.

Regards, Harvey Novak

  • The Timer A0 Initialization sets the Timer A interrupt enable bit TAIE:

      TACTL |= TAIE;         // Timer A interrupt enable.

    Which from the description of the TACTL, Timer_A Control Register in the MSP430x2xx Family User's Guide  enables the TAIFG interrupt request:

    The MSP430F23x, MSP430F24x(1), MSP430F2410 Mixed Signal Microcontroller datasheet shows that the TAIFG generates the interrupt vector address of 0xFFF0:

    The ISR handler is placed at the TIMERA0_VECTOR which from the msp430f249.h include file is address 0xFFF2:

    #define TIMERA0_VECTOR          (25 * 1u)                    /* 0xFFF2 Timer A CC0 */

    Since the code doesn't have an interrupt vector for address 0xFFF2 this explains why the ISR trap is entered.

    Suggest change the code to place the ISR handler as the TIMERA1_VECTOR which from msp430f249.h is address 0xFFF0:

    #define TIMERA1_VECTOR          (24 * 1u)                    /* 0xFFF0 Timer A CC1-2, TA */

    I.e.suggest change your code to:

    #pragma vector = TIMERA1_VECTOR
    
    __interrupt void evTMR_A0_isr(void)

  • Thanks Chester!

    However, the CPU now traps in the routine listed below.

    All I am trying to do is generate an interrupt every 30 microseconds that executes a few lines of code listed in the last submission. 

    Do I need to zero the counter in the interrupt routine?

    Do I need to reset the Interrupt flag?

    Is my initialization complete and correct?

    Would it be better to use Timer B?

    Thanks, Harvey

    /*****************************************************************************/

    /* copy_zero_init.c                                                          */

    /*                                                                           */

    /* Copyright (c) 2006 Texas Instruments Incorporated                         */

    /* http://www.ti.com/                                                        */

    /*                                                                           */

    /*  Redistribution and  use in source  and binary forms, with  or without    */

    /*  modification,  are permitted provided  that the  following conditions    */

    /*  are met:                                                                 */

    /*                                                                           */

    /*     Redistributions  of source  code must  retain the  above copyright    */

    /*     notice, this list of conditions and the following disclaimer.         */

    /*                                                                           */

    /*     Redistributions in binary form  must reproduce the above copyright    */

    /*     notice, this  list of conditions  and the following  disclaimer in    */

    /*     the  documentation  and/or   other  materials  provided  with  the    */

    /*     distribution.                                                         */

    /*                                                                           */

    /*     Neither the  name of Texas Instruments Incorporated  nor the names    */

    /*     of its  contributors may  be used to  endorse or  promote products    */

    /*     derived  from   this  software  without   specific  prior  written    */

    /*     permission.                                                           */

    /*                                                                           */

    /*  THIS SOFTWARE  IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS    */

    /*  "AS IS"  AND ANY  EXPRESS OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT    */

    /*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR    */

    /*  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT    */

    /*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,    */

    /*  SPECIAL,  EXEMPLARY,  OR CONSEQUENTIAL  DAMAGES  (INCLUDING, BUT  NOT    */

    /*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,    */

    /*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY    */

    /*  THEORY OF  LIABILITY, WHETHER IN CONTRACT, STRICT  LIABILITY, OR TORT    */

    /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE    */

    /*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     */

    /*                                                                           */

    /*                                                                           */

    /* Routine to initialize the output buffer with a zero. The input buffer has */

    /* the number of bytes to zero initialize.                                   */

    /*                                                                           */

    /* NOTE:                                                                     */

    /* 1. This routine could be used to copy uninitialized or initialized global */

    /*    data space of a program. Hence this routine cannot define any global   */

    /*    variable.                                                              */

    /* 2. This routine will never be used to initialize stack space and hence    */

    /*    all the variables are allocated to stack.                              */

    /* 3. The calling application should ensure the output buffer is big         */

    /*    enough to hold the uncompressed data.                                  */

    /*                                                                           */

    /*****************************************************************************/

    #include <string.h>

    #include <stddef.h>

    /*****************************************************************************/

    /*                                                                           */

    /* __TI_ZERO_INIT() - Zero initialize the output buffer. The number of bytes */

    /*                    to initialize is given in the input buffer.            */

    /*                                                                           */

    /*****************************************************************************/

    /*****************************************************************************/

    /* MSP copy tables can handle moving functions even in small data model +    */

    /* large code model, where data pointers are not big enough to represent     */

    /* function pointers.  This requires the EABI decompression functions        */

    /* (SHARED/copy_*.c) to be changed to accept "far" pointers.  For this       */

    /* memory model combination, the decompression functions are changed to use  */

    /* "unsigned long" to represent function pointers, so function pointers      */

    /* through which we call these functions also needs to have a prototype      */

    /* accepting "unsigned long" instead of pointer types.  All other memory     */

    /* model combinations use the same prototype that all the other targets use: */

    /* two data pointer arguments.  Ultimately we use MSP peek/poke intrinsics   */

    /* to read/write the "far" memory.                                           */

    /*****************************************************************************/

    #if defined(__MSP430__) && defined(__LARGE_CODE_MODEL__) && !defined(__LARGE_DATA_MODEL__)

    typedef unsigned long recordsize_t;

    typedef unsigned long pointer_t;

    typedef unsigned long pointer_to_const_t;

    #define READSZ(x) __data20_read_long(x)

    #define WRITE8_ADV(x, c) __data20_write_char(x++, c)

    #else

    #if defined(__MSP430__) && defined(__LARGE_CODE_MODEL__)

    typedef       unsigned long  recordsize_t;

    #else

    typedef              size_t  recordsize_t;

    #endif

    typedef       unsigned char *pointer_t;

    typedef const unsigned char *pointer_to_const_t;

    #define READSZ(x) (*(recordsize_t *)x)

    #define WRITE8_ADV(x, c) (*x++ = (c))

    #endif

    static __inline __attribute__((always_inline))

    void __TI_zero_init_template(pointer_to_const_t inbuf, pointer_t outbuf,

                                 int USE_MEMSET)

    {

       /*------------------------------------------------------------------------*/

       /* inbuf will always be pointing one byte into the compressed data (the   */

       /* first byte was read by autoinit to figure out which decompression      */

       /* routine to use).  Align inbuf to a size_t boundary and read the number */

       /* of bytes to be set to zero.                                            */

       /*------------------------------------------------------------------------*/

       pointer_t count_p = (pointer_t)inbuf + (__alignof__(recordsize_t) - 1);

       recordsize_t count = READSZ(count_p);

       /*------------------------------------------------------------------------*/

       /* Zero initialize the output buffer.                                     */

       /*------------------------------------------------------------------------*/

       #if __MSP430__

          while(count--) WRITE8_ADV(outbuf, 0);

       #else

          if (USE_MEMSET)

             memset((void*)outbuf, 0, count);

          else

             while(count--) WRITE8_ADV(outbuf, 0);

       #endif

    }

    /******************************************************************************/

    /* We cannot include specializations when virtual encoding is enabled.        */

    /* Vritual encodings from all sections are stored in a single .encode section */

    /* which may reference the .text sections. This means that if one .text       */

    /* section in a file is referenced, all .text sections will be included in    */

    /* the link. This breaks the specialization model which requires all          */

    /* specializatinos to be in their own subsections and removeable by the       */

    /* linker.                                                                    */

    /******************************************************************************/

    #if !defined(__VIRTUAL_ENCODING__)

    __attribute__((section(".text:decompress:ZI:__TI_zero_init_nomemset"), used))

    void __TI_zero_init_nomemset(pointer_to_const_t inbuf, pointer_t outbuf)

    {

       __TI_zero_init_template(inbuf, outbuf, 0);

    }

    #endif

    __attribute__((section(".text:decompress:ZI")))

    void __TI_zero_init(pointer_to_const_t inbuf, pointer_t outbuf)

    {

       __TI_zero_init_template(inbuf, outbuf, 1);

    }

  • Harvey Novak said:
    However, the CPU now traps in the routine listed below.

    All I am trying to do is generate an interrupt every 30 microseconds that executes a few lines of code listed in the last submission.

    There are some timer examples under http://dev.ti.com/tirex/explore/node?node=APbNbwzUDwYij82MW9a0-g__IOGqZri__LATEST

    Harvey Novak said:
    Do I need to reset the Interrupt flag?

    Given that the initial code enabled TAIE my initial suggestion was to change to use the TIMERA1_VECTOR. When using the TIMERA1_VECTOR, the TAIV Interrupt Vector Generator is read in the interrupt handler to obtain and then automatically reset the interrupt source.

    For what you are are trying to do, instead enable CCIE for the CCR0 interrupt and then in TIMERA0_VECTOR ; since the TACCR0 CCIFG flag is automatically reset when the TACCR0 interrupt request is serviced. See http://dev.ti.com/tirex/explore/node?node=AE7d65o1rSsbd3neDW0vpg__IOGqZri__LATEST for an example.

**Attention** This is a public forum