Merge pull request #1550 from thomas-ha/tsch-cc2538-port

Port of TSCH for CC2538
This commit is contained in:
Simon Duquennoy 2016-06-02 21:33:55 +02:00
commit 26bf33c762
7 changed files with 191 additions and 29 deletions

View file

@ -119,6 +119,25 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */
#else
#define CC2538_RF_AUTOACK 1
#endif
/*---------------------------------------------------------------------------
* MAC timer
*---------------------------------------------------------------------------*/
/* Timer conversion */
#define RADIO_TO_RTIMER(X) ((uint32_t)((uint64_t)(X) * RTIMER_ARCH_SECOND / SYS_CTRL_32MHZ))
#define CLOCK_STABLE() do { \
while ( !(REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_XOSC_STB))); \
} while(0)
/*---------------------------------------------------------------------------*/
/* Are we currently in poll mode? Disabled by default */
static uint8_t volatile poll_mode = 0;
/* Do we perform a CCA before sending? Enabled by default. */
static uint8_t send_on_cca = 1;
static int8_t rssi;
static uint8_t crc_corr;
void mac_timer_init(void);
uint32_t get_sfd_timestamp(void);
/*---------------------------------------------------------------------------*/
static uint8_t rf_flags;
static uint8_t rf_channel = CC2538_RF_CHANNEL;
@ -329,6 +348,28 @@ set_frame_filtering(uint8_t enable)
}
/*---------------------------------------------------------------------------*/
static void
set_poll_mode(uint8_t enable)
{
poll_mode = enable;
if(enable) {
mac_timer_init();
REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_FIFOP; // mask out FIFOP interrupt source
REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_FIFOP; // clear pending FIFOP interrupt
nvic_interrupt_disable(NVIC_INT_RF_RXTX); // disable RF interrupts
} else {
REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; // enable FIFOP interrupt source
nvic_interrupt_enable(NVIC_INT_RF_RXTX); // enable RF interrupts
}
}
/*---------------------------------------------------------------------------*/
static void
set_send_on_cca(uint8_t enable)
{
send_on_cca = enable;
}
/*---------------------------------------------------------------------------*/
static void
set_auto_ack(uint8_t enable)
{
if(enable) {
@ -395,7 +436,9 @@ off(void)
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
CC2538_RF_CSP_ISFLUSHRX();
if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP)) {
CC2538_RF_CSP_ISFLUSHRX();
}
/* Don't turn off if we are off as this will trigger a Strobe Error */
if(REG(RFCORE_XREG_RXENABLE) != 0) {
@ -459,10 +502,6 @@ init(void)
set_channel(rf_channel);
/* Acknowledge RF interrupts, FIFOP only */
REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP;
nvic_interrupt_enable(NVIC_INT_RF_RXTX);
/* Acknowledge all RF Error interrupts */
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
nvic_interrupt_enable(NVIC_INT_RF_ERR);
@ -488,6 +527,8 @@ init(void)
*/
udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA);
}
set_poll_mode(poll_mode);
process_start(&cc2538_rf_process, NULL);
@ -571,9 +612,11 @@ transmit(unsigned short transmit_len)
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
}
if(channel_clear() == CC2538_RF_CCA_BUSY) {
RIMESTATS_ADD(contentiondrop);
return RADIO_TX_COLLISION;
if(send_on_cca) {
if(channel_clear() == CC2538_RF_CCA_BUSY) {
RIMESTATS_ADD(contentiondrop);
return RADIO_TX_COLLISION;
}
}
/*
@ -630,8 +673,6 @@ read(void *buf, unsigned short bufsize)
{
uint8_t i;
uint8_t len;
uint8_t crc_corr;
int8_t rssi;
PRINTF("RF: Read\n");
@ -731,14 +772,18 @@ read(void *buf, unsigned short bufsize)
flush();
#endif
/* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
process_poll(&cc2538_rf_process);
} else {
CC2538_RF_CSP_ISFLUSHRX();
if(!poll_mode) {
/* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
process_poll(&cc2538_rf_process);
} else {
CC2538_RF_CSP_ISFLUSHRX();
}
}
}
CC2538_RF_CSP_ISFLUSHRX();
return (len);
}
@ -796,6 +841,15 @@ get_value(radio_param_t param, radio_value_t *value)
if(REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_AUTOACK) {
*value |= RADIO_RX_MODE_AUTOACK;
}
if(poll_mode) {
*value |= RADIO_RX_MODE_POLL_MODE;
}
return RADIO_RESULT_OK;
case RADIO_PARAM_TX_MODE:
*value = 0;
if(send_on_cca) {
*value |= RADIO_TX_MODE_SEND_ON_CCA;
}
return RADIO_RESULT_OK;
case RADIO_PARAM_TXPOWER:
*value = get_tx_power();
@ -806,6 +860,12 @@ get_value(radio_param_t param, radio_value_t *value)
case RADIO_PARAM_RSSI:
*value = get_rssi();
return RADIO_RESULT_OK;
case RADIO_PARAM_LAST_RSSI:
*value = rssi;
return RADIO_RESULT_OK;
case RADIO_PARAM_LAST_LINK_QUALITY:
*value = crc_corr & LQI_BIT_MASK;
return RADIO_RESULT_OK;
case RADIO_CONST_CHANNEL_MIN:
*value = CC2538_RF_CHANNEL_MIN;
return RADIO_RESULT_OK;
@ -854,13 +914,21 @@ set_value(radio_param_t param, radio_value_t value)
return RADIO_RESULT_OK;
case RADIO_PARAM_RX_MODE:
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;
}
set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0);
set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0);
return RADIO_RESULT_OK;
case RADIO_PARAM_TX_MODE:
if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) {
return RADIO_RESULT_INVALID_VALUE;
}
set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0);
return RADIO_RESULT_OK;
case RADIO_PARAM_TXPOWER:
if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
@ -895,6 +963,15 @@ get_object(radio_param_t param, void *dest, size_t size)
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 = get_sfd_timestamp();
return RADIO_RESULT_OK;
}
return RADIO_RESULT_NOT_SUPPORTED;
}
/*---------------------------------------------------------------------------*/
@ -950,15 +1027,18 @@ PROCESS_THREAD(cc2538_rf_process, ev, data)
PROCESS_BEGIN();
while(1) {
PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
/* Only if we are not in poll mode oder we are in poll mode and transceiver has to be reset */
PROCESS_YIELD_UNTIL((!poll_mode || (poll_mode && (rf_flags & RF_MUST_RESET))) && (ev == PROCESS_EVENT_POLL));
packetbuf_clear();
len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
if(!poll_mode) {
packetbuf_clear();
len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
if(len > 0) {
packetbuf_set_datalen(len);
if(len > 0) {
packetbuf_set_datalen(len);
NETSTACK_RDC.input();
NETSTACK_RDC.input();
}
}
/* If we were polled due to an RF error, reset the transceiver */
@ -995,8 +1075,10 @@ void
cc2538_rf_rx_tx_isr(void)
{
ENERGEST_ON(ENERGEST_TYPE_IRQ);
process_poll(&cc2538_rf_process);
if(!poll_mode) {
process_poll(&cc2538_rf_process);
}
/* We only acknowledge FIFOP so we can safely wipe out the entire SFR */
REG(RFCORE_SFR_RFIRQF0) = 0;
@ -1045,4 +1127,44 @@ cc2538_rf_set_promiscous_mode(char p)
set_frame_filtering(p);
}
/*---------------------------------------------------------------------------*/
uint32_t get_sfd_timestamp(void)
{
uint64_t sfd, timer_val, buffer;
REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000000;
REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE;
timer_val = REG(RFCORE_SFR_MTM0) & RFCORE_SFR_MTM0_MTM0;
timer_val |= ((REG(RFCORE_SFR_MTM1) & RFCORE_SFR_MTM1_MTM1) << 8);
REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000000;
timer_val |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16);
timer_val |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24);
buffer = REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2;
timer_val |= (buffer << 32);
REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000001;
REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE;
sfd = REG(RFCORE_SFR_MTM0) & RFCORE_SFR_MTM0_MTM0;
sfd |= ((REG(RFCORE_SFR_MTM1) & RFCORE_SFR_MTM1_MTM1) << 8);
REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000010;
sfd |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16);
sfd |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24);
buffer = REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2;
sfd |= (buffer << 32);
return (RTIMER_NOW() - RADIO_TO_RTIMER(timer_val - sfd));
}
/*---------------------------------------------------------------------------*/
void mac_timer_init(void)
{
CLOCK_STABLE();
REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_SYNC;
REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_RUN;
while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE));
REG(RFCORE_SFR_MTCTRL) &= ~RFCORE_SFR_MTCTRL_RUN;
while(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE);
REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_SYNC;
REG(RFCORE_SFR_MTCTRL) |= (RFCORE_SFR_MTCTRL_RUN);
while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE));
}
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -65,6 +65,20 @@
#define RTIMER_ARCH_SECOND 32768
/* Do the math in 32bits to save precision.
* Round to nearest integer rather than truncate. */
#define US_TO_RTIMERTICKS(US) ((US) >= 0 ? \
(((int32_t)(US) * (RTIMER_ARCH_SECOND) + 500000) / 1000000L) : \
((int32_t)(US) * (RTIMER_ARCH_SECOND) - 500000) / 1000000L)
#define RTIMERTICKS_TO_US(T) ((T) >= 0 ? \
(((int32_t)(T) * 1000000L + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)) : \
((int32_t)(T) * 1000000L - ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND))
/* A 64-bit version because the 32-bit one cannot handle T >= 4295 ticks.
Intended only for positive values of T. */
#define RTIMERTICKS_TO_US_64(T) ((uint32_t)(((uint64_t)(T) * 1000000 + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)))
/** \sa RTIMER_NOW() */
rtimer_clock_t rtimer_arch_now(void);