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.

TimerB0 msp430f5438a problem

Other Parts Discussed in Thread: MSP430F5438A, MSP430F5529, MSP430FR5739, MSP430WARE

Hello,

I am working in a code where I want to use a timeout to send the packet again after this time. I attach my code without timer and I explain what I am trying to do. I want to send the packet again if after one second after sending it the first time I haven't received a response. I try to configure the timer like that:

-----------------------------------------------------------------------------------------------------------------------------------------------------


  TB0CCR0 = 255;                        // Period = 1Mhz/256 = ~4.1Khz (8-bit DAC)
  TB0CCTL1 = CLLD_1 + OUTMOD_7;         // Use TB0.1 to output Sine Wave
  TB0CCTL0 = CCIE;                      // Enable Interrupt on Period
  TB0CCR1 =32768;             // Load first sample value
  TB0CTL = TBSSEL__SMCLK + MC_1;        // Timer uses SMCLK in up mode


--------------------------------------------------------------------------------------------------------------------------------------------------------

and this is the ISR I am using:

---------------------------------------------------------------------------------------------------------------------------------------------------------

// Timer B0 interrupt service routine
#pragma vector=TIMER0_B0_VECTOR
__interrupt void TIMER0_B0_ISR(void)
{
  TB0CCR1 = 32768;
   timeout=1;
  }

---------------------------------------------------------------------------------------------------------------------------------------------------------

It is not working, it's not going into the interrupt. I don't know what I am doing wrong. I don't know in which position of my code I should allocate the configuration of the timer. It shouldn't be difficult but I can't get it working...

Can any of you please suggest me what I should do, or if I should use another timer and where to allocate it? I would like an example or a modification of my code if it's possible.

Thank you in advance

