From 12a6eefa850676895a6e29d0a9e5ec7df181d07c Mon Sep 17 00:00:00 2001 From: Edvard Pettersen Date: Mon, 18 Jun 2018 19:23:50 +0200 Subject: [PATCH] Lots of fixes for prop-mode and ieee-mode --- arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c | 169 ++++++----- arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c | 262 +++++++++++------- .../cc13xx-cc26xx/Makefile.cc13xx-cc26xx | 2 +- .../simplelink/cc13xx-cc26xx/contiki-conf.h | 2 +- .../launchpad/button-sensor-arch.c | 2 +- 5 files changed, 257 insertions(+), 180 deletions(-) diff --git a/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c b/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c index 69ec00233..e9443a68e 100644 --- a/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c +++ b/arch/cpu/cc13xx-cc26xx/dev/rf-ieee-mode.c @@ -176,6 +176,10 @@ /* How long to wait for the rx read entry to become ready */ #define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 250) /*---------------------------------------------------------------------------*/ +#define CCA_STATE_IDLE 0 +#define CCA_STATE_BUSY 1 +#define CCA_STATE_INVALID 2 +/*---------------------------------------------------------------------------*/ /* TI-RTOS RF driver object */ static RF_Object g_rfObj; static RF_Handle g_rfHandle; @@ -204,23 +208,39 @@ static uint8_t g_txBuf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4); /*---------------------------------------------------------------------------*/ /* RX Data Queue */ static dataQueue_t g_rxDataQueue; -/* Receive entry pointer to keep track of read items */ -volatile static uint8_t *g_pRxReadEntry; - +/*---------------------------------------------------------------------------*/ /* Constants for receive buffers */ #define DATA_ENTRY_LENSZ_NONE 0 #define DATA_ENTRY_LENSZ_BYTE 1 #define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */ -#define RX_BUF_ENTRIES 4 +#define DATA_ENTRY_LENSZ DATA_ENTRY_LENSZ_BYTE +typedef uint8_t lensz_t; + +#define FRAME_OFFSET DATA_ENTRY_LENSZ +#define FRAME_SHAVE 8 /* FCS (2) + RSSI (1) + Status (1) + Timestamp (4) */ +/*---------------------------------------------------------------------------*/ +/* RX buf configuration */ +#ifdef IEEE_MODE_CONF_RX_BUF_CNT +# define RX_BUF_CNT IEEE_MODE_CONF_RX_BUF_CNT +#else +# define RX_BUF_CNT 4 +#endif + #define RX_BUF_SIZE 144 /* Receive buffer entries with room for 1 IEEE 802.15.4 frame in each */ +typedef rfc_dataEntryGeneral_t data_entry_t; + typedef union { - rfc_dataEntry_t dataEntry; - uint8_t buf[RX_BUF_SIZE] CC_ALIGN(4); -} RxBuf; -static RxBuf g_rxBufs[RX_BUF_ENTRIES]; + data_entry_t data_entry; + uint8_t buf[RX_BUF_SIZE]; +} rx_buf_t CC_ALIGN(4); + +static rx_buf_t rx_bufs[RX_BUF_CNT]; + +/* Receive entry pointer to keep track of read items */ +static data_entry_t *rx_read_entry; /*---------------------------------------------------------------------------*/ /* RAT overflow upkeep */ static struct ctimer g_ratOverflowTimer; @@ -331,10 +351,10 @@ static void init_data_queue(void) { // Initialize RF core data queue, circular buffer - g_rxDataQueue.pCurrEntry = g_rxBufs[0].buf; + g_rxDataQueue.pCurrEntry = rx_bufs[0].buf; g_rxDataQueue.pLastEntry = NULL; // Set current read pointer to first element - g_pRxReadEntry = g_rxDataQueue.pCurrEntry; + rx_read_entry = &rx_bufs[0].data_entry; } /*---------------------------------------------------------------------------*/ static void @@ -368,25 +388,20 @@ init_rf_params(void) static void init_rx_buffers(void) { -#define GET_ENTRY(n) (&(g_rxBufs[(n)].dataEntry)) - - rfc_dataEntry_t *entry = NULL; - const size_t length = sizeof(g_rxBufs[0].buf) - 8; - - size_t i; - for (i = 0; i < (size_t)(RX_BUF_ENTRIES - 1); ++i) { - entry = GET_ENTRY(i); - entry->pNextEntry = (uint8_t*)GET_ENTRY(i + 1); - entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = (uint16_t)length; + size_t i = 0; + for (i = 0; i < RX_BUF_CNT; ++i) { + const data_entry_t data_entry = { + .status = DATA_ENTRY_PENDING, + .config.type = DATA_ENTRY_TYPE_GEN, + .config.lenSz = DATA_ENTRY_LENSZ, + .length = RX_BUF_SIZE - sizeof(data_entry_t), /* TODO: is this sizeof sound? */ + /* Point to fist entry if this is last entry, else point to next entry */ + .pNextEntry = (i == (RX_BUF_CNT - 1)) + ? rx_bufs[0].buf + : rx_bufs[i].buf + }; + rx_bufs[i].data_entry = data_entry; } - - entry = GET_ENTRY(RX_BUF_ENTRIES - 1); - entry->pNextEntry = (uint8_t*)GET_ENTRY(0); - entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; - entry->length = (uint16_t)length; - -#undef getEntry } /*---------------------------------------------------------------------------*/ static bool @@ -613,8 +628,6 @@ transmit_aux(unsigned short transmit_len) // Configure TX command cmd_tx.payloadLen = (uint8_t)transmit_len; cmd_tx.pPayload = &g_txBuf[TX_BUF_HDR_LEN]; - cmd_tx.startTime = 0; - cmd_tx.startTrigger.triggerType = TRIG_NOW; RF_ScheduleCmdParams schedParams; RF_ScheduleCmdParams_init(&schedParams); @@ -672,68 +685,88 @@ send(const void *payload, unsigned short payload_len) static void release_data_entry(void) { - rfc_dataEntryGeneral_t *pEntry = (rfc_dataEntryGeneral_t *)g_pRxReadEntry; + data_entry_t *const data_entry = rx_read_entry; + uint8_t *const frame_ptr = (uint8_t*)&data_entry->data; + // Clear the length byte and set status to 0: "Pending" - g_pRxReadEntry[8] = 0; - pEntry->status = DATA_ENTRY_PENDING; - // Set next entry - g_pRxReadEntry = pEntry->pNextEntry; + *(lensz_t*)frame_ptr = 0; + data_entry->status = DATA_ENTRY_PENDING; + rx_read_entry = (data_entry_t*)data_entry->pNextEntry; } /*---------------------------------------------------------------------------*/ static int read(void *buf, unsigned short buf_len) { - volatile rfc_dataEntryGeneral_t *pEntry = (rfc_dataEntryGeneral_t *)g_pRxReadEntry; + volatile data_entry_t *data_entry = rx_read_entry; const rtimer_clock_t t0 = RTIMER_NOW(); // Only wait if the Radio timer is accessing the entry - while ((pEntry->status == DATA_ENTRY_BUSY) && + while ((data_entry->status == DATA_ENTRY_BUSY) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY)); - if (pEntry->status != DATA_ENTRY_FINISHED) { + if (data_entry->status != DATA_ENTRY_FINISHED) { // No available data return 0; } - // FIXME: something is wrong here about length constraints - const uint8_t frame_len = g_pRxReadEntry[8]; - if (frame_len < 8) { - PRINTF("read_frame: frame too short len=%d\n", frame_len); + /* First byte in the data entry is the length. + * Data frame is on the following format: + * Length (1) + Payload (N) + FCS (2) + RSSI (1) + Status (1) + Timestamp (4) + * Data frame DOES NOT contain the following: + * no PHY Header bytes + * no Source Index bytes + * +--------+---------+---------+--------+--------+-----------+ + * | 1 byte | N bytes | 2 bytes | 1 byte | 1 byte | 4 bytes | + * +--------+---------+---------+--------+--------+-----------+ + * | Length | Payload | FCS | RSSI | Status | Timestamp | + * +--------+---------+---------+--------+--------+-----------+ + * Length bytes equal total length of entire frame excluding itself, + * i.e.: Length = N + FCS (2) + RSSI (1) + Status (1) + Timestamp (4) + * = N + 8 + * N = Length - 8 */ + + uint8_t *const frame_ptr = (uint8_t*)&data_entry->data; + const lensz_t frame_len = *(lensz_t*)frame_ptr; + + /* Sanity check that Frame is at least Frame Shave bytes long */ + if (frame_len < FRAME_SHAVE) { + PRINTF("read: frame too short len=%d\n", frame_len); release_data_entry(); return 0; } - const uint8_t payload_len = frame_len - 8; + const uint8_t *payload_ptr = frame_ptr + sizeof(lensz_t); + const unsigned short payload_len = (unsigned short)(frame_len - FRAME_SHAVE); + /* Sanity check that Payload fits in Buffer */ if (payload_len > buf_len) { - PRINTF("read_frame: frame larger than buffer\n"); + PRINTF("read: payload too large for buffer len=%d buf_len=%d\n", payload_len, buf_len); release_data_entry(); return 0; } - const uint8_t *pData = (uint8_t *)&g_pRxReadEntry[9]; - memcpy(buf, pData, payload_len); + memcpy(buf, payload_ptr, payload_len); - g_lastRssi = (int8_t)(pData[payload_len + 2]); - g_lastCorrLqi = (uint8_t)(pData[payload_len + 3]) & STATUS_CORRELATION; - - uint32_t ratTimestamp; - memcpy(&ratTimestamp, pData + payload_len + 4, sizeof(ratTimestamp)); + /* RSSI stored FCS (2) bytes after payload */ + g_lastRssi = (int8_t)payload_ptr[payload_len + 2]; + /* LQI retrieved from Status byte, FCS (2) + RSSI (1) bytes after payload */ + g_lastCorrLqi = ((uint8_t)payload_ptr[payload_len + 3]) & STATUS_CORRELATION; + /* Timestamp stored FCS (2) + RSSI (1) + Status (1) bytes after payload */ + const uint32_t ratTimestamp = *(uint32_t*)(payload_ptr + payload_len + 4); g_lastTimestamp = rat_to_timestamp(ratTimestamp); if (!g_bPollMode) { // Not in poll mode: packetbuf should not be accessed in interrupt context. // In poll mode, the last packet RSSI and link quality can be obtained through // RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, g_lastRssi); - packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, g_lastCorrLqi); + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)g_lastRssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)g_lastCorrLqi); } release_data_entry(); - - return payload_len; + return (int)payload_len; } /*---------------------------------------------------------------------------*/ static int @@ -779,28 +812,18 @@ receiving_packet(void) return 0; } - rfc_CMD_IEEE_CCA_REQ_t RF_cmdIeeeCaaReq; - memset(&RF_cmdIeeeCaaReq, 0x0, sizeof(rfc_CMD_IEEE_CCA_REQ_t)); - RF_cmdIeeeCaaReq.commandNo = CMD_IEEE_CCA_REQ; + rfc_CMD_IEEE_CCA_REQ_t cca_req; + memset(&cca_req, 0x0, sizeof(rfc_CMD_IEEE_CCA_REQ_t)); + cca_req.commandNo = CMD_IEEE_CCA_REQ; - const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&RF_cmdIeeeCaaReq); + const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&cca_req); if (stat != RF_StatCmdDoneSuccess) { PRINTF("receiving_packet: CCA request failed stat=0x%02X\n", stat); return 0; } - // If the radio is transmitting an ACK or is suspended for running a TX operation, - // ccaEnergy, ccaCorr and ccaSync are all busy (1) - if ((RF_cmdIeeeCaaReq.ccaInfo.ccaEnergy == 1) && - (RF_cmdIeeeCaaReq.ccaInfo.ccaCorr == 1) && - (RF_cmdIeeeCaaReq.ccaInfo.ccaSync == 1)) { - PRINTF("receiving_packet: we were TXing\n"); - return 0; - } - - // We are on and not in TX, then we are in RX if a CCA sync has been seen, - // i.e. ccaSync is busy (1) - return (RF_cmdIeeeCaaReq.ccaInfo.ccaSync == 1); + // We are in RX if a CCA sync has been seen, i.e. ccaSync is busy (1) + return (cca_req.ccaInfo.ccaSync == CCA_STATE_BUSY); } /*---------------------------------------------------------------------------*/ static int @@ -853,8 +876,8 @@ off(void) // Reset RX buffers if there was an ongoing RX size_t i; - for (i = 0; i < RX_BUF_ENTRIES; ++i) { - rfc_dataEntry_t *entry = &(g_rxBufs[i].dataEntry); + for (i = 0; i < RX_BUF_CNT; ++i) { + data_entry_t *entry = &rx_bufs[i].data_entry; if (entry->status == DATA_ENTRY_BUSY) { entry->status = DATA_ENTRY_PENDING; } diff --git a/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c b/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c index c1642a2ba..0eb08470f 100644 --- a/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c +++ b/arch/cpu/cc13xx-cc26xx/dev/rf-prop-mode.c @@ -111,9 +111,9 @@ * Values of the individual bits of the ccaInfo field in CMD_IEEE_CCA_REQ's * status struct */ -#define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 /* 00 */ -#define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 /* 01 */ -#define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 10 */ +#define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 /* 0b00 */ +#define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 /* 0b01 */ +#define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 0b10 */ #ifdef PROP_MODE_CONF_RSSI_THRESHOLD # define PROP_MODE_RSSI_THRESHOLD PROP_MODE_CONF_RSSI_THRESHOLD @@ -147,6 +147,9 @@ /*---------------------------------------------------------------------------*/ /* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */ #define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10) + +/* How long to wait for the rx read entry to become ready */ +#define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 250) /*---------------------------------------------------------------------------*/ /* Configuration for TX power table */ #ifdef PROP_MODE_CONF_TX_POWER_TABLE @@ -178,9 +181,15 @@ #define RX_BUF_SIZE 140 /*---------------------------------------------------------------------------*/ -#define DATA_ENTRY_LENSZ_NONE 0 -#define DATA_ENTRY_LENSZ_BYTE 1 +#define DATA_ENTRY_LENSZ_NONE 0 /* 0 bytes */ +#define DATA_ENTRY_LENSZ_BYTE 1 /* 1 byte */ #define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */ + +#define DATA_ENTRY_LENSZ DATA_ENTRY_LENSZ_WORD +typedef uint16_t lensz_t; + +#define FRAME_OFFSET DATA_ENTRY_LENSZ +#define FRAME_SHAVE 2 /* RSSI (1) + Status (1) */ /*---------------------------------------------------------------------------*/ #define MAC_RADIO_RECEIVER_SENSITIVITY_DBM -110 #define MAC_RADIO_RECEIVER_SATURATION_DBM 10 @@ -190,18 +199,25 @@ #define ED_RF_POWER_MIN_DBM (MAC_RADIO_RECEIVER_SENSITIVITY_DBM + MAC_SPEC_ED_MIN_DBM_ABOVE_RECEIVER_SENSITIVITY) #define ED_RF_POWER_MAX_DBM MAC_RADIO_RECEIVER_SATURATION_DBM /*---------------------------------------------------------------------------*/ +typedef rfc_dataEntryGeneral_t data_entry_t; + +typedef union { + data_entry_t data_entry; + uint8_t buf[RX_BUF_SIZE]; +} rx_buf_t CC_ALIGN(4); + typedef struct { /* Outgoing frame buffer */ uint8_t tx_buf[TX_BUF_SIZE] CC_ALIGN(4); /* Incoming frame buffer */ - uint8_t rx_buf[RX_BUF_CNT][RX_BUF_SIZE] CC_ALIGN(4); + rx_buf_t rx_bufs[RX_BUF_CNT]; /* RX Data Queue */ dataQueue_t rx_data_queue; /* RX Statistics struct */ rfc_propRxOutput_t rx_stats; /* Receive entry pointer to keep track of read items */ - volatile uint8_t* rx_read_entry; + data_entry_t* rx_read_entry; /* RSSI Threshold */ int8_t rssi_threshold; @@ -267,14 +283,12 @@ static cmd_result_t stop_rx(void) { /* Abort any ongoing operation. Don't care about the result. */ - RF_cancelCmd(prop_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, 1); + RF_cancelCmd(prop_radio.rf_handle, RF_CMDHANDLE_FLUSH_ALL, RF_ABORT_GRACEFULLY); - /* Todo: maybe do a RF_pendCmd() to synchronize with command execution. */ - - if(cmd_rx.status != PROP_DONE_STOPPED && - cmd_rx.status != PROP_DONE_ABORT) { - PRINTF("RF_cmdPropRxAdv cancel: status=0x%04x\n", - cmd_rx.status); + if (cmd_rx.status != PROP_DONE_STOPPED && + cmd_rx.status != PROP_DONE_ABORT) { + PRINTF("RF_cmdPropRxAdv cancel: status=0x%04x\n", + cmd_rx.status); return CMD_RESULT_ERROR; } @@ -286,12 +300,13 @@ stop_rx(void) static cmd_result_t rf_run_setup() { - RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_radio_setup, RF_PriorityNormal, NULL, 0); - if (cmd_radio_setup.status != PROP_DONE_OK) { - return CMD_RESULT_ERROR; - } + // TODO not the right way to do this. + RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_radio_setup, RF_PriorityNormal, NULL, 0); + if (cmd_radio_setup.status != PROP_DONE_OK) { + return CMD_RESULT_ERROR; + } - return CMD_RESULT_OK; + return CMD_RESULT_OK; } /*---------------------------------------------------------------------------*/ static radio_value_t @@ -413,19 +428,19 @@ static void init_rx_buffers(void) { size_t i = 0; - for (i = 0; i < RX_BUF_CNT; i++) { - const rfc_dataEntry_t data_entry = { + for (i = 0; i < RX_BUF_CNT; ++i) { + const data_entry_t data_entry = { .status = DATA_ENTRY_PENDING, .config.type = DATA_ENTRY_TYPE_GEN, - .config.lenSz = DATA_ENTRY_LENSZ_WORD, - .length = RX_BUF_SIZE - sizeof(rfc_dataEntry_t), /* TODO is this sizeof sound? */ + .config.lenSz = DATA_ENTRY_LENSZ, + .length = RX_BUF_SIZE - sizeof(data_entry_t), /* TODO: is this sizeof sound? */ /* Point to fist entry if this is last entry, else point to next entry */ .pNextEntry = (i == (RX_BUF_CNT - 1)) - ? prop_radio.rx_buf[0] - : prop_radio.rx_buf[i] + ? prop_radio.rx_bufs[0].buf + : prop_radio.rx_bufs[i].buf }; /* Write back data entry struct */ - *(rfc_dataEntry_t *)prop_radio.rx_buf[i] = data_entry; + prop_radio.rx_bufs[i].data_entry = data_entry; } } /*---------------------------------------------------------------------------*/ @@ -441,62 +456,54 @@ prepare(const void *payload, unsigned short payload_len) static int transmit(unsigned short transmit_len) { - int ret; - uint8_t was_off = 0; + int ret = RADIO_TX_OK; if (tx_active()) { PRINTF("transmit: not allowed while transmitting\n"); return RADIO_TX_ERR; - } else if (rx_active()) { + } + + const bool rx_is_on = rx_active(); + if (rx_is_on) { stop_rx(); - } else { - was_off = 1; } /* Length in .15.4g PHY HDR. Includes the CRC but not the HDR itself */ - uint16_t total_length; - - /* - * Prepare the .15.4g PHY header - * MS=0, Length MSBits=0, DW and CRC configurable - * Total length = transmit_len (payload) + CRC length - * - * The Radio will flip the bits around, so tx_buf[0] must have the length - * LSBs (PHR[15:8] and tx_buf[1] will have PHR[7:0] - */ - total_length = transmit_len + CRC_LEN; - + uint16_t total_length = transmit_len + CRC_LEN; + /* Prepare the .15.4g PHY header + * MS=0, Length MSBits=0, DW and CRC configurable + * Total length = transmit_len (payload) + CRC length + * + * The Radio will flip the bits around, so tx_buf[0] must have the length + * LSBs (PHR[15:8] and tx_buf[1] will have PHR[7:0] */ prop_radio.tx_buf[0] = total_length & 0xFF; prop_radio.tx_buf[1] = (total_length >> 8) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT; - /* - * pktLen: Total number of bytes in the TX buffer, including the header if - * one exists, but not including the CRC (which is not present in the buffer) - */ + /* pktLen: Total number of bytes in the TX buffer, including the header if + * one exists, but not including the CRC (which is not present in the buffer) */ cmd_tx.pktLen = transmit_len + DOT_4G_PHR_LEN; cmd_tx.pPkt = prop_radio.tx_buf; - // TODO: Register callback - RF_runCmd(prop_radio.rf_handle, (RF_Op*)&cmd_tx, RF_PriorityNormal, NULL, 0); -// if (txHandle == RF_ALLOC_ERROR) -// { -// /* Failure sending the CMD_PROP_TX command */ -// PRINTF("transmit: PROP_TX_ERR ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", -// ret, cmd_status, cmd_tx_adv->status); -// return RADIO_TX_ERR; -// } -// -// ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); -// -// // watchdog_periodic(); -// -// /* Idle away while the command is running */ -// RF_pendCmd(rf_handle, txHandle, RF_EventLastCmdDone); + RF_CmdHandle tx_handle = RF_postCmd(prop_radio.rf_handle, (RF_Op*)&cmd_tx, RF_PriorityNormal, NULL, 0); + if (tx_handle == RF_ALLOC_ERROR) { + /* Failure sending the CMD_PROP_TX command */ + PRINTF("transmit: unable to allocate RF command handle\n"); + return RADIO_TX_ERR; + } - if(cmd_tx.status == PROP_DONE_OK) { - /* Sent OK */ - ret = RADIO_TX_OK; - } else { + ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); + + // watchdog_periodic(); + + /* Idle away while the command is running */ + RF_EventMask rf_events = RF_pendCmd(prop_radio.rf_handle, tx_handle, RF_EventLastCmdDone); + + if ((rf_events & (RF_EventCmdDone | RF_EventLastCmdDone)) == 0) { + PRINTF("transmit: RF_pendCmd failed, events=0x%llx\n", rf_events); + ret = RADIO_TX_ERR; + } + + else if (cmd_tx.status != PROP_DONE_OK) { /* Operation completed, but frame was not sent */ PRINTF("transmit: Not Sent OK status=0x%04x\n", cmd_tx.status); @@ -508,9 +515,7 @@ transmit(unsigned short transmit_len) /* Workaround. Set status to IDLE */ cmd_tx.status = IDLE; - if (was_off) { - RF_yield(prop_radio.rf_handle); - } else { + if (rx_is_on) { start_rx(); } @@ -524,42 +529,82 @@ send(const void *payload, unsigned short payload_len) return transmit(payload_len); } /*---------------------------------------------------------------------------*/ +static void +release_data_entry(void) +{ + data_entry_t *const data_entry = prop_radio.rx_read_entry; + uint8_t *const frame_ptr = (uint8_t*)&data_entry->data; + + // Clear the Length byte(s) and set status to 0: "Pending" + *(lensz_t*)frame_ptr = 0; + data_entry->status = DATA_ENTRY_PENDING; + prop_radio.rx_read_entry = (data_entry_t*)data_entry->pNextEntry; +} +/*---------------------------------------------------------------------------*/ static int read(void *buf, unsigned short buf_len) { - rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)prop_radio.rx_read_entry; - uint8_t *data_ptr = &entry->data; - uint16_t len = 0; + volatile data_entry_t *data_entry = prop_radio.rx_read_entry; - if (entry->status != DATA_ENTRY_FINISHED) { + const rtimer_clock_t t0 = RTIMER_NOW(); + // Only wait if the Radio timer is accessing the entry + while ((data_entry->status == DATA_ENTRY_BUSY) && + RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY)); + + if (data_entry->status != DATA_ENTRY_FINISHED) { + // No available data return 0; } /* First 2 bytes in the data entry are the length. - * Our data entry consists of: Payload + RSSI (1 byte) + Status (1 byte) - * This length includes all of those. */ - len = *(uint16_t *)data_ptr; - data_ptr += 2; - len -= 2; + * Data frame is on the following format: + * Length (2) + Payload (N) + RSSI (1) + Status (1) + * Data frame DOES NOT contain the following: + * no Header/PHY bytes + * no appended Received CRC bytes + * no Timestamp bytes + * +---------+---------+--------+--------+ + * | 2 bytes | N bytes | 1 byte | 1 byte | + * +---------+---------+--------+--------+ + * | Length | Payload | RSSI | Status | + * +---------+---------+--------+--------+ + * Length bytes equal total length of entire frame excluding itself, + * i.e.: Length = N + RSSI (1) + Status (1) + * = N + 2 + * N = Length - 2 */ - const bool len_ok = (0 < len) && (len <= (uint16_t)buf_len); - if (len_ok) { - memcpy(buf, data_ptr, len); + uint8_t *const frame_ptr = (uint8_t*)&data_entry->data; + const lensz_t frame_len = *(lensz_t*)frame_ptr; - int8_t rssi = (int8_t)data_ptr[len]; - uint8_t lqi = calculate_lqi(rssi); - - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)rssi); - packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)lqi); + /* Sanity check that Frame is at least Frame Shave bytes long */ + if (frame_len < FRAME_SHAVE) { + PRINTF("read: frame too short len=%d\n", frame_len); + release_data_entry(); + return 0; } - /* Move read entry pointer to next entry */ - prop_radio.rx_read_entry = entry->pNextEntry; - entry->status = DATA_ENTRY_PENDING; + const uint8_t *payload_ptr = frame_ptr + sizeof(lensz_t); + const unsigned short payload_len = (unsigned short)(frame_len - FRAME_SHAVE); - return (len_ok) - ? (int)len - : 0; + /* Sanity check that Payload fits in Buffer */ + if (payload_len > buf_len) { + PRINTF("read: payload too large for buffer len=%d buf_len=%d\n", payload_len, buf_len); + release_data_entry(); + return 0; + } + + memcpy(buf, payload_ptr, payload_len); + + /* RSSI stored after payload */ + const int8_t rssi = (int8_t)payload_ptr[payload_len]; + /* LQI calculated from RSSI */ + const uint8_t lqi = calculate_lqi(rssi); + + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, (packetbuf_attr_t)rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, (packetbuf_attr_t)lqi); + + release_data_entry(); + return (int)payload_len; } /*---------------------------------------------------------------------------*/ static int @@ -595,11 +640,11 @@ static int receiving_packet(void) { if (!rx_active()) { - return 0; + return 0; } if (channel_clear() == RF_CCA_CLEAR) { - return 0; + return 0; } return 1; @@ -636,12 +681,11 @@ static int on(void) { if (prop_radio.rf_is_on) { - PRINTF("RF on: Radio already in RX\n"); + PRINTF("on: Radio already on\n"); return CMD_RESULT_OK; } /* Reset all RF command statuses */ - cmd_radio_setup.status = IDLE; cmd_fs.status = IDLE; cmd_tx.status = IDLE; cmd_rx.status = IDLE; @@ -662,6 +706,7 @@ static int off(void) { if (!prop_radio.rf_is_on) { + PRINTF("off: Radio already off\n"); return CMD_RESULT_OK; } @@ -672,11 +717,19 @@ off(void) RF_yield(prop_radio.rf_handle); /* We pulled the plug, so we need to restore the status manually */ - cmd_radio_setup.status = IDLE; cmd_fs.status = IDLE; cmd_tx.status = IDLE; cmd_rx.status = IDLE; + // Reset RX buffers if there was an ongoing RX + size_t i; + for (i = 0; i < RX_BUF_CNT; ++i) { + data_entry_t *entry = &prop_radio.rx_bufs[i].data_entry; + if (entry->status == DATA_ENTRY_BUSY) { + entry->status = DATA_ENTRY_PENDING; + } + } + prop_radio.rf_is_on = false; return CMD_RESULT_OK; } @@ -783,6 +836,7 @@ set_value(radio_param_t param, radio_value_t value) /* If we reach here we had no errors. Apply new settings */ if (rx_active()) { stop_rx(); + // TODO fix this if (rf_run_setup() != CMD_RESULT_OK) { return RADIO_RESULT_ERROR; } @@ -803,28 +857,28 @@ set_value(radio_param_t param, radio_value_t value) static radio_result_t get_object(radio_param_t param, void *dest, size_t size) { - return RADIO_RESULT_NOT_SUPPORTED; + return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ static radio_result_t set_object(radio_param_t param, const void *src, size_t size) { - return RADIO_RESULT_NOT_SUPPORTED; + return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ static int init(void) { /* Zero initalize TX and RX buffers */ - memset(prop_radio.tx_buf, 0x0, sizeof(prop_radio.tx_buf)); - memset(prop_radio.rx_buf, 0x0, sizeof(prop_radio.rx_buf)); + memset(prop_radio.tx_buf, 0x0, sizeof(prop_radio.tx_buf)); + memset(prop_radio.rx_bufs, 0x0, sizeof(prop_radio.rx_bufs)); /* Circular buffer, no last entry */ - prop_radio.rx_data_queue.pCurrEntry = prop_radio.rx_buf[0]; + prop_radio.rx_data_queue.pCurrEntry = prop_radio.rx_bufs[0].buf; prop_radio.rx_data_queue.pLastEntry = NULL; /* Initialize current read pointer to first element (used in ISR) */ - prop_radio.rx_read_entry = prop_radio.rx_buf[0]; + prop_radio.rx_read_entry = &prop_radio.rx_bufs[0].data_entry; /* Set configured RSSI threshold */ prop_radio.rssi_threshold = PROP_MODE_RSSI_THRESHOLD; diff --git a/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx b/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx index c7287da4b..f0a866f24 100644 --- a/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx +++ b/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx @@ -6,7 +6,7 @@ BOARD_PLATFORMS = launchpad sensortag srf06 # Assigned lazily to avoid breaking environments which doesn't have cd and find -BOARDS = $(foreach BOARD_TYPE, $(BOARD_PLATFORMS), \ +BOARDS := $(foreach BOARD_TYPE, $(BOARD_PLATFORMS), \ $(shell cd $(FAMILY_PATH); find $(BOARD_TYPE)/* -type d -print)) BOARD_EXISTS := $(shell [ -d "$(FAMILY_PATH)/$(BOARD)" ]; echo $$?) diff --git a/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h index afb69933b..bd5cbb195 100644 --- a/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h +++ b/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h @@ -52,7 +52,7 @@ * @{ */ #ifndef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN -#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 1 +#define BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN 0 #endif /* diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/button-sensor-arch.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/button-sensor-arch.c index efc24a7c2..6950b16f1 100644 --- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/button-sensor-arch.c +++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/button-sensor-arch.c @@ -84,7 +84,7 @@ static PIN_Handle pin_handle; static void button_press_cb(PIN_Handle handle, PIN_Id pin_id) { -#ifdef BUTTON_SENSOR_ENABLE_SHUTDOWN +#if BUTTON_SENSOR_ENABLE_SHUTDOWN if (pin_id == BTN2_PIN) { Power_shutdown(Power_ENTERING_SHUTDOWN, 0); return;