47 #include PLATFORM_HEADER
65 #define LED_ACTIVITY 0
67 #ifdef ST_CONF_RADIO_AUTOACK
68 #define ST_RADIO_AUTOACK ST_CONF_RADIO_AUTOACK
70 #define ST_RADIO_AUTOACK 0
73 #if RDC_CONF_DEBUG_LED
74 #define LED_RDC RDC_CONF_DEBUG_LED
76 #define LED_ACTIVITY 1
83 #define PRINTF(...) printf(__VA_ARGS__)
85 #define PRINTF(...) do {} while (0)
89 #define LED_TX_ON() leds_on(LEDS_GREEN)
90 #define LED_TX_OFF() leds_off(LEDS_GREEN)
91 #define LED_RX_ON() do { \
96 #define LED_RX_OFF() do { \
101 #define LED_RDC_ON() do { \
106 #define LED_RDC_OFF() do { \
108 leds_off(LEDS_RED); \
117 #define LED_RDC_OFF()
120 #if RDC_CONF_HARDWARE_CSMA
122 #define MAC_RETRIES 0
126 #define MAC_RETRIES 1
130 int8_t mac_retries_left;
131 #define INIT_RETRY_CNT() (mac_retries_left = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS))
132 #define DEC_RETRY_CNT() (mac_retries_left--)
133 #define RETRY_CNT_GTZ() (mac_retries_left > 0)
135 #define INIT_RETRY_CNT()
136 #define DEC_RETRY_CNT()
137 #define RETRY_CNT_GTZ() 0
143 #ifndef RADIO_WAIT_FOR_PACKET_SENT
144 #define RADIO_WAIT_FOR_PACKET_SENT 1
147 #define TO_PREV_STATE() do { \
148 if(onoroff == OFF){ \
150 ENERGEST_OFF(ENERGEST_TYPE_LISTEN); \
153 #if RDC_CONF_HARDWARE_CSMA
154 #define ST_RADIO_CHECK_CCA FALSE
155 #define ST_RADIO_CCA_ATTEMPT_MAX 0
156 #define ST_BACKOFF_EXP_MIN 0
157 #define ST_BACKOFF_EXP_MAX 0
159 #define ST_RADIO_CHECK_CCA TRUE
160 #define ST_RADIO_CCA_ATTEMPT_MAX 4
161 #define ST_BACKOFF_EXP_MIN 2
162 #define ST_BACKOFF_EXP_MAX 6
165 const RadioTransmitConfig radioTransmitConfig = {
168 ST_RADIO_CCA_ATTEMPT_MAX,
175 #define MAC_RETRIES 0
181 #define RADIO_RXBUFS 1
185 static uint8_t stm32w_rxbufs[RADIO_RXBUFS][STM32W_MAX_PACKET_LEN + 1];
188 static volatile int8_t first = -1, last = 0;
190 static const int8_t first = 0, last = 0;
194 #define CLEAN_RXBUFS() do{first = -1; last = 0;}while(0)
195 #define RXBUFS_EMPTY() (first == -1)
199 int8_t first_tmp = first;
200 return first_tmp == last;
203 #define CLEAN_RXBUFS() (stm32w_rxbufs[0][0] = 0)
204 #define RXBUFS_EMPTY() (stm32w_rxbufs[0][0] == 0)
205 #define RXBUFS_FULL() (stm32w_rxbufs[0][0] != 0)
209 __attribute__ ((aligned(2))) stm32w_txbuf[STM32W_MAX_PACKET_LEN + 1];
212 #define CLEAN_TXBUF() (stm32w_txbuf[0] = 0)
213 #define TXBUF_EMPTY() (stm32w_txbuf[0] == 0)
214 #define CHECKSUM_LEN 2
222 #define BUSYWAIT_UNTIL(cond, max_time) \
226 while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
229 #define GET_LOCK() locked++
231 static volatile uint8_t onoroff = OFF;
232 static uint8_t receiving_packet = 0;
233 static int8_t last_rssi;
235 static uint8_t locked;
236 static volatile uint8_t is_transmit_ack;
245 PROCESS(stm32w_radio_process,
"STM32W radio driver");
247 static int stm32w_radio_init(
void);
249 static int stm32w_radio_prepare(
const void *payload,
250 unsigned short payload_len);
251 static int stm32w_radio_transmit(
unsigned short payload_len);
253 static int stm32w_radio_send(
const void *data,
unsigned short len);
255 static int stm32w_radio_read(
void *buf,
unsigned short bufsize);
257 static int stm32w_radio_channel_clear(
void);
259 static int stm32w_radio_receiving_packet(
void);
261 static int stm32w_radio_pending_packet(
void);
263 static int stm32w_radio_on(
void);
265 static int stm32w_radio_off(
void);
267 static int add_to_rxbuf(uint8_t * src);
269 static int read_from_rxbuf(
void *dest,
unsigned short len);
272 static radio_result_t
276 return RADIO_RESULT_INVALID_VALUE;
279 case RADIO_PARAM_POWER_MODE:
280 *value = onoroff == ON ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
281 return RADIO_RESULT_OK;
282 case RADIO_PARAM_CHANNEL:
283 *value = ST_RadioGetChannel();
284 return RADIO_RESULT_OK;
285 case RADIO_PARAM_PAN_ID:
287 return RADIO_RESULT_OK;
288 case RADIO_PARAM_16BIT_ADDR:
290 return RADIO_RESULT_OK;
291 case RADIO_PARAM_RX_MODE:
297 *value |= RADIO_RX_MODE_AUTOACK;
299 return RADIO_RESULT_OK;
300 case RADIO_PARAM_TXPOWER:
301 *value = ST_RadioGetPower();
302 return RADIO_RESULT_OK;
303 case RADIO_PARAM_CCA_THRESHOLD:
304 *value = ST_RadioGetEdCcaThreshold();
305 return RADIO_RESULT_OK;
306 case RADIO_PARAM_RSSI:
307 *value = ST_RadioEnergyDetection();
308 return RADIO_RESULT_OK;
310 case RADIO_CONST_CHANNEL_MIN:
311 *value = ST_MIN_802_15_4_CHANNEL_NUMBER;
312 return RADIO_RESULT_OK;
313 case RADIO_CONST_CHANNEL_MAX:
314 *value = ST_MAX_802_15_4_CHANNEL_NUMBER;
315 return RADIO_RESULT_OK;
317 case RADIO_CONST_TXPOWER_MIN:
318 *value = MIN_RADIO_POWER;
319 return RADIO_RESULT_OK;
320 case RADIO_CONST_TXPOWER_MAX:
321 *value = MAX_RADIO_POWER;
322 return RADIO_RESULT_OK;
325 return RADIO_RESULT_NOT_SUPPORTED;
329 static radio_result_t
333 case RADIO_PARAM_POWER_MODE:
334 if(value == RADIO_POWER_MODE_ON) {
336 return RADIO_RESULT_OK;
338 if(value == RADIO_POWER_MODE_OFF) {
340 return RADIO_RESULT_OK;
342 return RADIO_RESULT_INVALID_VALUE;
343 case RADIO_PARAM_CHANNEL:
344 if(value < ST_MIN_802_15_4_CHANNEL_NUMBER ||
345 value > ST_MAX_802_15_4_CHANNEL_NUMBER) {
346 return RADIO_RESULT_INVALID_VALUE;
349 return RADIO_RESULT_ERROR;
351 return RADIO_RESULT_OK;
352 case RADIO_PARAM_PAN_ID:
354 return RADIO_RESULT_OK;
355 case RADIO_PARAM_16BIT_ADDR:
357 return RADIO_RESULT_OK;
358 case RADIO_PARAM_RX_MODE:
360 RADIO_RX_MODE_AUTOACK)) {
361 return RADIO_RESULT_INVALID_VALUE;
365 return RADIO_RESULT_OK;
366 case RADIO_PARAM_TXPOWER:
367 if(value < MIN_RADIO_POWER || value > MAX_RADIO_POWER) {
368 return RADIO_RESULT_INVALID_VALUE;
370 if(ST_RadioSetPower((int8_t)value) !=
ST_SUCCESS) {
371 return RADIO_RESULT_INVALID_VALUE;
373 return RADIO_RESULT_OK;
374 case RADIO_PARAM_CCA_THRESHOLD:
375 ST_RadioSetEdCcaThreshold((int8_t)value);
376 return RADIO_RESULT_OK;
378 return RADIO_RESULT_NOT_SUPPORTED;
382 static radio_result_t
383 get_object(radio_param_t param,
void *dest,
size_t size)
385 const uint8_t *eui64;
389 if(param == RADIO_PARAM_64BIT_ADDR) {
390 if(size < 8 || !dest) {
391 return RADIO_RESULT_INVALID_VALUE;
395 return RADIO_RESULT_ERROR;
398 for(i = 0; i < 8; i++) {
399 target[i] = eui64[7 - i];
401 return RADIO_RESULT_OK;
403 return RADIO_RESULT_NOT_SUPPORTED;
406 static radio_result_t
407 set_object(radio_param_t param,
const void *src,
size_t size)
409 return RADIO_RESULT_NOT_SUPPORTED;
414 stm32w_radio_prepare,
415 stm32w_radio_transmit,
418 stm32w_radio_channel_clear,
419 stm32w_radio_receiving_packet,
420 stm32w_radio_pending_packet,
430 stm32w_radio_init(
void)
433 ST_RadioSetChannel(RF_CHANNEL);
437 ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
445 #if ST_RADIO_AUTOACK && !(UIP_CONF_LL_802154 && LINKADDR_CONF_SIZE==8)
446 #error "Autoack and address filtering can only be used with EUI 64"
458 stm32w_radio_set_promiscous(uint8_t
on)
468 stm32w_radio_set_channel(uint8_t channel)
470 if (ST_RadioSetChannel(channel) ==
ST_SUCCESS) {
482 while(!TXBUF_EMPTY()) {
484 PRINTF(
"stm32w: tx buffer full.\r\n");
494 stm32w_radio_prepare(
const void *payload,
unsigned short payload_len)
496 if(payload_len > STM32W_MAX_PACKET_LEN) {
497 PRINTF(
"stm32w: payload length=%d is too long.\r\n", payload_len);
500 #if !RADIO_WAIT_FOR_PACKET_SENT
507 PRINTF(
"stm32w: tx buffer full.\r\n");
517 memcpy(stm32w_txbuf + 1, payload, payload_len);
523 stm32w_radio_transmit(
unsigned short payload_len)
525 stm32w_txbuf[0] = payload_len + CHECKSUM_LEN;
529 PRINTF(
"stm32w: Radio is off, turning it on.\r\n");
531 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
533 #if RADIO_WAIT_FOR_PACKET_SENT
538 if(ST_RadioTransmit(stm32w_txbuf) ==
ST_SUCCESS) {
539 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
540 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
541 PRINTF(
"stm32w: sending %d bytes\r\n", payload_len);
544 for(uint8_t c = 1; c <= stm32w_txbuf[0] - 2; c++) {
545 PRINTF(
"%x:", stm32w_txbuf[c]);
550 #if RADIO_WAIT_FOR_PACKET_SENT
553 PRINTF(
"stm32w: unknown tx error.\r\n");
568 return RADIO_TX_NOACK;
583 #if RADIO_WAIT_FOR_PACKET_SENT
588 PRINTF(
"stm32w: transmission never started.\r\n");
597 stm32w_radio_send(
const void *payload,
unsigned short payload_len)
599 if (stm32w_radio_prepare(payload, payload_len) == RADIO_TX_ERR) {
602 return stm32w_radio_transmit(payload_len);
606 stm32w_radio_channel_clear(
void)
608 return ST_RadioChannelIsClear();
612 stm32w_radio_receiving_packet(
void)
614 return receiving_packet;
618 stm32w_radio_pending_packet(
void)
620 return !RXBUFS_EMPTY();
624 stm32w_radio_off(
void)
630 PRINTF(
"stm32w: try to off while sending/receiving (lock=%u).\r\n",
635 if(onoroff == ON && TXBUF_EMPTY() && !receiving_packet) {
642 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
649 stm32w_radio_on(
void)
651 PRINTF(
"stm32w: turn radio on\n");
657 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
664 stm32w_radio_is_on(
void)
666 return onoroff == ON;
671 boolean ackFramePendingSet,
672 uint32_t time, uint16_t errors, int8_t rssi)
675 PRINTF(
"stm32w: incomming packet received\n");
676 receiving_packet = 0;
679 if(add_to_rxbuf(packet)) {
687 BUSYWAIT_UNTIL(!is_transmit_ack, RTIMER_SECOND / 1500);
692 ST_RadioTxAckIsrCallback(
void)
705 uint32_t txSyncTime,
boolean framePending)
707 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
708 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
711 last_tx_status = status;
716 if(RETRY_CNT_GTZ()) {
720 if(ST_RadioTransmit(stm32w_txbuf) ==
ST_SUCCESS) {
721 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
722 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
723 PRINTF(
"stm32w: retransmission.\r\n");
728 PRINTF(
"stm32w: retransmission failed.\r\n");
737 PRINTF(
"stm32w: return status TX_END\r\n");
739 PRINTF(
"stm32w: return status TX_END_NOACK\r\n");
741 PRINTF(
"stm32w: return status TX_END_CCA_FAIL\r\n");
743 PRINTF(
"stm32w: return status TX_END_UNDERFLOW\r\n");
745 PRINTF(
"stm32w: return status TX_END_INCOMPLETE\r\n");
752 receiving_packet = 1;
759 receiving_packet = 1;
767 PRINTF(
"stm32w_radio_process: started\r\n");
771 PRINTF(
"stm32w_radio_process: calling receiver callback\r\n");
774 for(uint8_t c = 1; c <= RCVD_PACKET_LEN; c++) {
775 PRINTF(
"%x", stm32w_rxbuf[c]);
784 NETSTACK_RDC.input();
786 if(!RXBUFS_EMPTY()) {
799 stm32w_radio_read(
void *buf,
unsigned short bufsize)
801 return read_from_rxbuf(buf, bufsize);
807 PRINTF(
"stm32w: radio overflow\r\n");
821 add_to_rxbuf(uint8_t *src)
827 memcpy(stm32w_rxbufs[last], src, src[0] + 1);
829 last = (last + 1) % RADIO_RXBUFS;
839 read_from_rxbuf(
void *dest,
unsigned short len)
845 if(stm32w_rxbufs[first][0] > len) {
848 len = stm32w_rxbufs[first][0];
849 memcpy(dest, stm32w_rxbufs[first] + 1, len);
850 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
854 ATOMIC(first = (first + 1) % RADIO_RXBUFS;
855 int first_tmp = first;
if(first_tmp == last) {
#define TRUE
An alias for one, used for clarity.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
void process_poll(struct process *p)
Request a process to be polled.
Header file for the real-time timer module.
#define ST_PHY_ACK_RECEIVED(x8F)
The expected ACK was received after the last transmission.
boolean ST_RadioDataPendingLongIdIsrCallback(uint8_t *longId)
This function is called by the library after the long address fields of a packet have been received...
void ST_RadioEnableAddressFiltering(boolean enable)
This function enables or disables address filtering on PAN ID, node ID, and EUI 64.
#define __attribute__(nothing)
Define attribute to nothing since it isn't handled by IAR.
Generic set of HAL includes for all platforms.
#define ATOMIC(blah)
A block of code may be made atomic by wrapping it with this macro.
void packetbuf_clear(void)
Clear and reset the packetbuf.
boolean ST_RadioDataPendingShortIdIsrCallback(uint16_t shortId)
This function is called by the library after the short address fields of a packet have been received...
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Return codes for API functions and module definitions.
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define ST_PHY_TX_UNDERFLOW(x88)
The transmit hardware buffer underflowed.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
The structure of a device driver for a radio in Contiki.
STM32W radio driver header file
Header file for the Rime buffer (packetbuf) management
void ST_RadioSetPanId(u16 panId)
This function sets the PAN id of the node.
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
#define ST_SUCCESS(x00)
The generic "no error" message.
void ST_RadioEnableAutoAck(boolean enable)
This function enables or disables automatic transmission of ACKs in response to received packets whic...
void ST_RadioOverflowIsrCallback(void)
This function is called by the library in response to a receive overflow event if this notification i...
void ST_RadioMacTimerCompareIsrCallback(void)
This function is called by the library in response to MAC timer comparison event. ...
void ST_RadioSetNodeId(u16 nodeId)
This function sets the short address of the node.
boolean ST_RadioAutoAckEnabled(void)
This function gets the automatic acknowledgement status of the device.
#define ST_PHY_TX_CCA_FAIL(x8D)
The transmit attempt failed because all CCA attempts indicated that the channel was busy...
#define NULL
The null pointer.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
802.15.4 frame creation and parsing functions
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
void ST_RadioTransmitCompleteIsrCallback(StStatus status, uint32_t txSyncTime, boolean framePending)
This function is called by the library once after each ST_RadioTransmit() call that returned successf...
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
int(* on)(void)
Turn the radio on.
#define CLOCK_SECOND
A second, measured in system clock time.
static int last_tx_status
the result of the last transmitted fragment
void ST_RadioSfdSentIsrCallback(uint32_t sfdSentTime)
This function is called by the library in response to an SFD sent event if this notification has been...
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
void process_start(struct process *p, process_data_t data)
Start a process.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
u16 ST_RadioGetPanId(void)
This function gets the PAN id of the node.
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
void ST_RadioReceiveIsrCallback(uint8_t *packet, boolean ackFramePendingSet, uint32_t time, uint16_t errors, int8_t rssi)
This function is called by the library when a packet has been received.
#define FALSE
An alias for zero, used for clarity.
Header file for Rime statistics
u8 * ST_RadioGetEui64(void)
This function get the EUI 64 of the node.
void halSleepWithOptions(SleepModes sleepMode, uint32_t gpioWakeBitMask)
Puts the microcontroller to sleep in a specified mode, allows the GPIO wake sources to be determined ...
#define ST_MAC_NO_ACK_RECEIVED(x40)
We expected to receive an ACK following the transmission, but the MAC level ACK was never received...
u16 ST_RadioGetNodeId(void)
This function gets the short address of the node.
Include file for the Contiki low-layer network stack (NETSTACK)
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
uint8_t StStatus
Return type for St functions.
boolean ST_RadioAddressFilteringEnabled(void)
This function gets the address filtering status of the device.
int timer_expired(struct timer *t)
Check if a timer has expired.
#define PROCESS_BEGIN()
Define the beginning of a process.