Contiki 3.x
stm32w-radio.c
Go to the documentation of this file.
1 /**
2  * \addtogroup stm32w-cpu
3  *
4  * @{
5  */
6 
7 /*
8  * Copyright (c) 2010, STMicroelectronics.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * 3. The name of the author may not be used to endorse or promote
21  * products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
25  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
28  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
30  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37 
38 /**
39 * \file
40 * Machine dependent STM32W radio code.
41 * \author
42 * Salvatore Pitrulli
43 * Chi-Anh La la@imag.fr
44 * Simon Duquennoy <simonduq@sics.se>
45 */
46 
47 #include PLATFORM_HEADER
48 #include "hal/error.h"
49 #include "hal/hal.h"
50 
51 #include "contiki.h"
52 
53 #include "net/mac/frame802154.h"
54 
55 #include "dev/stm32w-radio.h"
56 #include "net/netstack.h"
57 
58 #include "net/packetbuf.h"
59 #include "net/rime/rimestats.h"
60 #include "sys/rtimer.h"
61 
62 #define DEBUG 0
63 
64 #include "dev/leds.h"
65 #define LED_ACTIVITY 0
66 
67 #ifdef ST_CONF_RADIO_AUTOACK
68 #define ST_RADIO_AUTOACK ST_CONF_RADIO_AUTOACK
69 #else
70 #define ST_RADIO_AUTOACK 0
71 #endif /* ST_CONF_RADIO_AUTOACK */
72 
73 #if RDC_CONF_DEBUG_LED
74 #define LED_RDC RDC_CONF_DEBUG_LED
75 #undef LED_ACTIVITY
76 #define LED_ACTIVITY 1
77 #else
78 #define LED_RDC 0
79 #endif /* RDC_CONF_DEBUG_LED */
80 
81 #if DEBUG > 0
82 #include <stdio.h>
83 #define PRINTF(...) printf(__VA_ARGS__)
84 #else
85 #define PRINTF(...) do {} while (0)
86 #endif /* DEBUG > 0 */
87 
88 #if LED_ACTIVITY
89 #define LED_TX_ON() leds_on(LEDS_GREEN)
90 #define LED_TX_OFF() leds_off(LEDS_GREEN)
91 #define LED_RX_ON() do { \
92  if(LED_RDC == 0){ \
93  leds_on(LEDS_RED); \
94  } \
95  } while (0)
96 #define LED_RX_OFF() do { \
97  if(LED_RDC == 0){ \
98  leds_off(LEDS_RED); \
99  } \
100  } while (0)
101 #define LED_RDC_ON() do { \
102  if(LED_RDC == 1){ \
103  leds_on(LEDS_RED); \
104  } \
105  } while (0)
106 #define LED_RDC_OFF() do { \
107  if(LED_RDC == 1){ \
108  leds_off(LEDS_RED); \
109  } \
110  } while (0)
111 #else
112 #define LED_TX_ON()
113 #define LED_TX_OFF()
114 #define LED_RX_ON()
115 #define LED_RX_OFF()
116 #define LED_RDC_ON()
117 #define LED_RDC_OFF()
118 #endif /* LED_ACTIVITY */
119 
120 #if RDC_CONF_HARDWARE_CSMA
121 #undef MAC_RETRIES
122 #define MAC_RETRIES 0
123 #endif /* RDC_CONF_HARDWARE_CSMA */
124 
125 #ifndef MAC_RETRIES
126 #define MAC_RETRIES 1
127 #endif /* MAC_RETRIES */
128 
129 #if MAC_RETRIES
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)
134 #else
135 #define INIT_RETRY_CNT()
136 #define DEC_RETRY_CNT()
137 #define RETRY_CNT_GTZ() 0
138 #endif /* MAC_RETRIES */
139 
140 
141 /* If set to 1, a send() returns only after the packet has been transmitted.
142  This is necessary if you use the x-mac module, for example. */
143 #ifndef RADIO_WAIT_FOR_PACKET_SENT
144 #define RADIO_WAIT_FOR_PACKET_SENT 1
145 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
146 
147 #define TO_PREV_STATE() do { \
148  if(onoroff == OFF){ \
149  ST_RadioSleep(); \
150  ENERGEST_OFF(ENERGEST_TYPE_LISTEN); \
151  } \
152  } while(0)
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
158 #else /* RDC_CONF_HARDWARE_CSMA */
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
163 #endif /* RDC_CONF_HARDWARE_CSMA */
164 
165 const RadioTransmitConfig radioTransmitConfig = {
166  TRUE, /* waitForAck; */
167  ST_RADIO_CHECK_CCA, /* checkCca;Set to FALSE with low-power MACs. */
168  ST_RADIO_CCA_ATTEMPT_MAX, /* ccaAttemptMax; */
169  ST_BACKOFF_EXP_MIN, /* backoffExponentMin; */
170  ST_BACKOFF_EXP_MAX, /* backoffExponentMax; */
171  TRUE /* appendCrc; */
172 };
173 
174 #undef MAC_RETRIES
175 #define MAC_RETRIES 0
176 
177 /*
178  * The buffers which hold incoming data.
179  */
180 #ifndef RADIO_RXBUFS
181 #define RADIO_RXBUFS 1
182 #endif /* RADIO_RXBUFS */
183 
184 /* +1 because of the first byte, which will contain the length of the packet. */
185 static uint8_t stm32w_rxbufs[RADIO_RXBUFS][STM32W_MAX_PACKET_LEN + 1];
186 
187 #if RADIO_RXBUFS > 1
188 static volatile int8_t first = -1, last = 0;
189 #else /* RADIO_RXBUFS > 1 */
190 static const int8_t first = 0, last = 0;
191 #endif /* RADIO_RXBUFS > 1 */
192 
193 #if RADIO_RXBUFS > 1
194 #define CLEAN_RXBUFS() do{first = -1; last = 0;}while(0)
195 #define RXBUFS_EMPTY() (first == -1)
196 int
197 RXBUFS_FULL()
198 {
199  int8_t first_tmp = first;
200  return first_tmp == last;
201 }
202 #else /* RADIO_RXBUFS > 1 */
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)
206 #endif /* RADIO_RXBUFS > 1 */
207 
208 static uint8_t
209  __attribute__ ((aligned(2))) stm32w_txbuf[STM32W_MAX_PACKET_LEN + 1];
210 
211 
212 #define CLEAN_TXBUF() (stm32w_txbuf[0] = 0)
213 #define TXBUF_EMPTY() (stm32w_txbuf[0] == 0)
214 #define CHECKSUM_LEN 2
215 
216 /*
217  * The transceiver state.
218  */
219 #define ON 0
220 #define OFF 1
221 
222 #define BUSYWAIT_UNTIL(cond, max_time) \
223  do { \
224  rtimer_clock_t t0; \
225  t0 = RTIMER_NOW(); \
226  while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
227  } while(0)
228 
229 #define GET_LOCK() locked++
230 
231 static volatile uint8_t onoroff = OFF;
232 static uint8_t receiving_packet = 0;
233 static int8_t last_rssi;
234 static volatile StStatus last_tx_status;
235 static uint8_t locked;
236 static volatile uint8_t is_transmit_ack;
237 /*--------------------------------------------------------------------------*/
238 static void
239 RELEASE_LOCK(void)
240 {
241  if(locked > 0)
242  locked--;
243 }
244 /*---------------------------------------------------------------------------*/
245 PROCESS(stm32w_radio_process, "STM32W radio driver");
246 /*---------------------------------------------------------------------------*/
247 static int stm32w_radio_init(void);
248 
249 static int stm32w_radio_prepare(const void *payload,
250  unsigned short payload_len);
251 static int stm32w_radio_transmit(unsigned short payload_len);
252 
253 static int stm32w_radio_send(const void *data, unsigned short len);
254 
255 static int stm32w_radio_read(void *buf, unsigned short bufsize);
256 
257 static int stm32w_radio_channel_clear(void);
258 
259 static int stm32w_radio_receiving_packet(void);
260 
261 static int stm32w_radio_pending_packet(void);
262 
263 static int stm32w_radio_on(void);
264 
265 static int stm32w_radio_off(void);
266 
267 static int add_to_rxbuf(uint8_t * src);
268 
269 static int read_from_rxbuf(void *dest, unsigned short len);
270 
271 /*--------------------------------------------------------------------------*/
272 static radio_result_t
273 get_value(radio_param_t param, radio_value_t *value)
274 {
275  if(!value) {
276  return RADIO_RESULT_INVALID_VALUE;
277  }
278  switch(param) {
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:
286  *value = ST_RadioGetPanId();
287  return RADIO_RESULT_OK;
288  case RADIO_PARAM_16BIT_ADDR:
289  *value = ST_RadioGetNodeId();
290  return RADIO_RESULT_OK;
291  case RADIO_PARAM_RX_MODE:
292  *value = 0;
295  }
296  if(ST_RadioAutoAckEnabled()) {
297  *value |= RADIO_RX_MODE_AUTOACK;
298  }
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;
309 
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;
316 
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;
323 
324  default:
325  return RADIO_RESULT_NOT_SUPPORTED;
326  }
327 }
328 /*--------------------------------------------------------------------------*/
329 static radio_result_t
330 set_value(radio_param_t param, radio_value_t value)
331 {
332  switch(param) {
333  case RADIO_PARAM_POWER_MODE:
334  if(value == RADIO_POWER_MODE_ON) {
335  stm32w_radio_on();
336  return RADIO_RESULT_OK;
337  }
338  if(value == RADIO_POWER_MODE_OFF) {
339  stm32w_radio_off();
340  return RADIO_RESULT_OK;
341  }
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;
347  }
348  if(ST_RadioSetChannel(value) != ST_SUCCESS) {
349  return RADIO_RESULT_ERROR;
350  }
351  return RADIO_RESULT_OK;
352  case RADIO_PARAM_PAN_ID:
353  ST_RadioSetPanId(value & 0xffff);
354  return RADIO_RESULT_OK;
355  case RADIO_PARAM_16BIT_ADDR:
356  ST_RadioSetNodeId(value & 0xffff);
357  return RADIO_RESULT_OK;
358  case RADIO_PARAM_RX_MODE:
359  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
360  RADIO_RX_MODE_AUTOACK)) {
361  return RADIO_RESULT_INVALID_VALUE;
362  }
364  ST_RadioEnableAutoAck((value & RADIO_RX_MODE_AUTOACK) != 0);
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;
369  }
370  if(ST_RadioSetPower((int8_t)value) != ST_SUCCESS) {
371  return RADIO_RESULT_INVALID_VALUE;
372  }
373  return RADIO_RESULT_OK;
374  case RADIO_PARAM_CCA_THRESHOLD:
375  ST_RadioSetEdCcaThreshold((int8_t)value);
376  return RADIO_RESULT_OK;
377  default:
378  return RADIO_RESULT_NOT_SUPPORTED;
379  }
380 }
381 /*--------------------------------------------------------------------------*/
382 static radio_result_t
383 get_object(radio_param_t param, void *dest, size_t size)
384 {
385  const uint8_t *eui64;
386  uint8_t *target;
387  int i;
388 
389  if(param == RADIO_PARAM_64BIT_ADDR) {
390  if(size < 8 || !dest) {
391  return RADIO_RESULT_INVALID_VALUE;
392  }
393  eui64 = ST_RadioGetEui64();
394  if(!eui64) {
395  return RADIO_RESULT_ERROR;
396  }
397  target = dest;
398  for(i = 0; i < 8; i++) {
399  target[i] = eui64[7 - i];
400  }
401  return RADIO_RESULT_OK;
402  }
403  return RADIO_RESULT_NOT_SUPPORTED;
404 }
405 /*--------------------------------------------------------------------------*/
406 static radio_result_t
407 set_object(radio_param_t param, const void *src, size_t size)
408 {
409  return RADIO_RESULT_NOT_SUPPORTED;
410 }
411 /*--------------------------------------------------------------------------*/
412 const struct radio_driver stm32w_radio_driver = {
413  stm32w_radio_init,
414  stm32w_radio_prepare,
415  stm32w_radio_transmit,
416  stm32w_radio_send,
417  stm32w_radio_read,
418  stm32w_radio_channel_clear,
419  stm32w_radio_receiving_packet,
420  stm32w_radio_pending_packet,
421  stm32w_radio_on,
422  stm32w_radio_off,
423  get_value,
424  set_value,
425  get_object,
426  set_object
427 };
428 /*---------------------------------------------------------------------------*/
429 static int
430 stm32w_radio_init(void)
431 {
432  /* A channel also needs to be set. */
433  ST_RadioSetChannel(RF_CHANNEL);
434 
435  /* Initialize radio (analog section, digital baseband and MAC). */
436  /* Leave radio powered up in non-promiscuous rx mode. */
437  ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
438 
439  onoroff = OFF;
440  ST_RadioSetPanId(IEEE802154_PANID);
441 
442  CLEAN_RXBUFS();
443  CLEAN_TXBUF();
444 
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"
447 #endif
448  ST_RadioEnableAutoAck(ST_RADIO_AUTOACK);
449  ST_RadioEnableAddressFiltering(ST_RADIO_AUTOACK);
450 
451  locked = 0;
452  process_start(&stm32w_radio_process, NULL);
453 
454  return 0;
455 }
456 /*---------------------------------------------------------------------------*/
457 void
458 stm32w_radio_set_promiscous(uint8_t on)
459 {
460  if(on) {
462  } else {
463  ST_RadioEnableAddressFiltering(ST_RADIO_AUTOACK);
464  }
465 }
466 /*---------------------------------------------------------------------------*/
467 int
468 stm32w_radio_set_channel(uint8_t channel)
469 {
470  if (ST_RadioSetChannel(channel) == ST_SUCCESS) {
471  return 0;
472  } else {
473  return 1;
474  }
475 }
476 /*---------------------------------------------------------------------------*/
477 static int
478 wait_for_tx(void)
479 {
480  struct timer t;
481  timer_set(&t, CLOCK_SECOND / 10);
482  while(!TXBUF_EMPTY()) {
483  if(timer_expired(&t)) {
484  PRINTF("stm32w: tx buffer full.\r\n");
485  return 1;
486  }
487  /* Put CPU in sleep mode. */
489  }
490  return 0;
491 }
492 /*---------------------------------------------------------------------------*/
493 static int
494 stm32w_radio_prepare(const void *payload, unsigned short payload_len)
495 {
496  if(payload_len > STM32W_MAX_PACKET_LEN) {
497  PRINTF("stm32w: payload length=%d is too long.\r\n", payload_len);
498  return RADIO_TX_ERR;
499  }
500 #if !RADIO_WAIT_FOR_PACKET_SENT
501  /*
502  * Check if the txbuf is empty. Wait for a finite time.
503  * This should not occur if we wait for the end of transmission in
504  * stm32w_radio_transmit().
505  */
506  if(wait_for_tx()) {
507  PRINTF("stm32w: tx buffer full.\r\n");
508  return RADIO_TX_ERR;
509  }
510 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
511 
512  /*
513  * Copy to the txbuf.
514  * The first byte must be the packet length.
515  */
516  CLEAN_TXBUF();
517  memcpy(stm32w_txbuf + 1, payload, payload_len);
518 
519  return RADIO_TX_OK;
520 }
521 /*---------------------------------------------------------------------------*/
522 static int
523 stm32w_radio_transmit(unsigned short payload_len)
524 {
525  stm32w_txbuf[0] = payload_len + CHECKSUM_LEN;
526  INIT_RETRY_CNT();
527 
528  if(onoroff == OFF) {
529  PRINTF("stm32w: Radio is off, turning it on.\r\n");
530  ST_RadioWake();
531  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
532  }
533 #if RADIO_WAIT_FOR_PACKET_SENT
534  GET_LOCK();
535 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
536  last_tx_status = -1;
537  LED_TX_ON();
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);
542 
543 #if DEBUG > 1
544  for(uint8_t c = 1; c <= stm32w_txbuf[0] - 2; c++) {
545  PRINTF("%x:", stm32w_txbuf[c]);
546  }
547  PRINTF("\r\n");
548 #endif
549 
550 #if RADIO_WAIT_FOR_PACKET_SENT
551 
552  if(wait_for_tx()) {
553  PRINTF("stm32w: unknown tx error.\r\n");
554  TO_PREV_STATE();
555  LED_TX_OFF();
556  RELEASE_LOCK();
557  return RADIO_TX_ERR;
558  }
559 
560  TO_PREV_STATE();
561  if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED ||
562  last_tx_status == ST_MAC_NO_ACK_RECEIVED) {
563  RELEASE_LOCK();
564  if(last_tx_status == ST_PHY_ACK_RECEIVED) {
565  return RADIO_TX_OK; /* ACK status */
566  } else if(last_tx_status == ST_MAC_NO_ACK_RECEIVED ||
567  last_tx_status == ST_SUCCESS) {
568  return RADIO_TX_NOACK;
569  }
570  }
571  LED_TX_OFF();
572  RELEASE_LOCK();
573  return RADIO_TX_ERR;
574 
575 #else /* RADIO_WAIT_FOR_PACKET_SENT */
576  TO_PREV_STATE();
577  LED_TX_OFF();
578  return RADIO_TX_OK;
579 
580 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
581  }
582 
583 #if RADIO_WAIT_FOR_PACKET_SENT
584  RELEASE_LOCK();
585 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
586  TO_PREV_STATE();
587 
588  PRINTF("stm32w: transmission never started.\r\n");
589  /* TODO: Do we have to retransmit? */
590 
591  CLEAN_TXBUF();
592  LED_TX_OFF();
593  return RADIO_TX_ERR;
594 }
595 /*---------------------------------------------------------------------------*/
596 static int
597 stm32w_radio_send(const void *payload, unsigned short payload_len)
598 {
599  if (stm32w_radio_prepare(payload, payload_len) == RADIO_TX_ERR) {
600  return RADIO_TX_ERR;
601  }
602  return stm32w_radio_transmit(payload_len);
603 }
604 /*---------------------------------------------------------------------------*/
605 static int
606 stm32w_radio_channel_clear(void)
607 {
608  return ST_RadioChannelIsClear();
609 }
610 /*---------------------------------------------------------------------------*/
611 static int
612 stm32w_radio_receiving_packet(void)
613 {
614  return receiving_packet;
615 }
616 /*---------------------------------------------------------------------------*/
617 static int
618 stm32w_radio_pending_packet(void)
619 {
620  return !RXBUFS_EMPTY();
621 }
622 /*---------------------------------------------------------------------------*/
623 static int
624 stm32w_radio_off(void)
625 {
626  /* Any transmit or receive packets in progress are aborted.
627  * Waiting for end of transmission or reception have to be done.
628  */
629  if(locked) {
630  PRINTF("stm32w: try to off while sending/receiving (lock=%u).\r\n",
631  locked);
632  return 0;
633  }
634  /* off only if there is no transmission or reception of packet. */
635  if(onoroff == ON && TXBUF_EMPTY() && !receiving_packet) {
636  LED_RDC_OFF();
637  ST_RadioSleep();
638  onoroff = OFF;
639  CLEAN_TXBUF();
640  CLEAN_RXBUFS();
641 
642  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
643  }
644 
645  return 1;
646 }
647 /*---------------------------------------------------------------------------*/
648 static int
649 stm32w_radio_on(void)
650 {
651  PRINTF("stm32w: turn radio on\n");
652  if(onoroff == OFF) {
653  LED_RDC_ON();
654  ST_RadioWake();
655  onoroff = ON;
656 
657  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
658  }
659 
660  return 1;
661 }
662 /*---------------------------------------------------------------------------*/
663 int
664 stm32w_radio_is_on(void)
665 {
666  return onoroff == ON;
667 }
668 /*---------------------------------------------------------------------------*/
669 void
671  boolean ackFramePendingSet,
672  uint32_t time, uint16_t errors, int8_t rssi)
673 {
674  LED_RX_ON();
675  PRINTF("stm32w: incomming packet received\n");
676  receiving_packet = 0;
677 
678  /* Copy packet into the buffer. It is better to do this here. */
679  if(add_to_rxbuf(packet)) {
680  process_poll(&stm32w_radio_process);
681  last_rssi = rssi;
682  }
683  LED_RX_OFF();
684  GET_LOCK();
685  is_transmit_ack = 1;
686  /* Wait for sending ACK */
687  BUSYWAIT_UNTIL(!is_transmit_ack, RTIMER_SECOND / 1500);
688  RELEASE_LOCK();
689 }
690 /*--------------------------------------------------------------------------*/
691 void
692 ST_RadioTxAckIsrCallback(void)
693 {
694  /*
695  * This callback is for simplemac 1.1.0.
696  * Till now we block (RTIMER_SECOND / 1500)
697  * to prevent radio off during ACK transmission.
698  */
699  is_transmit_ack = 0;
700  /* RELEASE_LOCK(); */
701 }
702 /*--------------------------------------------------------------------------*/
703 void
705  uint32_t txSyncTime, boolean framePending)
706 {
707  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
708  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
709  LED_TX_OFF();
710 
711  last_tx_status = status;
712 
713  if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED) {
714  CLEAN_TXBUF();
715  } else {
716  if(RETRY_CNT_GTZ()) {
717 
718  /* Retransmission */
719  LED_TX_ON();
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");
724  DEC_RETRY_CNT();
725  } else {
726  CLEAN_TXBUF();
727  LED_TX_OFF();
728  PRINTF("stm32w: retransmission failed.\r\n");
729  }
730  } else {
731  CLEAN_TXBUF();
732  }
733  }
734 
735  /* Debug outputs. */
736  if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED) {
737  PRINTF("stm32w: return status TX_END\r\n");
738  } else if(status == ST_MAC_NO_ACK_RECEIVED) {
739  PRINTF("stm32w: return status TX_END_NOACK\r\n");
740  } else if(status == ST_PHY_TX_CCA_FAIL) {
741  PRINTF("stm32w: return status TX_END_CCA_FAIL\r\n");
742  } else if(status == ST_PHY_TX_UNDERFLOW) {
743  PRINTF("stm32w: return status TX_END_UNDERFLOW\r\n");
744  } else {
745  PRINTF("stm32w: return status TX_END_INCOMPLETE\r\n");
746  }
747 }
748 /*--------------------------------------------------------------------------*/
749 boolean
751 {
752  receiving_packet = 1;
753  return FALSE;
754 }
755 /*--------------------------------------------------------------------------*/
756 boolean
758 {
759  receiving_packet = 1;
760  return FALSE;
761 }
762 /*---------------------------------------------------------------------------*/
763 PROCESS_THREAD(stm32w_radio_process, ev, data)
764 {
765  int len;
766  PROCESS_BEGIN();
767  PRINTF("stm32w_radio_process: started\r\n");
768 
769  while(1) {
770  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
771  PRINTF("stm32w_radio_process: calling receiver callback\r\n");
772 
773 #if DEBUG > 1
774  for(uint8_t c = 1; c <= RCVD_PACKET_LEN; c++) {
775  PRINTF("%x", stm32w_rxbuf[c]);
776  }
777  PRINTF("\r\n");
778 #endif
779 
780  packetbuf_clear();
781  len = stm32w_radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
782  if(len > 0) {
784  NETSTACK_RDC.input();
785  }
786  if(!RXBUFS_EMPTY()) {
787  /*
788  * Some data packet still in rx buffer (this happens because process_poll
789  * doesn't queue requests), so stm32w_radio_process needs to be called
790  * again.
791  */
792  process_poll(&stm32w_radio_process);
793  }
794  }
795  PROCESS_END();
796 }
797 /*---------------------------------------------------------------------------*/
798 static int
799 stm32w_radio_read(void *buf, unsigned short bufsize)
800 {
801  return read_from_rxbuf(buf, bufsize);
802 }
803 /*---------------------------------------------------------------------------*/
804 void
806 {
807  PRINTF("stm32w: radio overflow\r\n");
808 }
809 /*---------------------------------------------------------------------------*/
810 void
811 ST_RadioSfdSentIsrCallback(uint32_t sfdSentTime)
812 {
813 }
814 /*---------------------------------------------------------------------------*/
815 void
817 {
818 }
819 /*---------------------------------------------------------------------------*/
820 static int
821 add_to_rxbuf(uint8_t *src)
822 {
823  if(RXBUFS_FULL()) {
824  return 0;
825  }
826 
827  memcpy(stm32w_rxbufs[last], src, src[0] + 1);
828 #if RADIO_RXBUFS > 1
829  last = (last + 1) % RADIO_RXBUFS;
830  if(first == -1) {
831  first = 0;
832  }
833 #endif
834 
835  return 1;
836 }
837 /*---------------------------------------------------------------------------*/
838 static int
839 read_from_rxbuf(void *dest, unsigned short len)
840 {
841  if(RXBUFS_EMPTY()) { /* Buffers are all empty */
842  return 0;
843  }
844 
845  if(stm32w_rxbufs[first][0] > len) { /* Too large packet for dest. */
846  len = 0;
847  } else {
848  len = stm32w_rxbufs[first][0];
849  memcpy(dest, stm32w_rxbufs[first] + 1, len);
850  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
851  }
852 
853 #if RADIO_RXBUFS > 1
854  ATOMIC(first = (first + 1) % RADIO_RXBUFS;
855  int first_tmp = first; if(first_tmp == last) {
856  CLEAN_RXBUFS();}
857  )
858 #else
859  CLEAN_RXBUFS();
860 #endif
861 
862  return len;
863 }
864 /*---------------------------------------------------------------------------*/
865 short
866 last_packet_rssi()
867 {
868  return last_rssi;
869 }
870 /** @} */
#define TRUE
An alias for one, used for clarity.
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:158
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
Header file for the real-time timer module.
#define ST_PHY_ACK_RECEIVED(x8F)
The expected ACK was received after the last transmission.
Definition: error-def.h:814
boolean ST_RadioDataPendingLongIdIsrCallback(uint8_t *longId)
This function is called by the library after the long address fields of a packet have been received...
Definition: stm32w-radio.c:757
Oly the CPU is idled.
Definition: micro-common.h:91
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.
Definition: iar.h:194
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.
Definition: gnu.h:459
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:76
boolean ST_RadioDataPendingShortIdIsrCallback(uint16_t shortId)
This function is called by the library after the short address fields of a packet have been received...
Definition: stm32w-radio.c:750
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
Return codes for API functions and module definitions.
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
A timer.
Definition: timer.h:86
#define ST_PHY_TX_UNDERFLOW(x88)
The transmit hardware buffer underflowed.
Definition: error-def.h:741
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:66
The structure of a device driver for a radio in Contiki.
Definition: radio.h:237
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.
Definition: radio.h:273
#define ST_SUCCESS(x00)
The generic "no error" message.
Definition: error-def.h:45
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...
Definition: stm32w-radio.c:805
void ST_RadioMacTimerCompareIsrCallback(void)
This function is called by the library in response to MAC timer comparison event. ...
Definition: stm32w-radio.c:816
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...
Definition: error-def.h:793
#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...
Definition: radio.h:88
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...
Definition: radio.h:204
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...
Definition: stm32w-radio.c:704
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:280
int(* on)(void)
Turn the radio on.
Definition: radio.h:264
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82
static int last_tx_status
the result of the last transmitted fragment
Definition: sicslowpan.c:210
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...
Definition: stm32w-radio.c:811
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:151
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
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.
Definition: radio.h:270
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.
Definition: stm32w-radio.c:670
#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 ...
Definition: sleep.c:848
#define ST_MAC_NO_ACK_RECEIVED(x40)
We expected to receive an ACK following the transmission, but the MAC level ACK was never received...
Definition: error-def.h:337
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.
Definition: radio.h:286
uint8_t StStatus
Return type for St functions.
Definition: error.h:18
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.
Definition: timer.c:122
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120