Prototype RF driver for STM Sub-1 GHz RF expansion board based on the SPSGRF-868 module for STM32 Nucleo.
Dependents: DISCO_IOT-wifi_client
Fork of stm-spirit1-rf-driver by
Revision 45:2d01cc9bc761, committed 2016-12-19
- Comitter:
- Wolfgang Betz
- Date:
- Mon Dec 19 12:42:40 2016 +0100
- Parent:
- 44:aedd63cb0ce3
- Child:
- 46:d104e58c5caf
- Commit message:
- Return to avoidance of FIFO overflows
- See comments regarding macro 'RX_FIFO_THR_WA' in file 'spirit1-config.h'
- Reset SPI frequency at 1MHz
- Prepare for performing FIFO handling in IRQ handler
- Disable FIFO overflows by defining macro 'RX_FIFO_THR_WA'
- 'MAX_PACKET_LEN' is 'SPIRIT_MAX_FIFO_LEN-1' (i.e. 95) again
Changed in this revision
--- a/source/SimpleSpirit1.cpp Fri Dec 16 13:46:02 2016 +0100
+++ b/source/SimpleSpirit1.cpp Mon Dec 19 12:42:40 2016 +0100
@@ -51,7 +51,7 @@
/* configure spi */
_spi.format(8, 0); /* 8-bit, mode = 0, [order = SPI_MSB] only available in mbed3 */
- _spi.frequency(100000); // 100kHz // betzw: heuristic value // betzw - NOTE: high frequencies lead to instability of Spirit1
+ _spi.frequency(1000000); // 1MHz // betzw: heuristic value // betzw - NOTE: high frequencies lead to instability of Spirit1
/* install irq handler */
_irq.mode(PullUp);
@@ -110,6 +110,7 @@
irq_set_status(RX_DATA_READY,S_ENABLE);
irq_set_status(RX_DATA_DISC, S_ENABLE);
irq_set_status(TX_FIFO_ERROR, S_ENABLE);
+ irq_set_status(TX_FIFO_ALMOST_EMPTY, S_ENABLE);
irq_set_status(RX_FIFO_ERROR, S_ENABLE);
irq_set_status(RX_FIFO_ALMOST_FULL, S_ENABLE);
irq_set_status(VALID_SYNC, S_ENABLE);
@@ -150,7 +151,7 @@
csma_ca_init(&x_csma_init);
#ifdef RX_FIFO_THR_WA
- linear_fifo_set_almost_full_thr_rx(SPIRIT_MAX_FIFO_LEN-(MAX_PACKET_LEN+1));
+ linear_fifo_set_almost_full_thr_rx(0);
#endif
#ifdef USE_STANDBY_STATE
@@ -159,6 +160,9 @@
#endif // USE_STANDBY_STATE
}
+static volatile int tx_fifo_remaining = 0; // to be used in irq handler
+static volatile int tx_buffer_pos = 0; // to be used in irq handler
+const volatile uint8_t *tx_fifo_buffer = NULL; // to be used in irq handler
int SimpleSpirit1::send(const void *payload, unsigned int payload_len) {
/* Checks if the payload length is supported */
if(payload_len > MAX_PACKET_LEN) {
@@ -187,33 +191,30 @@
csma_ca_state(S_ENABLE); // enable CSMA/CA
- int i = 0;
- int remaining = payload_len;
- const uint8_t *buffer = (const uint8_t*)payload;
- bool tx_triggered = false;
- int8_t fifo_available = (3*SPIRIT_MAX_FIFO_LEN/4) - linear_fifo_read_num_elements_tx_fifo(); // betzw: heuristic value
- do {
- int8_t to_send = (remaining > fifo_available) ? fifo_available : remaining;
+ /* Init buffer & number of bytes to be send */
+ tx_fifo_remaining = payload_len;
+ tx_fifo_buffer = (const uint8_t*)payload;
+
+ int8_t fifo_available = SPIRIT_MAX_FIFO_LEN; // fill-up whole fifo
+ int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
- /* Fill FIFO Buffer */
- if(to_send > 0) {
- spi_write_linear_fifo(to_send, (uint8_t*)&buffer[i]);
- }
+ tx_fifo_remaining -= to_send;
- if(!tx_triggered) {
- cmd_strobe(SPIRIT1_STROBE_TX);
- tx_triggered = true;
- }
+ /* Fill FIFO Buffer */
+ if(to_send > 0) {
+ spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[0]);
+ }
- i += to_send;
- remaining -= to_send;
- fifo_available = SPIRIT_MAX_FIFO_LEN - linear_fifo_read_num_elements_tx_fifo();
- } while(remaining != 0);
-
+ tx_buffer_pos = to_send;
_spirit_tx_started = true;
enable_spirit_irq();
+ /* Start transmitting */
+ cmd_strobe(SPIRIT1_STROBE_TX);
+
+ while(tx_fifo_remaining != 0); // wait until not everything is yet send (evtl. by irq handler)
+
BUSYWAIT_UNTIL(!_spirit_tx_started, STATE_TIMEOUT);
#ifdef HEAVY_DEBUG
debug("\n\r%s (%d): state=%x, _spirit_tx_started=%d\n\r", __func__, __LINE__, SPIRIT1_STATUS()>>1, _spirit_tx_started);
@@ -445,24 +446,49 @@
/* get interrupt source from radio */
irq_get_status(&x_irq_status);
- /* Reception errors */
- if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
+ /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
+ if(x_irq_status.IRQ_TX_DATA_SENT) {
#ifdef DEBUG_IRQ
uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
- debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(tx_fifo_remaining != 0, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
#endif
- rx_timeout_handler();
- if(_spirit_tx_started) {
- _spirit_tx_started = false;
- /* call user callback */
- if(_current_irq_callback) {
- _current_irq_callback(TX_ERR);
- }
+
+ tx_fifo_buffer = NULL;
+ _spirit_tx_started = false;
+
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_DONE);
}
- /* Disable handling of other RX flags */
- x_irq_status.IRQ_RX_DATA_READY = x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
+ /* Disable handling of other TX flags */
+ x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY = x_irq_status.IRQ_TX_FIFO_ERROR = S_RESET;
+ }
+
+ /* The IRQ_TX_FIFO_ALMOST_EMPTY notifies an nearly empty TX fifo */
+ if(x_irq_status.IRQ_TX_FIFO_ALMOST_EMPTY) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug_if(!((*tmp) & IRQ_TX_FIFO_ALMOST_EMPTY_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+ debug_if(tx_fifo_buffer == NULL, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+
+ int8_t fifo_available = SPIRIT_MAX_FIFO_LEN/2; // fill-up half fifo
+ int8_t to_send = (tx_fifo_remaining > fifo_available) ? fifo_available : tx_fifo_remaining;
+
+ tx_fifo_remaining -= to_send;
+
+ /* Fill FIFO Buffer */
+ if(to_send > 0) {
+ spi_write_linear_fifo(to_send, (uint8_t*)&tx_fifo_buffer[tx_buffer_pos]);
+ }
+ tx_buffer_pos += to_send;
+
+ /* Disable handling of other TX flags */
+ x_irq_status.IRQ_TX_FIFO_ERROR = S_RESET;
}
/* Transmission error */
@@ -480,24 +506,8 @@
}
}
- /* Disable handling of other TX flags */
- x_irq_status.IRQ_TX_DATA_SENT = S_RESET;
- }
-
- /* The IRQ_TX_DATA_SENT notifies the packet received. Puts the SPIRIT1 in RX */
- if(x_irq_status.IRQ_TX_DATA_SENT) {
-#ifdef DEBUG_IRQ
- uint32_t *tmp = (uint32_t*)&x_irq_status;
- debug_if(!_spirit_tx_started, "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
- debug_if(!((*tmp) & IRQ_TX_DATA_SENT_MASK), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
-#endif
-
- _spirit_tx_started = false;
-
- /* call user callback */
- if(_current_irq_callback) {
- _current_irq_callback(TX_DONE);
- }
+ /* reset data still to be sent */
+ tx_fifo_remaining = 0;
}
/* The IRQ_RX_DATA_READY notifies a new packet arrived */
@@ -540,7 +550,7 @@
}
/* Disable handling of other RX flags */
- x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
+ x_irq_status.IRQ_RX_FIFO_ERROR = x_irq_status.IRQ_RX_FIFO_ALMOST_FULL = S_RESET;
}
}
@@ -559,7 +569,6 @@
spi_read_linear_fifo(fifo_available, &spirit_rx_buf[_spirit_rx_pos]);
_spirit_rx_pos += fifo_available;
-#if 1
spirit_rx_len = pkt_basic_get_received_pkt_length();
#ifdef DEBUG_IRQ
@@ -580,8 +589,25 @@
_current_irq_callback(RX_DONE);
}
}
-#endif // 0
+ /* Disable handling of other RX flags */
+ x_irq_status.IRQ_RX_FIFO_ERROR = S_RESET;
+ }
+ }
+ /* Reception errors */
+ if((x_irq_status.IRQ_RX_FIFO_ERROR) || (x_irq_status.IRQ_RX_DATA_DISC)) {
+#ifdef DEBUG_IRQ
+ uint32_t *tmp = (uint32_t*)&x_irq_status;
+ debug("\n\r%s (%d): irq=%x\n\r", __func__, __LINE__, *tmp);
+ debug_if(!((*tmp) & (IRQ_RX_FIFO_ERROR_MASK | IRQ_RX_DATA_DISC_MASK)), "\n\rAssert failed in: %s (%d)\n\r", __func__, __LINE__);
+#endif
+ rx_timeout_handler();
+ if(_spirit_tx_started) {
+ _spirit_tx_started = false;
+ /* call user callback */
+ if(_current_irq_callback) {
+ _current_irq_callback(TX_ERR);
+ }
}
}
--- a/source/libs/Contiki_STM32_Library/spirit1-config.h Fri Dec 16 13:46:02 2016 +0100 +++ b/source/libs/Contiki_STM32_Library/spirit1-config.h Mon Dec 19 12:42:40 2016 +0100 @@ -43,22 +43,19 @@ /*---------------------------------------------------------------------------*/ /* Sometimes Spirit1 seems to NOT deliver (correctly) the 'IRQ_RX_DATA_READY' - * event. + * event for packets which have a length which is close to a multiple of + * RX FIFO size. Furthermore, in these cases also the content delivery seems + * to be compromised as well as the generation of RX/TX FIFO errors. * This can be avoided by reducing the maximum packet length to a value which * is lower than the RX FIFO size. - * The mbed driver currently implements another workaround to this which allows - * stable packet delivery of packets with maximum length up to 128 bytes - * (which is the recommended 6LoWPAN payload length). + * * Enable beyond macro if you want to use the version of the driver which avoids * FIFO overflows by reducing packet length. * * NOTE: the non delivery of event 'IRQ_RX_DATA_READY' MUST still be * investigated further deeply (both on HW & SW level)! - * Furthermore, the current limit of 128 bytes should also be overcome, - * which again requires a further analysis of the RX process, which - * currently seems to run into RX FIFO (most likely) overflow situations. */ -// #define RX_FIFO_THR_WA +#define RX_FIFO_THR_WA /** * The MAX_PACKET_LEN is an arbitrary value used to define the two array @@ -69,7 +66,7 @@ #ifdef RX_FIFO_THR_WA #define MAX_PACKET_LEN (SPIRIT_MAX_FIFO_LEN-1) #else -#define MAX_PACKET_LEN (128) // betzw - WAS: SPIRIT_MAX_FIFO_LEN, but LEN_WIDTH is set to 7 so the variable payload length is theoretically from 0 to 255 bytes +#define MAX_PACKET_LEN (255) // betzw - WAS: SPIRIT_MAX_FIFO_LEN, but LEN_WIDTH is set to 7 so the variable payload length is theoretically from 0 to 255 bytes #endif /*---------------------------------------------------------------------------*/
--- a/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Irq.h Fri Dec 16 13:46:02 2016 +0100 +++ b/source/libs/spirit1/SPIRIT1_Library/Inc/SPIRIT_Irq.h Mon Dec 19 12:42:40 2016 +0100 @@ -211,7 +211,8 @@ } SpiritIrqs; // betzw: uint32_t masks -#define IRQ_RX_FIFO_ALMOST_FULL_MASK (0x00020000) /* (1<<16) */ +#define IRQ_TX_FIFO_ALMOST_EMPTY_MASK (0x00010000) /* (1<<16) */ +#define IRQ_RX_FIFO_ALMOST_FULL_MASK (0x00020000) /* (1<<17) */ #define IRQ_VALID_SYNC_MASK (0x00200000) /* (1<<21) */ #define IRQ_RX_DATA_READY_MASK (0x01000000) /* (1<<24) */ #define IRQ_RX_DATA_DISC_MASK (0x02000000) /* (1<<25) */
