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.

CC430F5137 - Interrupt driven radio communication hangs after 0 to 5 loop cycles

Other Parts Discussed in Thread: CC430F5137, TEST2, CC1101

Project:

The board harvest energy from an induction field. when it has enough energy the MCU measures the temperature from 2 sensors (ADC). after the measurement the MCU uses the build in radio to communicate the values to a base station.

because we use energy harvesting the MCU should be in Low Power Mode 3 / 4 whenever it has to wait.


Problem:

The MCU hang when trying to wake up the radio modules (Radio ready signal not triggering), or MCU hangs because an interrupt signaling transmission has been completed does not trigger.

CC430F5137 Chip 1 - problem doesn't occurs.
CC430F5137 Chip 2 - problem occurs in 0 to 3 loop cycles.
EM-CC430F5137 (Evaluation board) - problem occurs in 0 to 5 loop cycles.


Additional inforation

Chip: CC430F5137 rev. D/E
IDE: Code Composer 6.1.0

i hope one of you could help me figuring out what happens, as this is an project stopper at the moment

thanks in advance


/* Includes ------------------------------------------------------------------*/
#include "Radio.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void Radio_WriteSettings(const rfsettings *settings);
static void Radio_WritePATable(const uint8_t *patable, uint8_t count);
/* Exported functions --------------------------------------------------------*/
void Radio_Init(void)
{
	/* Set the High-Power Mode Request Enable bit so LPM3 can be entered with active radio enabled */
	PMMCTL0_H = 0xA5;
	PMMCTL0_L |= PMMHPMRE_L;
	PMMCTL0_H = 0x00;

	Radio_Reset();

	// Write Configuration
	Radio_WriteSettings(&RadioSettings_868MHz_38kBaud);
	Radio_WritePATable(patablesettings, 8);

}
void Radio_Reset(void)
{
	HAL_RF1A_CommandStrobe(RF_SRES);		// Reset radio
	HAL_RF1A_CommandStrobe(RF_SNOP);		// Reset radio pointer
}

void Radio_Transmit(uint8_t *buffer, uint8_t count)
{
	RF1AIES |= BIT9;                          					// Raise interrupt on falling edge
	RF1AIN &= ~BIT9;
	RF1AIFG &= ~BIT9;                         					// Clear pending interrupts
	RF1AIE |= BIT9;                           					// Enable TX end-of-packet interrupt

	HAL_RF1A_RegisterBurstWrite(RF_TXFIFOWR, buffer, count);	// write transmit fifo

	HAL_RF1A_CommandStrobe( RF_STX );             	            // Strobe STX to start transmit.
//TODO hang point
	if ((RF1AIE & BIT9) == BIT9)
	{
		__no_operation();
		__bis_SR_register(LPM1_bits + GIE);
	}

	HAL_RF1A_CommandStrobe( RF_SFTX );             	            // Strobe STX to start transmit.
	HAL_RF1A_CommandStrobe( RF_SPWD );             	            // Strobe STX to start transmit.
}
/* Private functions  --------------------------------------------------------*/
static void Radio_WriteSettings(const rfsettings *settings)
{
	HAL_RF1A_RegisterBurstWrite(IOCFG2, (uint8_t *) settings, sizeof(rfsettings));
}

static void Radio_WritePATable(const uint8_t *patable, uint8_t count)
{
	HAL_RF1A_RegisterBurstWrite(PATABLE, (uint8_t *)patable, count);

	HAL_RF1A_CommandStrobe(RF_SNOP);
}
/* Interrupt Service Routine -------------------------------------------------*/

