Merge pull request #2138 from atiselsts/bugfix/cc26xx/limited_busywait
CC26xx IEEE mode driver fixes and robustness improvements
This commit is contained in:
commit
6d51c1a9f9
|
@ -163,6 +163,18 @@ static uint8_t rf_stats[16] = { 0 };
|
||||||
|
|
||||||
/* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */
|
/* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */
|
||||||
#define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10)
|
#define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10)
|
||||||
|
|
||||||
|
/* How long to wait for the RF to react on CMD_ABORT: around 1 msec */
|
||||||
|
#define RF_TURN_OFF_WAIT_TIMEOUT (RTIMER_SECOND >> 10)
|
||||||
|
|
||||||
|
#define LIMITED_BUSYWAIT(cond, timeout) do { \
|
||||||
|
rtimer_clock_t end_time = RTIMER_NOW() + timeout; \
|
||||||
|
while(cond) { \
|
||||||
|
if(!RTIMER_CLOCK_LT(RTIMER_NOW(), end_time)) { \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/* TX Power dBm lookup table - values from SmartRF Studio */
|
/* TX Power dBm lookup table - values from SmartRF Studio */
|
||||||
typedef struct output_config {
|
typedef struct output_config {
|
||||||
|
@ -211,7 +223,7 @@ static uint64_t last_rat_timestamp64 = 0;
|
||||||
|
|
||||||
/* For RAT overflow handling */
|
/* For RAT overflow handling */
|
||||||
static struct ctimer rat_overflow_timer;
|
static struct ctimer rat_overflow_timer;
|
||||||
static uint32_t rat_overflow_counter = 0;
|
static volatile uint32_t rat_overflow_counter = 0;
|
||||||
static rtimer_clock_t last_rat_overflow = 0;
|
static rtimer_clock_t last_rat_overflow = 0;
|
||||||
|
|
||||||
/* RAT has 32-bit register, overflows once 18 minutes */
|
/* RAT has 32-bit register, overflows once 18 minutes */
|
||||||
|
@ -516,7 +528,6 @@ static uint8_t
|
||||||
rf_cmd_ieee_rx()
|
rf_cmd_ieee_rx()
|
||||||
{
|
{
|
||||||
uint32_t cmd_status;
|
uint32_t cmd_status;
|
||||||
rtimer_clock_t t0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = rf_core_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status);
|
ret = rf_core_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status);
|
||||||
|
@ -527,10 +538,8 @@ rf_cmd_ieee_rx()
|
||||||
return RF_CORE_CMD_ERROR;
|
return RF_CORE_CMD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
t0 = RTIMER_NOW();
|
LIMITED_BUSYWAIT(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE,
|
||||||
|
ENTER_RX_WAIT_TIMEOUT);
|
||||||
while(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE &&
|
|
||||||
(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ENTER_RX_WAIT_TIMEOUT)));
|
|
||||||
|
|
||||||
/* Wait to enter RX */
|
/* Wait to enter RX */
|
||||||
if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
|
if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_CORE_RADIO_OP_STATUS_ACTIVE) {
|
||||||
|
@ -693,7 +702,7 @@ rx_off(void)
|
||||||
/* Continue nonetheless */
|
/* Continue nonetheless */
|
||||||
}
|
}
|
||||||
|
|
||||||
while(rf_is_on());
|
LIMITED_BUSYWAIT(rf_is_on(), RF_TURN_OFF_WAIT_TIMEOUT);
|
||||||
|
|
||||||
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) {
|
||||||
|
@ -744,8 +753,8 @@ soft_off(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) ==
|
LIMITED_BUSYWAIT((cmd->status & RF_CORE_RADIO_OP_MASKED_STATUS) ==
|
||||||
RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING);
|
RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING, RF_TURN_OFF_WAIT_TIMEOUT);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static uint8_t
|
static uint8_t
|
||||||
|
@ -764,20 +773,25 @@ static const rf_core_primary_mode_t mode_ieee = {
|
||||||
soft_on,
|
soft_on,
|
||||||
};
|
};
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static uint8_t
|
||||||
check_rat_overflow(bool first_time)
|
check_rat_overflow(bool first_time)
|
||||||
{
|
{
|
||||||
static uint32_t last_value;
|
static uint32_t last_value;
|
||||||
uint32_t current_value;
|
uint32_t current_value;
|
||||||
uint8_t interrupts_disabled;
|
uint8_t interrupts_disabled;
|
||||||
|
|
||||||
|
/* Bail out if the RF is not on */
|
||||||
|
if(!rf_is_on()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
interrupts_disabled = ti_lib_int_master_disable();
|
interrupts_disabled = ti_lib_int_master_disable();
|
||||||
if(first_time) {
|
if(first_time) {
|
||||||
last_value = HWREG(RFC_RAT_BASE + RATCNT);
|
last_value = HWREG(RFC_RAT_BASE + RATCNT);
|
||||||
} else {
|
} else {
|
||||||
current_value = HWREG(RFC_RAT_BASE + RATCNT);
|
current_value = HWREG(RFC_RAT_BASE + RATCNT);
|
||||||
if(current_value + RAT_RANGE / 4 < last_value) {
|
if(current_value + RAT_RANGE / 4 < last_value) {
|
||||||
/* overflow detected */
|
/* Overflow detected */
|
||||||
last_rat_overflow = RTIMER_NOW();
|
last_rat_overflow = RTIMER_NOW();
|
||||||
rat_overflow_counter++;
|
rat_overflow_counter++;
|
||||||
}
|
}
|
||||||
|
@ -786,31 +800,40 @@ check_rat_overflow(bool first_time)
|
||||||
if(!interrupts_disabled) {
|
if(!interrupts_disabled) {
|
||||||
ti_lib_int_master_enable();
|
ti_lib_int_master_enable();
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
handle_rat_overflow(void *unused)
|
handle_rat_overflow(void *unused)
|
||||||
{
|
{
|
||||||
|
uint8_t success;
|
||||||
uint8_t was_off = 0;
|
uint8_t was_off = 0;
|
||||||
|
|
||||||
if(!rf_is_on()) {
|
if(!rf_is_on()) {
|
||||||
was_off = 1;
|
was_off = 1;
|
||||||
if(on() != RF_CORE_CMD_OK) {
|
if(on() != RF_CORE_CMD_OK) {
|
||||||
PRINTF("overflow: on() failed\n");
|
PRINTF("overflow: on() failed\n");
|
||||||
ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2,
|
ctimer_set(&rat_overflow_timer, CLOCK_SECOND,
|
||||||
handle_rat_overflow, NULL);
|
handle_rat_overflow, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_rat_overflow(false);
|
success = check_rat_overflow(false);
|
||||||
|
|
||||||
if(was_off) {
|
if(was_off) {
|
||||||
off();
|
off();
|
||||||
}
|
}
|
||||||
|
|
||||||
ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2,
|
if(success) {
|
||||||
handle_rat_overflow, NULL);
|
/* Retry after half of the interval */
|
||||||
|
ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2,
|
||||||
|
handle_rat_overflow, NULL);
|
||||||
|
} else {
|
||||||
|
/* Retry sooner */
|
||||||
|
ctimer_set(&rat_overflow_timer, CLOCK_SECOND,
|
||||||
|
handle_rat_overflow, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static int
|
static int
|
||||||
|
@ -1000,7 +1023,22 @@ static uint32_t
|
||||||
calc_last_packet_timestamp(uint32_t rat_timestamp)
|
calc_last_packet_timestamp(uint32_t rat_timestamp)
|
||||||
{
|
{
|
||||||
uint64_t rat_timestamp64;
|
uint64_t rat_timestamp64;
|
||||||
uint32_t adjusted_overflow_counter = rat_overflow_counter;
|
uint32_t adjusted_overflow_counter;
|
||||||
|
uint8_t was_off = 0;
|
||||||
|
|
||||||
|
if(!rf_is_on()) {
|
||||||
|
was_off = 1;
|
||||||
|
on();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rf_is_on()) {
|
||||||
|
check_rat_overflow(false);
|
||||||
|
if(was_off) {
|
||||||
|
off();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adjusted_overflow_counter = rat_overflow_counter;
|
||||||
|
|
||||||
/* if the timestamp is large and the last oveflow was recently,
|
/* if the timestamp is large and the last oveflow was recently,
|
||||||
assume that the timestamp refers to the time before the overflow */
|
assume that the timestamp refers to the time before the overflow */
|
||||||
|
@ -1028,10 +1066,6 @@ read_frame(void *buf, unsigned short buf_len)
|
||||||
rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
|
rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry;
|
||||||
uint32_t rat_timestamp;
|
uint32_t rat_timestamp;
|
||||||
|
|
||||||
if(rf_is_on()) {
|
|
||||||
check_rat_overflow(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wait for entry to become finished */
|
/* wait for entry to become finished */
|
||||||
rtimer_clock_t t0 = RTIMER_NOW();
|
rtimer_clock_t t0 = RTIMER_NOW();
|
||||||
while(entry->status == DATA_ENTRY_STATUS_BUSY
|
while(entry->status == DATA_ENTRY_STATUS_BUSY
|
||||||
|
@ -1503,9 +1537,9 @@ set_value(radio_param_t param, radio_value_t value)
|
||||||
|
|
||||||
/* Restart the radio timer (RAT).
|
/* Restart the radio timer (RAT).
|
||||||
This causes resynchronization between RAT and RTC: useful for TSCH. */
|
This causes resynchronization between RAT and RTC: useful for TSCH. */
|
||||||
rf_core_restart_rat();
|
if(rf_core_restart_rat() == RF_CORE_CMD_OK) {
|
||||||
|
check_rat_overflow(false);
|
||||||
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");
|
||||||
|
|
|
@ -419,8 +419,7 @@ rf_core_restart_rat(void)
|
||||||
{
|
{
|
||||||
if(rf_core_stop_rat() != RF_CORE_CMD_OK) {
|
if(rf_core_stop_rat() != RF_CORE_CMD_OK) {
|
||||||
PRINTF("rf_core_restart_rat: rf_core_stop_rat() failed\n");
|
PRINTF("rf_core_restart_rat: rf_core_stop_rat() failed\n");
|
||||||
|
/* Don't bail out here, still try to start it */
|
||||||
return RF_CORE_CMD_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rf_core_start_rat() != RF_CORE_CMD_OK) {
|
if(rf_core_start_rat() != RF_CORE_CMD_OK) {
|
||||||
|
|
Loading…
Reference in a new issue