** I am using the TrxEB, MSP430F5438A, CC1120 and the IAR workbench. And I posted this post in the Proprietary Sub 1 GHz & SimpliciTI Forum as well, I hope there's no problem.

  • Moving this to the MSP430 forum.

  • Did you set the GIE bit?

    Post the complete code from what you are asking here. Use the    button to insert the code.

  • Yes it is set

    //******************************************************************************
    //! @file       cc112x_easy_link_tx.c
    //! @brief      This program sets up an easy link between two trxEB's with
    //!             CC112x EM's connected.
    //!             The program can take any recomended register settings exported
    //!             from SmartRF Studio 7 without any modification with exeption
    //!             from the assumtions decribed below.
    //
    //              Notes: The following asumptions must be fulfilled for
    //              the program to work:
    //
    //                  1.  GPIO2 has to be set up with GPIO2_CFG = 0x06
    //                      PKT_SYNC_RXTX for correct interupt
    //                  2.  Packet engine has to be set up with status bytes enabled
    //                      PKT_CFG1.APPEND_STATUS = 1
    //
    //  Copyright (C) 2013 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.
    //*****************************************************************************/
    
    
    /*******************************************************************************
    * INCLUDES
    */
    #include "msp430.h"
    #include "lcd_dogm128_6.h"
    #include "hal_spi_rf_trxeb.h"
    #include "cc112x_spi.h"
    #include "stdlib.h"
    #include "bsp.h"
    #include "bsp_key.h"
    #include "io_pin_int.h"
    #include "bsp_led.h"
    #include "cc112x_easy_link_reg_config.h"
    #include "MSP430F5xx_6xx/driverlib.h"
    //*****************************************************************************
    //
    // Macros for hardware access
    //
    //*****************************************************************************
    #define HWREG16(x)                                                             \
            (*((volatile uint16_t*)((uint16_t)x)))
    /*******************************************************************************
    * DEFINES
    */
    #define ISR_ACTION_REQUIRED     1
    #define ISR_IDLE                0
    
    #define PKTLEN                  30  // 1 < PKTLEN < 126
    
    #define GPIO3                   0x04
    #define GPIO2                   0x08
    #define GPIO0                   0x80
    
    #define ADDRESS                 0xEF
    #define SENDER                  0xAB
    //Node 1 0xAB
    //Node 2 0xCD
    
    
    /*******************************************************************************
    * LOCAL VARIABLES
    */
    static uint8_t  packetSemaphore;
    static uint8_t  timeout=0;
    uint16_t packetCounter = 0;
    static uint32 delay;
    
    /*******************************************************************************
    * STATIC FUNCTIONS
    */
    static void initMCU(void);
    static void registerConfig(void);
    static void manualCalibration(void);
    static void runTX(void);
    static void createPacket(uint8_t randBuffer[]);
    static void radioTxRxISR(void);
    static void updateLcd(void);
    static void waitMs(uint16 mSec);
    static void waitUs(uint16 uSec);
    static void TimerConfig(void);
    
    /*******************************************************************************
    *   @fn         main
    *
    *   @brief      Runs the main routine
    *
    *   @param      none
    *
    *   @return     none
    */
    void main(void) {
      
        uint8 writeByte;
    
        // Initialize MCU and peripherals
        initMCU();
    
        // Write radio registers
        registerConfig();
        
        // TXOFF_MODE = RX
        writeByte = 0x30; cc112xSpiWriteReg(CC112X_RFEND_CFG0, &writeByte, 1); 
        
        // RXOFF_MODE = RX
        writeByte = 0x3F; cc112xSpiWriteReg(CC112X_RFEND_CFG1, &writeByte, 1); 
        
        // Max packet length = 2
        writeByte = 0x02; cc112xSpiWriteReg(CC112X_PKT_LEN, &writeByte, 1);
        
        writeByte = 0x25; cc112xSpiWriteReg(CC112X_PKT_CFG1, &writeByte, 1);
        writeByte = ADDRESS; cc112xSpiWriteReg(CC112X_DEV_ADDR, &writeByte, 1);
        
        TimerConfig();
        
        // Enter runTX, never coming back
        runTX();
    }
    
    
    /*******************************************************************************
    *   @fn         runTX
    *
    *   @brief      Continuously sends packets on button push until button is pushed
    *               again. After the radio has gone into TX the function waits for
    *               interrupt that packet has been sent. Updates packet counter and
    *               display for each packet sent.
    *
    *   @param      none
    *
    *   @return    none
    */
    static void runTX(void) {
    
        // Initialize packet buffer of size PKTLEN + 1
        uint8 txBuffer[PKTLEN+1] = {0};
        uint8 rxBuffer[4];
        uint8 marcState;
        uint8 rssi1;
        // Connect ISR function to GPIO2
        ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &radioTxRxISR);
    
        // Interrupt on falling edge
        ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_FALLING_EDGE);
    
        // Clear ISR flag
        ioPinIntClear(IO_PIN_PORT_1, GPIO2);
    
        // Enable interrupt
        ioPinIntEnable(IO_PIN_PORT_1, GPIO2);
       
        // Update LCD
        updateLcd();
    
        // Calibrate radio according to errata
        manualCalibration();
        
        // Infinite loop
        while(1) {
    
            // Wait for button push
            if(bspKeyPushed(BSP_KEY_ALL)) {
    
                // Continiously sent packets until button is pressed
                do {
    
                    // Update packet counter
                    
    
                    // Create a random packet with PKTLEN + 2 byte packet
                    // counter + n x random bytes
                    createPacket(txBuffer);
    
                    // Write packet to TX FIFO
                    cc112xSpiWriteTxFifo(txBuffer, sizeof(txBuffer));
                    /********************LBT**************************/
                    //trxSpiCmdStrobe(CC112X_SRX);
                
                    //Wait for radio to enter RX
                    do {
                        trxSpiCmdStrobe(CC112X_SRX);
                        cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    } while (marcState != 0x6D);
                
                    // Wait for RSSI_VALID
                    do {
                        cc112xSpiReadReg(CC112X_RSSI0, &rssi1, 1);
                    } while (!(rssi1 & 0x01));
                
                    waitMs(5);
                    delay=rand()%10+5;
                    //if(delay<5)delay=5;
                    waitMs(delay);//random delay before sending
                    /*******************************************************/
                    // Strobe TX to send packet
                    trxSpiCmdStrobe(CC112X_STX);
                    cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    // Wait for interrupt that packet has been sent.
                    // (Assumes the GPIO connected to the radioRxTxISR function is
                    // set to GPIOx_CFG = 0x06)
                    while(packetSemaphore != ISR_ACTION_REQUIRED);
    
                    // Clear semaphore flag
                    packetSemaphore = ISR_IDLE;
                    
                    //--------------------------------------------------------------
                    // Packet sent. Radio enters RX automatically to wait for ack. (2)
                    
                    // Wait for interrupt that packet has been received.
                    while((packetSemaphore != ISR_ACTION_REQUIRED)||(timeout==1));
    
                    // Clear semaphore flag
                    packetSemaphore = ISR_IDLE;
                    TBCCTL0 &= ~CCIE; 
                    // Wait for interrupt that packet has been received.
                    //while(packetSemaphore != ISR_ACTION_REQUIRED);
    
                    // Clear semaphore flag
                    //packetSemaphore = ISR_IDLE;
                    
                    // Strobe TX to send packet
                    trxSpiCmdStrobe(CC112X_SIDLE);
                    //cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    // Read 8 bytes from RX FIFO
                    cc112xSpiReadRxFifo(rxBuffer, 4);
                    
                    //if (((rxBuffer[2] == 0xAB) & (rxBuffer[7] == 0xCD)) | 
                      //  ((rxBuffer[2] == 0xCD) & (rxBuffer[7] == 0xAB))) {
                    if ((rxBuffer[1]==0xEF) && (rxBuffer[2]==SENDER)){//Checking the BS and the correct ACK
                      packetCounter++;  
                      // Update LCD
                        updateLcd();
                        
                    }
                    //trxSpiCmdStrobe(CC112X_SRX);
                    // Wait for a random amount of time between each packet
                    waitMs(3*(rand()%10+3));
                    
                } while (!bspKeyPushed(BSP_KEY_ALL));
            }
        }
    }
    
    
    /*******************************************************************************
    *   @fn         radioTxRXISR
    *
    *   @brief      ISR for packet handling in TX and RX. Sets packet semaphore
    *               and clears ISR flag
    *
    *   @param      none
    *
    *   @return     none
    */
    static void radioTxRxISR(void) {
    
        // Set packet semaphore
        packetSemaphore = ISR_ACTION_REQUIRED;
    //TA0CCTL0 = CCIE;
          TBCCTL0 = CCIE;                           // TRCCR0 interrupt enabled
        // Clear ISR flag
        ioPinIntClear(IO_PIN_PORT_1, GPIO2);
    }
    /******************************************************************************
    *     @fn TimerConfig
    *
    *     @brief Configurates the timer A3
    *
    *     @param none
    *   
    *     @return none
    */
    static void TimerConfig(void){
      
      TBCCR0 = 16384-1;
      TBCTL = TBSSEL_1 + MC_1 + TBCLR;          // ACLK, upmode, clear TBR
    }
    /*******************************************************************************
    *   @fn         initMCU
    *
    *   @brief      Initialize MCU and board peripherals
    *
    *   @param      none
    *
    *   @return     none
    */
    static void initMCU(void) {
    
        // Init clocks and I/O
        bspInit(BSP_SYS_CLK_8MHZ);
        
       
     
        // Init LEDs
        bspLedInit();
    
        // Init buttons
        bspKeyInit(BSP_KEY_MODE_POLL);
    
        // Initialize SPI interface to LCD (shared with SPI flash)
        bspIoSpiInit(BSP_FLASH_LCD_SPI, BSP_FLASH_LCD_SPI_SPD);
    
        // Init LCD
        lcdInit();
    
        // Instantiate transceiver RF SPI interface to SCLK ~ 4 MHz
        // Input parameter is clockDivider
        // SCLK frequency = SMCLK/clockDivider
        trxRfSpiInterfaceInit(2);
        
        // Enable global interrupt
        _BIS_SR(GIE);
    }
    
    
    /*******************************************************************************
    *   @fn         registerConfig
    *
    *   @brief      Write register settings as given by SmartRF Studio found in
    *               cc112x_easy_link_reg_config.h
    *
    *   @param      none
    *
    *   @return     none
    */
    static void registerConfig(void) {
    
        uint8 writeByte;
    
        // Reset radio
        trxSpiCmdStrobe(CC112X_SRES);
    
        // Write registers to radio
        for(uint16 i = 0;
            i < (sizeof(preferredSettings)/sizeof(registerSetting_t)); i++) {
            writeByte = preferredSettings[i].data;
            cc112xSpiWriteReg(preferredSettings[i].addr, &writeByte, 1);
        }
    }
    
    
    /*******************************************************************************
    *   @fn         createPacket
    *
    *   @brief      The packet format is as follows:
    *               |--------------------------------------------------------------|
    *               |           |           |           |         |       |        |
    *               | pktLength | Address   | rndData   |.........|.......| rndData|
    *               |           |           |           |         |       |        |
    *               |--------------------------------------------------------------|
    *                txBuffer[0] txBuffer[1] txBuffer[2]            txBuffer[PKTLEN]
    *
    *   @param       Pointer to start of txBuffer
    *
    *   @return      none
    */
    static void createPacket(uint8 txBuffer[]) {
    
        txBuffer[0] = PKTLEN;               // Length byte
        txBuffer[1] = 0x00;                 // Broadcast address                
        txBuffer[2] = SENDER;
        // Fill rest of buffer with random bytes
        for(uint8 i = 3; i < (PKTLEN + 1); i++) {
            txBuffer[i] = (uint8)rand();
        }
    }
    
    
    /*******************************************************************************
    *   @fn         updateLcd
    *
    *   @brief      Updates LCD buffer and sends buffer to LCD module
    *
    *   @param      none
    *
    *   @return     none
    */
    static void updateLcd(void) {
    
        // Update LDC buffer and send to screen.
        lcdBufferClear(0);
        lcdBufferPrintString(0, "EasyLink Test", 0, eLcdPage0);
        lcdBufferSetHLine(0, 0, LCD_COLS-1, 7);
        lcdBufferPrintString(0, "Node 1. Sent packets:", 0, eLcdPage3);
        lcdBufferPrintInt(0, packetCounter, 70, eLcdPage4);
        lcdBufferPrintString(0, "Packet TX" , 0, eLcdPage7);
        lcdBufferSetHLine(0, 0, LCD_COLS-1, 55);
        lcdBufferInvertPage(0, 0, LCD_COLS, eLcdPage7);
        lcdSendBuffer(0);
    }
    
    /*******************************************************************************
    *   @fn         waitMs
    *
    *   @brief      Busy wait function. Waits the specified number of milliseconds.
    *               Use assumptions about number of clock cycles needed for the
    *               various instructions.
    *
    *               NB! This function is highly dependent on architecture and
    *               compiler!
    *
    *   @param      uint16 mSec - number of milliseconds delay
    *
    *   @return     none
    */
    #pragma optimize=none
    static void waitMs(uint16 mSec) {
        while(mSec-- > 0) {
            waitUs(1000);
        }
    }
    
    /*******************************************************************************
    *   @fn         waitUs
    *
    *   @brief      Busy wait function. Waits the specified number of microseconds.
    *               Use assumptions about number of clock cycles needed for the
    *               various instructions. The duration of one cycle depends on MCLK.
    *               In this HAL it is set to 8 MHz, thus 8 cycles per us.
    *
    *               NB! This function is highly dependent on architecture
    *               and compiler!
    *
    *   @param      uint16 uSec - number of microseconds delay
    *
    *   @return     none
    */
    #pragma optimize=none
    static void waitUs(uint16 uSec) { // 5 cycles for calling
    
        // The least we can wait is 3 usec:
        // ~1 usec for call, 1 for first compare and 1 for return
        while(uSec > 3) {  // 2 cycles for compare
                           // 2 cycles for jump
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            uSec -= 2;     // 1 cycle for optimized decrement
        }
    }                      // 4 cycles for returning
    
    /*******************************************************************************
    *   @fn         manualCalibration
    *
    *   @brief      Calibrates radio according to CC112x errata
    *
    *   @param      none
    *
    *   @return     none
    */
    #define VCDAC_START_OFFSET 2
    #define FS_VCO2_INDEX 0
    #define FS_VCO4_INDEX 1
    #define FS_CHP_INDEX 2
    static void manualCalibration(void) {
    
        uint8 original_fs_cal2;
        uint8 calResults_for_vcdac_start_high[3];
        uint8 calResults_for_vcdac_start_mid[3];
        uint8 marcstate;
        uint8 writeByte;
    
        // 1) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
        writeByte = 0x00;
        cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
    
        // 2) Start with high VCDAC (original VCDAC_START + 2):
        cc112xSpiReadReg(CC112X_FS_CAL2, &original_fs_cal2, 1);
        writeByte = original_fs_cal2 + VCDAC_START_OFFSET;
        cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1);
    
        // 3) Calibrate and wait for calibration to be done
        //   (radio back in IDLE state)
        trxSpiCmdStrobe(CC112X_SCAL);
    
        do {
            cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1);
        } while (marcstate != 0x41);
    
        // 4) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained with 
        //    high VCDAC_START value
        cc112xSpiReadReg(CC112X_FS_VCO2,
                         &calResults_for_vcdac_start_high[FS_VCO2_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_VCO4,
                         &calResults_for_vcdac_start_high[FS_VCO4_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_CHP,
                         &calResults_for_vcdac_start_high[FS_CHP_INDEX], 1);
    
        // 5) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
        writeByte = 0x00;
        cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
    
        // 6) Continue with mid VCDAC (original VCDAC_START):
        writeByte = original_fs_cal2;
        cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1);
    
        // 7) Calibrate and wait for calibration to be done
        //   (radio back in IDLE state)
        trxSpiCmdStrobe(CC112X_SCAL);
    
        do {
            cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1);
        } while (marcstate != 0x41);
    
        // 8) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained 
        //    with mid VCDAC_START value
        cc112xSpiReadReg(CC112X_FS_VCO2, 
                         &calResults_for_vcdac_start_mid[FS_VCO2_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_VCO4,
                         &calResults_for_vcdac_start_mid[FS_VCO4_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_CHP,
                         &calResults_for_vcdac_start_mid[FS_CHP_INDEX], 1);
    
        // 9) Write back highest FS_VCO2 and corresponding FS_VCO
        //    and FS_CHP result
        if (calResults_for_vcdac_start_high[FS_VCO2_INDEX] >
            calResults_for_vcdac_start_mid[FS_VCO2_INDEX]) {
            writeByte = calResults_for_vcdac_start_high[FS_VCO2_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_high[FS_VCO4_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_high[FS_CHP_INDEX];
            cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1);
        } else {
            writeByte = calResults_for_vcdac_start_mid[FS_VCO2_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_mid[FS_VCO4_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_mid[FS_CHP_INDEX];
            cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1);
        }
    }
    
    
    
    // Timer B0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMERB0_VECTOR
    __interrupt void TIMERB1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMERB0_VECTOR))) TIMERB1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        timeout= 1;                          // Toggle P1.0 using exclusive-OR
    }
    
    
    

  • Hello I had to change my account, I am cprcpr.

    Can someone help me to solve the problem? Every time the timer expires the Flag goes on but the program resets instead of going into the interrupt. I think it is going into a bad memory position, but i don't know how to fix it.

    Thanks in advance

  • any help?
    I've checked that when the program goes first time into the Tx interrupt radioTxRxISR() the GIE goes to 0. And it stays in there without put it in 1, even when I include the line:  _BIS_SR(GIE); as you can see in the code:

    //******************************************************************************
    //! @file       cc112x_easy_link_tx.c
    //! @brief      This program sets up an easy link between two trxEB's with
    //!             CC112x EM's connected.
    //!             The program can take any recomended register settings exported
    //!             from SmartRF Studio 7 without any modification with exeption
    //!             from the assumtions decribed below.
    //
    //              Notes: The following asumptions must be fulfilled for
    //              the program to work:
    //
    //                  1.  GPIO2 has to be set up with GPIO2_CFG = 0x06
    //                      PKT_SYNC_RXTX for correct interupt
    //                  2.  Packet engine has to be set up with status bytes enabled
    //                      PKT_CFG1.APPEND_STATUS = 1
    //
    //  Copyright (C) 2013 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.
    //*****************************************************************************/
    
    
    /*******************************************************************************
    * INCLUDES
    */
    #include "msp430.h"
    #include "lcd_dogm128_6.h"
    #include "hal_spi_rf_trxeb.h"
    #include "cc112x_spi.h"
    #include "stdlib.h"
    #include "bsp.h"
    #include "bsp_key.h"
    #include "io_pin_int.h"
    #include "bsp_led.h"
    #include "cc112x_easy_link_reg_config.h"
    #include "MSP430F5xx_6xx/driverlib.h"
    //*****************************************************************************
    //
    // Macros for hardware access
    //
    //*****************************************************************************
    #define HWREG16(x)                                                             \
            (*((volatile uint16_t*)((uint16_t)x)))
    /*******************************************************************************
    * DEFINES
    */
    #define ISR_ACTION_REQUIRED     1
    #define ISR_IDLE                0
    
    #define PKTLEN                  30  // 1 < PKTLEN < 126
    
    #define GPIO3                   0x04
    #define GPIO2                   0x08
    #define GPIO0                   0x80
    
    #define ADDRESS                 0xEF
    #define SENDER                  0xAB
              
    //Node 1 0xAB
    //Node 2 0xCD
    
    #define COMPARE_VALUE           32768
    
    /*******************************************************************************
    * LOCAL VARIABLES
    */
    static uint8_t  packetSemaphore;
    static uint8_t  timeout=0;
    uint16_t packetCounter = 0;
    static uint32 delay;
    
    /*******************************************************************************
    * STATIC FUNCTIONS
    */
    static void initMCU(void);
    static void registerConfig(void);
    static void manualCalibration(void);
    static void runTX(void);
    static void createPacket(uint8_t randBuffer[]);
    static void radioTxRxISR(void);
    static void updateLcd(void);
    static void waitMs(uint16 mSec);
    static void waitUs(uint16 uSec);
    static void TimerConfig(void);
    
    /*******************************************************************************
    *   @fn         main
    *
    *   @brief      Runs the main routine
    *
    *   @param      none
    *
    *   @return     none
    */
    void main(void) {
      
        uint8 writeByte;
    
        // Initialize MCU and peripherals
        initMCU();
    
        // Write radio registers
        registerConfig();
        
        // TXOFF_MODE = RX
        writeByte = 0x30; cc112xSpiWriteReg(CC112X_RFEND_CFG0, &writeByte, 1); 
        
        // RXOFF_MODE = RX
        writeByte = 0x3F; cc112xSpiWriteReg(CC112X_RFEND_CFG1, &writeByte, 1); 
        
        // Max packet length = 2
        writeByte = 0x02; cc112xSpiWriteReg(CC112X_PKT_LEN, &writeByte, 1);
        
        writeByte = 0x25; cc112xSpiWriteReg(CC112X_PKT_CFG1, &writeByte, 1);
        writeByte = ADDRESS; cc112xSpiWriteReg(CC112X_DEV_ADDR, &writeByte, 1);
        
              
             //Start timer in continuous mode sourced by ACLK
            TIMER_A_clearTimerInterruptFlag(TIMER_A1_BASE);
            TIMER_A_configureContinuousMode(TIMER_A1_BASE,
                                            TIMER_A_CLOCKSOURCE_ACLK,
                                            TIMER_A_CLOCKSOURCE_DIVIDER_1,
                                            TIMER_A_TAIE_INTERRUPT_ENABLE,
                                            TIMER_A_DO_CLEAR
                                            );
    
       
        // Enter runTX, never coming back
        runTX();
    }
    
    
    /*******************************************************************************
    *   @fn         runTX
    *
    *   @brief      Continuously sends packets on button push until button is pushed
    *               again. After the radio has gone into TX the function waits for
    *               interrupt that packet has been sent. Updates packet counter and
    *               display for each packet sent.
    *
    *   @param      none
    *
    *   @return    none
    */
    static void runTX(void) {
    
        // Initialize packet buffer of size PKTLEN + 1
        uint8 txBuffer[PKTLEN+1] = {0};
        uint8 rxBuffer[4];
        uint8 marcState;
        uint8 rssi1;
        // Connect ISR function to GPIO2
        ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &radioTxRxISR);
    
        // Interrupt on falling edge
        ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_FALLING_EDGE);
    
        // Clear ISR flag
        ioPinIntClear(IO_PIN_PORT_1, GPIO2);
    
        // Enable interrupt
        ioPinIntEnable(IO_PIN_PORT_1, GPIO2);
       
        // Update LCD
        updateLcd();
    
        // Calibrate radio according to errata
        manualCalibration();
        
        // Infinite loop
        while(1) {
    
            // Wait for button push
            if(bspKeyPushed(BSP_KEY_ALL)) {
    
                // Continiously sent packets until button is pressed
                do {
    
                    // Update packet counter
                    
    
                    // Create a random packet with PKTLEN + 2 byte packet
                    // counter + n x random bytes
                    createPacket(txBuffer);
    
                    // Write packet to TX FIFO
                    cc112xSpiWriteTxFifo(txBuffer, sizeof(txBuffer));
                    /********************LBT**************************/
                    //trxSpiCmdStrobe(CC112X_SRX);
                
                    //Wait for radio to enter RX
                    do {
                        trxSpiCmdStrobe(CC112X_SRX);
                        cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    } while (marcState != 0x6D);
                
                    // Wait for RSSI_VALID
                    do {
                        cc112xSpiReadReg(CC112X_RSSI0, &rssi1, 1);
                    } while (!(rssi1 & 0x01));
                
                    waitMs(5);
                    delay=rand()%10+5;
                    //if(delay<5)delay=5;
                    waitMs(delay);//random delay before sending
                    /*******************************************************/
                    // Strobe TX to send packet
                    trxSpiCmdStrobe(CC112X_STX);
                    cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    // Wait for interrupt that packet has been sent.
                    // (Assumes the GPIO connected to the radioRxTxISR function is
                    // set to GPIOx_CFG = 0x06)
                    while(packetSemaphore != ISR_ACTION_REQUIRED);
                    
                    // Clear semaphore flag
                    packetSemaphore = ISR_IDLE;
                    
                    //--------------------------------------------------------------
                    // Packet sent. Radio enters RX automatically to wait for ack. (2)
                    
                    // Wait for interrupt that packet has been received.
                    while((packetSemaphore != ISR_ACTION_REQUIRED)||(timeout==1));
                    
                    // Clear semaphore flag
                    packetSemaphore = ISR_IDLE;
                    TA1CCTL0 &= ~CCIE; 
                    // Wait for interrupt that packet has been received.
                    //while(packetSemaphore != ISR_ACTION_REQUIRED);
    
                    // Clear semaphore flag
                    //packetSemaphore = ISR_IDLE;
                    
                    // Strobe TX to send packet
                    trxSpiCmdStrobe(CC112X_SIDLE);
                    //cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    // Read 8 bytes from RX FIFO
                    cc112xSpiReadRxFifo(rxBuffer, 4);
                    
                    //if (((rxBuffer[2] == 0xAB) & (rxBuffer[7] == 0xCD)) | 
                      //  ((rxBuffer[2] == 0xCD) & (rxBuffer[7] == 0xAB))) {
                    if ((rxBuffer[1]==0xEF) && (rxBuffer[2]==SENDER)){//Checking the BS and the correct ACK
                      packetCounter++;  
                      // Update LCD
                        updateLcd();
                        
                    }
                    //trxSpiCmdStrobe(CC112X_SRX);
                    // Wait for a random amount of time between each packet
                    waitMs(3*(rand()%10+3));
                    
                } while (!bspKeyPushed(BSP_KEY_ALL));
            }
        }
    }
    
    
    /*******************************************************************************
    *   @fn         radioTxRXISR
    *
    *   @brief      ISR for packet handling in TX and RX. Sets packet semaphore
    *               and clears ISR flag
    *
    *   @param      none
    *
    *   @return     none
    */
    static void radioTxRxISR(void) {
    
        // Set packet semaphore
        packetSemaphore = ISR_ACTION_REQUIRED;
        //TA0CCTL0 = CCIE;
        // TBCCTL0 = CCIE;                           // TRCCR0 interrupt enabled
        
        TIMER_A_startCounter(TIMER_A1_BASE,
                             TIMER_A_CONTINUOUS_MODE
                             );
        // Enable global interrupt
        _BIS_SR(GIE);
        // Clear ISR flag
        ioPinIntClear(IO_PIN_PORT_1, GPIO2);
    }
    /******************************************************************************
    *     @fn TimerConfig
    *
    *     @brief Configurates the timer A3
    *
    *     @param none
    *   
    *     @return none
    */
    static void TimerConfig(void){
      
      TBCCR0 = 16384-1;
      TBCTL = TBSSEL_1 + MC_1 + TBCLR;          // ACLK, upmode, clear TBR
    }
    /*******************************************************************************
    *   @fn         initMCU
    *
    *   @brief      Initialize MCU and board peripherals
    *
    *   @param      none
    *
    *   @return     none
    */
    static void initMCU(void) {
    
        // Init clocks and I/O
        bspInit(BSP_SYS_CLK_8MHZ);
          
        // Init LEDs
        bspLedInit();
    
        // Init buttons
        bspKeyInit(BSP_KEY_MODE_POLL);
    
        // Initialize SPI interface to LCD (shared with SPI flash)
        bspIoSpiInit(BSP_FLASH_LCD_SPI, BSP_FLASH_LCD_SPI_SPD);
    
        // Init LCD
        lcdInit();
    
        // Instantiate transceiver RF SPI interface to SCLK ~ 4 MHz
        // Input parameter is clockDivider
        // SCLK frequency = SMCLK/clockDivider
        trxRfSpiInterfaceInit(2);
        
        // Enable global interrupt
        _BIS_SR(GIE);
    }
    
    
    /*******************************************************************************
    *   @fn         registerConfig
    *
    *   @brief      Write register settings as given by SmartRF Studio found in
    *               cc112x_easy_link_reg_config.h
    *
    *   @param      none
    *
    *   @return     none
    */
    static void registerConfig(void) {
    
        uint8 writeByte;
    
        // Reset radio
        trxSpiCmdStrobe(CC112X_SRES);
    
        // Write registers to radio
        for(uint16 i = 0;
            i < (sizeof(preferredSettings)/sizeof(registerSetting_t)); i++) {
            writeByte = preferredSettings[i].data;
            cc112xSpiWriteReg(preferredSettings[i].addr, &writeByte, 1);
        }
    }
    
    
    /*******************************************************************************
    *   @fn         createPacket
    *
    *   @brief      The packet format is as follows:
    *               |--------------------------------------------------------------|
    *               |           |           |           |         |       |        |
    *               | pktLength | Address   | rndData   |.........|.......| rndData|
    *               |           |           |           |         |       |        |
    *               |--------------------------------------------------------------|
    *                txBuffer[0] txBuffer[1] txBuffer[2]            txBuffer[PKTLEN]
    *
    *   @param       Pointer to start of txBuffer
    *
    *   @return      none
    */
    static void createPacket(uint8 txBuffer[]) {
    
        txBuffer[0] = PKTLEN;               // Length byte
        txBuffer[1] = 0x00;                 // Broadcast address                
        txBuffer[2] = SENDER;
        // Fill rest of buffer with random bytes
        for(uint8 i = 3; i < (PKTLEN + 1); i++) {
            txBuffer[i] = (uint8)rand();
        }
    }
    
    
    /*******************************************************************************
    *   @fn         updateLcd
    *
    *   @brief      Updates LCD buffer and sends buffer to LCD module
    *
    *   @param      none
    *
    *   @return     none
    */
    static void updateLcd(void) {
    
        // Update LDC buffer and send to screen.
        lcdBufferClear(0);
        lcdBufferPrintString(0, "EasyLink Test", 0, eLcdPage0);
        lcdBufferSetHLine(0, 0, LCD_COLS-1, 7);
        lcdBufferPrintString(0, "Node 1. Sent packets:", 0, eLcdPage3);
        lcdBufferPrintInt(0, packetCounter, 70, eLcdPage4);
        lcdBufferPrintString(0, "Packet TX" , 0, eLcdPage7);
        lcdBufferSetHLine(0, 0, LCD_COLS-1, 55);
        lcdBufferInvertPage(0, 0, LCD_COLS, eLcdPage7);
        lcdSendBuffer(0);
    }
    
    /*******************************************************************************
    *   @fn         waitMs
    *
    *   @brief      Busy wait function. Waits the specified number of milliseconds.
    *               Use assumptions about number of clock cycles needed for the
    *               various instructions.
    *
    *               NB! This function is highly dependent on architecture and
    *               compiler!
    *
    *   @param      uint16 mSec - number of milliseconds delay
    *
    *   @return     none
    */
    #pragma optimize=none
    static void waitMs(uint16 mSec) {
        while(mSec-- > 0) {
            waitUs(1000);
        }
    }
    
    /*******************************************************************************
    *   @fn         waitUs
    *
    *   @brief      Busy wait function. Waits the specified number of microseconds.
    *               Use assumptions about number of clock cycles needed for the
    *               various instructions. The duration of one cycle depends on MCLK.
    *               In this HAL it is set to 8 MHz, thus 8 cycles per us.
    *
    *               NB! This function is highly dependent on architecture
    *               and compiler!
    *
    *   @param      uint16 uSec - number of microseconds delay
    *
    *   @return     none
    */
    #pragma optimize=none
    static void waitUs(uint16 uSec) { // 5 cycles for calling
    
        // The least we can wait is 3 usec:
        // ~1 usec for call, 1 for first compare and 1 for return
        while(uSec > 3) {  // 2 cycles for compare
                           // 2 cycles for jump
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            uSec -= 2;     // 1 cycle for optimized decrement
        }
    }                      // 4 cycles for returning
    
    /*******************************************************************************
    *   @fn         manualCalibration
    *
    *   @brief      Calibrates radio according to CC112x errata
    *
    *   @param      none
    *
    *   @return     none
    */
    #define VCDAC_START_OFFSET 2
    #define FS_VCO2_INDEX 0
    #define FS_VCO4_INDEX 1
    #define FS_CHP_INDEX 2
    static void manualCalibration(void) {
    
        uint8 original_fs_cal2;
        uint8 calResults_for_vcdac_start_high[3];
        uint8 calResults_for_vcdac_start_mid[3];
        uint8 marcstate;
        uint8 writeByte;
    
        // 1) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
        writeByte = 0x00;
        cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
    
        // 2) Start with high VCDAC (original VCDAC_START + 2):
        cc112xSpiReadReg(CC112X_FS_CAL2, &original_fs_cal2, 1);
        writeByte = original_fs_cal2 + VCDAC_START_OFFSET;
        cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1);
    
        // 3) Calibrate and wait for calibration to be done
        //   (radio back in IDLE state)
        trxSpiCmdStrobe(CC112X_SCAL);
    
        do {
            cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1);
        } while (marcstate != 0x41);
    
        // 4) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained with 
        //    high VCDAC_START value
        cc112xSpiReadReg(CC112X_FS_VCO2,
                         &calResults_for_vcdac_start_high[FS_VCO2_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_VCO4,
                         &calResults_for_vcdac_start_high[FS_VCO4_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_CHP,
                         &calResults_for_vcdac_start_high[FS_CHP_INDEX], 1);
    
        // 5) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
        writeByte = 0x00;
        cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
    
        // 6) Continue with mid VCDAC (original VCDAC_START):
        writeByte = original_fs_cal2;
        cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1);
    
        // 7) Calibrate and wait for calibration to be done
        //   (radio back in IDLE state)
        trxSpiCmdStrobe(CC112X_SCAL);
    
        do {
            cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1);
        } while (marcstate != 0x41);
    
        // 8) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained 
        //    with mid VCDAC_START value
        cc112xSpiReadReg(CC112X_FS_VCO2, 
                         &calResults_for_vcdac_start_mid[FS_VCO2_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_VCO4,
                         &calResults_for_vcdac_start_mid[FS_VCO4_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_CHP,
                         &calResults_for_vcdac_start_mid[FS_CHP_INDEX], 1);
    
        // 9) Write back highest FS_VCO2 and corresponding FS_VCO
        //    and FS_CHP result
        if (calResults_for_vcdac_start_high[FS_VCO2_INDEX] >
            calResults_for_vcdac_start_mid[FS_VCO2_INDEX]) {
            writeByte = calResults_for_vcdac_start_high[FS_VCO2_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_high[FS_VCO4_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_high[FS_CHP_INDEX];
            cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1);
        } else {
            writeByte = calResults_for_vcdac_start_mid[FS_VCO2_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_mid[FS_VCO4_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_mid[FS_CHP_INDEX];
            cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1);
        }
    }
    
    
    //******************************************************************************
    //
    //This is the TIMER1_A3 interrupt vector service routine.
    //
    //******************************************************************************
    #pragma vector=TIMER1_A1_VECTOR
    __interrupt void TIMER1_A1_ISR(void)
    {
            //Any access, read or write, of the TAIV register automatically resets the
            //highest "pending" interrupt flag
            switch ( __even_in_range(TA1IV, 14) ) {
            case  0: break;                                 //No interrupt
            case  2: break;                                 //CCR1 not used
            case  4: break;                                 //CCR2 not used
            case  6: break;                                 //CCR3 not used
            case  8: break;                                 //CCR4 not used
            case 10: break;                                 //CCR5 not used
            case 12: break;                                 //CCR6 not used
            case 14:
                    timeout=1;
                    break;
            default: break;
            }
    }
    
    
    
    

    I think maybe there's something missed. Can someone tell me which libraries I need or if I am not including any library that I should include?

    Thanks in advance

  • Does anyone know what I am doing wrong? or does anyone any suggestion how should I do it?
    I remind that the aim is to get a timeout to send the packet again when the timer expires.

    Thanks

    now I am trying this:

    //******************************************************************************
    //! @file       cc112x_easy_link_tx.c
    //! @brief      This program sets up an easy link between two trxEB's with
    //!             CC112x EM's connected.
    //!             The program can take any recomended register settings exported
    //!             from SmartRF Studio 7 without any modification with exeption
    //!             from the assumtions decribed below.
    //
    //              Notes: The following asumptions must be fulfilled for
    //              the program to work:
    //
    //                  1.  GPIO2 has to be set up with GPIO2_CFG = 0x06
    //                      PKT_SYNC_RXTX for correct interupt
    //                  2.  Packet engine has to be set up with status bytes enabled
    //                      PKT_CFG1.APPEND_STATUS = 1
    //
    //  Copyright (C) 2013 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.
    //*****************************************************************************/
    
    
    /*******************************************************************************
    * INCLUDES
    */
    #include "msp430.h"
    #include "lcd_dogm128_6.h"
    #include "hal_spi_rf_trxeb.h"
    #include "cc112x_spi.h"
    #include "stdlib.h"
    #include "bsp.h"
    #include "bsp_key.h"
    #include "io_pin_int.h"
    #include "bsp_led.h"
    #include "cc112x_easy_link_reg_config.h"
    #include "MSP430F5xx_6xx/driverlib.h"
    /*******************************************************************************
    * DEFINES
    */
    #define ISR_ACTION_REQUIRED     1
    #define ISR_IDLE                0
    
    #define PKTLEN                  30  // 1 < PKTLEN < 126
    
    #define GPIO3                   0x04
    #define GPIO2                   0x08
    #define GPIO0                   0x80
    
    #define ADDRESS                 0xEF
    
    
    /*******************************************************************************
    * LOCAL VARIABLES
    */
    static uint8_t  packetSemaphore;
    uint16_t packetCounter = 0;
    //uint8 rxBuffer[10];
    static uint32 delay;
    static uint32 timeout=0;
    /*******************************************************************************
    * STATIC FUNCTIONS
    */
    static void initMCU(void);
    static void registerConfig(void);
    static void manualCalibration(void);
    static void runTX(void);
    static void createPacket(uint8_t randBuffer[]);
    static void radioTxRxISR(void);
    static void updateLcd(void);
    static void waitMs(uint16 mSec);
    static void waitUs(uint16 uSec);
    
    
    /*******************************************************************************
    *   @fn         main
    *
    *   @brief      Runs the main routine
    *
    *   @param      none
    *
    *   @return     none
    */
    void main(void) {
      
        uint8 writeByte;
    
        // Initialize MCU and peripherals
        initMCU();
    
        // Write radio registers
        registerConfig();
        
        // TXOFF_MODE = RX
        writeByte = 0x30; cc112xSpiWriteReg(CC112X_RFEND_CFG0, &writeByte, 1); 
        
        // RXOFF_MODE = RX
        writeByte = 0x3F; cc112xSpiWriteReg(CC112X_RFEND_CFG1, &writeByte, 1); 
        
        // Max packet length = 2
        writeByte = 0x02; cc112xSpiWriteReg(CC112X_PKT_LEN, &writeByte, 1);
        
        writeByte = 0x25; cc112xSpiWriteReg(CC112X_PKT_CFG1, &writeByte, 1);
        writeByte = ADDRESS; cc112xSpiWriteReg(CC112X_DEV_ADDR, &writeByte, 1);
        
        /*TIMER_A_clearTimerInterruptFlag(TIMER_A1_BASE);
        TIMER_A_configureContinuousMode(TIMER_A1_BASE,
                                        TIMER_A_CLOCKSOURCE_ACLK,
                                        TIMER_A_CLOCKSOURCE_DIVIDER_1,
                                        TIMER_A_TAIE_INTERRUPT_ENABLE,
                                        TIMER_A_DO_CLEAR
                                        );
        */
        
       TBCCR0 = 32768-1;                           //1sec
       TBCTL = TBSSEL_1 + MC_1 + TBCLR;          // ACLK, upmode, clear TBR
       
        // Enter runTX, never coming back
        runTX();
    }
    
    
    /*******************************************************************************
    *   @fn         runTX
    *
    *   @brief      Continuously sends packets on button push until button is pushed
    *               again. After the radio has gone into TX the function waits for
    *               interrupt that packet has been sent. Updates packet counter and
    *               display for each packet sent.
    *
    *   @param      none
    *
    *   @return    none
    */
    static void runTX(void) {
    
        // Initialize packet buffer of size PKTLEN + 1
        uint8 txBuffer[PKTLEN+1] = {0};
        uint8 rxBuffer[4];
        uint8 marcState;
        uint8 rssi1;
        // Connect ISR function to GPIO2
        ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &radioTxRxISR);
    
        // Interrupt on falling edge
        ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_FALLING_EDGE);
    
        // Clear ISR flag
        ioPinIntClear(IO_PIN_PORT_1, GPIO2);
    
        // Enable interrupt
        ioPinIntEnable(IO_PIN_PORT_1, GPIO2);
    
        // Update LCD
        updateLcd();
    
        // Calibrate radio according to errata
        manualCalibration();
    
        // Infinite loop
        while(1) {
    
            // Wait for button push
            if(bspKeyPushed(BSP_KEY_ALL)) {
    
                // Continiously sent packets until button is pressed
                do {
    
                    // Update packet counter
                    
    
                    // Create a random packet with PKTLEN + 2 byte packet
                    // counter + n x random bytes
                    createPacket(txBuffer);
    
                    // Write packet to TX FIFO
                    cc112xSpiWriteTxFifo(txBuffer, sizeof(txBuffer));
                    /********************LBT**************************/
                    trxSpiCmdStrobe(CC112X_SRX);
                
                    //Wait for radio to enter RX
                    do {
                        trxSpiCmdStrobe(CC112X_SRX);
                        cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    } while (marcState != 0x6D);
                
                    // Wait for RSSI_VALID
                    do {
                        cc112xSpiReadReg(CC112X_RSSI0, &rssi1, 1);
                    } while (!(rssi1 & 0x01));
                
                    waitMs(5);
                    delay=rand()%10+5;
                    //if(delay<5)delay=5;
                    waitMs(delay);//random delay before sending
                    /*******************************************************/
                    // Strobe TX to send packet
                    trxSpiCmdStrobe(CC112X_STX);
                    cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    // Wait for interrupt that packet has been sent.
                    // (Assumes the GPIO connected to the radioRxTxISR function is
                    // set to GPIOx_CFG = 0x06)
                    while(packetSemaphore != ISR_ACTION_REQUIRED);
    
                    // Clear semaphore flag
                    packetSemaphore = ISR_IDLE;
                     //TBCCTL0 &= ~CCIE;                           // TRCCR0 interrupt enabled
                    //--------------------------------------------------------------
                    // Packet sent. Radio enters RX automatically to wait for ack. (2)
                    
                    // Wait for interrupt that packet has been received.
                    while(packetSemaphore != ISR_ACTION_REQUIRED);
                   
                    // Clear semaphore flag
                    packetSemaphore = ISR_IDLE;
                                            
                    // Strobe TX to send packet
                    trxSpiCmdStrobe(CC112X_SIDLE);
                    //cc112xSpiReadReg(CC112X_MARCSTATE, &marcState, 1);
                    // Read 8 bytes from RX FIFO
                    cc112xSpiReadRxFifo(rxBuffer, 4);
                    
                    //if (((rxBuffer[2] == 0xAB) & (rxBuffer[7] == 0xCD)) | 
                      //  ((rxBuffer[2] == 0xCD) & (rxBuffer[7] == 0xAB))) {
                    if ((rxBuffer[1]==0xEF) && (rxBuffer[2]==0xAB)){//Checking the BS and the correct ACK
                        // Update LCD
                        updateLcd();
                        packetCounter++;
                    }
                    //trxSpiCmdStrobe(CC112X_SRX);
                    // Wait for a random amount of time between each packet
                    waitMs(3*(rand()%10+3));
                    
                } while (!bspKeyPushed(BSP_KEY_ALL));
            }
        }
    }
    
    
    /*******************************************************************************
    *   @fn         radioTxRXISR
    *
    *   @brief      ISR for packet handling in TX and RX. Sets packet semaphore
    *               and clears ISR flag
    *
    *   @param      none
    *
    *   @return     none
    */
    static void radioTxRxISR(void) {
    
        // Set packet semaphore
        packetSemaphore = ISR_ACTION_REQUIRED;
    /*TIMER_A_startCounter(TIMER_A1_BASE,
                                 TIMER_A_CONTINUOUS_MODE
                                 );*/
        TBCCTL0 = CCIE;                           // TRCCR0 interrupt enabled
        // Clear ISR flag
        ioPinIntClear(IO_PIN_PORT_1, GPIO2);
    }
    
    
    /*******************************************************************************
    *   @fn         initMCU
    *
    *   @brief      Initialize MCU and board peripherals
    *
    *   @param      none
    *
    *   @return     none
    */
    static void initMCU(void) {
    
        // Init clocks and I/O
        bspInit(BSP_SYS_CLK_8MHZ);
    
        // Init LEDs
        bspLedInit();
    
        // Init buttons
        bspKeyInit(BSP_KEY_MODE_POLL);
    
        // Initialize SPI interface to LCD (shared with SPI flash)
        bspIoSpiInit(BSP_FLASH_LCD_SPI, BSP_FLASH_LCD_SPI_SPD);
    
        // Init LCD
        lcdInit();
    
        // Instantiate transceiver RF SPI interface to SCLK ~ 4 MHz
        // Input parameter is clockDivider
        // SCLK frequency = SMCLK/clockDivider
        trxRfSpiInterfaceInit(2);
    
        // Enable global interrupt
        _BIS_SR(GIE);
    }
    
    
    /*******************************************************************************
    *   @fn         registerConfig
    *
    *   @brief      Write register settings as given by SmartRF Studio found in
    *               cc112x_easy_link_reg_config.h
    *
    *   @param      none
    *
    *   @return     none
    */
    static void registerConfig(void) {
    
        uint8 writeByte;
    
        // Reset radio
        trxSpiCmdStrobe(CC112X_SRES);
    
        // Write registers to radio
        for(uint16 i = 0;
            i < (sizeof(preferredSettings)/sizeof(registerSetting_t)); i++) {
            writeByte = preferredSettings[i].data;
            cc112xSpiWriteReg(preferredSettings[i].addr, &writeByte, 1);
        }
    }
    
    
    /*******************************************************************************
    *   @fn         createPacket
    *
    *   @brief      The packet format is as follows:
    *               |--------------------------------------------------------------|
    *               |           |           |           |         |       |        |
    *               | pktLength | Address   | rndData   |.........|.......| rndData|
    *               |           |           |           |         |       |        |
    *               |--------------------------------------------------------------|
    *                txBuffer[0] txBuffer[1] txBuffer[2]            txBuffer[PKTLEN]
    *
    *   @param       Pointer to start of txBuffer
    *
    *   @return      none
    */
    static void createPacket(uint8 txBuffer[]) {
    
        txBuffer[0] = PKTLEN;               // Length byte
        txBuffer[1] = 0x00;                 // Broadcast address                
    
        // Fill rest of buffer with random bytes
        for(uint8 i = 2; i < (PKTLEN + 1); i++) {
            txBuffer[i] = (uint8)rand();
        }
    }
    
    
    /*******************************************************************************
    *   @fn         updateLcd
    *
    *   @brief      Updates LCD buffer and sends buffer to LCD module
    *
    *   @param      none
    *
    *   @return     none
    */
    static void updateLcd(void) {
    
        // Update LDC buffer and send to screen.
        lcdBufferClear(0);
        lcdBufferPrintString(0, "EasyLink Test", 0, eLcdPage0);
        lcdBufferSetHLine(0, 0, LCD_COLS-1, 7);
        lcdBufferPrintString(0, "Node 2. Sent packets:", 0, eLcdPage3);
        lcdBufferPrintInt(0, packetCounter, 70, eLcdPage4);
        lcdBufferPrintString(0, "Packet TX" , 0, eLcdPage7);
        lcdBufferSetHLine(0, 0, LCD_COLS-1, 55);
        lcdBufferInvertPage(0, 0, LCD_COLS, eLcdPage7);
        lcdSendBuffer(0);
    }
    
    /*******************************************************************************
    *   @fn         waitMs
    *
    *   @brief      Busy wait function. Waits the specified number of milliseconds.
    *               Use assumptions about number of clock cycles needed for the
    *               various instructions.
    *
    *               NB! This function is highly dependent on architecture and
    *               compiler!
    *
    *   @param      uint16 mSec - number of milliseconds delay
    *
    *   @return     none
    */
    #pragma optimize=none
    static void waitMs(uint16 mSec) {
        while(mSec-- > 0) {
            waitUs(1000);
        }
    }
    
    /*******************************************************************************
    *   @fn         waitUs
    *
    *   @brief      Busy wait function. Waits the specified number of microseconds.
    *               Use assumptions about number of clock cycles needed for the
    *               various instructions. The duration of one cycle depends on MCLK.
    *               In this HAL it is set to 8 MHz, thus 8 cycles per us.
    *
    *               NB! This function is highly dependent on architecture
    *               and compiler!
    *
    *   @param      uint16 uSec - number of microseconds delay
    *
    *   @return     none
    */
    #pragma optimize=none
    static void waitUs(uint16 uSec) { // 5 cycles for calling
    
        // The least we can wait is 3 usec:
        // ~1 usec for call, 1 for first compare and 1 for return
        while(uSec > 3) {  // 2 cycles for compare
                           // 2 cycles for jump
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            NOP();         // 1 cycle for nop
            uSec -= 2;     // 1 cycle for optimized decrement
        }
    }                      // 4 cycles for returning
    
    /*******************************************************************************
    *   @fn         manualCalibration
    *
    *   @brief      Calibrates radio according to CC112x errata
    *
    *   @param      none
    *
    *   @return     none
    */
    #define VCDAC_START_OFFSET 2
    #define FS_VCO2_INDEX 0
    #define FS_VCO4_INDEX 1
    #define FS_CHP_INDEX 2
    static void manualCalibration(void) {
    
        uint8 original_fs_cal2;
        uint8 calResults_for_vcdac_start_high[3];
        uint8 calResults_for_vcdac_start_mid[3];
        uint8 marcstate;
        uint8 writeByte;
    
        // 1) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
        writeByte = 0x00;
        cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
    
        // 2) Start with high VCDAC (original VCDAC_START + 2):
        cc112xSpiReadReg(CC112X_FS_CAL2, &original_fs_cal2, 1);
        writeByte = original_fs_cal2 + VCDAC_START_OFFSET;
        cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1);
    
        // 3) Calibrate and wait for calibration to be done
        //   (radio back in IDLE state)
        trxSpiCmdStrobe(CC112X_SCAL);
    
        do {
            cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1);
        } while (marcstate != 0x41);
    
        // 4) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained with 
        //    high VCDAC_START value
        cc112xSpiReadReg(CC112X_FS_VCO2,
                         &calResults_for_vcdac_start_high[FS_VCO2_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_VCO4,
                         &calResults_for_vcdac_start_high[FS_VCO4_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_CHP,
                         &calResults_for_vcdac_start_high[FS_CHP_INDEX], 1);
    
        // 5) Set VCO cap-array to 0 (FS_VCO2 = 0x00)
        writeByte = 0x00;
        cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
    
        // 6) Continue with mid VCDAC (original VCDAC_START):
        writeByte = original_fs_cal2;
        cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1);
    
        // 7) Calibrate and wait for calibration to be done
        //   (radio back in IDLE state)
        trxSpiCmdStrobe(CC112X_SCAL);
    
        do {
            cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1);
        } while (marcstate != 0x41);
    
        // 8) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained 
        //    with mid VCDAC_START value
        cc112xSpiReadReg(CC112X_FS_VCO2, 
                         &calResults_for_vcdac_start_mid[FS_VCO2_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_VCO4,
                         &calResults_for_vcdac_start_mid[FS_VCO4_INDEX], 1);
        cc112xSpiReadReg(CC112X_FS_CHP,
                         &calResults_for_vcdac_start_mid[FS_CHP_INDEX], 1);
    
        // 9) Write back highest FS_VCO2 and corresponding FS_VCO
        //    and FS_CHP result
        if (calResults_for_vcdac_start_high[FS_VCO2_INDEX] >
            calResults_for_vcdac_start_mid[FS_VCO2_INDEX]) {
            writeByte = calResults_for_vcdac_start_high[FS_VCO2_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_high[FS_VCO4_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_high[FS_CHP_INDEX];
            cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1);
        } else {
            writeByte = calResults_for_vcdac_start_mid[FS_VCO2_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_mid[FS_VCO4_INDEX];
            cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1);
            writeByte = calResults_for_vcdac_start_mid[FS_CHP_INDEX];
            cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1);
        }
    }
    //******************************************************************************
    //
    //This is the TIMER1_A3 interrupt vector service routine.
    //
    //******************************************************************************
    /*#pragma vector=TIMER1_A1_VECTOR
    __interrupt void TIMER1_A1_ISR(void)
    {
            //Any access, read or write, of the TAIV register automatically resets the
            //highest "pending" interrupt flag
            switch ( __even_in_range(TA1IV, 14) ) {
            case  0: break;                                 //No interrupt
            case  2: break;                                 //CCR1 not used
            case  4: break;                                 //CCR2 not used
            case  6: break;                                 //CCR3 not used
            case  8: break;                                 //CCR4 not used
            case 10: break;                                 //CCR5 not used
            case 12: break;                                 //CCR6 not used
            case 14:
                    //Toggle P1.0					 // overflow
                    GPIO_toggleOutputOnPin(
                            GPIO_PORT_P4,
                            GPIO_PIN0
                            );
                    break;
            default: break;
            }
    }*/
    // Timer B0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMERB0_VECTOR
    __interrupt void TIMERB1_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMERB0_VECTOR))) TIMERB1_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
        timeout = 1;                          // Toggle P1.0 using exclusive-OR
    }

  • Crawl, Walk, Run.

    Create a small sample program to configure TB0 how you want and get the ISR firing with that program. Once you understand that, you can integrate it back into your other program.

    No one here wants to wade through hundreds of lines of non-relevant code trying to figure out where you are/aren't setting bits properly. That's why you haven't received any replies.

    If you still can't get your small test program to work, come back here with that and your questions.

  • Thanks for the reply and advices.

    I was trying simple examples and they don't work for the msp430f5438a. I include the code I am using(from: C:\Program Files\IAR Systems\Embedded Workbench 7.0\430\examples\examples\MSP430F5xx_6xx\timer_a) It's an example from the IAR, it says it's tested on MSP430F5529, MSP430FR5739. If I load the program it shows a warning saying that it's configured for the MSP430F5529 and mine is MSP430F5438A but if I accept the warning it loads the program and works properly but when I modify the configuration of the project changing the target to MSP430F5438A in general options of the project it doesn't work. I've tried to find a timer example for the MSP430F5438A but I couldn't find it.

    Can any of you tell me what I should do to get it working in my MSP430?

    Thanks in advance.

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2013, Texas Instruments Incorporated
     * All rights reserved.
     *
     * 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.
     * --/COPYRIGHT--*/
    //******************************************************************************
    //! TIMER_A, Toggle P1.0, Overflow ISR, 32kHz ACLK
    //!
    //! Description: Toggle P1.0 using software and the TIMER_A overflow ISR.
    //! In this example an ISR triggers when TB overflows. Inside the ISR P1.0
    //! is toggled. Toggle rate is exactly 0.25Hz = [32kHz/FFFFh]/2. Proper use of the
    //! TAIV interrupt vector generator is demonstrated.
    //! ACLK = TBCLK = 32kHz, MCLK = SMCLK = default DCO ~ 1.045MHz
    //!
    //! Tested On: MSP430F5529,MSP430FR5739
    //!             ---------------
    //!     /|\|               |
    //!      | |               |
    //!      --|RST            |
    //!        |               |
    //!        |           P1.0|-->LED
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - Timer peripheral
    //! - GPIO peripheral
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - TIMER_A7
    //!
    //
    //*****************************************************************************
    
    
    /*******************************************************************************
    * INCLUDES
    */
    
    #include "driverlib.h"//#include "MSP430F5xx_6xx/driverlib.h"
    void main(void)
    {
            //Stop WDT
            WDT_A_hold(WDT_A_BASE);
    
            //Set P1.0 to output direction
            GPIO_setAsOutputPin(
                    GPIO_PORT_P4,
                    GPIO_PIN0
                    );
    
            //Start timer in continuous mode sourced by ACLK
            TIMER_A_clearTimerInterruptFlag(TIMER_A1_BASE);
            TIMER_A_configureContinuousMode(TIMER_A1_BASE,
                                            TIMER_A_CLOCKSOURCE_ACLK,
                                            TIMER_A_CLOCKSOURCE_DIVIDER_1,
                                            TIMER_A_TAIE_INTERRUPT_ENABLE,
                                            TIMER_A_DO_CLEAR
                                            );
    
            TIMER_A_startCounter(TIMER_A1_BASE,
                                 TIMER_A_CONTINUOUS_MODE
                                 );
    
            //Enter LPM0, enable interrupts
            __bis_SR_register(LPM0_bits + GIE);
    
            //For debugger
            __no_operation();
    }
    
    //******************************************************************************
    //
    //This is the TIMER1_A3 interrupt vector service routine.
    //
    //******************************************************************************
    #pragma vector=TIMER1_A1_VECTOR
    __interrupt void TIMER1_A1_ISR(void)
    {
            //Any access, read or write, of the TAIV register automatically resets the
            //highest "pending" interrupt flag
            switch ( __even_in_range(TA1IV, 14) ) {
            case  0: break;                                 //No interrupt
            case  2: break;                                 //CCR1 not used
            case  4: break;                                 //CCR2 not used
            case  6: break;                                 //CCR3 not used
            case  8: break;                                 //CCR4 not used
            case 10: break;                                 //CCR5 not used
            case 12: break;                                 //CCR6 not used
            case 14:
                    //Toggle P1.0					 // overflow
                    GPIO_toggleOutputOnPin(
                            GPIO_PORT_P4,
                            GPIO_PIN0
                            );
                    break;
            default: break;
            }
    }
    
    

  • If you go to the product page of your MCU there you can find specific examples for your device and/or download MSP430Ware here you will find also a lot of examples.

  • Hello Leo, thanks for your reply

    I already tried the examples from MSP430Ware and they are not working in the IAR... they work in the CCS but I want them in the IAR Workbench, that's why I asked. This is the code I am using in CSS:

    /* --COPYRIGHT--,BSD_EX
     * Copyright (c) 2012, Texas Instruments Incorporated
     * All rights reserved.
     *
     * 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.
     *
     *******************************************************************************
     * 
     *                       MSP430 CODE EXAMPLE DISCLAIMER
     *
     * MSP430 code examples are self-contained low-level programs that typically
     * demonstrate a single peripheral function or device feature in a highly
     * concise manner. For this the code may rely on the device's power-on default
     * register values and settings such as the clock configuration and care must
     * be taken when combining code from several examples to avoid potential side
     * effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware
     * for an API functional library-approach to peripheral configuration.
     *
     * --/COPYRIGHT--*/
    //******************************************************************************
    //  MSP430F543xA Demo - Timer_A3, Toggle P1.0, CCR0 Up Mode ISR, DCO SMCLK
    //
    //  Description: Toggle P1.0 using software and TA_1 ISR. Timer1_A is
    //  configured for up mode, thus the timer overflows when TAR counts
    //  to CCR0. In this example, CCR0 is loaded with 50000.
    //  ACLK = n/a, MCLK = SMCLK = TACLK = default DCO ~1.045MHz
    //
    //           MSP430F5438A
    //         ---------------
    //     /|\|               |
    //      | |               |
    //      --|RST            |
    //        |               |
    //        |           P1.0|-->LED
    //
    //   M. Morales
    //   Texas Instruments Inc.
    //   June 2009
    //   Built with CCE Version: 3.2.2 and IAR Embedded Workbench Version: 4.11B
    //******************************************************************************
    
    #include <msp430.h>
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      P4DIR |= 0x01;                            // P1.0 output
      TA1CCTL0 = CCIE;                          // CCR0 interrupt enabled
      TA1CCR0 = 50000;
      TA1CTL = TASSEL_2 + MC_1 + TACLR;         // SMCLK, upmode, clear TAR
    
      __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts
      __no_operation();                         // For debugger
    }
    
    // Timer A0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMER1_A0_VECTOR
    __interrupt void TIMER1_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMER1_A0_VECTOR))) TIMER1_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      P4OUT ^= 0x01;                            // Toggle P1.0
    }
    
    

    but it doesn't work in the IAR. In the IAR I can see that the interrupt flag goes to 1 but it doesn't goes into the ISR. When I stop the program and check the address memory, i see that the program is stopped in a point of memory different from the one where the ISR is allocated. Any suggestion why is this happening?

  • I’m not familiar with IAR but I don’t see any reason why it shouldn’t work.

    You need to configure IAR properly.

    Post the IAR error’s and then the IAR specialists here can give you maybe some answer to it.

  • C P34 said:
    they are not working in the IAR... they work in the CCS but I want them in the IAR Workbench,

    All of the examples will work in IAR in addition to CCS. The difference is that the examples aren't provided with a pre-configured IAR project file.

    You need to create a new empty project within IAR for your 5438A device. Then copy in the source file(s) for the example and save the project. This creates a default linker map for the device and allows the tools to properly build the example.

    BTW, this is most likely what is wrong with the F5529 IAR example. The 5529 and 5438A have different addresses for their memory regions. You need to make sure that your .xcl file is correct for the target device.

  • Thank you Leo,

    That's one of my problems haha, IAR doesn't shows any errors and I think I configured properly the IAR because I followed a tutorial to do it.

    but I copy the Debug log window:

    Fri Sep 26, 2014 13:49:51: Using license: Standalone license - IAR Embedded Workbench for Texas Instruments MSP430, 8K KickStart Edition 6.10 
    Fri Sep 26, 2014 13:49:52: Firmware version 30400020 
    Fri Sep 26, 2014 13:49:52: Interface dll version 3.4.0.20 
    Fri Sep 26, 2014 13:49:53: Device : MSP430F5438A 
    Fri Sep 26, 2014 13:49:53: External voltage : 3.3 V 
    Fri Sep 26, 2014 13:49:53: VCC voltage : 0.0 V 
    Fri Sep 26, 2014 13:49:55: Download complete. 
    Fri Sep 26, 2014 13:49:55: Loaded debugee: C:\Users\Dit\Documents\Texas Instruments\Programming\timertest\Debug\Exe\timertest.d43 
    Fri Sep 26, 2014 13:49:56: Target reset 
    Fri Sep 26, 2014 13:49:56: Failed to read one or more register values (busy). 
    Fri Sep 26, 2014 13:49:56: Failed to read one or more register values (busy). 
    

    Thank you in advance.

  • Hello Brian,
    thanks for the reply.


    You need to create a new empty project within IAR for your 5438A device. Then copy in the source file(s) for the example and save the project. This creates a default linker map for the device and allows the tools to properly build the example.



    I explain you below the steps I followed to create the project in the IAR, please let me know if there's something missing:

    1. Open IAR, New File. Copy in there the code from the CCS (the one i posted above). Save the file like .c file.
    2. New Workspace.
    3. New Project, MSP430 and empty project and save it.
    4. Add file -> file .c created before.
    5. Save Workspace.
    6. In the name of the project. Right click button and Options... Select target to MSP430F5438A.
      Debugger -->Driver: FET Debugger

      Thanks in advance
  • Can you post the .xcl file?

  • Brian Boorman said:

    Can you post the .xcl file?



    This is the lnk430f5438a.xcl file:

    -----------------------------------------------------------------------------------------------------------------------------------------------------

    // ************************************************
    //
    // XLINK configuration file for MSP430F5438A
    //
    // Copyright 1996-2014 IAR Systems AB.
    //
    // See the file 430/doc/licenses/IARSourceLicense.txt for detailed
    // license information.
    //
    // $Revision: 10651 $
    //
    // ************************************************

    // ---------------------------------------------------------
    // Description
    //

    //
    // Usage:
    //
    //   xlink [file file ...] -f lnk430f5438a.xcl
    //
    // -----------------------------------------------
    // Device summary
    //

    //
    // Core:                           MSP430X
    //
    // Interrupt vectors:              64
    //
    // Peripheral units:                   0-00FFF
    //
    // Information memory (FLASH):     01800-019FF
    //
    // Read/write memory (RAM):        01C00-05BFF
    //
    // Read-only memory (FLASH):       05C00-0FFFF
    //                                 10000-45BFF
    //


    // -----------------------------------------------
    // Segments
    //

    // -------------------------------------
    // Data read/write segments (RAM)
    //

    //
    // The following segments are available for both
    // the DATA16 and DATA20 segment groups.
    //
    // segment         Usage
    // -------         --------------------------
    // DATA<nn>_Z      Data initialized to zero
    // DATA<nn>_I      Data initialized by copying from DATA<nn>_ID
    // DATA<nn>_N      Data defined using __no_init
    // DATA<nn>_HEAP   The heap used by 'malloc' and 'free'
    //
    // segment         Usage
    // -------         --------------------------
    // CSTACK          Runtime stack
    // TLS16_I         Thread-local storage for main thread
    //


    // -------------------------------------
    // Program and data read-only segments (FLASH)
    //

    //
    // The following segments are available for both
    // the DATA16 and DATA20 segment groups.
    //
    // segment         Usage
    // -------         --------------------------
    // DATA<nn>_C      Constant data, including string literals
    // DATA<nn>_ID     Initializers for DATA<nn>_I
    //
    // segment         Usage
    // -------         --------------------------
    // INFO            Information memory
    // INFOA           Information memory, bank A
    // INFOB           Information memory, bank B
    // INFOC           Information memory, bank C
    // INFOD           Information memory, bank D
    // CSTART          Program startup code
    // CODE            Program code
    // ISR_CODE        Program code for interrupt service routines
    // DIFUNCT         Dynamic initialization vector used by C++
    // CHECKSUM        Checksum byte(s) generated by the -J option
    // INTVEC          Interrupt vectors
    // RESET           The reset vector
    // TLS16_ID        Thread-local initializers for main thread
    //
    // Notes:
    //
    // * The segments CSTART, ISR_CODE, and DIFUNCT, as well as the segments in
    //   the DATA16 and TLS16 segment groups must be placed in in the range
    //   0000-FFFD.
    //
    // * The INFOx and INFO segments overlap, this allows data either to be
    //   placed in a specific bank or anywhere in the info memory.
    //
    // * The INTVEC and RESET segments overlap. This allows an application to
    //   either use the reset vector provided by the runtime library, or
    //   provide a reset function by defining an interrupt function associated
    //   with the reset vector.
    //


    // ---------------------------------------------------------
    // Configuation
    //

    // -----------------------------------------------
    // Stack and heap sizes
    //

    // Uncomment for command line use
    //-D_STACK_SIZE=160
    //-D_DATA16_HEAP_SIZE=160
    //-D_DATA20_HEAP_SIZE=160


    // -----------------------------------------------
    // Define cpu
    //

    -cmsp430

    // Compensate for hardware bug in CPU
    -D?CPU30_OFFSET=2


    // -----------------------------------------------
    // Support for placing functions in read/write memory
    //

    -QCODE_I=CODE_ID


    // -----------------------------------------------
    // Support for thread local storage
    //

    -QTLS16_I=TLS16_ID


    // ---------------------------------------------------------
    // Placement directives
    //

    // -----------------------------------------------
    // Information memory
    //

    -Z(CONST)INFO=1800-19FF
    -Z(CONST)INFOA=1980-19FF
    -Z(CONST)INFOB=1900-197F
    -Z(CONST)INFOC=1880-18FF
    -Z(CONST)INFOD=1800-187F


    // -----------------------------------------------
    // RAM memory
    //

    -Z(DATA)DATA16_I,DATA16_Z,DATA16_N,TLS16_I=1C00-5BFF
    -Z(DATA)DATA16_HEAP+_DATA16_HEAP_SIZE
    -Z(DATA)CODE_I
    -Z(DATA)DATA20_I,DATA20_Z,DATA20_N,DATA20_HEAP+_DATA20_HEAP_SIZE
    -Z(DATA)CSTACK+_STACK_SIZE#


    // -----------------------------------------------
    // Read-only memory
    //

    // -------------------------------------
    // Low memory 0-0FFFF
    //

    // ---------------------------
    // Constant data
    //

    -Z(CONST)DATA16_C,DATA16_ID,TLS16_ID,DIFUNCT,CHECKSUM=5C00-FF7F

    // ---------------------------
    // Code
    //

    -Z(CODE)CSTART,ISR_CODE,CODE16=5C00-FF7F


    // -------------------------------------
    // All memory 0-FFFFF
    //

    // ---------------------------
    // Code
    //

    -P(CODE)CODE=5C00-FF7F,10000-45BFF
    -Z(CODE)CODE_ID

    // ---------------------------
    // Constant data
    //

    -Z(CONST)DATA20_C,DATA20_ID=5C00-FF7F,10000-45BFF


    // -------------------------------------
    // Interrupt vectors
    //

    -Z(CODE)INTVEC=FF80-FFFF
    -Z(CODE)RESET=FFFE-FFFF

    --------------------------------------------------------------------------------------------------------------------------------------------------

    multiplier32_loc2.xcl file:

    -----------------------------------------------------------------------------------------------------------------------------------------------------

    // **************************************************
    //
    // Linker command file for redirecting calls to routines that will use
    // the 32 bit hardware multiplier, located at an alternate address.
    //
    // Copyright 1996-2008 IAR Systems AB.
    //
    // $Revision: 10485 $
    //
    // **************************************************

    // The integer multipliers.

    -e?Mul8HwLoc2=?Mul8
    -e?Mul16HwLoc2=?Mul16
    -e?Mul16to32uHwLoc2=?Mul16to32u
    -e?Mul16to32sHwLoc2=?Mul16to32s
    -e?Mul32Hw32Loc2=?Mul32
    -e?Mul64Hw32Loc2=_Mul64i
    -e?Mul32u32uto64iHw32Loc2=_Mul32u32uto64i

    // Floating point multipliers.

    -e?Mul32fHwLoc2=_Mul32f
    -e_Mul64fHwPtrLoc2=_Mul64fPtr

    -----------------------------------------------------------------------------------------------------------------------------------------------------------

    Thanks in advance

  • any solution or idea or help? what was the purpose of posting the .xcl file?

    Thanks in advance

  • C P34 said:
    what was the purpose of posting the .xcl file?

    To make sure that the memory regions were defined correctly for 5438A. You said you were starting with 5529 examples. The XCL file looks fine.

  • Thanks for the reply.

    Brian Boorman said:

     The XCL file looks fine.


    so, any idea of why it is not working?

  • This is a verified working test for TB0. Source is from MSP430Ware 5438A examples (version 1.90.00.30). Compiled with IAR 5.50.1

    This uses the linker .xcl file you posted.

    0312.5438A_TB0_Example.zip

    Hope that is useful.

  • Hello Brian, thanks again for your reply.

    I've tried this project in the IAR 7.0 and it doesn't work. First thing I did was open the project with the IAR and I got that error:
    [Og007]: Assembler list file generation not allowed in this version of the compiler
    I googled it and I found that I should uncheck the box marked in the image:


    https://community.freescale.com/servlet/JiveServlet/download/324695-259016/image001.png

    I did it and I don't get any error in the IAR. But when I load and run the program it doesn't goes into the interrupt. It keeps restarting. I put the code to explain it better:

    #include <msp430.h>
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      P4DIR |= 0x01;                            // P1.0 output
      TBCCTL0 = CCIE;                           // CCR0 interrupt enabled
      TBCCR0 = 50000;
      TBCTL = TBSSEL_2 + MC_2 + TBCLR;          // SMCLK, contmode, clear TBR
    
      while(1)
      {
        __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0, enable interrupts
        __no_operation();                         // For debugger
      }
    }
    
    // Timer B0 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=TIMERB0_VECTOR
    __interrupt void TIMERB0_ISR (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(TIMERB0_VECTOR))) TIMERB0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      P4OUT ^= 0x01;                            // Toggle P1.0
      TBCCR0 += 50000;                          // Add Offset to CCR0 [Cont mode]
    }

    I have a breakpoint in the P4OUT ^= 0x01; // Toggle P1.0 inside the ISR and it never goes there. I put another breakpoint in the first instruction: WDTCTL = WDTPW + WDTHOLD; // Stop WDT and I see that it keeps going into that interrupt, like if the program was all the time restarting. What I mean is that I click the Go button and it keeps coming back to the first instruction and it doesn't goes into the ISR, I think it is reseting the program because the P4.0 keeps going to 0 every time the program comes back to the first instruction.

    EDIT:
    I have just realized that the flag (TBIFG) goes to 1 but it doesn't goes into the ISR. It stucks in the line:

     __no_operation();                         // For debugger

    I have found exactly the same code in the MSP430Ware as you told me and I run it in the CCS and it works perfectly. So, I don't know what is wrong with my IAR, because I've seen that you posted that this code was tested in IAR 5.50.1.

    Brian Boorman said:

    This is a verified working test for TB0. Source is from MSP430Ware 5438A examples (version 1.90.00.30). Compiled with IAR 5.50.1

    I am using IAR 7.0 I think it should work, but it is not working. I must have something wrong in my IAR because I've been trying other timer examples and they don't work either, but I don't know what it is. Any idea or help?

    Thank you in advance.


    ********The only modification I've done is the P4DIR instead of P1DIR and P4OUT instead of P1OUT. But I did it in CCS as well and it works.

  • Like I said, this example works fine on my setup (MSP430F5438A on an MSP-TS430P25x100 target board) and happily blinks the LED.

    I don't have access to IAR 7.0 on this machine. I would recommend asking the team over at IAR about this (and tell them about this thread - the MSP430 IAR compiler author checks in here occasionally).

  • Brian Boorman said:

    I would recommend asking the team over at IAR about this (and tell them about this thread - the MSP430 IAR compiler author checks in here occasionally).



    How/Where can I ask the team over at IAR?
    Thanks

  • Just to give a comment on the original question:

    In the code snippets, you set the period to 256 timer ticks. So the timer counts from 0 to 255 and then from 0 again.
    Since CCIE is set in TB0CCTL0, the ISR should be called at the end of each cycle, provided that GIE is set and that SMCLK is >0Hz.
    However, the trigger for changing the output signal on TB0CCR1 was set to 32768. Since the timer only counts up to 255, it will never reach 32768. And therefore never change the PWM output. It is also of no use to write 32768 again to TB0CCR1, as it is already there. In compare mode, the contents of the CCRs won’t change. Only the timer counter is advancing.
    Of course, this approach was meant for a PWM->analog DAC application, not for a delay.

    For a 1s delay, thins should be done differently:
    Timer should run from ACLK, 32768Hz (the typical watch crystal, or REFO on 5x family)
    TB0CTL = 0; // stop the timer
    timeout=0; // clear timeout flag
    TB0CCTL0 = CCIE; // enable compare interrupt for CCR0
    TB0CCR0 = 32768; // compare interrupt when timer counts to 32768
    TB0CTL = TBSSEL__ACLK|MC_2|TBCL; // ACLK, cont mode, clear timer count.

    After 32768 clock cycles (1s on 32768Hz ACLK), the ISR is called.
    In the ISR, timeout is set to 1 and TB0CTL is set to 0 (stop the timer).
    ‚timeout‘ must be declared as volatile (e.g. volatile unsigned int timeout = 0;)
    If the answer comes in in-time, just set TB0CTL=0 to stop the timer.

  • C P34 said:
    __no_operation(); // For debugger

    The NOP isn’t there to put a breakpoint on it. It is there so you can put a breakpoint on the next real instruction (and there is none in your loop). Due to code prefetch, a breakpoint on an instruction right after entering LPM will be triggered before LPM is entered. If you want a breakpoint after returning from LPM, and you do not have any further code in this loop, then add two NOPs and put the breakpoint on the second one.

  • Thanks for the replies.

    I've been trying again with your changes and I am getting the same problem. The program resets. It seems like every time the timer expires it resets the program. I attach a capture of the state of my program after the first reset. In it it's shown that the flag of the timer is on but the program does not go into the ISR.

    Any idea of why it's happening?

    Thanks in advance

  • any help?

  • The code shouldn’t cause the MSP to reset. You only set CCIE in TBCCTL0, and you have the proper ISR (TIMER0_B0_VECTOR) for it. So the cause must be somewhere else.
    Do you disable (or trigger) the watchdog? Keep in mind that the watchdog, if active, will continue to count even if the MSP is in LPM or otherwise waiting.

    Other possible reasons are stack corruption or stack overflow. Do you have other ISRs? Arrays where you accidentally write outside the array area? Do you define large amounts of local vars (like local arrays?) They will blow up the stack and are outside the linker space-checking control.
    Do you use pointers for data access? Maybe an uninitialized pointer or a wrong assignment makes you writing into the void rather than the intended data space.

**Attention** This is a public forum