#ifndef RFSETTINGS_H_
#define RFSETTINGS_H_

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
/* Exported types ------------------------------------------------------------*/
typedef struct
{
    uint8_t iocfg2;     // GDO2 Output Configuration
    uint8_t iocfg1;     // GDO1 Output Configuration
    uint8_t iocfg0;     // GDO0 Output Configuration
    uint8_t fifothr;    // RX FIFO and TX FIFO Thresholds
    uint8_t sync1;      // Sync Word, High Byte
    uint8_t sync0;      // Sync Word, Low Byte
    uint8_t pktlen;     // Packet Length
    uint8_t pktctrl1;   // Packet Automation Control
    uint8_t pktctrl0;   // Packet Automation Control
    uint8_t addr;       // Device Address
    uint8_t channr;     // Channel Number
    uint8_t fsctrl1;    // Frequency Synthesizer Control
    uint8_t fsctrl0;    // Frequency Synthesizer Control
    uint8_t freq2;      // Frequency Control Word, High Byte
    uint8_t freq1;      // Frequency Control Word, Middle Byte
    uint8_t freq0;      // Frequency Control Word, Low Byte
    uint8_t mdmcfg4;    // Modem Configuration
    uint8_t mdmcfg3;    // Modem Configuration
    uint8_t mdmcfg2;    // Modem Configuration
    uint8_t mdmcfg1;    // Modem Configuration
    uint8_t mdmcfg0;    // Modem Configuration
    uint8_t deviatn;    // Modem Deviation Setting
    uint8_t mcsm2;      // Main Radio Control State Machine Configuration
    uint8_t mcsm1;      // Main Radio Control State Machine Configuration
    uint8_t mcsm0;      // Main Radio Control State Machine Configuration
    uint8_t foccfg;     // Frequency Offset Compensation Configuration
    uint8_t bscfg;      // Bit Synchronization Configuration
    uint8_t agcctrl2;   // AGC Control
    uint8_t agcctrl1;   // AGC Control
    uint8_t agcctrl0;   // AGC Control
    uint8_t worevt1;    // High Byte Event0 Timeout
    uint8_t worevt0;    // Low Byte Event0 Timeout
    uint8_t worctrl;    // Wake On Radio Control
    uint8_t frend1;     // Front End RX Configuration
    uint8_t frend0;     // Front End TX Configuration
    uint8_t fscal3;     // Frequency Synthesizer Calibration
    uint8_t fscal2;     // Frequency Synthesizer Calibration
    uint8_t fscal1;     // Frequency Synthesizer Calibration
    uint8_t fscal0;     // Frequency Synthesizer Calibration
    uint8_t res_rcctrl1;// Reserved RC oscillator configuration
    uint8_t res_rcctrl0;// Reserved RC oscillator configuration
    uint8_t fstest;     // Frequency Synthesizer Calibration Control
    uint8_t ptest;      // Production Test
    uint8_t agctest;    // AGC Test
    uint8_t test2;      // Various Test Settings
    uint8_t test1;      // Various Test Settings
    uint8_t test0;      // Various Test Settings
} __attribute__((__packed__)) rfsettings;

