Other Parts Discussed in Thread: CC1350, SYSBIOS,
Tool/software: Code Composer Studio
I'm trying to modify the rfPacketRx example project to switch between RX and TX modes. When attempting to setup the radio, the program breaks somewhere in the C:\ti\tirtos_cc13xx_cc26xx_2_21_00_06\products\tidrivers_cc13xx_cc26xx_2_21_00_04\packages\ti\drivers\rf\RFCC26XX_singleMode.c file. I've nearly copied an example I found in the forums but it was based on the CC1350 part. Can you review the code below and offer any suggestions to where the application is configured incorrectly? The code compiles just fine and I do not use the RTOS as the program is a very simple operation of: RX Mode, wait 500mS and/or wait for UART command, TX updated status, Back to RX Mode and UART Receive mode.
Below is the rfPacketRx.c file I've modified.
/***** Includes *****/
#include <stdlib.h>
#include <xdc/std.h>
#include <xdc/cfg/global.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/hal/Hwi.h>
#include <driverlib/interrupt.h>
/* Drivers */
#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/pin/PINCC26XX.h>
#include <driverlib/rf_prop_mailbox.h>
#include <driverlib/systick.h>
/* Board Header files */
#include "Board.h"
#include "RFQueue.h"
#include "smartrf_settings/smartrf_settings.h"
#include <stdlib.h>
/* Global memory storage for a PIN_Config table */
static PIN_State buttonPinState;
static PIN_State ledPinState;
static PIN_Handle ledPinHandle;
static PIN_Handle buttonPinHandle;
PIN_Config ledPinTable[] = {
Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
Dimmer_Control | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_TERMINATE
};
PIN_Config buttonPinTable[] = {
Board_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
Board_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
Zero_Cross_Detect | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
PIN_TERMINATE
};
PIN_Config pinTable[] =
{
Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
PIN_TERMINATE
};
/***** Defines *****/
#define RX_TASK_STACK_SIZE 1024
#define RX_TASK_PRIORITY 2
#define TX_TASK_STACK_SIZE 1024
#define TX_TASK_PRIORITY 2
/* Packet TX Configuration */
#define PAYLOAD_LENGTH 30
#define PACKET_INTERVAL (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */
#define DATA_ENTRY_HEADER_SIZE 8 /* Constant header size of a Generic Data Entry */
#define NUM_DATA_ENTRIES 2 /* NOTE: Only two data entries supported at the moment */
#define NUM_APPENDED_BYTES 2 /* The Data Entries data field will contain:
* 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
* Max 30 payload bytes
* 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */
#define RX_TIMEOUT (uint32_t)(4000000*0.5f)
#define DUTY_CYCLE_MULT 3840
/***** Function Prototypes *****/
static void Receive(void);
static void rxCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
static void txCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
static void Transmit(void);
void TickTimerISR(void);
static void TickTimerInit(void);
static uint8_t TimerExpired(uint32_t *timer, uint32_t delay_time);
static void SetTimer(uint32_t *timer);
static rfc_propRxOutput_t rxStatistics;
static dataQueue_t dataQueue;
static rfc_dataEntryGeneral_t* currentDataEntry;
static uint8_t packetLength;
static uint8_t* packetDataPointer;
extern uint32_t clk_ticks = 0;
static uint32_t curtime;
static uint8_t DimmingLevel = 30; //default of 30% Duty Cycle
static uint16_t seqNumber;
static uint16_t DUTY_CYCLE_NUMBER = 10;
static RF_Object rfObject;
static RF_Handle rfHandle;
#ifdef LOG_RADIO_EVENTS
static volatile RF_EventMask eventLog[32];
static volatile uint8_t evIndex = 0;
#endif // LOG_RADIO_EVENTS
static uint8_t txPacket[PAYLOAD_LENGTH];
static uint8_t rxPacket[PAYLOAD_LENGTH + NUM_APPENDED_BYTES - 1];
static uint16_t seqNumber;
int nReceived = 0;
static uint32_t curtime;
static volatile bool bRxSuccess = false;
union FLAG_REG{ /** Data type for flags register */
uint16_t Flag_Status;
struct flagStatusStruct{
uint8_t Reserved_1 :1;
uint8_t Reserved_2 :1;
uint8_t Reserved_3 :1;
uint8_t Reserved_4 :1;
uint8_t Reserved_5 :1;
uint8_t Reserved_6 :1;
uint8_t Reserved_7 :1;
uint8_t Reserved_8 :1;
uint8_t Reserved_9 :1;
uint8_t Reserved_10 :1;
uint8_t Reserved_11 :1;
uint8_t Reserved_12 :1;
uint8_t Reserved_13 :1;
uint8_t Reserved_14 :1;
uint8_t Reserved_15 :1;
uint8_t UartMessageReceived :1;
} Bits;
};
union FLAG_REG statusFlags;
/* Buffer which contains all Data Entries for receiving data.
* Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
#if defined(__TI_COMPILER_VERSION__)
#pragma DATA_ALIGN (rxDataEntryBuffer, 4);
static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
PAYLOAD_LENGTH,
NUM_APPENDED_BYTES)];
#elif defined(__IAR_SYSTEMS_ICC__)
#pragma data_alignment = 4
static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
PAYLOAD_LENGTH,
NUM_APPENDED_BYTES)];
#elif defined(__GNUC__)
static uint8_t rxDataEntryBuffer [RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
PAYLOAD_LENGTH, NUM_APPENDED_BYTES)] __attribute__ ((aligned (4)));
#else
#error This compiler is not supported.
#endif
void TickTimerInit(void){
Hwi_Params hwiParams;
Hwi_Struct hwi;
SysTickDisable();
SysTickPeriodSet(48000); // 1mS interrupt timing
/* Create Hwi object for this peripheral */
Hwi_Params_init(&hwiParams);
hwiParams.priority = 4; // Lowest
Hwi_construct(&hwi, INT_SYSTICK, TickTimerISR, &hwiParams, NULL);
SysTickEnable();
} //end of void TickTimerInit(void){
void SetTimer(uint32_t *timer){
*timer = clk_ticks;
} //end of void SetTimer(int timer){
uint8_t TimerExpired(uint32_t *timer, uint32_t delay_time){
if((clk_ticks - *timer) >= delay_time) return 1;
else return 0;
} //end of int TimerExpired(int timer, int time){
void TickTimerISR(void){
clk_ticks++;
}
void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId) {
/* Debounce logic, only toggle if the button is still pushed (low) */
CPUdelay(5); //short debounce for ZeroCross Detector
if (!PIN_getInputValue(pinId)) {
switch (pinId) {
case Board_BUTTON0:
if (DUTY_CYCLE_NUMBER >=100) DUTY_CYCLE_NUMBER = 100;
else DUTY_CYCLE_NUMBER++;
break;
case Board_BUTTON1:
if (DUTY_CYCLE_NUMBER == 0)
{
DUTY_CYCLE_NUMBER = 0;
}
else DUTY_CYCLE_NUMBER--;
break;
case Zero_Cross_Detect:
PIN_setOutputValue(ledPinHandle, Dimmer_Control, 0);//Disable Triac
CPUdelay(DUTY_CYCLE_MULT * DUTY_CYCLE_NUMBER); //max time is 38400 CPU cycles in 8mS (half of 60Hz)
PIN_setOutputValue(ledPinHandle, Dimmer_Control, 1);
break;
default:
/* Do nothing */
break;
}
}
}
static void rxCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
#ifdef LOG_RADIO_EVENTS
eventLog[evIndex++ & 0x1F] = e;
#endif// LOG_RADIO_EVENTS
if (e & RF_EventRxEntryDone)
{
bRxSuccess = true;
currentDataEntry = RFQueue_getDataEntry();
packetLength = *(uint8_t*)(¤tDataEntry->data);
packetDataPointer = (uint8_t*)(¤tDataEntry->data + 1);
memcpy(rxPacket, packetDataPointer, (packetLength + 1));
nReceived++;
//dimming range boudry check
if(rxPacket[3] >= 100) rxPacket[3] = 100;
else if(rxPacket[3] <= 0) rxPacket[3] = 0;
DUTY_CYCLE_NUMBER = 100 - rxPacket[3];
RFQueue_nextEntry();
}
}
static void txCallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
{
if(e & RF_EventCmdDone)
{
PIN_setOutputValue(ledPinHandle, Board_LED1,
!PIN_getOutputValue(Board_LED1));
PIN_setOutputValue(ledPinHandle, Board_LED2, 0);
}
else
{
PIN_setOutputValue(ledPinHandle, Board_LED1, 1);
PIN_setOutputValue(ledPinHandle, Board_LED2, 1);
}
}
static void Transmit(void)
{
txPacket[0] = (uint8_t)(seqNumber >> 8);
txPacket[1] = (uint8_t)(seqNumber++);
txPacket[2] = (uint8_t)(0xFF);
txPacket[3] = DimmingLevel; // increment from 0 - 100 for 0% to 100% Dimming duty cycle
uint8_t i;
for (i = 4; i < PAYLOAD_LENGTH; i++)
{
txPacket[i] = 0; //set remaining bytes to 0 for now
}
RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, txCallback, RF_EventCmdDone);
// RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
}
void Receive()
{
nReceived = 0;
while (nReceived <= 1)
{
RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, rxCallback, RF_EventRxEntryDone);
}
}
int main(void)
{
uint32_t txTimer;
uint32_t currVal = 0;
RF_Params rfParams;
RF_Params_init(&rfParams);
/* Call board init functions. */
Board_initGeneral();
TickTimerInit();
IntMasterEnable();
/* Open LED pins */
ledPinHandle = PIN_open(&ledPinState, ledPinTable);
if(!ledPinHandle) {
System_abort("Error initializing board LED pins\n");
}
buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable);
if(!buttonPinHandle) {
System_abort("Error initializing button pins\n");
}
if(RFQueue_defineQueue(&dataQueue,
rxDataEntryBuffer,
sizeof(rxDataEntryBuffer),
NUM_DATA_ENTRIES,
PAYLOAD_LENGTH + NUM_APPENDED_BYTES))
/* Setup callback for button pins */
if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFxn) != 0) {
System_abort("Error registering button callback function");
}
//CMD_PRO_TX and CMD_PROP_RX command setup
RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
RF_cmdPropTx.pPkt = txPacket;
RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;
RF_cmdPropTx.startTrigger.pastTrig = 1;
RF_cmdPropTx.startTime = 0;
RF_cmdPropRx.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1; /* Discard ignored packets from Rx queue */
RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1; /* Discard packets with CRC error from Rx queue */
RF_cmdPropRx.maxPktLen = PAYLOAD_LENGTH; /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
RF_cmdPropRx.pktConf.bRepeatOk = 0; //no repeat
RF_cmdPropRx.pktConf.bRepeatNok = 0; //no repeat
RF_cmdPropRx.pOutput = (uint8_t *)&rxStatistics;
/* Request access to the radio */
rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
/* Set the frequency */
RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
/* Get current time */
curtime = RF_getCurrentTime();
Receive();// place radio into receive mode prior to entering tx loop
SetTimer(&txTimer); //set timer
while(1){
//trigger tx every ~500mS for now
if(TimerExpired(&txTimer, 500)){ //trigger every 500mS
currVal = PIN_getOutputValue(Board_LED1);
PIN_setOutputValue(ledPinHandle, Board_LED1, !currVal);
Transmit(); //Send Data
SetTimer(&txTimer); // reset timer here, may nned to move to the top of the function if the function timing takes too long...dlh
Receive();// go back to receive mode
} // end of if(TimerExpired(&txTimer, 500)){
if(statusFlags.Bits.UartMessageReceived){//wait for new message(via RF or UART) to update status etc
//processMessage(); //update packet info
// sendAck(); //reply with ACK would need to add a NACK handler here DLH
} //end of if(UartMessageReceived){
//
}
/* Start BIOS */
// BIOS_start();
return (0);
}