cc26xx: implement poll mode, hardware timestamps, and other minor changes in the IEEE radio driver
This commit is contained in:
parent
3ff8aa8ad8
commit
ac6f8008fd
4 changed files with 328 additions and 72 deletions
|
@ -51,6 +51,7 @@
|
||||||
#include "sys/energest.h"
|
#include "sys/energest.h"
|
||||||
#include "sys/clock.h"
|
#include "sys/clock.h"
|
||||||
#include "sys/rtimer.h"
|
#include "sys/rtimer.h"
|
||||||
|
#include "sys/ctimer.h"
|
||||||
#include "sys/cc.h"
|
#include "sys/cc.h"
|
||||||
#include "lpm.h"
|
#include "lpm.h"
|
||||||
#include "ti-lib.h"
|
#include "ti-lib.h"
|
||||||
|
@ -102,6 +103,9 @@
|
||||||
#define IEEE_MODE_RSSI_THRESHOLD 0xA6
|
#define IEEE_MODE_RSSI_THRESHOLD 0xA6
|
||||||
#endif /* IEEE_MODE_CONF_RSSI_THRESHOLD */
|
#endif /* IEEE_MODE_CONF_RSSI_THRESHOLD */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#define STATUS_CRC_OK 0x80
|
||||||
|
#define STATUS_CORRELATION 0x7f
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Data entry status field constants */
|
/* Data entry status field constants */
|
||||||
#define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */
|
#define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */
|
||||||
#define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */
|
#define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */
|
||||||
|
@ -186,6 +190,35 @@ static const output_config_t output_power[] = {
|
||||||
/* Default TX Power - position in output_power[] */
|
/* Default TX Power - position in output_power[] */
|
||||||
const output_config_t *tx_power_current = &output_power[0];
|
const output_config_t *tx_power_current = &output_power[0];
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static volatile int8_t last_rssi = 0;
|
||||||
|
static volatile uint8_t last_corr_lqi = 0;
|
||||||
|
|
||||||
|
extern int32_t rat_offset;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* SFD timestamp in RTIMER ticks */
|
||||||
|
static volatile uint32_t last_packet_timestamp = 0;
|
||||||
|
/* SFD timestamp in RAT ticks (but 64 bits) */
|
||||||
|
static uint64_t last_rat_timestamp64 = 0;
|
||||||
|
|
||||||
|
/* For RAT overflow handling */
|
||||||
|
static struct ctimer rat_overflow_timer;
|
||||||
|
static uint32_t rat_overflow_counter = 0;
|
||||||
|
static rtimer_clock_t last_rat_overflow = 0;
|
||||||
|
|
||||||
|
/* RAT has 32-bit register, overflows once 18 minutes */
|
||||||
|
#define RAT_RANGE 4294967296ull
|
||||||
|
/* approximate value */
|
||||||
|
#define RAT_OVERFLOW_PERIOD_SECONDS (60 * 18)
|
||||||
|
|
||||||
|
/* XXX: don't know what exactly is this, looks like the time to Tx 3 octets */
|
||||||
|
#define TIMESTAMP_OFFSET -(USEC_TO_RADIO(32 * 3) - 1) /* -95.75 usec */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Are we currently in poll mode? */
|
||||||
|
static uint8_t poll_mode = 0;
|
||||||
|
|
||||||
|
static rfc_CMD_IEEE_MOD_FILT_t filter_cmd;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
* Buffers used to send commands to the RF core (generic and IEEE commands).
|
* Buffers used to send commands to the RF core (generic and IEEE commands).
|
||||||
* Some of those buffers are re-usable, some are not.
|
* Some of those buffers are re-usable, some are not.
|
||||||
|
@ -202,7 +235,7 @@ static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN(4);
|
||||||
#define DATA_ENTRY_LENSZ_BYTE 1
|
#define DATA_ENTRY_LENSZ_BYTE 1
|
||||||
#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
|
#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */
|
||||||
|
|
||||||
#define RX_BUF_SIZE 140
|
#define RX_BUF_SIZE 144
|
||||||
/* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */
|
/* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */
|
||||||
static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4);
|
static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4);
|
||||||
static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4);
|
static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4);
|
||||||
|
@ -544,7 +577,7 @@ init_rf_params(void)
|
||||||
cmd->rxConfig.bAppendRssi = 1;
|
cmd->rxConfig.bAppendRssi = 1;
|
||||||
cmd->rxConfig.bAppendCorrCrc = 1;
|
cmd->rxConfig.bAppendCorrCrc = 1;
|
||||||
cmd->rxConfig.bAppendSrcInd = 0;
|
cmd->rxConfig.bAppendSrcInd = 0;
|
||||||
cmd->rxConfig.bAppendTimestamp = 0;
|
cmd->rxConfig.bAppendTimestamp = 1;
|
||||||
|
|
||||||
cmd->pRxQ = &rx_data_queue;
|
cmd->pRxQ = &rx_data_queue;
|
||||||
cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats;
|
cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats;
|
||||||
|
@ -647,13 +680,14 @@ rx_off(void)
|
||||||
if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED ||
|
if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED ||
|
||||||
RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) {
|
RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) {
|
||||||
/* Stopped gracefully */
|
/* Stopped gracefully */
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
|
||||||
ret = RF_CORE_CMD_OK;
|
ret = RF_CORE_CMD_OK;
|
||||||
} else {
|
} else {
|
||||||
PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
|
PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf));
|
||||||
ret = RF_CORE_CMD_ERROR;
|
ret = RF_CORE_CMD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -712,6 +746,55 @@ static const rf_core_primary_mode_t mode_ieee = {
|
||||||
soft_on,
|
soft_on,
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
check_rat_overflow(bool first_time)
|
||||||
|
{
|
||||||
|
static uint32_t last_value;
|
||||||
|
uint32_t current_value;
|
||||||
|
uint8_t interrupts_enabled;
|
||||||
|
|
||||||
|
interrupts_enabled = ti_lib_int_master_disable();
|
||||||
|
if(first_time) {
|
||||||
|
last_value = HWREG(RFC_RAT_BASE + RATCNT);
|
||||||
|
} else {
|
||||||
|
current_value = HWREG(RFC_RAT_BASE + RATCNT);
|
||||||
|
if(current_value + RAT_RANGE / 4 < last_value) {
|
||||||
|
/* overflow detected */
|
||||||
|
last_rat_overflow = RTIMER_NOW();
|
||||||
|
rat_overflow_counter++;
|
||||||
|
}
|
||||||
|
last_value = current_value;
|
||||||
|
}
|
||||||
|
if(interrupts_enabled) {
|
||||||
|
ti_lib_int_master_enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static void
|
||||||
|
handle_rat_overflow(void *unused)
|
||||||
|
{
|
||||||
|
uint8_t was_off = 0;
|
||||||
|
|
||||||
|
if(!rf_is_on()) {
|
||||||
|
was_off = 1;
|
||||||
|
if(on() != RF_CORE_CMD_OK) {
|
||||||
|
PRINTF("overflow: on() failed\n");
|
||||||
|
ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2,
|
||||||
|
handle_rat_overflow, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
check_rat_overflow(false);
|
||||||
|
|
||||||
|
if(was_off) {
|
||||||
|
off();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2,
|
||||||
|
handle_rat_overflow, NULL);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
init(void)
|
init(void)
|
||||||
{
|
{
|
||||||
|
@ -745,6 +828,10 @@ init(void)
|
||||||
|
|
||||||
rf_core_primary_mode_register(&mode_ieee);
|
rf_core_primary_mode_register(&mode_ieee);
|
||||||
|
|
||||||
|
check_rat_overflow(true);
|
||||||
|
ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2,
|
||||||
|
handle_rat_overflow, NULL);
|
||||||
|
|
||||||
process_start(&rf_core_process, NULL);
|
process_start(&rf_core_process, NULL);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -768,6 +855,7 @@ transmit(unsigned short transmit_len)
|
||||||
uint8_t tx_active = 0;
|
uint8_t tx_active = 0;
|
||||||
rtimer_clock_t t0;
|
rtimer_clock_t t0;
|
||||||
volatile rfc_CMD_IEEE_TX_t cmd;
|
volatile rfc_CMD_IEEE_TX_t cmd;
|
||||||
|
uint8_t interrupts_enabled;
|
||||||
|
|
||||||
if(!rf_is_on()) {
|
if(!rf_is_on()) {
|
||||||
was_off = 1;
|
was_off = 1;
|
||||||
|
@ -805,8 +893,19 @@ transmit(unsigned short transmit_len)
|
||||||
cmd.payloadLen = transmit_len;
|
cmd.payloadLen = transmit_len;
|
||||||
cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
|
cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN];
|
||||||
|
|
||||||
|
cmd.startTime = 0;
|
||||||
|
cmd.startTrigger.triggerType = TRIG_NOW;
|
||||||
|
|
||||||
|
/* XXX: there seems to be no function that gets interrupt state w/o changing it */
|
||||||
|
interrupts_enabled = ti_lib_int_master_disable();
|
||||||
|
if(interrupts_enabled) {
|
||||||
|
ti_lib_int_master_enable();
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */
|
/* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */
|
||||||
rf_core_cmd_done_en(true);
|
if(interrupts_enabled) {
|
||||||
|
rf_core_cmd_done_en(true, poll_mode);
|
||||||
|
}
|
||||||
|
|
||||||
ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status);
|
ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status);
|
||||||
|
|
||||||
|
@ -818,7 +917,14 @@ transmit(unsigned short transmit_len)
|
||||||
/* Idle away while the command is running */
|
/* Idle away while the command is running */
|
||||||
while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS)
|
while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS)
|
||||||
== RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
|
== RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
|
||||||
lpm_sleep();
|
/* Note: for now sleeping while Tx'ing in polling mode is disabled.
|
||||||
|
* To enable it:
|
||||||
|
* 1) make the `lpm_sleep()` call here unconditional;
|
||||||
|
* 2) change the radio ISR priority to allow radio ISR to interrupt rtimer ISR.
|
||||||
|
*/
|
||||||
|
if(interrupts_enabled) {
|
||||||
|
lpm_sleep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stat = cmd.status;
|
stat = cmd.status;
|
||||||
|
@ -848,12 +954,13 @@ transmit(unsigned short transmit_len)
|
||||||
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
|
||||||
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
ENERGEST_ON(ENERGEST_TYPE_LISTEN);
|
||||||
|
|
||||||
/*
|
if(interrupts_enabled) {
|
||||||
* Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
|
/*
|
||||||
* except when we are transmitting
|
* Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
|
||||||
*/
|
* except when we are transmitting
|
||||||
rf_core_cmd_done_dis();
|
*/
|
||||||
|
rf_core_cmd_done_dis(poll_mode);
|
||||||
|
}
|
||||||
|
|
||||||
if(was_off) {
|
if(was_off) {
|
||||||
off();
|
off();
|
||||||
|
@ -880,13 +987,48 @@ release_data_entry(void)
|
||||||
/* Set status to 0 "Pending" in element */
|
/* Set status to 0 "Pending" in element */
|
||||||
entry->status = DATA_ENTRY_STATUS_PENDING;
|
entry->status = DATA_ENTRY_STATUS_PENDING;
|
||||||
rx_read_entry = entry->pNextEntry;
|
rx_read_entry = entry->pNextEntry;
|
||||||
}/*---------------------------------------------------------------------------*/
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static uint32_t
|
||||||
|
calc_last_packet_timestamp(uint32_t rat_timestamp)
|
||||||
|
{
|
||||||
|
uint64_t rat_timestamp64;
|
||||||
|
uint32_t adjusted_overflow_counter = rat_overflow_counter;
|
||||||
|
|
||||||
|
/* if the timestamp is large and the last oveflow was recently,
|
||||||
|
assume that the timestamp refers to the time before the overflow */
|
||||||
|
if(rat_timestamp > (uint32_t)(RAT_RANGE * 3 / 4)) {
|
||||||
|
if(RTIMER_CLOCK_LT(RTIMER_NOW(),
|
||||||
|
last_rat_overflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) {
|
||||||
|
adjusted_overflow_counter--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the overflowed time to the timestamp */
|
||||||
|
rat_timestamp64 = rat_timestamp + RAT_RANGE * adjusted_overflow_counter;
|
||||||
|
/* correct timestamp so that it refers to the end of the SFD */
|
||||||
|
rat_timestamp64 += TIMESTAMP_OFFSET;
|
||||||
|
|
||||||
|
last_rat_timestamp64 = rat_timestamp64 - rat_offset;
|
||||||
|
|
||||||
|
return RADIO_TO_RTIMER(rat_timestamp64 - rat_offset);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
read_frame(void *buf, unsigned short buf_len)
|
read_frame(void *buf, unsigned short buf_len)
|
||||||
{
|
{
|
||||||
int8_t rssi;
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
|
rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
|
||||||
|
uint32_t rat_timestamp;
|
||||||
|
|
||||||
|
if(rf_is_on()) {
|
||||||
|
check_rat_overflow(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for entry to become finished */
|
||||||
|
rtimer_clock_t t0 = RTIMER_NOW();
|
||||||
|
while(entry->status == DATA_ENTRY_STATUS_BUSY
|
||||||
|
&& RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 250)));
|
||||||
|
|
||||||
if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
|
if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
|
||||||
/* No available data */
|
/* No available data */
|
||||||
|
@ -901,7 +1043,7 @@ read_frame(void *buf, unsigned short buf_len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = rx_read_entry[8] - 4;
|
len = rx_read_entry[8] - 8;
|
||||||
|
|
||||||
if(len > buf_len) {
|
if(len > buf_len) {
|
||||||
PRINTF("RF: too long\n");
|
PRINTF("RF: too long\n");
|
||||||
|
@ -913,9 +1055,21 @@ read_frame(void *buf, unsigned short buf_len)
|
||||||
|
|
||||||
memcpy(buf, (char *)&rx_read_entry[9], len);
|
memcpy(buf, (char *)&rx_read_entry[9], len);
|
||||||
|
|
||||||
rssi = (int8_t)rx_read_entry[9 + len + 2];
|
last_rssi = (int8_t)rx_read_entry[9 + len + 2];
|
||||||
|
last_corr_lqi = (uint8_t)rx_read_entry[9 + len + 2] & STATUS_CORRELATION;
|
||||||
|
|
||||||
packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi);
|
/* get the timestamp */
|
||||||
|
memcpy(&rat_timestamp, (char *)rx_read_entry + 9 + len + 4, 4);
|
||||||
|
|
||||||
|
last_packet_timestamp = calc_last_packet_timestamp(rat_timestamp);
|
||||||
|
|
||||||
|
if(!poll_mode) {
|
||||||
|
/* 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, last_rssi);
|
||||||
|
packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, last_corr_lqi);
|
||||||
|
}
|
||||||
RIMESTATS_ADD(llrx);
|
RIMESTATS_ADD(llrx);
|
||||||
|
|
||||||
release_data_entry();
|
release_data_entry();
|
||||||
|
@ -983,9 +1137,7 @@ channel_clear(void)
|
||||||
static int
|
static int
|
||||||
receiving_packet(void)
|
receiving_packet(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
|
||||||
uint8_t cca_info;
|
uint8_t cca_info;
|
||||||
uint8_t was_off = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are in the middle of a BLE operation, we got called by ContikiMAC
|
* If we are in the middle of a BLE operation, we got called by ContikiMAC
|
||||||
|
@ -1035,7 +1187,9 @@ pending_packet(void)
|
||||||
do {
|
do {
|
||||||
if(entry->status == DATA_ENTRY_STATUS_FINISHED) {
|
if(entry->status == DATA_ENTRY_STATUS_FINISHED) {
|
||||||
rv = 1;
|
rv = 1;
|
||||||
process_poll(&rf_core_process);
|
if(!poll_mode) {
|
||||||
|
process_poll(&rf_core_process);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = (rfc_dataEntry_t *)entry->pNextEntry;
|
entry = (rfc_dataEntry_t *)entry->pNextEntry;
|
||||||
|
@ -1076,7 +1230,7 @@ on(void)
|
||||||
|
|
||||||
init_rx_buffers();
|
init_rx_buffers();
|
||||||
|
|
||||||
rf_core_setup_interrupts();
|
rf_core_setup_interrupts(poll_mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trigger a switch to the XOSC, so that we can subsequently use the RF FS
|
* Trigger a switch to the XOSC, so that we can subsequently use the RF FS
|
||||||
|
@ -1162,6 +1316,9 @@ get_value(radio_param_t param, radio_value_t *value)
|
||||||
if(cmd->frameFiltOpt.autoAckEn) {
|
if(cmd->frameFiltOpt.autoAckEn) {
|
||||||
*value |= RADIO_RX_MODE_AUTOACK;
|
*value |= RADIO_RX_MODE_AUTOACK;
|
||||||
}
|
}
|
||||||
|
if(poll_mode) {
|
||||||
|
*value |= RADIO_RX_MODE_POLL_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
case RADIO_PARAM_TXPOWER:
|
case RADIO_PARAM_TXPOWER:
|
||||||
|
@ -1222,6 +1379,7 @@ set_value(radio_param_t param, radio_value_t value)
|
||||||
return RADIO_RESULT_INVALID_VALUE;
|
return RADIO_RESULT_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note: this return may lead to long periods when RAT and RTC are not resynchronized */
|
||||||
if(cmd->channel == (uint8_t)value) {
|
if(cmd->channel == (uint8_t)value) {
|
||||||
/* We already have that very same channel configured.
|
/* We already have that very same channel configured.
|
||||||
* Nothing to do here. */
|
* Nothing to do here. */
|
||||||
|
@ -1239,7 +1397,7 @@ set_value(radio_param_t param, radio_value_t value)
|
||||||
case RADIO_PARAM_RX_MODE:
|
case RADIO_PARAM_RX_MODE:
|
||||||
{
|
{
|
||||||
if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
|
if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
|
||||||
RADIO_RX_MODE_AUTOACK)) {
|
RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) {
|
||||||
return RADIO_RESULT_INVALID_VALUE;
|
return RADIO_RESULT_INVALID_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1252,6 +1410,8 @@ set_value(radio_param_t param, radio_value_t value)
|
||||||
cmd->frameFiltOpt.bPendDataReqOnly = 0;
|
cmd->frameFiltOpt.bPendDataReqOnly = 0;
|
||||||
cmd->frameFiltOpt.bPanCoord = 0;
|
cmd->frameFiltOpt.bPanCoord = 0;
|
||||||
cmd->frameFiltOpt.bStrictLenFilter = 0;
|
cmd->frameFiltOpt.bStrictLenFilter = 0;
|
||||||
|
|
||||||
|
poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RADIO_PARAM_TXPOWER:
|
case RADIO_PARAM_TXPOWER:
|
||||||
|
@ -1269,30 +1429,28 @@ set_value(radio_param_t param, radio_value_t value)
|
||||||
return RADIO_RESULT_NOT_SUPPORTED;
|
return RADIO_RESULT_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we reach here we had no errors. Apply new settings */
|
/* If off, the new configuration will be applied the next time radio is started */
|
||||||
if(!rf_is_on()) {
|
if(!rf_is_on()) {
|
||||||
was_off = 1;
|
return RADIO_RESULT_OK;
|
||||||
if(on() != RF_CORE_CMD_OK) {
|
|
||||||
PRINTF("set_value: on() failed (2)\n");
|
|
||||||
return RADIO_RESULT_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we reach here we had no errors. Apply new settings */
|
||||||
if(rx_off() != RF_CORE_CMD_OK) {
|
if(rx_off() != RF_CORE_CMD_OK) {
|
||||||
PRINTF("set_value: rx_off() failed\n");
|
PRINTF("set_value: rx_off() failed\n");
|
||||||
rv = RADIO_RESULT_ERROR;
|
rv = RADIO_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Restart the radio timer (RAT).
|
||||||
|
This causes resynchronization between RAT and RTC: useful for TSCH. */
|
||||||
|
rf_core_restart_rat();
|
||||||
|
|
||||||
|
check_rat_overflow(false);
|
||||||
|
|
||||||
if(rx_on() != RF_CORE_CMD_OK) {
|
if(rx_on() != RF_CORE_CMD_OK) {
|
||||||
PRINTF("set_value: rx_on() failed\n");
|
PRINTF("set_value: rx_on() failed\n");
|
||||||
rv = RADIO_RESULT_ERROR;
|
rv = RADIO_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we were off, turn back off */
|
|
||||||
if(was_off) {
|
|
||||||
off();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -1318,13 +1476,22 @@ get_object(radio_param_t param, void *dest, size_t size)
|
||||||
|
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) {
|
||||||
|
if(size != sizeof(rtimer_clock_t) || !dest) {
|
||||||
|
return RADIO_RESULT_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
*(rtimer_clock_t *)dest = last_packet_timestamp;
|
||||||
|
|
||||||
|
return RADIO_RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
return RADIO_RESULT_NOT_SUPPORTED;
|
return RADIO_RESULT_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static radio_result_t
|
static radio_result_t
|
||||||
set_object(radio_param_t param, const void *src, size_t size)
|
set_object(radio_param_t param, const void *src, size_t size)
|
||||||
{
|
{
|
||||||
uint8_t was_off = 0;
|
|
||||||
radio_result_t rv;
|
radio_result_t rv;
|
||||||
int i;
|
int i;
|
||||||
uint8_t *dst;
|
uint8_t *dst;
|
||||||
|
@ -1341,12 +1508,9 @@ set_object(radio_param_t param, const void *src, size_t size)
|
||||||
dst[i] = ((uint8_t *)src)[7 - i];
|
dst[i] = ((uint8_t *)src)[7 - i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If off, the new configuration will be applied the next time radio is started */
|
||||||
if(!rf_is_on()) {
|
if(!rf_is_on()) {
|
||||||
was_off = 1;
|
return RADIO_RESULT_OK;
|
||||||
if(on() != RF_CORE_CMD_OK) {
|
|
||||||
PRINTF("set_object: on() failed\n");
|
|
||||||
return RADIO_RESULT_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rx_off() != RF_CORE_CMD_OK) {
|
if(rx_off() != RF_CORE_CMD_OK) {
|
||||||
|
@ -1359,11 +1523,6 @@ set_object(radio_param_t param, const void *src, size_t size)
|
||||||
rv = RADIO_RESULT_ERROR;
|
rv = RADIO_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we were off, turn back off */
|
|
||||||
if(was_off) {
|
|
||||||
off();
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
return RADIO_RESULT_NOT_SUPPORTED;
|
return RADIO_RESULT_NOT_SUPPORTED;
|
||||||
|
|
|
@ -683,7 +683,7 @@ transmit(unsigned short transmit_len)
|
||||||
rx_off_prop();
|
rx_off_prop();
|
||||||
|
|
||||||
/* Enable the LAST_COMMAND_DONE interrupt to wake us up */
|
/* Enable the LAST_COMMAND_DONE interrupt to wake us up */
|
||||||
rf_core_cmd_done_en(false);
|
rf_core_cmd_done_en(false, false);
|
||||||
|
|
||||||
ret = rf_core_send_cmd((uint32_t)cmd_tx_adv, &cmd_status);
|
ret = rf_core_send_cmd((uint32_t)cmd_tx_adv, &cmd_status);
|
||||||
|
|
||||||
|
@ -728,7 +728,7 @@ transmit(unsigned short transmit_len)
|
||||||
* Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
|
* Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it
|
||||||
* except when we are transmitting
|
* except when we are transmitting
|
||||||
*/
|
*/
|
||||||
rf_core_cmd_done_dis();
|
rf_core_cmd_done_dis(false);
|
||||||
|
|
||||||
/* Workaround. Set status to IDLE */
|
/* Workaround. Set status to IDLE */
|
||||||
cmd_tx_adv->status = RF_CORE_RADIO_OP_STATUS_IDLE;
|
cmd_tx_adv->status = RF_CORE_RADIO_OP_STATUS_IDLE;
|
||||||
|
@ -933,7 +933,7 @@ on(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rf_core_setup_interrupts();
|
rf_core_setup_interrupts(false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Trigger a switch to the XOSC, so that we can subsequently use the RF FS
|
* Trigger a switch to the XOSC, so that we can subsequently use the RF FS
|
||||||
|
|
|
@ -92,6 +92,8 @@
|
||||||
#define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ)
|
#define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define ENABLED_IRQS_POLL_MODE (ENABLED_IRQS & ~(RX_FRAME_IRQ | ERROR_IRQ))
|
||||||
|
|
||||||
#define cc26xx_rf_cpe0_isr RFCCPE0IntHandler
|
#define cc26xx_rf_cpe0_isr RFCCPE0IntHandler
|
||||||
#define cc26xx_rf_cpe1_isr RFCCPE1IntHandler
|
#define cc26xx_rf_cpe1_isr RFCCPE1IntHandler
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -101,6 +103,10 @@ static rfc_radioOp_t *last_radio_op = NULL;
|
||||||
/* A struct holding pointers to the primary mode's abort() and restore() */
|
/* A struct holding pointers to the primary mode's abort() and restore() */
|
||||||
static const rf_core_primary_mode_t *primary_mode = NULL;
|
static const rf_core_primary_mode_t *primary_mode = NULL;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Radio timer (RAT) offset as compared to the rtimer counter (RTC) */
|
||||||
|
int32_t rat_offset = 0;
|
||||||
|
static bool rat_offset_known = false;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
PROCESS(rf_core_process, "CC13xx / CC26xx RF driver");
|
PROCESS(rf_core_process, "CC13xx / CC26xx RF driver");
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \
|
#define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \
|
||||||
|
@ -265,6 +271,66 @@ rf_core_power_up()
|
||||||
return RF_CORE_CMD_OK;
|
return RF_CORE_CMD_OK;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint8_t
|
||||||
|
rf_core_start_rat(void)
|
||||||
|
{
|
||||||
|
uint32_t cmd_status;
|
||||||
|
rfc_CMD_SYNC_START_RAT_t cmd_start;
|
||||||
|
|
||||||
|
/* Start radio timer (RAT) */
|
||||||
|
rf_core_init_radio_op((rfc_radioOp_t *)&cmd_start, sizeof(cmd_start), CMD_SYNC_START_RAT);
|
||||||
|
|
||||||
|
/* copy the value and send back */
|
||||||
|
cmd_start.rat0 = rat_offset;
|
||||||
|
|
||||||
|
if(rf_core_send_cmd((uint32_t)&cmd_start, &cmd_status) != RF_CORE_CMD_OK) {
|
||||||
|
PRINTF("rf_core_get_rat_rtc_offset: SYNC_START_RAT fail, CMDSTA=0x%08lx\n",
|
||||||
|
cmd_status);
|
||||||
|
return RF_CORE_CMD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until done (?) */
|
||||||
|
if(rf_core_wait_cmd_done(&cmd_start) != RF_CORE_CMD_OK) {
|
||||||
|
PRINTF("rf_core_cmd_ok: SYNC_START_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
|
||||||
|
cmd_status, cmd_start.status);
|
||||||
|
return RF_CORE_CMD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RF_CORE_CMD_OK;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint8_t
|
||||||
|
rf_core_stop_rat(void)
|
||||||
|
{
|
||||||
|
rfc_CMD_SYNC_STOP_RAT_t cmd_stop;
|
||||||
|
uint32_t cmd_status;
|
||||||
|
|
||||||
|
rf_core_init_radio_op((rfc_radioOp_t *)&cmd_stop, sizeof(cmd_stop), CMD_SYNC_STOP_RAT);
|
||||||
|
|
||||||
|
int ret = rf_core_send_cmd((uint32_t)&cmd_stop, &cmd_status);
|
||||||
|
if(ret != RF_CORE_CMD_OK) {
|
||||||
|
PRINTF("rf_core_get_rat_rtc_offset: SYNC_STOP_RAT fail, ret %d CMDSTA=0x%08lx\n",
|
||||||
|
ret, cmd_status);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until done */
|
||||||
|
ret = rf_core_wait_cmd_done(&cmd_stop);
|
||||||
|
if(ret != RF_CORE_CMD_OK) {
|
||||||
|
PRINTF("rf_core_cmd_ok: SYNC_STOP_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n",
|
||||||
|
cmd_status, cmd_stop.status);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!rat_offset_known) {
|
||||||
|
/* save the offset, but only if this is the first time */
|
||||||
|
rat_offset_known = true;
|
||||||
|
rat_offset = cmd_stop.rat0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RF_CORE_CMD_OK;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
rf_core_power_down()
|
rf_core_power_down()
|
||||||
{
|
{
|
||||||
|
@ -280,6 +346,8 @@ rf_core_power_down()
|
||||||
fs_powerdown();
|
fs_powerdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rf_core_stop_rat();
|
||||||
|
|
||||||
/* Shut down the RFCORE clock domain in the MCU VD */
|
/* Shut down the RFCORE clock domain in the MCU VD */
|
||||||
ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
|
ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE);
|
||||||
ti_lib_prcm_load_set();
|
ti_lib_prcm_load_set();
|
||||||
|
@ -329,22 +397,6 @@ rf_core_set_modesel()
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
uint8_t
|
uint8_t
|
||||||
rf_core_start_rat()
|
|
||||||
{
|
|
||||||
uint32_t cmd_status;
|
|
||||||
|
|
||||||
/* Start radio timer (RAT) */
|
|
||||||
if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_START_RAT), &cmd_status)
|
|
||||||
!= RF_CORE_CMD_OK) {
|
|
||||||
PRINTF("rf_core_apply_patches: START_RAT fail, CMDSTA=0x%08lx\n",
|
|
||||||
cmd_status);
|
|
||||||
return RF_CORE_CMD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RF_CORE_CMD_OK;
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
|
||||||
uint8_t
|
|
||||||
rf_core_boot()
|
rf_core_boot()
|
||||||
{
|
{
|
||||||
if(rf_core_power_up() != RF_CORE_CMD_OK) {
|
if(rf_core_power_up() != RF_CORE_CMD_OK) {
|
||||||
|
@ -366,10 +418,31 @@ rf_core_boot()
|
||||||
return RF_CORE_CMD_OK;
|
return RF_CORE_CMD_OK;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint8_t
|
||||||
|
rf_core_restart_rat(void)
|
||||||
|
{
|
||||||
|
if(rf_core_stop_rat() != RF_CORE_CMD_OK) {
|
||||||
|
PRINTF("rf_core_restart_rat: rf_core_stop_rat() failed\n");
|
||||||
|
|
||||||
|
return RF_CORE_CMD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rf_core_start_rat() != RF_CORE_CMD_OK) {
|
||||||
|
PRINTF("rf_core_restart_rat: rf_core_start_rat() failed\n");
|
||||||
|
|
||||||
|
rf_core_power_down();
|
||||||
|
|
||||||
|
return RF_CORE_CMD_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RF_CORE_CMD_OK;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
rf_core_setup_interrupts()
|
rf_core_setup_interrupts(bool poll_mode)
|
||||||
{
|
{
|
||||||
bool interrupts_disabled;
|
bool interrupts_disabled;
|
||||||
|
const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
|
||||||
|
|
||||||
/* We are already turned on by the caller, so this should not happen */
|
/* We are already turned on by the caller, so this should not happen */
|
||||||
if(!rf_core_is_accessible()) {
|
if(!rf_core_is_accessible()) {
|
||||||
|
@ -384,7 +457,7 @@ rf_core_setup_interrupts()
|
||||||
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
|
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ;
|
||||||
|
|
||||||
/* Acknowledge configured interrupts */
|
/* Acknowledge configured interrupts */
|
||||||
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS;
|
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
|
||||||
|
|
||||||
/* Clear interrupt flags, active low clear(?) */
|
/* Clear interrupt flags, active low clear(?) */
|
||||||
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
|
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0;
|
||||||
|
@ -400,18 +473,20 @@ rf_core_setup_interrupts()
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
rf_core_cmd_done_en(bool fg)
|
rf_core_cmd_done_en(bool fg, bool poll_mode)
|
||||||
{
|
{
|
||||||
uint32_t irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
|
uint32_t irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE;
|
||||||
|
const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
|
||||||
|
|
||||||
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ENABLED_IRQS;
|
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = enabled_irqs;
|
||||||
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS | irq;
|
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs | irq;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
rf_core_cmd_done_dis()
|
rf_core_cmd_done_dis(bool poll_mode)
|
||||||
{
|
{
|
||||||
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS;
|
const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS;
|
||||||
|
HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
rfc_radioOp_t *
|
rfc_radioOp_t *
|
||||||
|
|
|
@ -228,6 +228,9 @@ typedef struct rf_core_primary_mode_s {
|
||||||
#define RF_CORE_COMMAND_PROTOCOL_IEEE 0x2000
|
#define RF_CORE_COMMAND_PROTOCOL_IEEE 0x2000
|
||||||
#define RF_CORE_COMMAND_PROTOCOL_PROP 0x3000
|
#define RF_CORE_COMMAND_PROTOCOL_PROP 0x3000
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/* Radio timer register */
|
||||||
|
#define RATCNT 0x00000004
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/* Make the main driver process visible to mode drivers */
|
/* Make the main driver process visible to mode drivers */
|
||||||
PROCESS_NAME(rf_core_process);
|
PROCESS_NAME(rf_core_process);
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -310,6 +313,24 @@ uint8_t rf_core_set_modesel(void);
|
||||||
*/
|
*/
|
||||||
uint8_t rf_core_start_rat(void);
|
uint8_t rf_core_start_rat(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Stop the CM0 RAT synchronously
|
||||||
|
* \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR
|
||||||
|
*
|
||||||
|
* This function is not strictly necessary, but through calling it it's possibly
|
||||||
|
* to learn the RAT / RTC offset, which useful to get accurate radio timestamps.
|
||||||
|
*/
|
||||||
|
uint8_t rf_core_stop_rat(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Restart the CM0 RAT
|
||||||
|
* \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR
|
||||||
|
*
|
||||||
|
* This function restarts the CM0 RAT and therefore resynchornizes it with RTC.
|
||||||
|
* To achieve good timing accuracy, it should be called periodically.
|
||||||
|
*/
|
||||||
|
uint8_t rf_core_restart_rat(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Boot the RF Core
|
* \brief Boot the RF Core
|
||||||
* \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR
|
* \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR
|
||||||
|
@ -327,19 +348,20 @@ uint8_t rf_core_boot(void);
|
||||||
/**
|
/**
|
||||||
* \brief Setup RF core interrupts
|
* \brief Setup RF core interrupts
|
||||||
*/
|
*/
|
||||||
void rf_core_setup_interrupts(void);
|
void rf_core_setup_interrupts(bool poll_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Enable interrupt on command done.
|
* \brief Enable interrupt on command done.
|
||||||
* \param fg set true to enable irq on foreground command done and false for
|
* \param fg set true to enable irq on foreground command done and false for
|
||||||
* background commands or if not in ieee mode.
|
* background commands or if not in ieee mode.
|
||||||
|
* \param poll_mode true if the driver is in poll mode
|
||||||
*
|
*
|
||||||
* This is used within TX routines in order to be able to sleep the CM3 and
|
* This is used within TX routines in order to be able to sleep the CM3 and
|
||||||
* wake up after TX has finished
|
* wake up after TX has finished
|
||||||
*
|
*
|
||||||
* \sa rf_core_cmd_done_dis()
|
* \sa rf_core_cmd_done_dis()
|
||||||
*/
|
*/
|
||||||
void rf_core_cmd_done_en(bool fg);
|
void rf_core_cmd_done_en(bool fg, bool poll_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
|
* \brief Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts.
|
||||||
|
@ -348,7 +370,7 @@ void rf_core_cmd_done_en(bool fg);
|
||||||
*
|
*
|
||||||
* \sa rf_core_cmd_done_en()
|
* \sa rf_core_cmd_done_en()
|
||||||
*/
|
*/
|
||||||
void rf_core_cmd_done_dis(void);
|
void rf_core_cmd_done_dis(bool poll_mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Returns a pointer to the most recent proto-dependent Radio Op
|
* \brief Returns a pointer to the most recent proto-dependent Radio Op
|
||||||
|
|
Loading…
Add table
Reference in a new issue