diff --git a/arch/cpu/simplelink/Makefile.simplelink b/arch/cpu/simplelink/Makefile.simplelink index 3df82643c..266565bdb 100644 --- a/arch/cpu/simplelink/Makefile.simplelink +++ b/arch/cpu/simplelink/Makefile.simplelink @@ -31,7 +31,9 @@ CFLAGS += -I$(SDK_KERNEL)/posix LDFLAGS += --entry resetISR LDFLAGS += -static LDFLAGS += --specs=nano.specs -LDFLAGS += -Wl,--defsym=_stack_origin=__stack +# NB! The symbol _stack, pointing to the stack start, is expected, +# but should already be defined in the linker script. +LDFLAGS += -Wl,--defsym=_stack_origin=__stack_end LDFLAGS += -Wl,--defsym=_heap=__heap_start__ LDFLAGS += -Wl,--defsym=_eheap=__heap_end__ @@ -63,7 +65,9 @@ CONTIKI_CPU_DIRS += dev rf-settings CONTIKI_CPU_SOURCEFILES += rtimer-arch.c clock-arch.c CONTIKI_CPU_SOURCEFILES += watchdog-arch.c putchar-arch.c CONTIKI_CPU_SOURCEFILES += uart0-arch.c -CONTIKI_CPU_SOURCEFILES += proprietary-rf.c proprietary-rf-settings.c +CONTIKI_CPU_SOURCEFILES += rf-core.c +CONTIKI_CPU_SOURCEFILES += rf-prop-mode.c rf-prop-settings.c +CONTIKI_CPU_SOURCEFILES += rf-ieee-mode.c rf-ieee-settings.c CONTIKI_CPU_SOURCEFILES += ieee-addr.c ### CPU-dependent debug source files diff --git a/arch/cpu/simplelink/dev/proprietary-rf.h b/arch/cpu/simplelink/dev/rf-core.c similarity index 64% rename from arch/cpu/simplelink/dev/proprietary-rf.h rename to arch/cpu/simplelink/dev/rf-core.c index de61e53ec..232cffb86 100644 --- a/arch/cpu/simplelink/dev/proprietary-rf.h +++ b/arch/cpu/simplelink/dev/rf-core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,29 +32,58 @@ * \addtogroup rf-core * @{ * - * \defgroup rf-core-prop CC13xx Prop mode driver - * - * @{ - * * \file - * Header file for the CC13xx prop mode NETSTACK_RADIO driver + * Implementation of the CC13xx/CC26xx RF core driver */ /*---------------------------------------------------------------------------*/ -#ifndef PROP_MODE_H_ -#define PROP_MODE_H_ -/*---------------------------------------------------------------------------*/ #include "contiki.h" - +#include "dev/watchdog.h" +#include "sys/process.h" +#include "sys/clock.h" +#include "sys/ctimer.h" +#include "sys/energest.h" +#include "sys/cc.h" +#include "net/netstack.h" +#include "net/packetbuf.h" +/*---------------------------------------------------------------------------*/ +#include +/*---------------------------------------------------------------------------*/ #include +#include +#include +#include +#include /*---------------------------------------------------------------------------*/ -typedef struct prop_mode_tx_power_config { - radio_value_t dbm; - uint16_t tx_power; /* Value for the PROP_DIV_RADIO_SETUP.txPower field */ -} prop_mode_tx_power_config_t; +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif /*---------------------------------------------------------------------------*/ -#endif /* PROP_MODE_H_ */ +PROCESS(RF_coreProcess, "SimpleLink RF driver"); /*---------------------------------------------------------------------------*/ -/** - * @} - * @} - */ +PROCESS_THREAD(RF_coreProcess, ev, data) +{ + int len; + + PROCESS_BEGIN(); + + while(1) { + PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + do { + watchdog_periodic(); + packetbuf_clear(); + len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); + + if(len > 0) { + packetbuf_set_datalen(len); + + NETSTACK_MAC.input(); + } + } while(len > 0); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/arch/cpu/simplelink/dev/rf-core.h b/arch/cpu/simplelink/dev/rf-core.h index e28937384..02e882f66 100644 --- a/arch/cpu/simplelink/dev/rf-core.h +++ b/arch/cpu/simplelink/dev/rf-core.h @@ -2,8 +2,36 @@ #define CONTIKI_NG_ARCH_CPU_SIMPLELINK_DEV_RF_CORE_H_ /*---------------------------------------------------------------------------*/ -#define RF_CORE_CMD_ERROR 0 -#define RF_CORE_CMD_OK 1 +/* Contiki API */ +#include +#include +/*---------------------------------------------------------------------------*/ +#include +/*---------------------------------------------------------------------------*/ +/* Standard library */ +#include +/*---------------------------------------------------------------------------*/ +#ifdef RF_CORE_CONF_CHANNEL +# define RF_CORE_CHANNEL RF_CORE_CONF_CHANNEL +#else +# define RF_CORE_CHANNEL 25 +#endif +/*---------------------------------------------------------------------------*/ +typedef enum { + CMD_ERROR = 0, + CMD_OK = 1, +} CmdResult; +/*---------------------------------------------------------------------------*/ +typedef struct { + radio_value_t dbm; + uint16_t power; /* Value for the PROP_DIV_RADIO_SETUP.txPower field */ +} RF_TxPower; + +#define TX_POWER_UNKNOWN 0xFFFF +/*---------------------------------------------------------------------------*/ +#define RSSI_UNKNOWN -128 +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(RF_coreProcess); /*---------------------------------------------------------------------------*/ #endif /* CONTIKI_NG_ARCH_CPU_SIMPLELINK_DEV_RF_CORE_H_ */ diff --git a/arch/cpu/simplelink/dev/rf-ieee-mode.c b/arch/cpu/simplelink/dev/rf-ieee-mode.c new file mode 100644 index 000000000..f3686505c --- /dev/null +++ b/arch/cpu/simplelink/dev/rf-ieee-mode.c @@ -0,0 +1,1095 @@ +/* + * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup rf-core + * @{ + * + * \defgroup rf-core-ieee CC13xx/CC26xx IEEE mode driver + * + * @{ + * + * \file + * Implementation of the CC13xx/CC26xx IEEE mode NETSTACK_RADIO driver + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "net/packetbuf.h" +#include "net/linkaddr.h" +#include "net/netstack.h" +#include "sys/energest.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "sys/ctimer.h" +#include "sys/cc.h" +/*---------------------------------------------------------------------------*/ +/* RF driver and RF Core API */ +#include +#include +#include +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +/* Simplelink Platform RF dev */ +#include "rf-core.h" +#include "dot-15-4g.h" +/*---------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#ifdef NDEBUG +# define PRINTF(...) +#else +# define PRINTF(...) printf(__VA_ARGS__) +#endif +/*---------------------------------------------------------------------------*/ +/* Configuration parameters */ + +/* Configuration to enable/disable auto ACKs in IEEE mode */ +#ifdef IEEE_MODE_CONF_AUTOACK +# define IEEE_MODE_AUTOACK IEEE_MODE_CONF_AUTOACK +# undef IEEE_MODE_CONF_AUTOACK +#else +# define IEEE_MODE_AUTOACK 1 +#endif /* IEEE_MODE_CONF_AUTOACK */ + +/* Configuration to enable/disable frame filtering in IEEE mode */ +#ifdef IEEE_MODE_CONF_PROMISCOUS +# define IEEE_MODE_PROMISCOUS IEEE_MODE_CONF_PROMISCOUS +# undef IEEE_MODE_CONF_PROMISCOUS +#else +# define IEEE_MODE_PROMISCOUS 0 +#endif /* IEEE_MODE_CONF_PROMISCOUS */ + +/* Configuration to set the RSSI threshold */ +#ifdef IEEE_MODE_CONF_RSSI_THRESHOLD +# define IEEE_MODE_RSSI_THRESHOLD IEEE_MODE_CONF_RSSI_THRESHOLD +# undef IEEE_MODE_CONF_RSSI_THRESHOLD +#else +# define IEEE_MODE_RSSI_THRESHOLD 0xA6 +#endif /* IEEE_MODE_CONF_RSSI_THRESHOLD */ + +/* Configuration for default IEEE channel */ +#ifdef IEEE_MODE_CONF_CHANNEL +# define IEEE_MODE_CHANNEL IEEE_MODE_CONF_CHANNEL +# undef IEEE_MODE_CONF_CHANNEL +#else +# define IEEE_MODE_CHANNEL RF_CORE_CHANNEL +#endif + +/* Configuration for TX power table */ +#ifdef TX_POWER_CONF_DRIVER +# define TX_POWER_DRIVER TX_POWER_CONF_DRIVER +# undef TX_POWER_CONF_DRIVER +#else +# define TX_POWER_DRIVER RF_ieeeTxPower +#endif + +#ifdef TX_POWER_CONF_COUNT +# define TX_POWER_COUNT TX_POWER_CONF_COUNT +# undef TX_POWER_CONF_COUNT +#else +# define TX_POWER_COUNT RF_ieeeTxPowerLen +#endif +/*---------------------------------------------------------------------------*/ +/* TX power convenience macros */ +static RF_TxPower * const g_pTxPower = TX_POWER_DRIVER; + +#define TX_POWER_MAX (g_pTxPower[0]) +#define TX_POWER_MIN (g_pTxPower[(TX_POWER_COUNT) - 1]) + +#define TX_POWER_IN_RANGE(dbm) (((dbm) >= TX_POWER_MIN) && ((dbm) <= TX_POWER_MAX)) +/*---------------------------------------------------------------------------*/ +/* IEEE channel-to-frequency conversion constants */ +/* Channel frequency base: 2.405 GHz */ +/* Channel frequency spacing: 5 MHz */ +/* Channel range: 11 - 26 */ +#define IEEE_MODE_FREQ_BASE 2405000 +#define IEEE_MODE_FREQ_SPACING 5000 +#define IEEE_MODE_CHAN_MIN 11 +#define IEEE_MODE_CHAN_MAX 26 + +#define IEEE_MODE_CHAN_IN_RANGE(ch) (((ch) >= IEEE_MODE_CHAN_MIN) && ((ch) <= IEEE_MODE_CHAN_MAX)) + +/* Sanity check of default IEEE channel */ +#if !IEEE_MODE_CHAN_IN_RANGE(IEEE_MODE_CHANNEL) +# error "Default IEEE channel IEEE_MODE_CHANNEL is outside allowed channel range" +#endif +/*---------------------------------------------------------------------------*/ +/* Timeout constants */ + +/* How long to wait for an ongoing ACK TX to finish before starting frame TX */ +#define TIMEOUT_TX_WAIT (RTIMER_SECOND >> 11) + +/* How long to wait for the RF to enter RX in RF_cmdIeeeRx */ +#define TIMEOUT_ENTER_RX_WAIT (RTIMER_SECOND >> 10) + +/* How long to wait for the RF to react on CMD_ABORT: around 1 msec */ +#define TIMEOUT_RF_TURN_OFF_WAIT (RTIMER_SECOND >> 10) + +/* How long to wait for the RF to finish TX of a packet or an ACK */ +#define TIMEOUT_TX_FINISH_WAIT (RTIMER_SECOND >> 7) + +/* How long to wait for the rx read entry to become ready */ +#define TIMEOUT_DATA_ENTRY_BUSY (RTIMER_SECOND / 250) +/*---------------------------------------------------------------------------*/ +/* TI-RTOS RF driver object */ +static RF_Object g_rfObj; +static RF_Handle g_rfHandle; + +/* RF Core command pointers */ +static volatile rfc_CMD_RADIO_SETUP_t *g_vpCmdRadioSetup = &RF_cmdRadioSetup; +static volatile rfc_CMD_FS_t *g_vpCmdFs = &RF_cmdFs; +static volatile rfc_CMD_IEEE_TX_t *g_vpCmdTx = &RF_cmdIeeeTx; +static volatile rfc_CMD_IEEE_RX_t *g_vpCmdRx = &RF_cmdIeeeRx; + +/* RF command handles */ +static RF_CmdHandle g_cmdTxHandle; +static RF_CmdHandle g_cmdRxHandle; + +/* Global RF Core commands */ +static rfc_CMD_IEEE_MOD_FILT_t g_cmdModFilt; + +/* RF stats data structure */ +static rfc_ieeeRxOutput_t g_rxStats; +/*---------------------------------------------------------------------------*/ +/* The outgoing frame buffer */ +#define TX_BUF_PAYLOAD_LEN 180 +#define TX_BUF_HDR_LEN 2 + +static uint8_t g_txBuf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4); +/*---------------------------------------------------------------------------*/ +/* RX Data Queue */ +static dataQueue_t g_rxDataQueue; +/* Receive entry pointer to keep track of read items */ +volatile static uint8_t *g_pRxReadEntry; + +/* Constants for receive buffers */ +#define DATA_ENTRY_LENSZ_NONE 0 +#define DATA_ENTRY_LENSZ_BYTE 1 +#define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */ + +#define RX_BUF_ENTRIES 4 +#define RX_BUF_SIZE 144 + +/* Receive buffer entries with room for 1 IEEE 802.15.4 frame in each */ +typedef union { + rfc_dataEntry_t dataEntry; + uint8_t buf[RX_BUF_SIZE] CC_ALIGN(4); +} RxBuf; +static RxBuf g_rxBufs[RX_BUF_ENTRIES]; +/*---------------------------------------------------------------------------*/ +/* RAT overflow upkeep */ +static struct ctimer g_ratOverflowTimer; +static rtimer_clock_t g_lastRatOverflow; +static volatile uint32_t g_ratOverflowCount; + +#define RAT_RANGE (~(uint32_t)0) +#define RAT_OVERFLOW_PERIOD_SECONDS (RAT_RANGE / (uint32_t)RADIO_TIMER_SECOND) +/* XXX: don't know what exactly is this, looks like the time to TX 3 octets */ +#define RAT_TIMESTAMP_OFFSET -(USEC_TO_RADIO(32 * 3) - 1) /* -95.75 usec */ +/*---------------------------------------------------------------------------*/ +#define STATUS_CORRELATION 0x3f // bits 0-5 +#define STATUS_REJECT_FRAME 0x40 // bit 6 +#define STATUS_CRC_FAIL 0x80 // bit 7 +/*---------------------------------------------------------------------------*/ +#define CHANNEL_CLEAR_ERROR -1 +/*---------------------------------------------------------------------------*/ +/* Global state */ + +/* Current RX channel */ +static volatile uint8_t g_currChannel; + +/* Current TX power */ +static volatile RF_TxPower *g_pCurrTxPower; + +/* Are we currently in poll mode? */ +static volatile bool g_bPollMode = false; + +/* Enable/disable CCA before sending */ +static volatile bool g_bSendOnCca = false; + +/* Last RX operation stats */ +static volatile int8_t g_lastRssi; +static volatile uint8_t g_lastCorrLqi; +static volatile uint32_t g_lastTimestamp; +/*---------------------------------------------------------------------------*/ +typedef enum { + POWER_STATE_ON, + POWER_STATE_OFF, + POWER_STATE_RESTART, +} PowerState; +/*---------------------------------------------------------------------------*/ +/* Forward declarations of static functions */ +static int on(void); +static int off(void); +static int set_rx(const PowerState); +static int channel_clear(void); +static void check_rat_overflow(void); +static bool rf_is_on(void); +static uint32_t rat_to_timestamp(const uint32_t); +/*---------------------------------------------------------------------------*/ +static void +synth_error_cb(RF_Handle h, RF_CmdHandle ch, RF_EventMask e) +{ + if ((ch == RF_ERROR_CMDFS_SYNTH_PROG) && + (g_vpCmdFs->status == ERROR_SYNTH_PROG)) { + // See SWRA521: Synth failed to calibrate, CMD_FS must be repeated + RF_postCmd(g_rfHandle, (RF_Op*)g_vpCmdFs, RF_PriorityNormal, synth_error_cb, 0); + } +} +/*---------------------------------------------------------------------------*/ +static void +rat_overflow_cb(void *arg) +{ + check_rat_overflow(); + // Check next time after half of the RAT interval + ctimer_set(&g_ratOverflowTimer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2, + rat_overflow_cb, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +init_data_queue(void) +{ + // Initialize RF core data queue, circular buffer + g_rxDataQueue.pCurrEntry = g_rxBufs[0].buf; + g_rxDataQueue.pLastEntry = NULL; + // Set current read pointer to first element + g_pRxReadEntry = g_rxDataQueue.pCurrEntry; +} +/*---------------------------------------------------------------------------*/ +static void +init_rf_params(void) +{ + g_vpCmdRx->pRxQ = &g_rxDataQueue; + g_vpCmdRx->pOutput = &g_rxStats; + +#if IEEE_MODE_PROMISCOUS + g_vpCmdRx->frameFiltOpt.frameFiltEn = 0; +#else + g_vpCmdRx->frameFiltOpt.frameFiltEn = 1; +#endif + +#if IEEE_MODE_AUTOACK + g_vpCmdRx->frameFiltOpt.autoAckEn = 1; +#else + g_vpCmdRx->frameFiltOpt.autoAckEn = 0; +#endif + + g_vpCmdRx->ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD; + + // Initialize address filter command + g_cmdModFilt.commandNo = CMD_IEEE_MOD_FILT; + memcpy(&g_cmdModFilt.newFrameFiltOpt, &RF_cmdIeeeRx.frameFiltOpt, sizeof(RF_cmdIeeeRx.frameFiltOpt)); + memcpy(&g_cmdModFilt.newFrameTypes, &RF_cmdIeeeRx.frameTypes, sizeof(RF_cmdIeeeRx.frameTypes)); +} +/*---------------------------------------------------------------------------*/ +static void +init_rx_buffers(void) +{ +#define getEntry(n) (&(g_rxBufs[(n)].dataEntry)) + + rfc_dataEntry_t *entry = NULL; + const uint16_t length = sizeof(g_rxBufs[0].buf) - 8; + + size_t i; + for (i = 0; i < (size_t)(RX_BUF_ENTRIES - 1); ++i) { + entry = getEntry(i); + entry->pNextEntry = (uint8_t*)getEntry(i + 1); + entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; + entry->length = length; + } + + entry = getEntry(RX_BUF_ENTRIES - 1); + entry->pNextEntry = (uint8_t*)getEntry(0); + entry->config.lenSz = DATA_ENTRY_LENSZ_BYTE; + entry->length = length; + +#undef getEntry +} +/*---------------------------------------------------------------------------*/ +static void +set_channel(uint8_t channel) +{ + if (!IEEE_MODE_CHAN_IN_RANGE(channel)) { + PRINTF("set_channel: illegal channel %d, defaults to %d\n", + channel, IEEE_MODE_CHANNEL); + channel = IEEE_MODE_CHANNEL; + } + if (channel == g_currChannel) { + // We are already calibrated to this channel + return; + } + g_currChannel = channel; + // freq = freq_base + freq_spacing * (channel - channel_min) + const uint32_t newFreq = (uint32_t)IEEE_MODE_FREQ_BASE + + (uint32_t)IEEE_MODE_FREQ_SPACING * ((uint32_t)channel - (uint32_t)IEEE_MODE_CHAN_MIN); + const uint16_t freq = (uint16_t)(newFreq / 1000); + const uint16_t frac = (uint16_t)((newFreq - (freq * 1000)) * 65536 / 1000); + + PRINTF("set_channel: %d = 0x%04X.0x%04X (%lu)\n", + channel, freq, frac, newFreq); + + g_vpCmdFs->frequency = freq; + g_vpCmdFs->fractFreq = frac; + + // Start FS command asynchronously. We don't care when it is finished + RF_postCmd(g_rfHandle, (RF_Op*)g_vpCmdFs, RF_PriorityNormal, synth_error_cb, 0); + if (g_vpCmdRx->status == ACTIVE) { + set_rx(POWER_STATE_RESTART); + } +} +/*---------------------------------------------------------------------------*/ +static int +set_tx_power(const radio_value_t dbm) +{ + g_pCurrTxPower = NULL; + if (dbm > TX_POWER_MAX.dbm) { + g_pCurrTxPower = &TX_POWER_MAX; + } else { + size_t i; + for (i = 0; g_pTxPower[i + 1].power != TX_POWER_UNKNOWN; ++i) { + if (dbm > g_pTxPower[i + 1].dbm) { + break; + } + } + g_pCurrTxPower = &g_pTxPower[i + 1]; + } + + if (!g_pCurrTxPower) { + return CMD_ERROR; + } + + rfc_CMD_SET_TX_POWER_t cmdSetTxPower = { + .commandNo = CMD_SET_TX_POWER, + .txPower = g_pCurrTxPower->power, + }; + + const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&cmdSetTxPower); + if (stat != RF_StatCmdDoneSuccess) { + PRINTF("set_tx_power: stat=0x%02X\n", stat); + return CMD_ERROR; + } + return CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static radio_value_t +get_tx_power(void) +{ + return (g_pCurrTxPower) + ? g_pCurrTxPower->power + : (radio_value_t)TX_POWER_UNKNOWN; +} +/*---------------------------------------------------------------------------*/ +static void +set_send_on_cca(bool enable) +{ + g_bSendOnCca = enable; +} +/*---------------------------------------------------------------------------*/ +static void +check_rat_overflow(void) +{ + const bool was_off = rf_is_on(); + if (was_off) { + RF_runDirectCmd(g_rfHandle, CMD_NOP); + } + const uint32_t currentValue = RF_getCurrentTime(); + + static uint32_t lastValue; + static bool bFirstTime = true; + if (bFirstTime) { + // First time checking overflow will only store the current value + bFirstTime = false; + } else { + // Overflow happens in the last quarter of the RAT range + if (currentValue + RAT_RANGE / 4 < lastValue) { + // Overflow detected + g_lastRatOverflow = RTIMER_NOW(); + g_ratOverflowCount += 1; + } + } + + lastValue = currentValue; + + if (was_off) { + off(); + } +} +/*---------------------------------------------------------------------------*/ +static uint32_t +rat_to_timestamp(const uint32_t ratTimestamp) +{ + check_rat_overflow(); + + uint64_t adjustedOverflowCount = g_ratOverflowCount; + + // If the timestamp is in the 4th quarter and the last oveflow was recently, + // assume that the timestamp refers to the time before the overflow + if(ratTimestamp > (uint32_t)(RAT_RANGE * 3 / 4)) { + if(RTIMER_CLOCK_LT(RTIMER_NOW(), + g_lastRatOverflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) { + adjustedOverflowCount -= 1; + } + } + + // Add the overflowed time to the timestamp + const uint64_t ratTimestamp64 = (uint64_t)ratTimestamp + (uint64_t)RAT_RANGE * adjustedOverflowCount; + + // Correct timestamp so that it refers to the end of the SFD and convert to RTIMER + return RADIO_TO_RTIMER(ratTimestamp64 + RAT_TIMESTAMP_OFFSET); +} +/*---------------------------------------------------------------------------*/ +static int +init(void) +{ + RF_Params params; + RF_Params_init(¶ms); + // Disable automatic power-down just to not interfere with stack timing + params.nInactivityTimeout = 0; + + init_rf_params(); + init_data_queue(); + + g_rfHandle = RF_open(&g_rfObj, &RF_ieeeMode, (RF_RadioSetup*)g_vpCmdRadioSetup, ¶ms); + assert(g_rfHandle != NULL); + + set_channel(IEEE_MODE_CHANNEL); + + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + // Start RAT overflow upkeep + check_rat_overflow(); + ctimer_set(&g_ratOverflowTimer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2, + rat_overflow_cb, NULL); + + process_start(&RF_coreProcess, NULL); + + return CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static int +prepare(const void *payload, unsigned short payload_len) +{ + const size_t len = MIN((size_t)payload_len, + (size_t)TX_BUF_PAYLOAD_LEN); + memcpy(&g_txBuf[TX_BUF_HDR_LEN], payload, len); + return 0; +} +/*---------------------------------------------------------------------------*/ +static bool +rf_is_on(void) +{ + RF_InfoVal infoVal; + memset(&infoVal, 0x0, sizeof(RF_InfoVal)); + const RF_Stat stat = RF_getInfo(g_rfHandle, RF_GET_RADIO_STATE, &infoVal); + return (stat == RF_StatSuccess) + ? infoVal.bRadioState // 0: Radio OFF, 1: Radio ON + : false; +} +/*---------------------------------------------------------------------------*/ +static int +set_rx(const PowerState state) +{ + if (state == POWER_STATE_OFF || state == POWER_STATE_RESTART) { + const uint8_t stopGracefully = 1; + const RF_Stat stat = RF_cancelCmd(g_rfHandle, g_cmdRxHandle, + stopGracefully); + if (stat != RF_StatSuccess) + { + PRINTF("set_rx(off): unable to cancel RX\n"); + return CMD_ERROR; + } + + } + if (state == POWER_STATE_ON || state == POWER_STATE_RESTART) { + if (g_vpCmdRx->status == ACTIVE) { + PRINTF("set_rx(on): already in RX\n"); + return CMD_OK; + } + + RF_ScheduleCmdParams schedParams = { + .endTime = 0, + .priority = RF_PriorityNormal, + .bIeeeBgCmd = true, + }; + + g_vpCmdRx->status = IDLE; + g_cmdRxHandle = RF_scheduleCmd(g_rfHandle, (RF_Op*)g_vpCmdRx, &schedParams, NULL, 0); + if ((g_cmdTxHandle == RF_ALLOC_ERROR) || (g_cmdTxHandle == RF_SCHEDULE_CMD_ERROR)) { + PRINTF("transmit: unable to allocate RX command\n"); + return CMD_ERROR; + } + } + + return CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static int +transmit_aux(unsigned short transmit_len) +{ + // Configure TX command + g_vpCmdTx->payloadLen = (uint8_t)transmit_len; + g_vpCmdTx->pPayload = &g_txBuf[TX_BUF_HDR_LEN]; + g_vpCmdTx->startTime = 0; + g_vpCmdTx->startTrigger.triggerType = TRIG_NOW; + + RF_ScheduleCmdParams schedParams = { + .endTime = 0, + .priority = RF_PriorityNormal, + .bIeeeBgCmd = false, + }; + + // As IEEE_TX is a FG command, the TX operation will be executed + // either way if RX is running or not + g_vpCmdTx->status = IDLE; + g_cmdTxHandle = RF_scheduleCmd(g_rfHandle, (RF_Op*)g_vpCmdTx, &schedParams, NULL, 0); + if ((g_cmdTxHandle == RF_ALLOC_ERROR) || (g_cmdTxHandle == RF_SCHEDULE_CMD_ERROR)) { + // Failure sending the CMD_IEEE_TX command + PRINTF("transmit: failed to allocate TX command cmdHandle=%d, status=%04x\n", + g_cmdTxHandle, g_vpCmdTx->status); + return RADIO_TX_ERR; + } + + ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT); + + // Wait until TX operation finishes + RF_EventMask events = RF_pendCmd(g_rfHandle, g_cmdTxHandle, 0); + if ((events & (RF_EventFGCmdDone | RF_EventLastFGCmdDone)) == 0) { + PRINTF("transmit: TX command error events=0x%08llx, status=0x%04x\n", + events, g_vpCmdTx->status); + return RADIO_TX_ERR; + } + + return RADIO_TX_OK; +} +/*---------------------------------------------------------------------------*/ +static int +transmit(unsigned short transmit_len) +{ + const bool was_rx = (g_vpCmdRx->status == ACTIVE); + + if (g_bSendOnCca && channel_clear() != 1) { + PRINTF("transmit: channel wasn't clear\n"); + return RADIO_TX_COLLISION; + } + + const int rv = transmit_aux(transmit_len); + ENERGEST_SWITCH(ENERGEST_TYPE_TRANSMIT, ENERGEST_TYPE_LISTEN); + + if (!was_rx) { + off(); + } + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +send(const void *payload, unsigned short payload_len) +{ + prepare(payload, payload_len); + return transmit(payload_len); +} +/*---------------------------------------------------------------------------*/ +static void +release_data_entry(void) +{ + rfc_dataEntryGeneral_t *pEntry = (rfc_dataEntryGeneral_t *)g_pRxReadEntry; + + // Clear the length byte and set status to 0: "Pending" + pEntry->length = 0; + pEntry->status = DATA_ENTRY_PENDING; + // Set next entry + g_pRxReadEntry = pEntry->pNextEntry; +} +/*---------------------------------------------------------------------------*/ +static int +read_frame(void *buf, unsigned short buf_len) +{ + volatile rfc_dataEntryGeneral_t *pEntry = (rfc_dataEntryGeneral_t *)g_pRxReadEntry; + + const rtimer_clock_t t0 = RTIMER_NOW(); + // Only wait if the Radio timer is accessing the entry + while ((pEntry->status == DATA_ENTRY_BUSY) && + RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_DATA_ENTRY_BUSY)); + + if (pEntry->status != DATA_ENTRY_FINISHED) { + // No available data + return 0; + } + + // FIXME: something is wrong here about length constraints + if (pEntry->length < 4) { + PRINTF("read_frame: frame too short \n"); + release_data_entry(); + return 0; + } + + const int frame_len = pEntry->length - 8; + + if (frame_len > buf_len) { + PRINTF("read_frame: frame larger than buffer\n"); + release_data_entry(); + return 0; + } + + const uint8_t *pData = (uint8_t *)&pEntry->data; + + memcpy(buf, pData, frame_len); + + g_lastRssi = (int8_t)(pData[frame_len + 2]); + g_lastCorrLqi = (uint8_t)(pData[frame_len + 3]) & STATUS_CORRELATION; + + uint32_t ratTimestamp; + memcpy(&ratTimestamp, pData + frame_len + 4, sizeof(ratTimestamp)); + g_lastTimestamp = rat_to_timestamp(ratTimestamp); + + if (!g_bPollMode) { + // 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, g_lastRssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, g_lastCorrLqi); + } + + release_data_entry(); + + return frame_len; +} +/*---------------------------------------------------------------------------*/ +static int +channel_clear_aux(void) +{ + rfc_CMD_IEEE_CCA_REQ_t RF_cmdIeeeCaaReq; + memset(&RF_cmdIeeeCaaReq, 0x0, sizeof(rfc_CMD_IEEE_CCA_REQ_t)); + RF_cmdIeeeCaaReq.commandNo = CMD_IEEE_CCA_REQ; + + const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&RF_cmdIeeeCaaReq); + if (stat != RF_StatCmdDoneSuccess) { + PRINTF("channel_clear: CCA request failed stat=0x%02X\n", stat); + return CMD_ERROR; + } + + // Channel is clear if CCA state is idle (0) or invalid (2), i.e. not busy (1) + return (RF_cmdIeeeCaaReq.ccaInfo.ccaState != 1); +} +/*---------------------------------------------------------------------------*/ +static int +channel_clear(void) +{ + const bool was_rx = (g_vpCmdRx->status == ACTIVE); + if (!was_rx && set_rx(POWER_STATE_ON) != CMD_OK) { + PRINTF("channel_clear: unable to start RX\n"); + return CHANNEL_CLEAR_ERROR; + } + + const int rv = channel_clear_aux(); + + if (!was_rx) { + set_rx(POWER_STATE_OFF); + } + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +receiving_packet(void) +{ + // If we are not in RX, we are not receiving + if (g_vpCmdRx->status != ACTIVE) { + PRINTF("receiving_packet: not in RX\n"); + return 0; + } + + rfc_CMD_IEEE_CCA_REQ_t RF_cmdIeeeCaaReq; + memset(&RF_cmdIeeeCaaReq, 0x0, sizeof(rfc_CMD_IEEE_CCA_REQ_t)); + RF_cmdIeeeCaaReq.commandNo = CMD_IEEE_CCA_REQ; + + const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&RF_cmdIeeeCaaReq); + if (stat != RF_StatCmdDoneSuccess) { + PRINTF("receiving_packet: CCA request failed stat=0x%02X\n", stat); + return 0; + } + + // If the radio is transmitting an ACK or is suspended for running a TX operation, + // ccaEnergy, ccaCorr and ccaSync are all busy (1) + if ((RF_cmdIeeeCaaReq.ccaInfo.ccaEnergy == 1) && + (RF_cmdIeeeCaaReq.ccaInfo.ccaCorr == 1) && + (RF_cmdIeeeCaaReq.ccaInfo.ccaSync == 1)) { + PRINTF("receiving_packet: we were TXing\n"); + return 0; + } + + // We are on and not in TX, then we are in RX if a CCA sync has been seen, + // i.e. ccaSync is busy (1) + return (RF_cmdIeeeCaaReq.ccaInfo.ccaSync == 1); +} +/*---------------------------------------------------------------------------*/ +static int +pending_packet(void) +{ + const rfc_dataEntry_t *const pStartEntry = (rfc_dataEntry_t *)g_rxDataQueue.pCurrEntry; + volatile const rfc_dataEntry_t *pCurrEntry = pStartEntry; + + // Check all RX buffers and check their statuses, stopping when looping the circular buffer + int bIsPending = 0; + do { + const uint8_t status = pCurrEntry->status; + if ((status == DATA_ENTRY_FINISHED) || + (status == DATA_ENTRY_BUSY)) { + bIsPending = 1; + if (!g_bPollMode) { + process_poll(&RF_coreProcess); + } + } + + pCurrEntry = (rfc_dataEntry_t *)pCurrEntry->pNextEntry; + } while (pCurrEntry != pStartEntry); + + // If we didn't find an entry at status finished or busy, no frames are pending + return bIsPending; +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + init_rx_buffers(); + + const int rv = set_rx(POWER_STATE_ON); + + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +off(void) +{ + set_rx(POWER_STATE_OFF); + RF_yield(g_rfHandle); + + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + + // Reset RX buffers if there was an ongoing RX + size_t i; + for (i = 0; i < RX_BUF_ENTRIES; ++i) { + rfc_dataEntry_t *entry = &(g_rxBufs[i].dataEntry); + if (entry->status == DATA_ENTRY_BUSY) { + entry->status = DATA_ENTRY_PENDING; + } + } + + return CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + if (!value) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch (param) { + case RADIO_PARAM_POWER_MODE: + *value = rf_is_on() ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + return RADIO_RESULT_OK; + + case RADIO_PARAM_CHANNEL: + *value = (radio_value_t)g_currChannel; + return RADIO_RESULT_OK; + + case RADIO_PARAM_PAN_ID: + *value = (radio_value_t)g_vpCmdRx->localPanID; + return RADIO_RESULT_OK; + + case RADIO_PARAM_16BIT_ADDR: + *value = (radio_value_t)g_vpCmdRx->localShortAddr; + return RADIO_RESULT_OK; + + case RADIO_PARAM_RX_MODE: + *value = 0; + if (g_vpCmdRx->frameFiltOpt.frameFiltEn) { + *value |= (radio_value_t)RADIO_RX_MODE_ADDRESS_FILTER; + } + if (g_vpCmdRx->frameFiltOpt.autoAckEn) { + *value |= (radio_value_t)RADIO_RX_MODE_AUTOACK; + } + if (g_bPollMode) { + *value |= (radio_value_t)RADIO_RX_MODE_POLL_MODE; + } + return RADIO_RESULT_OK; + + case RADIO_PARAM_TX_MODE: + *value = 0; + return RADIO_RESULT_OK; + + case RADIO_PARAM_TXPOWER: + *value = get_tx_power(); + return (*value == TX_POWER_UNKNOWN) + ? RADIO_RESULT_ERROR + : RADIO_RESULT_OK; + + case RADIO_PARAM_CCA_THRESHOLD: + *value = g_vpCmdRx->ccaRssiThr; + return RADIO_RESULT_OK; + + case RADIO_PARAM_RSSI: + *value = RF_getRssi(g_rfHandle); + return (*value == RF_GET_RSSI_ERROR_VAL) + ? RADIO_RESULT_ERROR + : RADIO_RESULT_OK; + + case RADIO_CONST_CHANNEL_MIN: + *value = (radio_value_t)IEEE_MODE_CHAN_MIN; + return RADIO_RESULT_OK; + + case RADIO_CONST_CHANNEL_MAX: + *value = (radio_value_t)IEEE_MODE_CHAN_MAX; + return RADIO_RESULT_OK; + + case RADIO_CONST_TXPOWER_MIN: + *value = (radio_value_t)(TX_POWER_MIN.dbm); + return RADIO_RESULT_OK; + + case RADIO_CONST_TXPOWER_MAX: + *value = (radio_value_t)(TX_POWER_MAX.dbm); + return RADIO_RESULT_OK; + + case RADIO_PARAM_LAST_RSSI: + *value = (radio_value_t)g_lastRssi; + return RADIO_RESULT_OK; + + case RADIO_PARAM_LAST_LINK_QUALITY: + *value = (radio_value_t)g_lastCorrLqi; + return RADIO_RESULT_OK; + + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + switch(param) { + case RADIO_PARAM_POWER_MODE: + switch (value) { + case RADIO_POWER_MODE_ON: + if (on() != CMD_OK) { + PRINTF("set_value: on() failed (1)\n"); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + + case RADIO_POWER_MODE_OFF: + off(); + return RADIO_RESULT_OK; + + default: + return RADIO_RESULT_INVALID_VALUE; + } + + case RADIO_PARAM_CHANNEL: + if (!IEEE_MODE_CHAN_IN_RANGE(value)) { + return RADIO_RESULT_INVALID_VALUE; + } + set_channel((uint8_t)value); + return RADIO_RESULT_OK; + + case RADIO_PARAM_PAN_ID: + g_vpCmdRx->localPanID = (uint16_t)value; + if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_OK) { + PRINTF("failed to restart RX"); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + + case RADIO_PARAM_16BIT_ADDR: + g_vpCmdRx->localShortAddr = (uint16_t)value; + if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_OK) { + PRINTF("failed to restart RX"); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + + case RADIO_PARAM_RX_MODE: { + if (value & ~(RADIO_RX_MODE_ADDRESS_FILTER | + RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) { + return RADIO_RESULT_INVALID_VALUE; + } + + g_vpCmdRx->frameFiltOpt.frameFiltEn = (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0; + g_vpCmdRx->frameFiltOpt.frameFiltStop = 1; + g_vpCmdRx->frameFiltOpt.autoAckEn = (value & RADIO_RX_MODE_AUTOACK) != 0; + g_vpCmdRx->frameFiltOpt.slottedAckEn = 0; + g_vpCmdRx->frameFiltOpt.autoPendEn = 0; + g_vpCmdRx->frameFiltOpt.defaultPend = 0; + g_vpCmdRx->frameFiltOpt.bPendDataReqOnly = 0; + g_vpCmdRx->frameFiltOpt.bPanCoord = 0; + g_vpCmdRx->frameFiltOpt.bStrictLenFilter = 0; + + const bool bOldPollMode = g_bPollMode; + g_bPollMode = (value & RADIO_RX_MODE_POLL_MODE) != 0; + if (g_bPollMode == bOldPollMode) { + // Do not turn the radio off and on, just send an update command + memcpy(&g_cmdModFilt.newFrameFiltOpt, &RF_cmdIeeeRx.frameFiltOpt, sizeof(RF_cmdIeeeRx.frameFiltOpt)); + const RF_Stat stat = RF_runImmediateCmd(g_rfHandle, (uint32_t*)&g_cmdModFilt); + if (stat != RF_StatCmdDoneSuccess) { + PRINTF("setting address filter failed: stat=0x%02X\n", stat); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + } + if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_OK) { + PRINTF("failed to restart RX"); + return RADIO_RESULT_ERROR; + } + 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 < TX_POWER_MIN.dbm || value > TX_POWER_MAX.dbm) { + return RADIO_RESULT_INVALID_VALUE; + } + return (set_tx_power(value) != CMD_OK) + ? RADIO_RESULT_ERROR + : RADIO_RESULT_OK; + + case RADIO_PARAM_CCA_THRESHOLD: + g_vpCmdRx->ccaRssiThr = (int8_t)value; + if (rf_is_on() && set_rx(POWER_STATE_RESTART) != CMD_OK) { + PRINTF("failed to restart RX"); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + if (!dest) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch (param) { + case RADIO_PARAM_64BIT_ADDR: { + const size_t srcSize = sizeof(g_vpCmdRx->localExtAddr); + if(size != srcSize) { + return RADIO_RESULT_INVALID_VALUE; + } + + const uint8_t *pSrc = (const uint8_t *)&g_vpCmdRx->localExtAddr; + uint8_t *pDest = dest; + for(size_t i = 0; i < srcSize; ++i) { + pDest[i] = pSrc[srcSize - 1 - i]; + } + + return RADIO_RESULT_OK; + } + case RADIO_PARAM_LAST_PACKET_TIMESTAMP: + if(size != sizeof(rtimer_clock_t)) { + return RADIO_RESULT_INVALID_VALUE; + } + + *(rtimer_clock_t *)dest = g_lastTimestamp; + + return RADIO_RESULT_OK; + + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + if (!src) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch (param) { + case RADIO_PARAM_64BIT_ADDR: { + const size_t destSize = sizeof(g_vpCmdRx->localExtAddr); + if (size != destSize) { + return RADIO_RESULT_INVALID_VALUE; + } + + const uint8_t *pSrc = (const uint8_t *)src; + uint8_t *pDest = (uint8_t *)&g_vpCmdRx->localExtAddr; + for (size_t i = 0; i < destSize; ++i) { + pDest[i] = pSrc[destSize - 1 - i]; + } + + const bool is_rx = (g_vpCmdRx->status == ACTIVE); + if (is_rx && set_rx(POWER_STATE_RESTART) != CMD_OK) { + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + } + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +const struct radio_driver ieee_mode_driver = { + init, + prepare, + transmit, + send, + read_frame, + channel_clear, + receiving_packet, + pending_packet, + on, + off, + get_value, + set_value, + get_object, + set_object, +}; +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/arch/cpu/simplelink/dev/proprietary-rf.c b/arch/cpu/simplelink/dev/rf-prop-mode.c similarity index 75% rename from arch/cpu/simplelink/dev/proprietary-rf.c rename to arch/cpu/simplelink/dev/rf-prop-mode.c index b8a2ec7c1..375b79554 100644 --- a/arch/cpu/simplelink/dev/proprietary-rf.c +++ b/arch/cpu/simplelink/dev/rf-prop-mode.c @@ -44,22 +44,19 @@ #include "sys/rtimer.h" #include "sys/cc.h" #include "dev/watchdog.h" -#include "proprietary-rf.h" -#include "rf-core.h" -#include "dot-15-4g.h" -/*---------------------------------------------------------------------------*/ -/* RF core and RF HAL API */ -#include -#include /*---------------------------------------------------------------------------*/ /* RF Core Mailbox API */ #include #include #include -#include #include -#include +#include #include +#include +/*---------------------------------------------------------------------------*/ +/* Platform RF dev */ +#include "rf-core.h" +#include "dot-15-4g.h" /*---------------------------------------------------------------------------*/ #include #include @@ -67,31 +64,23 @@ #include #include /*---------------------------------------------------------------------------*/ -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) +#ifdef NDEBUG +# define PRINTF(...) #else -#define PRINTF(...) +# define PRINTF(...) printf(__VA_ARGS__) #endif /*---------------------------------------------------------------------------*/ -/* Data entry status field constants */ -#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_BUSY 0x02 /* Ongoing r/w */ -#define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */ -#define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */ -/*---------------------------------------------------------------------------*/ /* Data whitener. 1: Whitener, 0: No whitener */ #ifdef PROP_MODE_CONF_DW -#define PROP_MODE_DW PROP_MODE_CONF_DW +# define PROP_MODE_DW PROP_MODE_CONF_DW #else -#define PROP_MODE_DW 0 +# define PROP_MODE_DW 0 #endif #ifdef PROP_MODE_CONF_USE_CRC16 -#define PROP_MODE_USE_CRC16 PROP_MODE_CONF_USE_CRC16 +# define PROP_MODE_USE_CRC16 PROP_MODE_CONF_USE_CRC16 #else -#define PROP_MODE_USE_CRC16 0 +# define PROP_MODE_USE_CRC16 0 #endif /*---------------------------------------------------------------------------*/ /** @@ -169,14 +158,14 @@ static rfc_propRxOutput_t rx_stats; #ifdef PROP_MODE_CONF_TX_POWER_431_527 #define PROP_MODE_TX_POWER_431_527 PROP_MODE_CONF_TX_POWER_431_527 #else -#define PROP_MODE_TX_POWER_431_527 prop_mode_tx_power_431_527 +#define PROP_MODE_TX_POWER_431_527 RF_propTxPower431_527 #endif /*---------------------------------------------------------------------------*/ /* TX power table for the 779-930MHz band */ #ifdef PROP_MODE_CONF_TX_POWER_779_930 #define PROP_MODE_TX_POWER_779_930 PROP_MODE_CONF_TX_POWER_779_930 #else -#define PROP_MODE_TX_POWER_779_930 prop_mode_tx_power_779_930 +#define PROP_MODE_TX_POWER_779_930 RF_propTxPower779_930 #endif /*---------------------------------------------------------------------------*/ /* Select power table based on the frequency band */ @@ -185,21 +174,12 @@ static rfc_propRxOutput_t rx_stats; #else #define TX_POWER_DRIVER PROP_MODE_TX_POWER_779_930 #endif -/*---------------------------------------------------------------------------*/ -extern const prop_mode_tx_power_config_t TX_POWER_DRIVER[]; /* Max and Min Output Power in dBm */ #define OUTPUT_POWER_MAX (TX_POWER_DRIVER[0].dbm) -#define OUTPUT_POWER_UNKNOWN 0xFFFF /* Default TX Power - position in output_power[] */ -static const prop_mode_tx_power_config_t *tx_power_current = &TX_POWER_DRIVER[1]; -/*---------------------------------------------------------------------------*/ -#ifdef PROP_MODE_CONF_LO_DIVIDER -#define PROP_MODE_LO_DIVIDER PROP_MODE_CONF_LO_DIVIDER -#else -#define PROP_MODE_LO_DIVIDER 0x05 -#endif +static const RF_TxPower *tx_power_current = &TX_POWER_DRIVER[0]; /*---------------------------------------------------------------------------*/ #ifdef PROP_MODE_CONF_RX_BUF_CNT #define PROP_MODE_RX_BUF_CNT PROP_MODE_CONF_RX_BUF_CNT @@ -231,128 +211,110 @@ volatile static uint8_t *rx_read_entry; static uint8_t tx_buf[TX_BUF_HDR_LEN + TX_BUF_PAYLOAD_LEN] CC_ALIGN(4); /*---------------------------------------------------------------------------*/ +volatile static rfc_CMD_PROP_RADIO_DIV_SETUP_t *gvp_cmd_radio_div_setup = &rf_cmd_prop_radio_div_setup; +volatile static rfc_CMD_FS_t *gvp_cmd_fs = &rf_cmd_prop_fs; +volatile static rfc_CMD_PROP_TX_ADV_t *gvp_cmd_tx_adv = &rf_cmd_prop_tx_adv; +volatile static rfc_CMD_PROP_RX_ADV_t *gvp_cmd_rx_adv = &rf_cmd_prop_rx_adv; +/*---------------------------------------------------------------------------*/ /* RF driver */ static RF_Object rfObject; static RF_Handle rfHandle; -static RF_CmdHandle rxCmdHandle = RF_ALLOC_ERROR; /*---------------------------------------------------------------------------*/ -PROCESS(rf_core_process, "CC13xx / CC26xx RF driver"); - -static uint8_t -rf_transmitting(void) -{ - return smartrf_settings_cmd_prop_tx_adv.status == ACTIVE; -} -/*---------------------------------------------------------------------------*/ -static uint8_t -rf_receiving(void) -{ - return smartrf_settings_cmd_prop_rx_adv.status == ACTIVE; -} -/*---------------------------------------------------------------------------*/ -static uint8_t -rf_is_on(void) -{ - return rf_receiving() | rf_transmitting(); -} +static inline bool rf_is_transmitting(void) { return gvp_cmd_tx_adv->status == ACTIVE; } +static inline bool rf_is_receiving(void) { return gvp_cmd_rx_adv->status == ACTIVE; } +static inline bool rf_is_on(void) { return rf_is_transmitting() || rf_is_receiving(); } /*---------------------------------------------------------------------------*/ static void rf_rx_callback(RF_Handle client, RF_CmdHandle command, RF_EventMask events) { if (events & RF_EventRxEntryDone) { - process_poll(&rf_core_process); + process_poll(&RF_coreProcess); } } /*---------------------------------------------------------------------------*/ -static uint8_t +static CmdResult rf_start_rx() { - rtimer_clock_t t0; - volatile rfc_CMD_PROP_RX_ADV_t *cmd_rx_adv; - - cmd_rx_adv = (rfc_CMD_PROP_RX_ADV_t *)&smartrf_settings_cmd_prop_rx_adv; - cmd_rx_adv->status = IDLE; + gvp_cmd_rx_adv->status = IDLE; /* * Set the max Packet length. This is for the payload only, therefore * 2047 - length offset */ - cmd_rx_adv->maxPktLen = DOT_4G_MAX_FRAME_LEN - cmd_rx_adv->lenOffset; + gvp_cmd_rx_adv->maxPktLen = DOT_4G_MAX_FRAME_LEN - gvp_cmd_rx_adv->lenOffset; - rxCmdHandle = RF_postCmd(rfHandle, (RF_Op*)&smartrf_settings_cmd_prop_rx_adv, RF_PriorityNormal, &rf_rx_callback, RF_EventRxEntryDone); + RF_CmdHandle rxCmdHandle = RF_postCmd(rfHandle, (RF_Op*)gvp_cmd_rx_adv, RF_PriorityNormal, + &rf_rx_callback, RF_EventRxEntryDone); if (rxCmdHandle == RF_ALLOC_ERROR) { - return RF_CORE_CMD_ERROR; + return CMD_ERROR; } - t0 = RTIMER_NOW(); - - while(cmd_rx_adv->status != ACTIVE && - (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ENTER_RX_WAIT_TIMEOUT))); - /* Wait to enter RX */ - if(cmd_rx_adv->status != ACTIVE) { - PRINTF("rf_cmd_prop_rx: CMDSTA=0x%08lx, status=0x%04x\n", - md_status, cmd_rx_adv->status); + const rtimer_clock_t t0 = RTIMER_NOW(); + while (!rf_is_receiving() && + (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ENTER_RX_WAIT_TIMEOUT))); + + if (!rf_is_receiving()) { + PRINTF("RF_cmdPropRxAdv: handle=0x%08lx, status=0x%04x\n", + (unsigned long)rxCmdHandle, gvp_cmd_rx_adv->status); rf_switch_off(); - return RF_CORE_CMD_ERROR; + return CMD_ERROR; } - return RF_CORE_CMD_OK; + return CMD_OK; } /*---------------------------------------------------------------------------*/ -static int +static CmdResult rf_stop_rx(void) { - int ret; - /* If we are off, do nothing */ - if(!rf_receiving()) { - return RF_CORE_CMD_OK; + if (!rf_is_receiving()) { + return CMD_OK; } /* Abort any ongoing operation. Don't care about the result. */ RF_cancelCmd(rfHandle, RF_CMDHANDLE_FLUSH_ALL, 1); - /* Todo: maybe do a RF_pendCmd() to synchronise with command execution. */ + /* Todo: maybe do a RF_pendCmd() to synchronize with command execution. */ - if(smartrf_settings_cmd_prop_rx_adv.status == PROP_DONE_STOPPED || - smartrf_settings_cmd_prop_rx_adv.status == PROP_DONE_ABORT) { - /* Stopped gracefully */ - ENERGEST_OFF(ENERGEST_TYPE_LISTEN); - ret = RF_CORE_CMD_OK; - } else { - PRINTF("rx_off_prop: status=0x%04x\n", - smartrf_settings_cmd_prop_rx_adv.status); - ret = RF_CORE_CMD_ERROR; + if(gvp_cmd_rx_adv->status != PROP_DONE_STOPPED && + gvp_cmd_rx_adv->status != PROP_DONE_ABORT) { + PRINTF("RF_cmdPropRxAdv cancel: status=0x%04x\n", + gvp_cmd_rx_adv->status); + return CMD_ERROR; } - return ret; -}/*---------------------------------------------------------------------------*/ -static uint8_t + /* Stopped gracefully */ + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + return CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static CmdResult rf_run_setup() { - RF_runCmd(rfHandle, (RF_Op*)&smartrf_settings_cmd_prop_radio_div_setup, RF_PriorityNormal, NULL, 0); - if (((volatile RF_Op*)&smartrf_settings_cmd_prop_radio_div_setup)->status != PROP_DONE_OK) { - return RF_CORE_CMD_ERROR; + RF_runCmd(rfHandle, (RF_Op*)gvp_cmd_radio_div_setup, RF_PriorityNormal, NULL, 0); + if (gvp_cmd_radio_div_setup->status != PROP_DONE_OK) { + return CMD_ERROR; } - return RF_CORE_CMD_OK; + return CMD_OK; } /*---------------------------------------------------------------------------*/ static radio_value_t get_rssi(void) { - int8_t rssi = RF_GET_RSSI_ERROR_VAL; - uint8_t was_off = 0; - - if (rf_transmitting()) { - PRINTF("channel_clear: called while in TX\n"); - return RF_CCA_CLEAR; - } else if (!rf_receiving()) { - was_off = 1; - rf_start_rx(); + if (rf_is_transmitting()) { + PRINTF("get_rssi: called while in TX\n"); + return RF_GET_RSSI_ERROR_VAL; } + const bool was_off = !rf_is_receiving(); + if (was_off && rf_start_rx() == CMD_ERROR) { + PRINTF("get_rssi: unable to start RX\n"); + return RF_GET_RSSI_ERROR_VAL; + } + + int8_t rssi = RF_GET_RSSI_ERROR_VAL; while(rssi == RF_GET_RSSI_ERROR_VAL || rssi == 0) { rssi = RF_getRssi(rfHandle); } @@ -369,7 +331,7 @@ get_channel(void) { uint32_t freq_khz; - freq_khz = smartrf_settings_cmd_prop_fs.frequency * 1000; + freq_khz = gvp_cmd_fs->frequency * 1000; /* * For some channels, fractFreq * 1000 / 65536 will return 324.99xx. @@ -377,7 +339,7 @@ get_channel(void) * function returning channel - 1 instead of channel. Thus, we do a quick * positive integer round up. */ - freq_khz += (((smartrf_settings_cmd_prop_fs.fractFreq * 1000) + 65535) / 65536); + freq_khz += (((gvp_cmd_fs->fractFreq * 1000) + 65535) / 65536); return (freq_khz - DOT_15_4G_CHAN0_FREQUENCY) / DOT_15_4G_CHANNEL_SPACING; } @@ -385,20 +347,17 @@ get_channel(void) static void set_channel(uint8_t channel) { - uint32_t new_freq; - uint16_t freq, frac; + uint32_t new_freq = DOT_15_4G_CHAN0_FREQUENCY + (channel * DOT_15_4G_CHANNEL_SPACING); - new_freq = DOT_15_4G_CHAN0_FREQUENCY + (channel * DOT_15_4G_CHANNEL_SPACING); + uint16_t freq = (uint16_t)(new_freq / 1000); + uint16_t frac = (new_freq - (freq * 1000)) * 65536 / 1000; - freq = (uint16_t)(new_freq / 1000); - frac = (new_freq - (freq * 1000)) * 65536 / 1000; + PRINTF("set_channel: %u = 0x%04x.0x%04x (%lu)\n", + channel, freq, frac, new_freq); - PRINTF("set_channel: %u = 0x%04x.0x%04x (%lu)\n", channel, freq, frac, - new_freq); - - smartrf_settings_cmd_prop_radio_div_setup.centerFreq = freq; - smartrf_settings_cmd_prop_fs.frequency = freq; - smartrf_settings_cmd_prop_fs.fractFreq = frac; + gvp_cmd_radio_div_setup->centerFreq = freq; + gvp_cmd_fs->frequency = freq; + gvp_cmd_fs->fractFreq = frac; // Todo: Need to re-run setup command when deviation from previous frequency // is too large @@ -406,16 +365,16 @@ set_channel(uint8_t channel) // We don't care whether the FS command is successful because subsequent // TX and RX commands will tell us indirectly. - RF_postCmd(rfHandle, (RF_Op*)&smartrf_settings_cmd_prop_fs, RF_PriorityNormal, NULL, 0); + RF_postCmd(rfHandle, (RF_Op*)gvp_cmd_fs, RF_PriorityNormal, NULL, 0); } /*---------------------------------------------------------------------------*/ -static uint8_t +static size_t get_tx_power_array_last_element(void) { - const prop_mode_tx_power_config_t *array = TX_POWER_DRIVER; + const RF_TxPower *array = TX_POWER_DRIVER; uint8_t count = 0; - while(array->tx_power != OUTPUT_POWER_UNKNOWN) { + while(array->power != TX_POWER_UNKNOWN) { count++; array++; } @@ -434,21 +393,34 @@ get_tx_power(void) * radio after calling this function. */ static void -set_tx_power(radio_value_t power) +set_tx_power(const radio_value_t power) { - int i; + if (power > OUTPUT_POWER_MAX) + { + tx_power_current = &TX_POWER_DRIVER[0]; + } + else + { + size_t i; + for (i = 0; TX_POWER_DRIVER[i + 1].power != TX_POWER_UNKNOWN; ++i) + { + if (power > TX_POWER_DRIVER[i + 1].dbm) + { + break; + } + } - for(i = get_tx_power_array_last_element(); i >= 0; --i) { - if(power <= TX_POWER_DRIVER[i].dbm) { - /* - * Merely save the value. It will be used in all subsequent usages of - * CMD_PROP_RADIO_DIV_SETP, including one immediately after this function - * has returned - */ tx_power_current = &TX_POWER_DRIVER[i]; + } - return; - } + rfc_CMD_SET_TX_POWER_t cmd_set_tx_power; + memset(&cmd_set_tx_power, 0x00, sizeof(rfc_CMD_SET_TX_POWER_t)); + cmd_set_tx_power.commandNo = CMD_SET_TX_POWER; + cmd_set_tx_power.txPower = tx_power_current->power; + + RF_Stat stat = RF_runImmediateCmd(rfHandle, (uint32_t*)&cmd_set_tx_power); + if (stat != RF_StatCmdDoneSuccess) { + PRINTF("set_tx_power: stat=0x%02X\n", stat); } } /*---------------------------------------------------------------------------*/ @@ -460,7 +432,7 @@ init_rx_buffers(void) for(i = 0; i < PROP_MODE_RX_BUF_CNT; i++) { entry = (rfc_dataEntry_t *)rx_buf[i]; - entry->status = DATA_ENTRY_STATUS_PENDING; + entry->status = DATA_ENTRY_PENDING; entry->config.type = DATA_ENTRY_TYPE_GEN; entry->config.lenSz = DATA_ENTRY_LENSZ_WORD; entry->length = RX_BUF_SIZE - 8; @@ -484,12 +456,11 @@ transmit(unsigned short transmit_len) { int ret; uint8_t was_off = 0; - volatile rfc_CMD_PROP_TX_ADV_t *cmd_tx_adv; - if (rf_transmitting()) { + if (rf_is_transmitting()) { PRINTF("transmit: not allowed while transmitting\n"); return RADIO_TX_ERR; - } else if (rf_receiving()) { + } else if (rf_is_receiving()) { rf_stop_rx(); } else { was_off = 1; @@ -511,18 +482,15 @@ transmit(unsigned short transmit_len) tx_buf[0] = total_length & 0xFF; tx_buf[1] = (total_length >> 8) + DOT_4G_PHR_DW_BIT + DOT_4G_PHR_CRC_BIT; - /* Prepare the CMD_PROP_TX_ADV command */ - cmd_tx_adv = (rfc_CMD_PROP_TX_ADV_t *)&smartrf_settings_cmd_prop_tx_adv; - /* * pktLen: Total number of bytes in the TX buffer, including the header if * one exists, but not including the CRC (which is not present in the buffer) */ - cmd_tx_adv->pktLen = transmit_len + DOT_4G_PHR_LEN; - cmd_tx_adv->pPkt = tx_buf; + gvp_cmd_tx_adv->pktLen = transmit_len + DOT_4G_PHR_LEN; + gvp_cmd_tx_adv->pPkt = tx_buf; // TODO: Register callback - RF_runCmd(rfHandle, (RF_Op*)cmd_tx_adv, RF_PriorityNormal, NULL, 0); + RF_runCmd(rfHandle, (RF_Op*)gvp_cmd_tx_adv, RF_PriorityNormal, NULL, 0); // if (txHandle == RF_ALLOC_ERROR) // { // /* Failure sending the CMD_PROP_TX command */ @@ -538,20 +506,20 @@ transmit(unsigned short transmit_len) // /* Idle away while the command is running */ // RF_pendCmd(rfHandle, txHandle, RF_EventLastCmdDone); - if(cmd_tx_adv->status == PROP_DONE_OK) { + if(gvp_cmd_tx_adv->status == PROP_DONE_OK) { /* Sent OK */ ret = RADIO_TX_OK; } else { /* Operation completed, but frame was not sent */ PRINTF("transmit: Not Sent OK status=0x%04x\n", - cmd_tx_adv->status); + gvp_cmd_tx_adv->status); ret = RADIO_TX_ERR; } ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); /* Workaround. Set status to IDLE */ - cmd_tx_adv->status = IDLE; + gvp_cmd_tx_adv->status = IDLE; if (was_off) { RF_yield(rfHandle); @@ -576,7 +544,7 @@ read_frame(void *buf, unsigned short buf_len) uint8_t *data_ptr = &entry->data; int len = 0; - if(entry->status == DATA_ENTRY_STATUS_FINISHED) { + if(entry->status == DATA_ENTRY_FINISHED) { /* * First 2 bytes in the data entry are the length. @@ -598,7 +566,7 @@ read_frame(void *buf, unsigned short buf_len) /* Move read entry pointer to next entry */ rx_read_entry = entry->pNextEntry; - entry->status = DATA_ENTRY_STATUS_PENDING; + entry->status = DATA_ENTRY_PENDING; } return len; @@ -618,10 +586,10 @@ channel_clear(void) // return RF_CCA_CLEAR; // } - if (rf_transmitting()) { + if (rf_is_transmitting()) { PRINTF("channel_clear: called while in TX\n"); return RF_CCA_CLEAR; - } else if (!rf_receiving()) { + } else if (!rf_is_receiving()) { was_off = 1; rf_start_rx(); } @@ -644,7 +612,7 @@ channel_clear(void) static int receiving_packet(void) { - if(!rf_receiving()) { + if(!rf_is_receiving()) { return 0; } @@ -663,9 +631,9 @@ pending_packet(void) /* Go through all RX buffers and check their status */ do { - if(entry->status == DATA_ENTRY_STATUS_FINISHED) { + if(entry->status == DATA_ENTRY_FINISHED) { rv += 1; - process_poll(&rf_core_process); + process_poll(&RF_coreProcess); } entry = (rfc_dataEntry_t *)entry->pNextEntry; @@ -690,7 +658,7 @@ rf_switch_off(void) // * from within an interrupt context. Abort, but pretend everything is OK. // */ // if(rf_ble_is_active() == RF_BLE_ACTIVE) { -// return RF_CORE_CMD_OK; +// return CMD_OK; // } // Force abort of any ongoing RF operation. @@ -700,9 +668,9 @@ rf_switch_off(void) RF_yield(rfHandle); /* We pulled the plug, so we need to restore the status manually */ - smartrf_settings_cmd_prop_rx_adv.status = IDLE; + gvp_cmd_rx_adv->status = IDLE; - return RF_CORE_CMD_OK; + return CMD_OK; } /*---------------------------------------------------------------------------*/ static radio_result_t @@ -797,13 +765,13 @@ set_value(radio_param_t param, radio_value_t value) } /* If we reach here we had no errors. Apply new settings */ - if (rf_receiving()) { + if (rf_is_receiving()) { rf_stop_rx(); - if (rf_run_setup() != RF_CORE_CMD_OK) { + if (rf_run_setup() != CMD_OK) { return RADIO_RESULT_ERROR; } rf_start_rx(); - } else if (rf_transmitting()) { + } else if (rf_is_transmitting()) { // Should not happen. TX is always synchronous and blocking. // Todo: maybe remove completely here. PRINTF("set_value: cannot apply new value while transmitting. \n"); @@ -833,10 +801,10 @@ rf_init(void) { RF_Params params; RF_Params_init(¶ms); - params.nInactivityTimeout = 0; // disable automatic power-down - // just to not interfere with stack timing + // Disable automatic power-down just to not interfere with stack timing + params.nInactivityTimeout = 0; - rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&smartrf_settings_cmd_prop_radio_div_setup, ¶ms); + rfHandle = RF_open(&rfObject, &RF_propMode, (RF_RadioSetup*)gvp_cmd_radio_div_setup, ¶ms); assert(rfHandle != NULL); /* Initialise RX buffers */ @@ -849,39 +817,16 @@ rf_init(void) /* Initialize current read pointer to first element (used in ISR) */ rx_read_entry = rx_buf[0]; - smartrf_settings_cmd_prop_rx_adv.pQueue = &rx_data_queue; - smartrf_settings_cmd_prop_rx_adv.pOutput = (uint8_t *)&rx_stats; + gvp_cmd_rx_adv->pQueue = &rx_data_queue; + gvp_cmd_rx_adv->pOutput = (uint8_t *)&rx_stats; set_channel(RF_CORE_CHANNEL); ENERGEST_ON(ENERGEST_TYPE_LISTEN); - process_start(&rf_core_process, NULL); + process_start(&RF_coreProcess, NULL); - return 1; -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(rf_core_process, ev, data) -{ - int len; - - PROCESS_BEGIN(); - - while(1) { - PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); - do { - watchdog_periodic(); - packetbuf_clear(); - len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); - - if(len > 0) { - packetbuf_set_datalen(len); - - NETSTACK_MAC.input(); - } - } while(len > 0); - } - PROCESS_END(); + return CMD_OK; } /*---------------------------------------------------------------------------*/ const struct radio_driver prop_mode_driver = { diff --git a/arch/cpu/simplelink/dev/watchdog-arch.c b/arch/cpu/simplelink/dev/watchdog-arch.c index ac137e577..505570ccd 100644 --- a/arch/cpu/simplelink/dev/watchdog-arch.c +++ b/arch/cpu/simplelink/dev/watchdog-arch.c @@ -109,6 +109,7 @@ lock_config(uint32_t status) void watchdog_init(void) { + return; WatchdogReloadSet(CONTIKI_WATCHDOG_TIMER_TOP); lock_config(LOCK_REGISTERS_UNLOCKED); } @@ -119,6 +120,7 @@ watchdog_init(void) void watchdog_start(void) { + return; uint32_t lock_status = unlock_config(); watchdog_periodic(); @@ -133,6 +135,7 @@ watchdog_start(void) void watchdog_periodic(void) { + return; WatchdogReloadSet(CONTIKI_WATCHDOG_TIMER_TOP); WatchdogIntClear(); } @@ -143,6 +146,7 @@ watchdog_periodic(void) void watchdog_stop(void) { + return; uint32_t lock_status = unlock_config(); WatchdogResetDisable(); @@ -156,6 +160,7 @@ watchdog_stop(void) void watchdog_reboot(void) { + return; watchdog_start(); while(1); } diff --git a/arch/cpu/simplelink/rf-settings/rf-ieee-settings.c b/arch/cpu/simplelink/rf-settings/rf-ieee-settings.c new file mode 100644 index 000000000..85dda307d --- /dev/null +++ b/arch/cpu/simplelink/rf-settings/rf-ieee-settings.c @@ -0,0 +1,209 @@ +//********************************************************************************* +// Generated by SmartRF Studio version 2.8.0 ( build #41) +// Compatible with SimpleLink SDK version: CC13x2 SDK 1.60.xx.xx +// Device: CC1352 Rev. 1.0 +// +//********************************************************************************* + + +//********************************************************************************* +// Parameter summary +// IEEE Channel: 11 +// Frequency: 2405 MHz +// SFD: 0 +// Preamble (32 bit): 01010101... +// TX Power: 5 dBm + +#include +#include DeviceFamily_constructPath(driverlib/rf_mailbox.h) +#include DeviceFamily_constructPath(driverlib/rf_common_cmd.h) +#include DeviceFamily_constructPath(driverlib/rf_ieee_cmd.h) +#include +#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_ieee_802_15_4.h) +#include DeviceFamily_constructPath(rf_patches/rf_patch_mce_ieee_802_15_4.h) + +#include +#include + +#include "rf-core.h" + +/*---------------------------------------------------------------------------*/ +/* Default TX power settings for the 2.4 GHz band */ +RF_TxPower RF_ieeeTxPower[] = { + { 5, 0x9330 }, + { 4, 0x9324 }, + { 3, 0x5a1c }, + { 2, 0x4e18 }, + { 1, 0x4214 }, + { 0, 0x3161 }, + { -3, 0x2558 }, + { -6, 0x1d52 }, + { -9, 0x194e }, + { -12, 0x144b }, + { -15, 0x0ccb }, + { -18, 0x0cc9 }, + { -21, 0x0cc7 }, + {-128, 0xFFFF }, +}; +const size_t RF_ieeeTxPowerLen = sizeof(RF_ieeeTxPower) / sizeof(RF_ieeeTxPower[0]); + + +// TI-RTOS RF Mode Object +RF_Mode RF_ieeeMode = +{ + .rfMode = RF_MODE_AUTO, + .cpePatchFxn = &rf_patch_cpe_ieee_802_15_4, + .mcePatchFxn = &rf_patch_mce_ieee_802_15_4, + .rfePatchFxn = 0, +}; + + +// Overrides for CMD_RADIO_SETUP +static uint32_t pOverrides[] = +{ + // override_use_patch_ieee_802_15_4.xml + // PHY: Use MCE RAM patch, RFE ROM bank 1 + MCE_RFE_OVERRIDE(1,0,0,0,1,0), + // override_synth_ieee_802_15_4.xml + // Synth: Use 48 MHz crystal + (uint32_t)0x00408403, + // override_dcdc_rx_tx_common.xml + // DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0xC (DITHER_EN=1 and IPEAK=4). In Rx, use DCDCCTL5[3:0]=0xC (DITHER_EN=1 and IPEAK=4). + (uint32_t)0xFCFC08C3, + (uint32_t)0xFFFFFFFF, +}; + + +// CMD_RADIO_SETUP +// Radio Setup Command for Pre-Defined Schemes +rfc_CMD_RADIO_SETUP_t RF_cmdRadioSetup = +{ + .commandNo = 0x0802, + .status = 0x0000, + .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx + .startTime = 0x00000000, + .startTrigger.triggerType = 0x0, + .startTrigger.bEnaCmd = 0x0, + .startTrigger.triggerNo = 0x0, + .startTrigger.pastTrig = 0x0, + .condition.rule = 0x1, + .condition.nSkip = 0x0, + .mode = 0x01, + .loDivider = 0x00, + .config.frontEndMode = 0x0, + .config.biasMode = 0x0, + .config.analogCfgMode = 0x0, + .config.bNoFsPowerUp = 0x0, + .txPower = 0x001F, + .pRegOverride = pOverrides, +}; + + +// CMD_FS +// Frequency Synthesizer Programming Command +rfc_CMD_FS_t RF_cmdFs = +{ + .commandNo = 0x0803, + .status = 0x0000, + .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx + .startTime = 0x00000000, + .startTrigger.triggerType = 0x0, + .startTrigger.bEnaCmd = 0x0, + .startTrigger.triggerNo = 0x0, + .startTrigger.pastTrig = 0x0, + .condition.rule = 0x1, + .condition.nSkip = 0x0, + .frequency = 0x0965, + .fractFreq = 0x0000, + .synthConf.bTxMode = 0x0, + .synthConf.refFreq = 0x0, + .__dummy0 = 0x00, + .__dummy1 = 0x00, + .__dummy2 = 0x00, + .__dummy3 = 0x0000, +}; + + +// CMD_IEEE_RX +// IEEE 802.15.4 Receive Command +rfc_CMD_IEEE_RX_t RF_cmdIeeeRx = +{ + .commandNo = CMD_IEEE_RX, + .status = IDLE, + .pNextOp = NULL, + .startTime = 0x00000000, + .startTrigger.triggerType = TRIG_NOW, + .condition.rule = COND_NEVER, + .channel = 0, + .rxConfig.bAutoFlushCrc = 0x1, + .rxConfig.bAutoFlushIgn = 0x0, + .rxConfig.bIncludePhyHdr = 0x0, + .rxConfig.bIncludeCrc = 0x1, + .rxConfig.bAppendRssi = 0x1, + .rxConfig.bAppendCorrCrc = 0x1, + .rxConfig.bAppendSrcInd = 0x0, + .rxConfig.bAppendTimestamp = 0x1, + .pRxQ = NULL, + .pOutput = NULL, + .frameFiltOpt.frameFiltEn = 0x0, + .frameFiltOpt.frameFiltStop = 0x1, + .frameFiltOpt.autoAckEn = 0x0, + .frameFiltOpt.slottedAckEn = 0x0, + .frameFiltOpt.autoPendEn = 0x0, + .frameFiltOpt.defaultPend = 0x0, + .frameFiltOpt.bPendDataReqOnly = 0x0, + .frameFiltOpt.bPanCoord = 0x0, + .frameFiltOpt.maxFrameVersion = 0x2, + .frameFiltOpt.bStrictLenFilter = 0x0, + .frameTypes.bAcceptFt0Beacon = 0x1, + .frameTypes.bAcceptFt1Data = 0x1, + .frameTypes.bAcceptFt2Ack = 0x1, + .frameTypes.bAcceptFt3MacCmd = 0x1, + .frameTypes.bAcceptFt4Reserved = 0x1, + .frameTypes.bAcceptFt5Reserved = 0x1, + .frameTypes.bAcceptFt6Reserved = 0x1, + .frameTypes.bAcceptFt7Reserved = 0x1, + .ccaOpt.ccaEnEnergy = 0x1, + .ccaOpt.ccaEnCorr = 0x1, + .ccaOpt.ccaEnSync = 0x1, + .ccaOpt.ccaCorrOp = 0x1, + .ccaOpt.ccaSyncOp = 0x0, + .ccaOpt.ccaCorrThr = 0x3, + .ccaRssiThr = 0x64, + .numExtEntries = 0x00, + .numShortEntries = 0x00, + .pExtEntryList = NULL, + .pShortEntryList = NULL, + .localExtAddr = 0x0000000012345678, + .localShortAddr = 0xABBA, + .localPanID = 0x0000, + .endTrigger.triggerType = TRIG_NEVER, + .endTrigger.bEnaCmd = 0x0, + .endTrigger.triggerNo = 0x0, + .endTrigger.pastTrig = 0x0, + .endTime = 0x00000000, +}; + + +// CMD_IEEE_TX +// IEEE 802.15.4 Transmit Command +rfc_CMD_IEEE_TX_t RF_cmdIeeeTx = +{ + .commandNo = 0x2C01, + .status = 0x0000, + .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx + .startTime = 0x00000000, + .startTrigger.triggerType = 0x0, + .startTrigger.bEnaCmd = 0x0, + .startTrigger.triggerNo = 0x0, + .startTrigger.pastTrig = 0x0, + .condition.rule = 0x1, + .condition.nSkip = 0x0, + .txOpt.bIncludePhyHdr = 0x0, + .txOpt.bIncludeCrc = 0x0, + .txOpt.payloadLenMsb = 0x0, + .payloadLen = 0x1E, + .pPayload = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx + .timeStamp = 0x00000000, +}; + diff --git a/arch/cpu/simplelink/rf-settings/rf-ieee-settings.h b/arch/cpu/simplelink/rf-settings/rf-ieee-settings.h new file mode 100644 index 000000000..898c830cf --- /dev/null +++ b/arch/cpu/simplelink/rf-settings/rf-ieee-settings.h @@ -0,0 +1,26 @@ +#ifndef IEEE_SETTINGS_H_ +#define IEEE_SETTINGS_H_ + + +#include +#include DeviceFamily_constructPath(driverlib/rf_mailbox.h) +#include DeviceFamily_constructPath(driverlib/rf_common_cmd.h) +#include DeviceFamily_constructPath(driverlib/rf_prop_cmd.h) +#include + +#include + +// RF TX power table +extern RF_TxPower RF_ieeeTxPower[]; +extern const size_t RF_ieeeTxPowerLen; + +// TI-RTOS RF Mode Object +extern RF_Mode RF_ieeeMode; + +// RF Core API commands +extern rfc_CMD_RADIO_SETUP_t RF_cmdRadioSetup; +extern rfc_CMD_FS_t RF_cmdFs; +extern rfc_CMD_IEEE_RX_t RF_cmdIeeeRx; +extern rfc_CMD_IEEE_TX_t RF_cmdIeeeTx; + +#endif /* IEEE_SETTINGS_H_ */ diff --git a/arch/cpu/simplelink/rf-settings/proprietary-rf-settings.c b/arch/cpu/simplelink/rf-settings/rf-prop-settings.c similarity index 94% rename from arch/cpu/simplelink/rf-settings/proprietary-rf-settings.c rename to arch/cpu/simplelink/rf-settings/rf-prop-settings.c index 40bca3458..2307acffb 100644 --- a/arch/cpu/simplelink/rf-settings/proprietary-rf-settings.c +++ b/arch/cpu/simplelink/rf-settings/rf-prop-settings.c @@ -34,11 +34,11 @@ #include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_prop.h) #include DeviceFamily_constructPath(rf_patches/rf_patch_rfe_genfsk.h) #include DeviceFamily_constructPath(rf_patches/rf_patch_mce_genfsk.h) -#include "proprietary-rf-settings.h" -#include "contiki.h" -#include "dev/radio.h" -#include +#include +#include + +#include "rf-core.h" /*---------------------------------------------------------------------------*/ /** @@ -52,7 +52,7 @@ /*---------------------------------------------------------------------------*/ /* Default TX power settings for the 779-930MHz band */ -const prop_mode_tx_power_config_t prop_mode_tx_power_779_930[] = { +RF_TxPower RF_propTxPower779_930[] = { { 14, 0xa73f }, { 13, 0xa63f }, /* 12.5 */ { 12, 0xb818 }, @@ -73,7 +73,7 @@ const prop_mode_tx_power_config_t prop_mode_tx_power_779_930[] = { }; /*---------------------------------------------------------------------------*/ /* Default TX power settings for the 431-527MHz band */ -const prop_mode_tx_power_config_t prop_mode_tx_power_431_527[] = { +RF_TxPower RF_propTxPower431_527[] = { { 15, 0x003f }, { 14, 0xbe3f }, /* 13.7 */ { 13, 0x6a0f }, @@ -87,7 +87,7 @@ const prop_mode_tx_power_config_t prop_mode_tx_power_431_527[] = { */ // TI-RTOS RF Mode Object -RF_Mode RF_prop = +RF_Mode RF_propMode = { .rfMode = RF_MODE_AUTO, .cpePatchFxn = &rf_patch_cpe_prop, @@ -136,7 +136,7 @@ static uint32_t pOverrides[] = // CMD_PROP_RADIO_DIV_SETUP // Proprietary Mode Radio Setup Command for All Frequency Bands -rfc_CMD_PROP_RADIO_DIV_SETUP_t smartrf_settings_cmd_prop_radio_div_setup = +rfc_CMD_PROP_RADIO_DIV_SETUP_t rf_cmd_prop_radio_div_setup = { .commandNo = 0x3807, .status = 0x0000, @@ -175,7 +175,7 @@ rfc_CMD_PROP_RADIO_DIV_SETUP_t smartrf_settings_cmd_prop_radio_div_setup = // CMD_FS // Frequency Synthesizer Programming Command -rfc_CMD_FS_t smartrf_settings_cmd_prop_fs = +rfc_CMD_FS_t rf_cmd_prop_fs = { .commandNo = 0x0803, .status = 0x0000, @@ -198,7 +198,7 @@ rfc_CMD_FS_t smartrf_settings_cmd_prop_fs = }; /* CMD_PROP_TX_ADV */ -rfc_CMD_PROP_TX_ADV_t smartrf_settings_cmd_prop_tx_adv = +rfc_CMD_PROP_TX_ADV_t rf_cmd_prop_tx_adv = { .commandNo = 0x3803, .status = 0x0000, @@ -229,7 +229,7 @@ rfc_CMD_PROP_TX_ADV_t smartrf_settings_cmd_prop_tx_adv = }; /*---------------------------------------------------------------------------*/ /* CMD_PROP_RX_ADV */ -rfc_CMD_PROP_RX_ADV_t smartrf_settings_cmd_prop_rx_adv = +rfc_CMD_PROP_RX_ADV_t rf_cmd_prop_rx_adv = { .commandNo = 0x3804, .status = 0x0000, diff --git a/arch/cpu/simplelink/rf-settings/proprietary-rf-settings.h b/arch/cpu/simplelink/rf-settings/rf-prop-settings.h similarity index 56% rename from arch/cpu/simplelink/rf-settings/proprietary-rf-settings.h rename to arch/cpu/simplelink/rf-settings/rf-prop-settings.h index f01ae3498..d0ac01ff3 100644 --- a/arch/cpu/simplelink/rf-settings/proprietary-rf-settings.h +++ b/arch/cpu/simplelink/rf-settings/rf-prop-settings.h @@ -1,5 +1,5 @@ -#ifndef _PROPRIETARY_RF_SETTINGS_H_ -#define _PROPRIETARY_RF_SETTINGS_H_ +#ifndef RF_PROP_SETTINGS_H_ +#define RF_PROP_SETTINGS_H_ //********************************************************************************* // Generated by SmartRF Studio version 2.8.0 ( build #41) @@ -13,15 +13,20 @@ #include DeviceFamily_constructPath(driverlib/rf_prop_cmd.h) #include +#include + +// RF TX power table +extern RF_TxPower RF_propTxPower779_930[]; +extern RF_TxPower RF_propTxPower431_527[]; + // TI-RTOS RF Mode Object -extern RF_Mode RF_prop; +extern RF_Mode RF_propMode; // RF Core API commands -extern rfc_CMD_PROP_RADIO_DIV_SETUP_t smartrf_settings_cmd_prop_radio_div_setup; -extern rfc_CMD_FS_t smartrf_settings_cmd_prop_fs; -extern rfc_CMD_PROP_TX_ADV_t smartrf_settings_cmd_prop_tx_adv; -extern rfc_CMD_PROP_RX_ADV_t smartrf_settings_cmd_prop_rx_adv; +extern rfc_CMD_PROP_RADIO_DIV_SETUP_t rf_cmd_prop_radio_div_setup; +extern rfc_CMD_FS_t rf_cmd_prop_fs; +extern rfc_CMD_PROP_TX_ADV_t rf_cmd_prop_tx_adv; +extern rfc_CMD_PROP_RX_ADV_t rf_cmd_prop_rx_adv; -#endif // _PROPRIETARY_RF_SETTINGS_H_ - +#endif /* RF_PROP_SETTINGS_H_ */ diff --git a/arch/platform/simplelink/platform.c b/arch/platform/simplelink/platform.c index 3647a6134..53cfcefb9 100644 --- a/arch/platform/simplelink/platform.c +++ b/arch/platform/simplelink/platform.c @@ -60,6 +60,7 @@ #include "leds.h" //#include "gpio-interrupt.h" #include "ieee-addr.h" +#include "dev/rf-core.h" #include "uart0-arch.h" #include "sys/clock.h" #include "sys/rtimer.h"