Prototype RF driver for STM Sub-1 GHz RF expansion board based on the SPSGRF-868 module for STM32 Nucleo.
Prototype RF Driver for STM Sub-1 GHz RF Expansion Boards based on the SPSGRF-868 and SPSGRF-915 Modules for STM32 Nucleo
Currently supported boards:
Note, in order to use expansion board X-NUCLEO-IDS01A4 in mbed you need to perform the following HW modifications on the board:
- Unmount resistor
R4 - Mount resistor
R7
Furthermore, on some Nucleo development boards (e.g. the NUCLEO_F429ZI), in order to be able to use Ethernet together with these Sub-1 GHz RF expansion boards, you need to compile this driver with macro SPIRIT1_SPI_MOSI=PB_5 defined, while the development board typically requires some HW modification as e.g. described here!
This driver can be used together with the 6LoWPAN stack (a.k.a. Nanostack).
Diff: SimpleSpirit1.cpp
- Revision:
- 7:e90fa8f6bc6c
- Parent:
- 6:f5d01793bf86
- Child:
- 8:10967c884e38
--- a/SimpleSpirit1.cpp Wed Oct 19 10:04:00 2016 +0200
+++ b/SimpleSpirit1.cpp Fri Oct 21 14:56:55 2016 +0200
@@ -11,6 +11,7 @@
_spirit_rx_pos = 0; \
} while(0)
+#define NDEBUG
#ifndef NDEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
@@ -33,8 +34,8 @@
#define BUSYWAIT_UNTIL(cond, millisecs) \
do { \
- uint32_t start = _busywait_timer.read_us(); \
- while (!(cond) && ((((uint32_t)(_busywait_timer.read_us())) - start) < ((uint32_t)millisecs)*1000U)); \
+ uint32_t start = us_ticker_read(); \
+ while (!(cond) && ((us_ticker_read() - start) < ((uint32_t)millisecs)*1000U)); \
} while(0)
extern volatile SpiritStatus g_xStatus;
@@ -46,7 +47,6 @@
/*** Class Implementation ***/
/** Static Class Variables **/
SimpleSpirit1 *SimpleSpirit1::_singleton = NULL;
-Timer SimpleSpirit1::_busywait_timer;
/** Constructor **/
SimpleSpirit1::SimpleSpirit1(PinName mosi, PinName miso, PinName sclk,
@@ -70,9 +70,6 @@
_spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
_spi.frequency(5000000); // 5MHz
- /* start timer */
- _busywait_timer.start();
-
/* install irq handler */
_irq.fall(Callback<void()>(this, &SimpleSpirit1::IrqHandler));
@@ -153,6 +150,7 @@
spirit_on = OFF;
CLEAR_TXBUF();
CLEAR_RXBUF();
+ _spirit_tx_started = false;
_spirit_rx_err = false;
/* Configure the radio to route the IRQ signal to its GPIO 3 */
@@ -228,6 +226,7 @@
CLEAR_RXBUF();
disable_spirit_irq();
irq_clear_status();
+ receiving_packet = 0;
cmd_strobe(SPIRIT1_STROBE_SABORT);
wait_us(SABORT_WAIT_US);
cmd_strobe(SPIRIT1_STROBE_READY);
@@ -243,9 +242,9 @@
#if NULLRDC_CONF_802154_AUTOACK
if (wants_an_ack) {
- rtimer_txdone = _busywait_timer.read_us();
+ rtimer_txdone = us_ticker_read();
BUSYWAIT_UNTIL(just_got_an_ack, 2);
- rtimer_rxack = _busywait_timer.read_us();
+ rtimer_rxack = us_ticker_read();
if(just_got_an_ack) {
ACKPRINTF("debug_ack: ack received after %u us\n",
@@ -305,11 +304,13 @@
remaining -= to_send;
} while(remaining != 0);
+ _spirit_tx_started = true;
+
+ enable_spirit_irq();
+
BUSYWAIT_UNTIL(SPIRIT1_STATUS() != SPIRIT1_STATE_TX, 50);
MBED_ASSERT(linear_fifo_read_num_elements_tx_fifo() == 0);
- enable_spirit_irq();
-
return RADIO_TX_OK;
}
@@ -317,15 +318,15 @@
void SimpleSpirit1::set_ready_state(void) {
PRINTF("READY IN\n");
- irq_clear_status();
disable_spirit_irq();
if(SPIRIT1_STATUS() == SPIRIT1_STATE_STANDBY) {
cmd_strobe(SPIRIT1_STROBE_READY);
} else if(SPIRIT1_STATUS() == SPIRIT1_STATE_RX) {
+ receiving_packet = 0;
cmd_strobe(SPIRIT1_STROBE_SABORT);
- irq_clear_status();
}
+ irq_clear_status();
enable_spirit_irq();
@@ -339,6 +340,7 @@
disable_spirit_irq();
/* first stop rx/tx */
+ receiving_packet = 0;
cmd_strobe(SPIRIT1_STROBE_SABORT);
/* Clear any pending irqs */
@@ -360,6 +362,7 @@
spirit_on = OFF;
_nr_of_irq_disables = 1;
+ _spirit_tx_started = false;
CLEAR_TXBUF();
CLEAR_RXBUF();
}
@@ -391,6 +394,7 @@
//return 1;
}
CLEAR_RXBUF();
+ receiving_packet = 0;
_spirit_rx_err = false;
/* Enables the mcu to get IRQ from the SPIRIT1 */
@@ -433,6 +437,7 @@
/* Checks if the RX buffer is empty */
if(IS_RXBUF_EMPTY()) {
CLEAR_RXBUF();
+ receiving_packet = 0;
cmd_strobe(SPIRIT1_STROBE_SABORT);
wait_us(SABORT_WAIT_US);
cmd_strobe(SPIRIT1_STROBE_READY);
@@ -487,26 +492,26 @@
spirit_state = OFF;
}
- /* */
disable_spirit_irq();
- cmd_strobe(SPIRIT1_STROBE_SABORT);
- /* SpiritCmdStrobeSabort();*/
- irq_clear_status();
+
+ /* Reset State to Ready */
+ set_ready_state();
{
- uint32_t timeout = _busywait_timer.read_us() + 5000;
+ uint32_t timeout = us_ticker_read() + 5000;
do {
mgmt_refresh_status();
- } while((st_lib_g_x_status.MC_STATE != MC_STATE_READY) && (((uint32_t)_busywait_timer.read_us()) < timeout));
+ } while((st_lib_g_x_status.MC_STATE != MC_STATE_READY) && (us_ticker_read() < timeout));
if(st_lib_g_x_status.MC_STATE != MC_STATE_READY) {
enable_spirit_irq();
return 1;
}
}
- enable_spirit_irq();
/* Stores the RSSI value */
rssi_value = qi_get_rssi_dbm();
+ enable_spirit_irq();
+
/* Puts the SPIRIT1 in its previous state */
if(spirit_state==OFF) {
off();
@@ -531,12 +536,7 @@
}
}
-int SimpleSpirit1::incoming_packet(void)
-{
- return receiving_packet;
-}
-
-int SimpleSpirit1::pending_packet(void)
+int SimpleSpirit1::get_pending_packet(void)
{
PRINTF("PENDING PACKET\n");
return !IS_RXBUF_EMPTY();
@@ -556,6 +556,14 @@
_spirit_rx_err = true;
CLEAR_RXBUF();
cmd_strobe(SPIRIT1_STROBE_FRX);
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
+ CLEAR_TXBUF();
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(-1); // betzw - TODO: define enums for callback values
+ }
+ }
}
/* Transmission error */
@@ -563,6 +571,14 @@
error("IRQ_TX_FIFO_ERROR should never happen!\n");
receiving_packet = 0;
cmd_strobe(SPIRIT1_STROBE_FTX);
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
+ CLEAR_TXBUF();
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(-1); // betzw - TODO: define enums for callback values
+ }
+ }
}
/* The IRQ_VALID_SYNC is used to notify a new packet is coming */
@@ -570,6 +586,14 @@
receiving_packet = 1;
_spirit_rx_err = false;
CLEAR_RXBUF();
+ if(_spirit_tx_started) { // betzw - TOCHECK: is this really correct to be done here?
+ _spirit_tx_started = false;
+ CLEAR_TXBUF();
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(-1); // betzw - TODO: define enums for callback values
+ }
+ }
}
/* RX FIFO almost full */
@@ -593,12 +617,20 @@
/* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
if(x_irq_status.IRQ_TX_DATA_SENT) {
+ MBED_ASSERT(_spirit_tx_started);
+
cmd_strobe(SPIRIT1_STROBE_FRX);
cmd_strobe(SPIRIT1_STROBE_RX);
/* SpiritCmdStrobeRx();*/
CLEAR_TXBUF();
CLEAR_RXBUF();
_spirit_rx_err = false;
+ _spirit_tx_started = false;
+
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(0); // betzw - TODO: define enums for callback values
+ }
}
/* The IRQ_RX_DATA_READY notifies a new packet arrived */
@@ -642,7 +674,7 @@
/* call user callback */
if(_current_irq_callback) {
- _current_irq_callback();
+ _current_irq_callback(1); // betzw - TODO: define enums for callback values
}
}
}
X-NUCLEO-IDS01A4 Sub-1GHz RF Expansion Board