/* Exported constants --------------------------------------------------------*/
/* PA table */
static const uint8_t patablesettings[8] = {0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

static const rfsettings RadioSettings_868MHz_38kBaud =
{
    0x69,  // IOCFG2        GDO2 Output Configuration
    0x2E,  // IOCFG1        GDO1 Output Configuration
    0x06,  // IOCFG0        GDO0 Output Configuration
    0x47,  // FIFOTHR       RX FIFO and TX FIFO Thresholds
    0xD3,  // SYNC1         Sync Word, High Byte
    0x91,  // SYNC0         Sync Word, Low Byte
    0x3D,  // PKTLEN        Packet Length
    0x04,  // PKTCTRL1      Packet Automation Control
    0x05,  // PKTCTRL0      Packet Automation Control
    0x00,  // ADDR          Device Address
    0x00,  // CHANNR        Channel Number
    0x08,  // FSCTRL1       Frequency Synthesizer Control
    0x00,  // FSCTRL0       Frequency Synthesizer Control
    0x21,  // FREQ2         Frequency Control Word, High Byte
    0x62,  // FREQ1         Frequency Control Word, Middle Byte
    0x76,  // FREQ0         Frequency Control Word, Low Byte
    0xCA,  // MDMCFG4       Modem Configuration
    0x83,  // MDMCFG3       Modem Configuration
    0x93,  // MDMCFG2       Modem Configuration
    0x22,  // MDMCFG1       Modem Configuration
    0xF8,  // MDMCFG0       Modem Configuration
    0x35,  // DEVIATN       Modem Deviation Setting
    0x07,  // MCSM2         Main Radio Control State Machine Configuration
    0x30,  // MCSM1         Main Radio Control State Machine Configuration
    0x18,  // MCSM0         Main Radio Control State Machine Configuration
    0x16,  // FOCCFG        Frequency Offset Compensation Configuration
    0x6C,  // BSCFG         Bit Synchronization Configuration
    0x43,  // AGCCTRL2      AGC Control
    0x40,  // AGCCTRL1      AGC Control
    0x91,  // AGCCTRL0      AGC Control
    0x80,  // WOREVT1       High Byte Event0 Timeout
    0x00,  // WOREVT0       Low Byte Event0 Timeout
    0xF0,  // WORCTRL       Wake On Radio Control
    0x56,  // FREND1        Front End RX Configuration
    0x10,  // FREND0        Front End TX Configuration
    0xE9,  // FSCAL3        Frequency Synthesizer Calibration
    0x2A,  // FSCAL2        Frequency Synthesizer Calibration
    0x00,  // FSCAL1        Frequency Synthesizer Calibration
    0x1F,  // FSCAL0        Frequency Synthesizer Calibration
    0x00,  // RCCTRL1        Reserved RC oscillator configuration
    0x00,  // RCCTRL0        Reserved RC oscillator configuration
    0x59,  // FSTEST        Frequency Synthesizer Calibration Control
    0x7F,  // PTEST         Production Test
    0x3F,  // AGCTEST       AGC Test
    0x81,  // TEST2         Various Test Settings
    0x35,  // TEST1         Various Test Settings
    0x09,  // TEST0         Various Test Settings
};


/* Includes ------------------------------------------------------------------*/
#include "HAL_RF1A.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t instruction;    // instruction + 1st address
uint8_t *buffer;        // value buffer
uint8_t bufferlength;    // buffer length in bytes
uint8_t buffercount;    // buffer count in bytes
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

uint8_t HAL_RF1A_RegisterSingleRead(uint8_t addr)
{
    uint8_t value;

    // Check for valid configuration register address, 0x3E refers to PATABLE
    if ((addr <= 0x2E) || (addr == 0x3E))
    {
        // Send address + Instruction + 1 dummy byte (auto-read)
        instruction = (addr | RF_SNGLREGRD);
    }
    else
    {
        // Send address + Instruction + 1 dummy byte (auto-read)
        instruction = (addr | RF_STATREGRD);
    }

    buffer = &value;
    bufferlength = 1;
    buffercount = 0;

    // Enable instruction interrupt
    RF1AIFCTL1 |= RFINSTRIE;

    // Wait for the transfer to complete
    __bis_SR_register(LPM3_bits + GIE);

    // Return register value
    return value;
}

void HAL_RF1A_RegisterBurstRead(uint8_t addr, uint8_t *databuffer, uint8_t count)
{
    // Check for valid count value
    if (count == 0)
        return;

    instruction = (addr | RF_REGRD);
    buffer = databuffer;
    bufferlength = count;
    buffercount = 0;

    // Enable instruction interrupt
    RF1AIFCTL1 |= RFINSTRIE;

    // Wait for the transfer to complete
    __bis_SR_register(LPM3_bits + GIE);
}

void HAL_RF1A_RegisterSingleWrite(uint8_t addr, uint8_t value)
{
    instruction = (addr | RF_SNGLREGWR);

    buffer = &value;
    bufferlength = 1;
    buffercount = 0;

    // Enable instruction interrupt
    RF1AIFCTL1 |= RFINSTRIE;

    // Wait for the transfer to complete
    __bis_SR_register(LPM3_bits + GIE);
}

void HAL_RF1A_RegisterBurstWrite(uint8_t addr, uint8_t *databuffer, uint8_t count)
{
    // Check for valid count value
    if (count == 0)
        return;

    instruction = (addr | RF_REGWR);
    buffer = databuffer;
    bufferlength = count;
    buffercount = 0;

    // Enable instruction interrupt
    RF1AIFCTL1 |= RFINSTRIE;

    // Wait for the transfer to complete
    __bis_SR_register(LPM3_bits + GIE);
}

uint8_t HAL_RF1A_CommandStrobe(uint8_t cmd)
{
    uint8_t status;
    uint8_t gdo_state;

    // Check for valid command strobe
    if (((cmd >= (RF_SRES | RF_TXSTAT)) && (cmd <= (RF_SNOP | RF_TXSTAT))) || ((cmd >= (RF_SRES | RF_RXSTAT)) && (cmd <= (RF_SNOP | RF_RXSTAT))))
    {
        // Clear status flag
        RF1AIFCTL1 &= ~RFSTATIFG;

        // Write command strobe
        if (((cmd > (RF_SRES | RF_TXSTAT)) && (cmd < (RF_SNOP | RF_TXSTAT))) || ((cmd > (RF_SRES | RF_RXSTAT)) && (cmd < (RF_SNOP | RF_RXSTAT))))
        {
            // Change GDO2 signal so chip ready can be monitored
            gdo_state = HAL_RF1A_RegisterSingleRead(IOCFG2);                    // Backup GDO2 configuration
            HAL_RF1A_RegisterSingleWrite(IOCFG2, 0x69);                            // Change GDO2 to chip ready (active high)

            // Write command
            RF1AINSTRB = cmd;
            // TODO further check behavior
            if ((RF1AIN & 0x04) == 0x00)                                        // chip in sleep mode
            {
                if ((cmd == (RF_SXOFF | RF_TXSTAT)) || (cmd == (RF_SPWD | RF_TXSTAT)) || (cmd == (RF_SWOR | RF_TXSTAT)) ||
                    (cmd == (RF_SXOFF | RF_RXSTAT)) || (cmd == (RF_SPWD | RF_RXSTAT)) || (cmd == (RF_SWOR | RF_RXSTAT)))
                {
                    // do nothing command puts chip in sleep, which is already sleeping.
                }
                else
                {
                    // Wait for rf chip to be ready
                    /* Note: When the radio needs to transition from the SLEEP state to an active state
                     * (for example, from IDLE, to RX or TX) the CPU must not go into a low-power mode until the radio is active.
                     */
// TODO Hangpoint
                    while((RF1AIN & 0x04) == 0x00);
                    /* Note: The necessary delay of up to 810us for the radio's transition during which the radio oscillator turns on and stabilizes,
                     * is required in order for the radio core to obtain its high speed clock and re-synchronize with the '430 core.
                     * Since no stable clock is available to the radio core during this time, interactions with the radio core should be avoided or postponed.
                     */
                    __delay_cycles(1000);
                }
            }
            // Restore GDO2 setting
            HAL_RF1A_RegisterSingleWrite(IOCFG2, gdo_state);

            // wait for status register to update
            RF1AIFCTL1 |= RFSTATIE;
            __bis_SR_register(LPM3_bits + GIE);
        }
        else
        {
            RF1AINSTRB = cmd;
        }
        status = RF1ASTATB;
    }
    return status;
}
/* Private functions  --------------------------------------------------------*/
/* Interrupt Service Routine -------------------------------------------------*/
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=CC1101_VECTOR
__interrupt void CC1101_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(CC1101_VECTOR))) CC1101_ISR (void)
#else
#error Compiler not supported!
#endif
{
    // radio interface interrupt register
    switch(__even_in_range(RF1AIFIV, 14))
    {
        case 0: break;                                                                        // No interrupt
        case 2:                                                                                // Interrupt source: Radio interface error
            // radio error interrupt register
            switch(__even_in_range(RF1AIFERRV, 8))
            {
                case 0: break;                                                                // No interrupt
                case 2: break;                                                                // Error source: Low voltage
                case 4: break;                                                                // Error source: Operand
                case 6: break;                                                                // Error source: Output data not available
                case 8: break;                                                                // Error source: Operand overwrite
                default: break;
            }
            break;
        case 4:                                                                             // Interrupt source: Radio interface data out
            if (buffercount < (bufferlength-1))                                                // Read complete?
            {
                buffer[buffercount] = RF1ADOUT1B;                                            // Read data
                buffercount++;                                                                // Increase buffer counter
            }
            else
            {
                buffer[buffercount] = RF1ADOUT0B;                                            // Read data
                RF1AIFCTL1 &= ~RFDOUTIE;                                                    // Disable data out interrupt
                LPM4_EXIT;
            }
            break;
        case 6:                                                                                // Interrupt source: Radio interface status out
            RF1AIFCTL1 &= ~RFSTATIE;
            LPM4_EXIT;
            break;
        case 8:                                                                             // Interrupt source: Radio interface data in
            if (buffercount < bufferlength)                                                    // Write complete?
            {
                RF1ADINB = buffer[buffercount];                                                // Write data
                buffercount++;                                                                // increase buffer counter
            }
            else
            {
                buffercount = RF1ADOUTB;                                                    // Read data out to clear interrupt flag
                RF1AIFCTL1 &= ~RFDINIE;                                                        // Disable data in interrupt;
                LPM4_EXIT;
            }
            break;
        case 10:                                                                             // Interrupt source: Radio interface instruction in
            switch(instruction & 0x80)
            {
                case RF_SNGLREGRD:                                                            // Read register
                    RF1AINSTR1B = instruction;                                                // Send address + Instruction + 1 dummy byte (auto-read)
                    RF1AIFCTL1 |= RFDOUTIE;                                                    // Enable data out interrupt
                    break;
                case RF_SNGLREGWR:                                                            // Write register
                    RF1AINSTRW = (instruction <<8 ) | buffer[buffercount];                     // Send address + instruction
                    buffercount++;                                                            // increase counter
                    RF1AIFCTL1 |= RFDINIE;                                                    // Enable data in interrupt
                    break;
                default: break;
            }
            RF1AIFCTL1 &= ~RFINSTRIE;                                                        // Disable instruction interrupt
            break;
        case 12: break;                                                                        // Interrupt source: Reserved
        case 14: break;                                                                        // Interrupt source: Reserved
        default: break;
    }
    // radio core interrupt register
    // see: Table 25-5. CC1101 Radio Core Interrupt Mapping of the CC430 Family User's guide
    switch(__even_in_range(RF1AIV, 32))
    {
        case 0: break;                                                                        // No interrupt
        case 2:    break;                                                                        // Interrupt source: Radio core signal 0: GDO0
        case 4: break;                                                                        // Interrupt source: Radio core signal 1: GDO1
        case 6:                                                                                // Interrupt source: Radio core signal 2: GDO2
// TODO Hang point
            __no_operation();
            LPM4_EXIT;
            break;
        case 8: break;                                                                        // Interrupt source: Radio core signal 3:
        case 10: break;                                                                        // Interrupt source: Radio core signal 4:
        case 12: break;                                                                        // Interrupt source: Radio core signal 5:
        case 14: break;                                                                        // Interrupt source: Radio core signal 6:
        case 16: break;                                                                        // Interrupt source: Radio core signal 7:
        case 18: break;                                                                        // Interrupt source: Radio core signal 8:
        case 20:                                                                             // Interrupt source: Radio core signal 9:
            if ((RF1AIN & BIT9) == BIT9)
            {
                RF1AIE &= ~BIT9;                                                            // Disable TX end-of-packet interrupt
                LPM4_EXIT;
            }
            break;
        case 22: break;                                                                        // Interrupt source: Radio core signal 10:
        case 24: break;                                                                        // Interrupt source: Radio core signal 11:
        case 26: break;                                                                        // Interrupt source: Radio core signal 12:
        case 28: break;                                                                        // Interrupt source: Radio core signal 13:
        case 30: break;                                                                        // Interrupt source: Radio core signal 14:
        case 32: break;                                                                        // Interrupt source: Radio core signal 15:
        default: break;
    }
}

CodeTI.7z

  • Johan,

    You are missing the code that forces the chip into power mode 2 or higher for RF to work. Please look at the example code for PMM and make sure your device is set to power mode 2 before RF is started.

    Regards,
    /TA
  • TA12012 said:
    Johan,

    You are missing the code that forces the chip into power mode 2 or higher for RF to work. Please look at the example code for PMM and make sure your device is set to power mode 2 before RF is started.

    Regards,
    /TA


    Thanks for your reply,

    but i set the core voltage level in my main loop. (see code below)
    and i always keep it at the point. i do not increase or decrease it at any other point in my code.

    besides that i have it working on 1 chip, but 2 other (incl. the evaluation board) hang occasionally.

    as far as i'm with testing now there are 2 point my code hangs.

    1. Sending a command that should put the radio module in active mode, while the module is in sleep mode.
      GDO2 set to signal Chip ready, but never triggers.
      (see function: HAL_RF1A_CommandStrobe)
    2. Transmitting my message
      RF1A interrupt flag 9 set to TX Package transmit complete, but doesn't trigger
      (see function: Radio_Transmit)

    both hang point happen, but there is a randomness to it.

    In the .7zip file i attached to my main post the full code should be visible.


    int main(void)
    {
        uint16_t RawTemperatures[2];
        uint8_t CycleCount = 0;

        WDTCTL = WDTPW | WDTHOLD;    // Stop watchdog timer
        UCSCTL4 |= SELA__VLOCLK;    // Set VLO as auxiliary clock source

        // Set Vcore to a minimum of level 2 to support the radio
        HAL_PMM_SetVCore(2);

        // Initialize delay timer
        DelayTimer_Init();

        // Initialize Led Indicator timer
        LedIndicatorTimer_Init();

        // Initialize GPIO
        /* Pre-setup all gpio ports */                                                        // This is done to reduce current consumption
        PADIR = 0x00;                                                                        // Set to input;
        PAOUT = 0x00;                                                                        // Set to logic low

        PBDIR = 0x00;                                                                        // Set to input;
        PBOUT = 0x00;                                                                        // Set to logic low

        PCDIR = 0x00;                                                                        // Set to input;
        PCOUT = 0x00;                                                                        // Set to logic low

        P2DIR &= ~(BIT2 | BIT3);                                                            // Set P2.2 and P2.5 to input
        P2DIR |= (BIT6);                                                                    // Set P2.6 to output
        P3DIR |= (BIT4 | BIT6);                                                                // Set P3.4 and P3.6 to output

        // Set Port Mapping
        HAL_PMAP_MAPIO(portmapping, (uint8_t *) &P1MAP0, 3, 0);

        // Set Pin Function Select
        P1SEL = 0x00;
        P2SEL = BIT2 | BIT5;
        P3SEL = 0x00;

        // Initialize Temperature sensor circuit
        TSC_Init();
        // Initialize Led indicator timer

        // Initialize Radio
        Radio_Init();

        // Wait for the energy harvesting to acquire enough charge.
        DelayTimer_Wait(250);

        while(1)
        {
            // Do temperature measurement
            TSC_Measure(&RawTemperatures[0], &RawTemperatures[1]);

            // Wait for the energy harvesting to acquire enough charge.
            DelayTimer_Wait(250);

            // Write temperatures to Tx packet
            TxPacket[3] = (RawTemperatures[0] >> 8);
            TxPacket[4] = (RawTemperatures[0] >> 0);
            TxPacket[5] = (RawTemperatures[1] >> 8);
            TxPacket[6] = (RawTemperatures[1] >> 0);
            // Transmit temperatures
            Radio_Transmit((uint8_t *)TxPacket, sizeof(TxPacket));

            // Enable Led indicator
            if (CycleCount == 0)
                LedIndicatorTimer_Enable();

            // increase cycle counter
            CycleCount = (++CycleCount) % 5;

            // Wait for next measurement
            DelayTimer_Wait(750);
        }
    }