2016-07-08 03:33:54 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 MUTEX NZ Ltd.
|
|
|
|
* Copyright (C) 2015 Loci Controls Inc.
|
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
* directory for more details.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ingroup cpu_cc2538
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Low-level radio driver for the CC2538
|
|
|
|
*
|
|
|
|
* @author Aaron Sowry <aaron@mutex.nz>
|
|
|
|
* @author Ian Martin <ian@locicontrols.com>
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "periph_conf.h"
|
|
|
|
|
|
|
|
#include "cc2538_rf.h"
|
|
|
|
|
2020-10-22 11:34:00 +02:00
|
|
|
#define ENABLE_DEBUG 0
|
2016-07-08 03:33:54 +02:00
|
|
|
#include "debug.h"
|
|
|
|
|
2020-09-25 17:12:08 +02:00
|
|
|
/**
|
2020-06-24 12:09:24 +02:00
|
|
|
* @brief MAC timer period
|
|
|
|
*
|
|
|
|
* The period is set to the CSMA-CA Backoff Period Unit (20 symbols, 320 us).
|
|
|
|
* The system clock runs at 32 MHz. Thus, the timeout period is
|
|
|
|
* 320us * 32MHz = ~10738 (0x29F2)
|
|
|
|
*/
|
|
|
|
#define TIMER_PERIOD_LSB (0xF2)
|
|
|
|
#define TIMER_PERIOD_MSB (0x29)
|
2016-09-27 15:04:39 +02:00
|
|
|
|
2020-09-25 17:12:08 +02:00
|
|
|
/**
|
|
|
|
* @brief MAC timer period
|
|
|
|
*
|
|
|
|
* The period is set to the CSMA-CA Backoff Period Unit (20 symbols, 320 us).
|
|
|
|
* The system clock runs at 32 MHz. Thus, the timeout period is
|
|
|
|
* 320us * 32MHz = ~10738 (0x29F2)
|
|
|
|
*/
|
|
|
|
#define CCTEST_OBSSELX_EN (BIT(7))
|
|
|
|
|
|
|
|
static void _cc2538_setup_mac_timer(void)
|
|
|
|
{
|
|
|
|
RFCORE_SFR_MTMSEL &= ~CC2538_SFR_MTMSEL_MASK;
|
|
|
|
/* Select timer period */
|
|
|
|
RFCORE_SFR_MTMSEL |= CC2538_SFR_MTMSEL_TIMER_P;
|
|
|
|
|
|
|
|
/* Fix timer to Backoff period */
|
|
|
|
RFCORE_SFR_MTM0 |= TIMER_PERIOD_LSB;
|
|
|
|
RFCORE_SFR_MTM1 |= TIMER_PERIOD_MSB;
|
|
|
|
|
|
|
|
RFCORE_SFR_MTMSEL &= ~CC2538_SFR_MTMSEL_MASK;
|
|
|
|
RFCORE_SFR_MTCTRL |= CC2538_MCTRL_SYNC_MASK | CC2538_MCTRL_RUN_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _cc2538_observable_signals(void)
|
|
|
|
{
|
|
|
|
/* Select on which pin PC0:7 should the selected observable signals
|
|
|
|
be wired through, the signal is selected in CONFIG_CC2538_RF_OBS_%
|
|
|
|
and the pin in CONFIG_CC2538_RF_OBS_SIG_%_PCX */
|
|
|
|
if (IS_USED(MODULE_CC2538_RF_OBS_SIG)) {
|
|
|
|
if (CONFIG_CC2538_RF_OBS_0 != disabled) {
|
|
|
|
RFCORE_XREG_RFC_OBS_CTRL0 = CONFIG_CC2538_RF_OBS_0;
|
|
|
|
*(&CCTEST_OBSSEL0 + CONFIG_CC2538_RF_OBS_SIG_0_PCX) = \
|
|
|
|
CCTEST_OBSSELX_EN | rfc_obs_sig0;
|
|
|
|
}
|
|
|
|
if (CONFIG_CC2538_RF_OBS_1 != disabled) {
|
|
|
|
RFCORE_XREG_RFC_OBS_CTRL1 = CONFIG_CC2538_RF_OBS_1;
|
|
|
|
*(&CCTEST_OBSSEL0 + CONFIG_CC2538_RF_OBS_SIG_1_PCX) = \
|
|
|
|
CCTEST_OBSSELX_EN | rfc_obs_sig1;
|
|
|
|
}
|
|
|
|
if (CONFIG_CC2538_RF_OBS_2 != disabled) {
|
|
|
|
RFCORE_XREG_RFC_OBS_CTRL2 = CONFIG_CC2538_RF_OBS_2;
|
|
|
|
*(&CCTEST_OBSSEL0 + CONFIG_CC2538_RF_OBS_SIG_2_PCX) = \
|
|
|
|
CCTEST_OBSSELX_EN | rfc_obs_sig2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-08 03:33:54 +02:00
|
|
|
bool cc2538_channel_clear(void)
|
|
|
|
{
|
|
|
|
if (RFCORE->XREG_FSMSTAT0bits.FSM_FFCTRL_STATE == FSM_STATE_IDLE) {
|
|
|
|
bool result;
|
|
|
|
cc2538_on();
|
2016-07-16 02:55:12 +02:00
|
|
|
RFCORE_WAIT_UNTIL(RFCORE->XREG_RSSISTATbits.RSSI_VALID);
|
2016-07-08 03:33:54 +02:00
|
|
|
result = BOOLEAN(RFCORE->XREG_FSMSTAT1bits.CCA);
|
|
|
|
cc2538_off();
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
else {
|
2016-07-16 02:55:12 +02:00
|
|
|
RFCORE_WAIT_UNTIL(RFCORE->XREG_RSSISTATbits.RSSI_VALID);
|
2016-07-08 03:33:54 +02:00
|
|
|
return BOOLEAN(RFCORE->XREG_FSMSTAT1bits.CCA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void cc2538_init(void)
|
|
|
|
{
|
2020-09-25 17:12:08 +02:00
|
|
|
/* Enable RF CORE clock in active mode */
|
|
|
|
SYS_CTRL_RCGCRFC = 1UL;
|
|
|
|
/* Enable RF CORE clock in sleep mode */
|
|
|
|
SYS_CTRL_SCGCRFC = 1UL;
|
|
|
|
/* Enable RF CORE clock in PM0 (system clock always powered down
|
|
|
|
in PM1-3) */
|
|
|
|
SYS_CTRL_DCGCRFC = 1UL;
|
|
|
|
/* Wait for the clock enabling to take effect */
|
|
|
|
while (!(SYS_CTRL_RCGCRFC & 1UL) || \
|
|
|
|
!(SYS_CTRL_SCGCRFC & 1UL) || \
|
|
|
|
!(SYS_CTRL_DCGCRFC & 1UL)
|
|
|
|
) {}
|
|
|
|
|
|
|
|
/* Register Setting updates for optimal performance, RM section 23.15 */
|
|
|
|
RFCORE_XREG_TXFILTCFG = 0x09;
|
|
|
|
RFCORE_XREG_AGCCTRL1 = 0x15;
|
|
|
|
RFCORE_XREG_FSCAL1 = 0x01;
|
|
|
|
ANA_REGS_IVCTRL = 0x0B;
|
|
|
|
|
|
|
|
/* Enable AUTOCRC and AUTOACK by default*/
|
|
|
|
RFCORE_XREG_FRMCTRL0 = AUTOCRC | AUTOACK;
|
|
|
|
|
|
|
|
/* Disable RX after TX, let upper layer change the state */
|
|
|
|
RFCORE_XREG_FRMCTRL1 = 0x00;
|
|
|
|
|
|
|
|
/* Disable source address matching and pending bits */
|
|
|
|
RFCORE_XREG_SRCMATCH = 0x00;
|
|
|
|
|
|
|
|
/* Set FIFOP_THR to its max value*/
|
|
|
|
RFCORE_XREG_FIFOPCTRL = CC2538_RF_MAX_DATA_LEN;
|
|
|
|
|
|
|
|
/* Set default IRQ */
|
2021-09-07 15:52:08 +02:00
|
|
|
cc2538_rf_enable_irq();
|
2016-07-08 03:33:54 +02:00
|
|
|
|
2020-09-25 17:12:08 +02:00
|
|
|
/* Enable all RF CORE error interrupts */
|
|
|
|
RFCORE_XREG_RFERRM = STROBE_ERR | TXUNDERF | TXOVERF | \
|
|
|
|
RXUNDERF | RXOVERF | NLOCK;
|
|
|
|
|
|
|
|
_cc2538_observable_signals();
|
|
|
|
|
|
|
|
/* Enable IRQs */
|
|
|
|
if (SYS_CTRL_I_MAP) {
|
|
|
|
NVIC_SetPriority(RF_RXTX_ALT_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
2016-07-08 03:33:54 +02:00
|
|
|
NVIC_EnableIRQ(RF_RXTX_ALT_IRQn);
|
|
|
|
|
2020-09-25 16:31:44 +02:00
|
|
|
NVIC_SetPriority(RF_ERR_ALT_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
2016-07-08 03:33:54 +02:00
|
|
|
NVIC_EnableIRQ(RF_ERR_ALT_IRQn);
|
2020-06-24 12:09:24 +02:00
|
|
|
|
2020-09-25 16:31:44 +02:00
|
|
|
NVIC_SetPriority(MAC_TIMER_ALT_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
2020-06-24 12:09:24 +02:00
|
|
|
NVIC_EnableIRQ(MAC_TIMER_ALT_IRQn);
|
2016-07-08 03:33:54 +02:00
|
|
|
}
|
|
|
|
else {
|
2020-09-25 16:31:44 +02:00
|
|
|
NVIC_SetPriority(RF_RXTX_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
2016-07-08 03:33:54 +02:00
|
|
|
NVIC_EnableIRQ(RF_RXTX_IRQn);
|
|
|
|
|
2020-09-25 16:31:44 +02:00
|
|
|
NVIC_SetPriority(RF_ERR_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
2016-07-08 03:33:54 +02:00
|
|
|
NVIC_EnableIRQ(RF_ERR_IRQn);
|
2020-06-24 12:09:24 +02:00
|
|
|
|
2020-09-25 16:31:44 +02:00
|
|
|
NVIC_SetPriority(MACTIMER_IRQn, CPU_DEFAULT_IRQ_PRIO);
|
2020-06-24 12:09:24 +02:00
|
|
|
NVIC_EnableIRQ(MACTIMER_IRQn);
|
2016-07-08 03:33:54 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 17:12:08 +02:00
|
|
|
/* setup mac timer */
|
|
|
|
_cc2538_setup_mac_timer();
|
2020-06-24 12:09:24 +02:00
|
|
|
|
2020-11-18 13:57:46 +01:00
|
|
|
/* Enable Auto ACK */
|
|
|
|
RFCORE->XREG_FRMCTRL0bits.AUTOACK = !IS_ACTIVE(CONFIG_IEEE802154_AUTO_ACK_DISABLE);
|
|
|
|
|
2016-07-08 03:33:54 +02:00
|
|
|
/* Flush the receive and transmit FIFOs */
|
|
|
|
RFCORE_SFR_RFST = ISFLUSHTX;
|
|
|
|
RFCORE_SFR_RFST = ISFLUSHRX;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cc2538_is_on(void)
|
|
|
|
{
|
2020-09-25 17:12:08 +02:00
|
|
|
return RFCORE->XREG_FSMSTAT1bits.RX_ACTIVE || \
|
|
|
|
RFCORE->XREG_FSMSTAT1bits.TX_ACTIVE;
|
2016-07-08 03:33:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void cc2538_off(void)
|
|
|
|
{
|
|
|
|
/* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */
|
|
|
|
RFCORE_WAIT_UNTIL(RFCORE->XREG_FSMSTAT1bits.TX_ACTIVE == 0);
|
|
|
|
|
|
|
|
/* Flush RX FIFO */
|
|
|
|
RFCORE_SFR_RFST = ISFLUSHRX;
|
|
|
|
|
|
|
|
/* Don't turn off if we are off as this will trigger a Strobe Error */
|
|
|
|
if (RFCORE_XREG_RXENABLE != 0) {
|
|
|
|
RFCORE_SFR_RFST = ISRFOFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool cc2538_on(void)
|
|
|
|
{
|
|
|
|
/* Flush RX FIFO */
|
|
|
|
RFCORE_SFR_RFST = ISFLUSHRX;
|
|
|
|
|
|
|
|
/* Enable/calibrate RX */
|
|
|
|
RFCORE_SFR_RFST = ISRXON;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cc2538_setup(cc2538_rf_t *dev)
|
|
|
|
{
|
2020-10-15 14:12:01 +02:00
|
|
|
(void) dev;
|
|
|
|
cc2538_init();
|
2016-07-08 03:33:54 +02:00
|
|
|
}
|