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;
}
}