ST / stm-spirit1-rf-driver

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).

Revision:
20:0b738b9ca855
Parent:
16:25dc4b811ad3
Child:
21:d5c10e5742f6
--- a/mbed_driver_api.cpp	Mon Nov 07 10:06:16 2016 +0100
+++ b/mbed_driver_api.cpp	Mon Nov 07 11:28:22 2016 +0100
@@ -8,6 +8,9 @@
 /* Define beyond macro if you want to perform heavy debug tracing also in IRQ context */
 // #define HEAVY_TRACING
 
+/* Define beyond macro if you want to use acknowledgment frames with only 3 bytes */
+#define SHORT_ACK_FRAMES
+
 /*Atmel RF Part Type*/
 // betzw - TODO
 typedef enum
@@ -53,8 +56,10 @@
 #define RF_SIG_ACK_NEEDED (1<<0)
 static Thread rf_ack_sender(osPriorityRealtime);
 static uint8_t rf_rx_sequence;
+#ifndef SHORT_ACK_FRAMES
 static uint8_t rf_src_adr[8];
 static uint8_t rf_src_adr_len = 0;
+#endif
 static bool rf_ack_sent = false;
 
 /* MAC frame helper macros */
@@ -325,8 +330,10 @@
 	uint8_t dst_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
 	uint8_t src_addr_mode = 0x0; /*0x00 = no address 0x01 = reserved 0x02 = 16-bit short address 0x03 = 64-bit extended address */
 	uint8_t min_size = 3; // FCF & SeqNr
+	bool ret = false;
+#ifndef SHORT_ACK_FRAMES
 	bool panid_compr = false;
-	bool ret = false;
+#endif
 
 	if(len < 3) {
     	tr_debug("%s (%d)", __func__, __LINE__);
@@ -338,16 +345,21 @@
 	(*ack_requested) = ((fcf & MAC_FCF_ACK_REQ_BIT_MASK) >> MAC_FCF_ACK_REQ_BIT_SHIFT);
 	dst_addr_mode = ((fcf & MAC_FCF_DST_ADDR_MASK) >> MAC_FCF_DST_ADDR_SHIFT);
 	src_addr_mode = ((fcf & MAC_FCF_SRC_ADDR_MASK) >> MAC_FCF_SRC_ADDR_SHIFT);
+#ifndef SHORT_ACK_FRAMES
 	panid_compr = ((fcf & MAC_FCF_INTRA_PANID_MASK) >> MAC_FCF_INTRA_PANID_SHIFT);
-
-	rf_rx_sequence = rf_rx_buf[2];
+#endif
 
 #ifdef HEAVY_TRACING
 	tr_debug("%s (%d): len=%d, ftype=%x, snr=%x, ack=%d, dst=%x, src=%x, intra=%d", __func__, __LINE__, len, frame_type,
 			rf_rx_buf[2], (*ack_requested), dst_addr_mode, src_addr_mode, panid_compr);
 #endif
 
-	if(frame_type == FC_ACK_FRAME) { // betzw: we just support to forms of ACK frames!
+	if(frame_type == FC_ACK_FRAME) { // betzw: we support up to two different forms of ACK frames!
+#ifdef SHORT_ACK_FRAMES
+		if((len == 3) && (dst_addr_mode == 0x0) && (src_addr_mode == 0x0)) {
+			ret = true;
+		}
+#else // !SHORT_ACK_FRAMES
 		if((dst_addr_mode == 0x3) && (src_addr_mode == 0x3)) {
 			if(panid_compr) { // no PAN ID is in the frame
 				ret = rf_check_mac_address(&rf_rx_buf[3]);
@@ -371,6 +383,8 @@
 #endif
 			}
 		}
+#endif // !SHORT_ACK_FRAMES
+
 #ifdef HEAVY_TRACING
 		tr_debug("%s (%d): ret=%d", __func__, __LINE__, ret);
 #endif
@@ -478,6 +492,9 @@
 	}
 
 	if(ret && (*ack_requested)) {
+		rf_rx_sequence = rf_rx_buf[2];
+
+#ifndef SHORT_ACK_FRAMES
 		if(!panid_compr) { // Src PAN Id is present
 			min_size += 2; // src pan id
 		}
@@ -517,6 +534,7 @@
 #endif
 			return false;
 		}
+#endif // !SHORT_ACK_FRAMES
 	}
 
 #ifdef HEAVY_TRACING
@@ -633,6 +651,59 @@
 	}
 }
 
+#ifdef SHORT_ACK_FRAMES
+static void rf_ack_loop(void) {
+	static uint16_t buffer[2] = {
+			(FC_ACK_FRAME << MAC_FCF_FRAME_TYPE_SHIFT),
+			0x0
+	};
+
+	tr_debug("%s (%d)", __func__, __LINE__);
+
+	do {
+		/* Wait for signal */
+		rf_ack_sender.signal_wait(RF_SIG_ACK_NEEDED);
+
+#ifdef HEAVY_TRACING
+    	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+
+    	/* Get Lock */
+		rf_if_lock();
+
+#ifdef HEAVY_TRACING
+    	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+
+		/* Prepare payload */
+		uint8_t *ptr = (uint8_t*)&buffer[1];
+		ptr[0] = rf_rx_sequence;   // Sequence number
+
+		/* Wait for device not receiving */
+		while(rf_device->is_receiving()) {
+#ifdef HEAVY_TRACING
+	    	tr_debug("%s (%d)", __func__, __LINE__);
+#endif
+			wait_us(10);
+		}
+
+#ifdef HEAVY_TRACING
+    	tr_debug("%s (%d), hdr=%x", __func__, __LINE__, buffer[0], ptr[0];
+#endif
+
+    	/* Set information that we have sent an ACK */
+		rf_ack_sent = true;
+
+        /*Send the packet*/
+        rf_device->send((uint8_t*)buffer, 3);
+
+		/* Release Lock */
+		rf_if_unlock();
+
+		tr_debug("%s (%d)", __func__, __LINE__);
+	} while(true);
+}
+#else // !SHORT_ACK_FRAMES
 static void rf_ack_loop(void) {
 	static uint16_t buffer[6];
 	uint8_t *dest;
@@ -658,11 +729,12 @@
     	/* Prepare header */
 		uint8_t *ptr = (uint8_t*)&buffer[1];
 		if(rf_src_adr_len == 2) {
-			buffer[0] = FC_ACK_FRAME | (0x02 << MAC_FCF_DST_ADDR_SHIFT); // dest PAN id present
+			buffer[0] = (FC_ACK_FRAME << MAC_FCF_FRAME_TYPE_SHIFT) | (0x02 << MAC_FCF_DST_ADDR_SHIFT); // dest PAN id present
 			dest = &ptr[3];
 			msg_len = 7;
 		} else {
-			buffer[0] = FC_ACK_FRAME |
+			buffer[0] =
+					(FC_ACK_FRAME << MAC_FCF_FRAME_TYPE_SHIFT) |
 					(0x03 << MAC_FCF_DST_ADDR_SHIFT) |
 					(0x03 << MAC_FCF_SRC_ADDR_SHIFT) |
 					(0x01 << MAC_FCF_INTRA_PANID_SHIFT); // no PAN IDs
@@ -699,6 +771,7 @@
 		tr_debug("%s (%d)", __func__, __LINE__);
 	} while(true);
 }
+#endif // !SHORT_ACK_FRAMES
 
 static void rf_init(void) {
 	rf_device = &SimpleSpirit1::CreateInstance(D11, D12, D13, D9, D10, D2);