Merge pull request #1550 from thomas-ha/tsch-cc2538-port
Port of TSCH for CC2538
This commit is contained in:
commit
26bf33c762
|
@ -36,6 +36,7 @@ It has been tested on the following platforms:
|
||||||
* NXP JN516x (`jn516x`, tested on hardware)
|
* NXP JN516x (`jn516x`, tested on hardware)
|
||||||
* Tmote Sky (`sky`, tested on hardware and in cooja)
|
* Tmote Sky (`sky`, tested on hardware and in cooja)
|
||||||
* Zolertia Z1 (`z1`, tested in cooja only)
|
* Zolertia Z1 (`z1`, tested in cooja only)
|
||||||
|
* CC2538DK (`cc2538dk`, tested on hardware)
|
||||||
|
|
||||||
This implementation was present at the ETSI Plugtest
|
This implementation was present at the ETSI Plugtest
|
||||||
event in Prague in July 2015, and did successfully inter-operate with all
|
event in Prague in July 2015, and did successfully inter-operate with all
|
||||||
|
@ -76,7 +77,7 @@ Orchestra is implemented in:
|
||||||
|
|
||||||
A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`.
|
A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`.
|
||||||
To use TSCH, first make sure your platform supports it.
|
To use TSCH, first make sure your platform supports it.
|
||||||
Currently, `jn516x`, `sky` and `z1` are the supported platforms.
|
Currently, `jn516x`, `sky`, `z1` and `cc2538dk` are the supported platforms.
|
||||||
To add your own, we refer the reader to the next section.
|
To add your own, we refer the reader to the next section.
|
||||||
|
|
||||||
To add TSCH to your application, first include the TSCH module from your makefile with:
|
To add TSCH to your application, first include the TSCH module from your makefile with:
|
||||||
|
@ -162,7 +163,7 @@ Finally, one can also implement his own scheduler, centralized or distributed, b
|
||||||
## Porting TSCH to a new platform
|
## Porting TSCH to a new platform
|
||||||
|
|
||||||
Porting TSCH to a new platform requires a few new features in the radio driver, a number of timing-related configuration paramters.
|
Porting TSCH to a new platform requires a few new features in the radio driver, a number of timing-related configuration paramters.
|
||||||
The easiest is probably to start from one of the existing port: `jn516x`, `sky`, `z1`.
|
The easiest is probably to start from one of the existing port: `jn516x`, `sky`, `z1`, `cc2538dk`.
|
||||||
|
|
||||||
### Radio features required for TSCH
|
### Radio features required for TSCH
|
||||||
|
|
||||||
|
|
|
@ -175,4 +175,11 @@
|
||||||
#define TSCH_ADAPTIVE_TIMESYNC 0
|
#define TSCH_ADAPTIVE_TIMESYNC 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* HW frame filtering enabled */
|
||||||
|
#ifdef TSCH_CONF_HW_FRAME_FILTERING
|
||||||
|
#define TSCH_HW_FRAME_FILTERING TSCH_CONF_HW_FRAME_FILTERING
|
||||||
|
#else /* TSCH_CONF_HW_FRAME_FILTERING */
|
||||||
|
#define TSCH_HW_FRAME_FILTERING 1
|
||||||
|
#endif /* TSCH_CONF_HW_FRAME_FILTERING */
|
||||||
|
|
||||||
#endif /* __TSCH_CONF_H__ */
|
#endif /* __TSCH_CONF_H__ */
|
||||||
|
|
|
@ -493,9 +493,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
uint8_t ack_hdrlen;
|
uint8_t ack_hdrlen;
|
||||||
frame802154_t frame;
|
frame802154_t frame;
|
||||||
|
|
||||||
|
#if TSCH_HW_FRAME_FILTERING
|
||||||
/* Entering promiscuous mode so that the radio accepts the enhanced ACK */
|
/* Entering promiscuous mode so that the radio accepts the enhanced ACK */
|
||||||
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
|
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
|
||||||
NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode & (~RADIO_RX_MODE_ADDRESS_FILTER));
|
NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode & (~RADIO_RX_MODE_ADDRESS_FILTER));
|
||||||
|
#endif /* TSCH_HW_FRAME_FILTERING */
|
||||||
/* Unicast: wait for ack after tx: sleep until ack time */
|
/* Unicast: wait for ack after tx: sleep until ack time */
|
||||||
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start,
|
TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start,
|
||||||
tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck");
|
tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck");
|
||||||
|
@ -514,9 +516,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
|
||||||
TSCH_DEBUG_TX_EVENT();
|
TSCH_DEBUG_TX_EVENT();
|
||||||
NETSTACK_RADIO.off();
|
NETSTACK_RADIO.off();
|
||||||
|
|
||||||
|
#if TSCH_HW_FRAME_FILTERING
|
||||||
/* Leaving promiscuous mode */
|
/* Leaving promiscuous mode */
|
||||||
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
|
NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode);
|
||||||
NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode | RADIO_RX_MODE_ADDRESS_FILTER);
|
NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode | RADIO_RX_MODE_ADDRESS_FILTER);
|
||||||
|
#endif /* TSCH_HW_FRAME_FILTERING */
|
||||||
|
|
||||||
/* Read ack frame */
|
/* Read ack frame */
|
||||||
ack_len = NETSTACK_RADIO.read((void *)ackbuf, sizeof(ackbuf));
|
ack_len = NETSTACK_RADIO.read((void *)ackbuf, sizeof(ackbuf));
|
||||||
|
|
|
@ -119,6 +119,25 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */
|
||||||
#else
|
#else
|
||||||
#define CC2538_RF_AUTOACK 1
|
#define CC2538_RF_AUTOACK 1
|
||||||
#endif
|
#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_flags;
|
||||||
static uint8_t rf_channel = CC2538_RF_CHANNEL;
|
static uint8_t rf_channel = CC2538_RF_CHANNEL;
|
||||||
|
@ -329,6 +348,28 @@ set_frame_filtering(uint8_t enable)
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
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)
|
set_auto_ack(uint8_t enable)
|
||||||
{
|
{
|
||||||
if(enable) {
|
if(enable) {
|
||||||
|
@ -395,7 +436,9 @@ off(void)
|
||||||
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
|
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
|
||||||
while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
|
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 */
|
/* Don't turn off if we are off as this will trigger a Strobe Error */
|
||||||
if(REG(RFCORE_XREG_RXENABLE) != 0) {
|
if(REG(RFCORE_XREG_RXENABLE) != 0) {
|
||||||
|
@ -459,10 +502,6 @@ init(void)
|
||||||
|
|
||||||
set_channel(rf_channel);
|
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 */
|
/* Acknowledge all RF Error interrupts */
|
||||||
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
|
REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM;
|
||||||
nvic_interrupt_enable(NVIC_INT_RF_ERR);
|
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);
|
udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_poll_mode(poll_mode);
|
||||||
|
|
||||||
process_start(&cc2538_rf_process, NULL);
|
process_start(&cc2538_rf_process, NULL);
|
||||||
|
|
||||||
|
@ -571,9 +612,11 @@ transmit(unsigned short transmit_len)
|
||||||
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
|
while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(channel_clear() == CC2538_RF_CCA_BUSY) {
|
if(send_on_cca) {
|
||||||
RIMESTATS_ADD(contentiondrop);
|
if(channel_clear() == CC2538_RF_CCA_BUSY) {
|
||||||
return RADIO_TX_COLLISION;
|
RIMESTATS_ADD(contentiondrop);
|
||||||
|
return RADIO_TX_COLLISION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -630,8 +673,6 @@ read(void *buf, unsigned short bufsize)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
uint8_t crc_corr;
|
|
||||||
int8_t rssi;
|
|
||||||
|
|
||||||
PRINTF("RF: Read\n");
|
PRINTF("RF: Read\n");
|
||||||
|
|
||||||
|
@ -731,14 +772,18 @@ read(void *buf, unsigned short bufsize)
|
||||||
flush();
|
flush();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
|
if(!poll_mode) {
|
||||||
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
|
/* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */
|
||||||
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
|
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) {
|
||||||
process_poll(&cc2538_rf_process);
|
if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) {
|
||||||
} else {
|
process_poll(&cc2538_rf_process);
|
||||||
CC2538_RF_CSP_ISFLUSHRX();
|
} else {
|
||||||
|
CC2538_RF_CSP_ISFLUSHRX();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CC2538_RF_CSP_ISFLUSHRX();
|
||||||
|
|
||||||
return (len);
|
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) {
|
if(REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_AUTOACK) {
|
||||||
*value |= RADIO_RX_MODE_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;
|
return RADIO_RESULT_OK;
|
||||||
case RADIO_PARAM_TXPOWER:
|
case RADIO_PARAM_TXPOWER:
|
||||||
*value = get_tx_power();
|
*value = get_tx_power();
|
||||||
|
@ -806,6 +860,12 @@ get_value(radio_param_t param, radio_value_t *value)
|
||||||
case RADIO_PARAM_RSSI:
|
case RADIO_PARAM_RSSI:
|
||||||
*value = get_rssi();
|
*value = get_rssi();
|
||||||
return RADIO_RESULT_OK;
|
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:
|
case RADIO_CONST_CHANNEL_MIN:
|
||||||
*value = CC2538_RF_CHANNEL_MIN;
|
*value = CC2538_RF_CHANNEL_MIN;
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
|
@ -854,13 +914,21 @@ set_value(radio_param_t param, radio_value_t value)
|
||||||
return RADIO_RESULT_OK;
|
return RADIO_RESULT_OK;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
|
set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0);
|
||||||
set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 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;
|
return RADIO_RESULT_OK;
|
||||||
case RADIO_PARAM_TXPOWER:
|
case RADIO_PARAM_TXPOWER:
|
||||||
if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) {
|
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;
|
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;
|
return RADIO_RESULT_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -950,15 +1027,18 @@ PROCESS_THREAD(cc2538_rf_process, ev, data)
|
||||||
PROCESS_BEGIN();
|
PROCESS_BEGIN();
|
||||||
|
|
||||||
while(1) {
|
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();
|
if(!poll_mode) {
|
||||||
len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
packetbuf_clear();
|
||||||
|
len = read(packetbuf_dataptr(), PACKETBUF_SIZE);
|
||||||
|
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
packetbuf_set_datalen(len);
|
packetbuf_set_datalen(len);
|
||||||
|
|
||||||
NETSTACK_RDC.input();
|
NETSTACK_RDC.input();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we were polled due to an RF error, reset the transceiver */
|
/* If we were polled due to an RF error, reset the transceiver */
|
||||||
|
@ -995,8 +1075,10 @@ void
|
||||||
cc2538_rf_rx_tx_isr(void)
|
cc2538_rf_rx_tx_isr(void)
|
||||||
{
|
{
|
||||||
ENERGEST_ON(ENERGEST_TYPE_IRQ);
|
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 */
|
/* We only acknowledge FIFOP so we can safely wipe out the entire SFR */
|
||||||
REG(RFCORE_SFR_RFIRQF0) = 0;
|
REG(RFCORE_SFR_RFIRQF0) = 0;
|
||||||
|
@ -1045,4 +1127,44 @@ cc2538_rf_set_promiscous_mode(char p)
|
||||||
set_frame_filtering(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));
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -65,6 +65,20 @@
|
||||||
|
|
||||||
#define RTIMER_ARCH_SECOND 32768
|
#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() */
|
/** \sa RTIMER_NOW() */
|
||||||
rtimer_clock_t rtimer_arch_now(void);
|
rtimer_clock_t rtimer_arch_now(void);
|
||||||
|
|
||||||
|
|
|
@ -67,13 +67,19 @@
|
||||||
#define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network
|
#define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network
|
||||||
#define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network
|
#define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network
|
||||||
|
|
||||||
|
/* Needed for CC2538 platforms only */
|
||||||
|
/* For TSCH we have to use the more accurate crystal oscillator
|
||||||
|
* by default the RC oscillator is activated */
|
||||||
|
#undef SYS_CTRL_CONF_OSC32K_USE_XTAL
|
||||||
|
#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1
|
||||||
|
|
||||||
/* Needed for cc2420 platforms only */
|
/* Needed for cc2420 platforms only */
|
||||||
/* Disable DCO calibration (uses timerB) */
|
/* Disable DCO calibration (uses timerB) */
|
||||||
#undef DCOSYNCH_CONF_ENABLED
|
#undef DCOSYNCH_CONF_ENABLED
|
||||||
#define DCOSYNCH_CONF_ENABLED 0
|
#define DCOSYNCH_CONF_ENABLED 0
|
||||||
/* Enable SFD timestamps (uses timerB) */
|
/* Enable SFD timestamps (uses timerB) */
|
||||||
#undef CC2420_CONF_SFD_TIMESTAMPS
|
#undef CC2420_CONF_SFD_TIMESTAMPS
|
||||||
#define CC2420_CONF_SFD_TIMESTAMPS 1
|
#define CC2420_CONF_SFD_TIMESTAMPS 1
|
||||||
|
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
/******************* Configure TSCH ********************/
|
/******************* Configure TSCH ********************/
|
||||||
|
|
|
@ -40,6 +40,14 @@ typedef uint32_t rtimer_clock_t;
|
||||||
#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b)))
|
#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b)))
|
||||||
/** @} */
|
/** @} */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
#define TSCH_CONF_HW_FRAME_FILTERING 0
|
||||||
|
|
||||||
|
/* 352us from calling transmit() until the SFD byte has been sent */
|
||||||
|
#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352))
|
||||||
|
/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */
|
||||||
|
#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250))
|
||||||
|
#define RADIO_DELAY_BEFORE_DETECT 0
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/**
|
/**
|
||||||
* \name Serial Boot Loader Backdoor configuration
|
* \name Serial Boot Loader Backdoor configuration
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue