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 #define LED_ACTIVITY 1
76 #else
77 #define LED_RDC 0
78 #endif /* RDC_CONF_DEBUG_LED */
79 
80 #if DEBUG > 0
81 #include <stdio.h>
82 #define PRINTF(...) printf(__VA_ARGS__)
83 #else
84 #define PRINTF(...) do {} while (0)
85 #endif /* DEBUG > 0 */
86 
87 #if LED_ACTIVITY
88 #define LED_TX_ON() leds_on(LEDS_GREEN)
89 #define LED_TX_OFF() leds_off(LEDS_GREEN)
90 #define LED_RX_ON() do { \
91  if(LED_RDC == 0){ \
92  leds_on(LEDS_RED); \
93  } \
94  } while (0)
95 #define LED_RX_OFF() do { \
96  if(LED_RDC == 0){ \
97  leds_off(LEDS_RED); \
98  } \
99  } while (0)
100 #define LED_RDC_ON() do { \
101  if(LED_RDC == 1){ \
102  leds_on(LEDS_RED); \
103  } \
104  } while (0)
105 #define LED_RDC_OFF() do { \
106  if(LED_RDC == 1){ \
107  leds_off(LEDS_RED); \
108  } \
109  } while (0)
110 #else
111 #define LED_TX_ON()
112 #define LED_TX_OFF()
113 #define LED_RX_ON()
114 #define LED_RX_OFF()
115 #define LED_RDC_ON()
116 #define LED_RDC_OFF()
117 #endif /* LED_ACTIVITY */
118 
119 #if RDC_CONF_HARDWARE_CSMA
120 #define MAC_RETRIES 0
121 #endif /* RDC_CONF_HARDWARE_CSMA */
122 
123 #ifndef MAC_RETRIES
124 #define MAC_RETRIES 1
125 #endif /* MAC_RETRIES */
126 
127 #if MAC_RETRIES
128 int8_t mac_retries_left;
129 #define INIT_RETRY_CNT() (mac_retries_left = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS))
130 #define DEC_RETRY_CNT() (mac_retries_left--)
131 #define RETRY_CNT_GTZ() (mac_retries_left > 0)
132 #else
133 #define INIT_RETRY_CNT()
134 #define DEC_RETRY_CNT()
135 #define RETRY_CNT_GTZ() 0
136 #endif /* MAC_RETRIES */
137 
138 
139 /* If set to 1, a send() returns only after the packet has been transmitted.
140  This is necessary if you use the x-mac module, for example. */
141 #ifndef RADIO_WAIT_FOR_PACKET_SENT
142 #define RADIO_WAIT_FOR_PACKET_SENT 1
143 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
144 
145 #define TO_PREV_STATE() do { \
146  if(onoroff == OFF){ \
147  ST_RadioSleep(); \
148  ENERGEST_OFF(ENERGEST_TYPE_LISTEN); \
149  } \
150  } while(0)
151 #if RDC_CONF_HARDWARE_CSMA
152 #define ST_RADIO_CHECK_CCA FALSE
153 #define ST_RADIO_CCA_ATTEMPT_MAX 0
154 #define ST_BACKOFF_EXP_MIN 0
155 #define ST_BACKOFF_EXP_MAX 0
156 #else /* RDC_CONF_HARDWARE_CSMA */
157 #define ST_RADIO_CHECK_CCA TRUE
158 #define ST_RADIO_CCA_ATTEMPT_MAX 4
159 #define ST_BACKOFF_EXP_MIN 2
160 #define ST_BACKOFF_EXP_MAX 6
161 #endif /* RDC_CONF_HARDWARE_CSMA */
162 
163 const RadioTransmitConfig radioTransmitConfig = {
164  TRUE, /* waitForAck; */
165  ST_RADIO_CHECK_CCA, /* checkCca;Set to FALSE with low-power MACs. */
166  ST_RADIO_CCA_ATTEMPT_MAX, /* ccaAttemptMax; */
167  ST_BACKOFF_EXP_MIN, /* backoffExponentMin; */
168  ST_BACKOFF_EXP_MAX, /* backoffExponentMax; */
169  TRUE /* appendCrc; */
170 };
171 
172 #define MAC_RETRIES 0
173 
174 /*
175  * The buffers which hold incoming data.
176  */
177 #ifndef RADIO_RXBUFS
178 #define RADIO_RXBUFS 1
179 #endif /* RADIO_RXBUFS */
180 
181 /* +1 because of the first byte, which will contain the length of the packet. */
182 static uint8_t stm32w_rxbufs[RADIO_RXBUFS][STM32W_MAX_PACKET_LEN + 1];
183 
184 #if RADIO_RXBUFS > 1
185 static volatile int8_t first = -1, last = 0;
186 #else /* RADIO_RXBUFS > 1 */
187 static const int8_t first = 0, last = 0;
188 #endif /* RADIO_RXBUFS > 1 */
189 
190 #if RADIO_RXBUFS > 1
191 #define CLEAN_RXBUFS() do{first = -1; last = 0;}while(0)
192 #define RXBUFS_EMPTY() (first == -1)
193 int
194 RXBUFS_FULL()
195 {
196  int8_t first_tmp = first;
197  return first_tmp == last;
198 }
199 #else /* RADIO_RXBUFS > 1 */
200 #define CLEAN_RXBUFS() (stm32w_rxbufs[0][0] = 0)
201 #define RXBUFS_EMPTY() (stm32w_rxbufs[0][0] == 0)
202 #define RXBUFS_FULL() (stm32w_rxbufs[0][0] != 0)
203 #endif /* RADIO_RXBUFS > 1 */
204 
205 static uint8_t
206  __attribute__ ((aligned(2))) stm32w_txbuf[STM32W_MAX_PACKET_LEN + 1];
207 
208 
209 #define CLEAN_TXBUF() (stm32w_txbuf[0] = 0)
210 #define TXBUF_EMPTY() (stm32w_txbuf[0] == 0)
211 #define CHECKSUM_LEN 2
212 
213 /*
214  * The transceiver state.
215  */
216 #define ON 0
217 #define OFF 1
218 
219 #define BUSYWAIT_UNTIL(cond, max_time) \
220  do { \
221  rtimer_clock_t t0; \
222  t0 = RTIMER_NOW(); \
223  while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
224  } while(0)
225 
226 #define GET_LOCK() locked++
227 
228 static volatile uint8_t onoroff = OFF;
229 static uint8_t receiving_packet = 0;
230 static int8_t last_rssi;
231 static volatile StStatus last_tx_status;
232 static uint8_t locked;
233 static volatile uint8_t is_transmit_ack;
234 /*--------------------------------------------------------------------------*/
235 static void
236 RELEASE_LOCK(void)
237 {
238  if(locked > 0)
239  locked--;
240 }
241 /*---------------------------------------------------------------------------*/
242 PROCESS(stm32w_radio_process, "STM32W radio driver");
243 /*---------------------------------------------------------------------------*/
244 static int stm32w_radio_init(void);
245 
246 static int stm32w_radio_prepare(const void *payload,
247  unsigned short payload_len);
248 static int stm32w_radio_transmit(unsigned short payload_len);
249 
250 static int stm32w_radio_send(const void *data, unsigned short len);
251 
252 static int stm32w_radio_read(void *buf, unsigned short bufsize);
253 
254 static int stm32w_radio_channel_clear(void);
255 
256 static int stm32w_radio_receiving_packet(void);
257 
258 static int stm32w_radio_pending_packet(void);
259 
260 static int stm32w_radio_on(void);
261 
262 static int stm32w_radio_off(void);
263 
264 static int add_to_rxbuf(uint8_t * src);
265 
266 static int read_from_rxbuf(void *dest, unsigned short len);
267 
268 /*--------------------------------------------------------------------------*/
269 static radio_result_t
270 get_value(radio_param_t param, radio_value_t *value)
271 {
272  if(!value) {
273  return RADIO_RESULT_INVALID_VALUE;
274  }
275  switch(param) {
276  case RADIO_PARAM_POWER_MODE:
277  *value = onoroff == ON ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
278  return RADIO_RESULT_OK;
279  case RADIO_PARAM_CHANNEL:
280  *value = ST_RadioGetChannel();
281  return RADIO_RESULT_OK;
282  case RADIO_PARAM_PAN_ID:
283  *value = ST_RadioGetPanId();
284  return RADIO_RESULT_OK;
285  case RADIO_PARAM_16BIT_ADDR:
286  *value = ST_RadioGetNodeId();
287  return RADIO_RESULT_OK;
288  case RADIO_PARAM_RX_MODE:
289  *value = 0;
292  }
293  if(ST_RadioAutoAckEnabled()) {
294  *value |= RADIO_RX_MODE_AUTOACK;
295  }
296  return RADIO_RESULT_OK;
297  case RADIO_PARAM_TXPOWER:
298  *value = ST_RadioGetPower();
299  return RADIO_RESULT_OK;
300  case RADIO_PARAM_CCA_THRESHOLD:
301  *value = ST_RadioGetEdCcaThreshold();
302  return RADIO_RESULT_OK;
303  case RADIO_PARAM_RSSI:
304  *value = ST_RadioEnergyDetection();
305  return RADIO_RESULT_OK;
306 
307  case RADIO_CONST_CHANNEL_MIN:
308  *value = ST_MIN_802_15_4_CHANNEL_NUMBER;
309  return RADIO_RESULT_OK;
310  case RADIO_CONST_CHANNEL_MAX:
311  *value = ST_MAX_802_15_4_CHANNEL_NUMBER;
312  return RADIO_RESULT_OK;
313 
314  case RADIO_CONST_TXPOWER_MIN:
315  *value = MIN_RADIO_POWER;
316  return RADIO_RESULT_OK;
317  case RADIO_CONST_TXPOWER_MAX:
318  *value = MAX_RADIO_POWER;
319  return RADIO_RESULT_OK;
320 
321  default:
322  return RADIO_RESULT_NOT_SUPPORTED;
323  }
324 }
325 /*--------------------------------------------------------------------------*/
326 static radio_result_t
327 set_value(radio_param_t param, radio_value_t value)
328 {
329  switch(param) {
330  case RADIO_PARAM_POWER_MODE:
331  if(value == RADIO_POWER_MODE_ON) {
332  stm32w_radio_on();
333  return RADIO_RESULT_OK;
334  }
335  if(value == RADIO_POWER_MODE_OFF) {
336  stm32w_radio_off();
337  return RADIO_RESULT_OK;
338  }
339  return RADIO_RESULT_INVALID_VALUE;
340  case RADIO_PARAM_CHANNEL:
341  if(value < ST_MIN_802_15_4_CHANNEL_NUMBER ||
342  value > ST_MAX_802_15_4_CHANNEL_NUMBER) {
343  return RADIO_RESULT_INVALID_VALUE;
344  }
345  if(ST_RadioSetChannel(value) != ST_SUCCESS) {
346  return RADIO_RESULT_ERROR;
347  }
348  return RADIO_RESULT_OK;
349  case RADIO_PARAM_PAN_ID:
350  ST_RadioSetPanId(value & 0xffff);
351  return RADIO_RESULT_OK;
352  case RADIO_PARAM_16BIT_ADDR:
353  ST_RadioSetNodeId(value & 0xffff);
354  return RADIO_RESULT_OK;
355  case RADIO_PARAM_RX_MODE:
356  if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER |
357  RADIO_RX_MODE_AUTOACK)) {
358  return RADIO_RESULT_INVALID_VALUE;
359  }
361  ST_RadioEnableAutoAck((value & RADIO_RX_MODE_AUTOACK) != 0);
362  return RADIO_RESULT_OK;
363  case RADIO_PARAM_TXPOWER:
364  if(value < MIN_RADIO_POWER || value > MAX_RADIO_POWER) {
365  return RADIO_RESULT_INVALID_VALUE;
366  }
367  if(ST_RadioSetPower((int8_t)value) != ST_SUCCESS) {
368  return RADIO_RESULT_INVALID_VALUE;
369  }
370  return RADIO_RESULT_OK;
371  case RADIO_PARAM_CCA_THRESHOLD:
372  ST_RadioSetEdCcaThreshold((int8_t)value);
373  return RADIO_RESULT_OK;
374  default:
375  return RADIO_RESULT_NOT_SUPPORTED;
376  }
377 }
378 /*--------------------------------------------------------------------------*/
379 static radio_result_t
380 get_object(radio_param_t param, void *dest, size_t size)
381 {
382  const uint8_t *eui64;
383  uint8_t *target;
384  int i;
385 
386  if(param == RADIO_PARAM_64BIT_ADDR) {
387  if(size < 8 || !dest) {
388  return RADIO_RESULT_INVALID_VALUE;
389  }
390  eui64 = ST_RadioGetEui64();
391  if(!eui64) {
392  return RADIO_RESULT_ERROR;
393  }
394  target = dest;
395  for(i = 0; i < 8; i++) {
396  target[i] = eui64[7 - i];
397  }
398  return RADIO_RESULT_OK;
399  }
400  return RADIO_RESULT_NOT_SUPPORTED;
401 }
402 /*--------------------------------------------------------------------------*/
403 static radio_result_t
404 set_object(radio_param_t param, const void *src, size_t size)
405 {
406  return RADIO_RESULT_NOT_SUPPORTED;
407 }
408 /*--------------------------------------------------------------------------*/
409 const struct radio_driver stm32w_radio_driver = {
410  stm32w_radio_init,
411  stm32w_radio_prepare,
412  stm32w_radio_transmit,
413  stm32w_radio_send,
414  stm32w_radio_read,
415  stm32w_radio_channel_clear,
416  stm32w_radio_receiving_packet,
417  stm32w_radio_pending_packet,
418  stm32w_radio_on,
419  stm32w_radio_off,
420  get_value,
421  set_value,
422  get_object,
423  set_object
424 };
425 /*---------------------------------------------------------------------------*/
426 static int
427 stm32w_radio_init(void)
428 {
429  /* A channel also needs to be set. */
430  ST_RadioSetChannel(RF_CHANNEL);
431 
432  /* Initialize radio (analog section, digital baseband and MAC). */
433  /* Leave radio powered up in non-promiscuous rx mode. */
434  ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
435 
436  onoroff = OFF;
437  ST_RadioSetPanId(IEEE802154_PANID);
438 
439  CLEAN_RXBUFS();
440  CLEAN_TXBUF();
441 
442 #if ST_RADIO_AUTOACK && !(UIP_CONF_LL_802154 && LINKADDR_CONF_SIZE==8)
443 #error "Autoack and address filtering can only be used with EUI 64"
444 #endif
445  ST_RadioEnableAutoAck(ST_RADIO_AUTOACK);
446  ST_RadioEnableAddressFiltering(ST_RADIO_AUTOACK);
447 
448  locked = 0;
449  process_start(&stm32w_radio_process, NULL);
450 
451  return 0;
452 }
453 /*---------------------------------------------------------------------------*/
454 void
455 stm32w_radio_set_promiscous(uint8_t on)
456 {
457  if(on) {
459  } else {
460  ST_RadioEnableAddressFiltering(ST_RADIO_AUTOACK);
461  }
462 }
463 /*---------------------------------------------------------------------------*/
464 int
465 stm32w_radio_set_channel(uint8_t channel)
466 {
467  if (ST_RadioSetChannel(channel) == ST_SUCCESS) {
468  return 0;
469  } else {
470  return 1;
471  }
472 }
473 /*---------------------------------------------------------------------------*/
474 static int
475 wait_for_tx(void)
476 {
477  struct timer t;
478  timer_set(&t, CLOCK_SECOND / 10);
479  while(!TXBUF_EMPTY()) {
480  if(timer_expired(&t)) {
481  PRINTF("stm32w: tx buffer full.\r\n");
482  return 1;
483  }
484  /* Put CPU in sleep mode. */
485  halSleepWithOptions(SLEEPMODE_IDLE, 0);
486  }
487  return 0;
488 }
489 /*---------------------------------------------------------------------------*/
490 static int
491 stm32w_radio_prepare(const void *payload, unsigned short payload_len)
492 {
493  if(payload_len > STM32W_MAX_PACKET_LEN) {
494  PRINTF("stm32w: payload length=%d is too long.\r\n", payload_len);
495  return RADIO_TX_ERR;
496  }
497 #if !RADIO_WAIT_FOR_PACKET_SENT
498  /*
499  * Check if the txbuf is empty. Wait for a finite time.
500  * This should not occur if we wait for the end of transmission in
501  * stm32w_radio_transmit().
502  */
503  if(wait_for_tx()) {
504  PRINTF("stm32w: tx buffer full.\r\n");
505  return RADIO_TX_ERR;
506  }
507 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
508 
509  /*
510  * Copy to the txbuf.
511  * The first byte must be the packet length.
512  */
513  CLEAN_TXBUF();
514  memcpy(stm32w_txbuf + 1, payload, payload_len);
515 
516  return RADIO_TX_OK;
517 }
518 /*---------------------------------------------------------------------------*/
519 static int
520 stm32w_radio_transmit(unsigned short payload_len)
521 {
522  stm32w_txbuf[0] = payload_len + CHECKSUM_LEN;
523  INIT_RETRY_CNT();
524 
525  if(onoroff == OFF) {
526  PRINTF("stm32w: Radio is off, turning it on.\r\n");
527  ST_RadioWake();
528  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
529  }
530 #if RADIO_WAIT_FOR_PACKET_SENT
531  GET_LOCK();
532 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
533  last_tx_status = -1;
534  LED_TX_ON();
535  if(ST_RadioTransmit(stm32w_txbuf) == ST_SUCCESS) {
536  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
537  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
538  PRINTF("stm32w: sending %d bytes\r\n", payload_len);
539 
540 #if DEBUG > 1
541  for(uint8_t c = 1; c <= stm32w_txbuf[0] - 2; c++) {
542  PRINTF("%x:", stm32w_txbuf[c]);
543  }
544  PRINTF("\r\n");
545 #endif
546 
547 #if RADIO_WAIT_FOR_PACKET_SENT
548 
549  if(wait_for_tx()) {
550  PRINTF("stm32w: unknown tx error.\r\n");
551  TO_PREV_STATE();
552  LED_TX_OFF();
553  RELEASE_LOCK();
554  return RADIO_TX_ERR;
555  }
556 
557  TO_PREV_STATE();
558  if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED ||
559  last_tx_status == ST_MAC_NO_ACK_RECEIVED) {
560  RELEASE_LOCK();
561  if(last_tx_status == ST_PHY_ACK_RECEIVED) {
562  return RADIO_TX_OK; /* ACK status */
563  } else if(last_tx_status == ST_MAC_NO_ACK_RECEIVED ||
564  last_tx_status == ST_SUCCESS) {
565  return RADIO_TX_NOACK;
566  }
567  }
568  LED_TX_OFF();
569  RELEASE_LOCK();
570  return RADIO_TX_ERR;
571 
572 #else /* RADIO_WAIT_FOR_PACKET_SENT */
573  TO_PREV_STATE();
574  LED_TX_OFF();
575  return RADIO_TX_OK;
576 
577 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
578  }
579 
580 #if RADIO_WAIT_FOR_PACKET_SENT
581  RELEASE_LOCK();
582 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
583  TO_PREV_STATE();
584 
585  PRINTF("stm32w: transmission never started.\r\n");
586  /* TODO: Do we have to retransmit? */
587 
588  CLEAN_TXBUF();
589  LED_TX_OFF();
590  return RADIO_TX_ERR;
591 }
592 /*---------------------------------------------------------------------------*/
593 static int
594 stm32w_radio_send(const void *payload, unsigned short payload_len)
595 {
596  if (stm32w_radio_prepare(payload, payload_len) == RADIO_TX_ERR) {
597  return RADIO_TX_ERR;
598  }
599  return stm32w_radio_transmit(payload_len);
600 }
601 /*---------------------------------------------------------------------------*/
602 static int
603 stm32w_radio_channel_clear(void)
604 {
605  return ST_RadioChannelIsClear();
606 }
607 /*---------------------------------------------------------------------------*/
608 static int
609 stm32w_radio_receiving_packet(void)
610 {
611  return receiving_packet;
612 }
613 /*---------------------------------------------------------------------------*/
614 static int
615 stm32w_radio_pending_packet(void)
616 {
617  return !RXBUFS_EMPTY();
618 }
619 /*---------------------------------------------------------------------------*/
620 static int
621 stm32w_radio_off(void)
622 {
623  /* Any transmit or receive packets in progress are aborted.
624  * Waiting for end of transmission or reception have to be done.
625  */
626  if(locked) {
627  PRINTF("stm32w: try to off while sending/receiving (lock=%u).\r\n",
628  locked);
629  return 0;
630  }
631  /* off only if there is no transmission or reception of packet. */
632  if(onoroff == ON && TXBUF_EMPTY() && !receiving_packet) {
633  LED_RDC_OFF();
634  ST_RadioSleep();
635  onoroff = OFF;
636  CLEAN_TXBUF();
637  CLEAN_RXBUFS();
638 
639  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
640  }
641 
642  return 1;
643 }
644 /*---------------------------------------------------------------------------*/
645 static int
646 stm32w_radio_on(void)
647 {
648  PRINTF("stm32w: turn radio on\n");
649  if(onoroff == OFF) {
650  LED_RDC_ON();
651  ST_RadioWake();
652  onoroff = ON;
653 
654  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
655  }
656 
657  return 1;
658 }
659 /*---------------------------------------------------------------------------*/
660 int
661 stm32w_radio_is_on(void)
662 {
663  return onoroff == ON;
664 }
665 /*---------------------------------------------------------------------------*/
666 void
668  boolean ackFramePendingSet,
669  uint32_t time, uint16_t errors, int8_t rssi)
670 {
671  LED_RX_ON();
672  PRINTF("stm32w: incomming packet received\n");
673  receiving_packet = 0;
674 
675  /* Copy packet into the buffer. It is better to do this here. */
676  if(add_to_rxbuf(packet)) {
677  process_poll(&stm32w_radio_process);
678  last_rssi = rssi;
679  }
680  LED_RX_OFF();
681  GET_LOCK();
682  is_transmit_ack = 1;
683  /* Wait for sending ACK */
684  BUSYWAIT_UNTIL(!is_transmit_ack, RTIMER_SECOND / 1500);
685  RELEASE_LOCK();
686 }
687 /*--------------------------------------------------------------------------*/
688 void
689 ST_RadioTxAckIsrCallback(void)
690 {
691  /*
692  * This callback is for simplemac 1.1.0.
693  * Till now we block (RTIMER_SECOND / 1500)
694  * to prevent radio off during ACK transmission.
695  */
696  is_transmit_ack = 0;
697  /* RELEASE_LOCK(); */
698 }
699 /*--------------------------------------------------------------------------*/
700 void
702  uint32_t txSyncTime, boolean framePending)
703 {
704  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
705  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
706  LED_TX_OFF();
707 
708  last_tx_status = status;
709 
710  if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED) {
711  CLEAN_TXBUF();
712  } else {
713  if(RETRY_CNT_GTZ()) {
714 
715  /* Retransmission */
716  LED_TX_ON();
717  if(ST_RadioTransmit(stm32w_txbuf) == ST_SUCCESS) {
718  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
719  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
720  PRINTF("stm32w: retransmission.\r\n");
721  DEC_RETRY_CNT();
722  } else {
723  CLEAN_TXBUF();
724  LED_TX_OFF();
725  PRINTF("stm32w: retransmission failed.\r\n");
726  }
727  } else {
728  CLEAN_TXBUF();
729  }
730  }
731 
732  /* Debug outputs. */
733  if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED) {
734  PRINTF("stm32w: return status TX_END\r\n");
735  } else if(status == ST_MAC_NO_ACK_RECEIVED) {
736  PRINTF("stm32w: return status TX_END_NOACK\r\n");
737  } else if(status == ST_PHY_TX_CCA_FAIL) {
738  PRINTF("stm32w: return status TX_END_CCA_FAIL\r\n");
739  } else if(status == ST_PHY_TX_UNDERFLOW) {
740  PRINTF("stm32w: return status TX_END_UNDERFLOW\r\n");
741  } else {
742  PRINTF("stm32w: return status TX_END_INCOMPLETE\r\n");
743  }
744 }
745 /*--------------------------------------------------------------------------*/
746 boolean
748 {
749  receiving_packet = 1;
750  return FALSE;
751 }
752 /*--------------------------------------------------------------------------*/
753 boolean
755 {
756  receiving_packet = 1;
757  return FALSE;
758 }
759 /*---------------------------------------------------------------------------*/
760 PROCESS_THREAD(stm32w_radio_process, ev, data)
761 {
762  int len;
763  PROCESS_BEGIN();
764  PRINTF("stm32w_radio_process: started\r\n");
765 
766  while(1) {
767  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
768  PRINTF("stm32w_radio_process: calling receiver callback\r\n");
769 
770 #if DEBUG > 1
771  for(uint8_t c = 1; c <= RCVD_PACKET_LEN; c++) {
772  PRINTF("%x", stm32w_rxbuf[c]);
773  }
774  PRINTF("\r\n");
775 #endif
776 
777  packetbuf_clear();
778  len = stm32w_radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
779  if(len > 0) {
781  NETSTACK_RDC.input();
782  }
783  if(!RXBUFS_EMPTY()) {
784  /*
785  * Some data packet still in rx buffer (this happens because process_poll
786  * doesn't queue requests), so stm32w_radio_process needs to be called
787  * again.
788  */
789  process_poll(&stm32w_radio_process);
790  }
791  }
792  PROCESS_END();
793 }
794 /*---------------------------------------------------------------------------*/
795 static int
796 stm32w_radio_read(void *buf, unsigned short bufsize)
797 {
798  return read_from_rxbuf(buf, bufsize);
799 }
800 /*---------------------------------------------------------------------------*/
801 void
803 {
804  PRINTF("stm32w: radio overflow\r\n");
805 }
806 /*---------------------------------------------------------------------------*/
807 void
808 ST_RadioSfdSentIsrCallback(uint32_t sfdSentTime)
809 {
810 }
811 /*---------------------------------------------------------------------------*/
812 void
814 {
815 }
816 /*---------------------------------------------------------------------------*/
817 static int
818 add_to_rxbuf(uint8_t *src)
819 {
820  if(RXBUFS_FULL()) {
821  return 0;
822  }
823 
824  memcpy(stm32w_rxbufs[last], src, src[0] + 1);
825 #if RADIO_RXBUFS > 1
826  last = (last + 1) % RADIO_RXBUFS;
827  if(first == -1) {
828  first = 0;
829  }
830 #endif
831 
832  return 1;
833 }
834 /*---------------------------------------------------------------------------*/
835 static int
836 read_from_rxbuf(void *dest, unsigned short len)
837 {
838  if(RXBUFS_EMPTY()) { /* Buffers are all empty */
839  return 0;
840  }
841 
842  if(stm32w_rxbufs[first][0] > len) { /* Too large packet for dest. */
843  len = 0;
844  } else {
845  len = stm32w_rxbufs[first][0];
846  memcpy(dest, stm32w_rxbufs[first] + 1, len);
847  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
848  }
849 
850 #if RADIO_RXBUFS > 1
851  ATOMIC(first = (first + 1) % RADIO_RXBUFS;
852  int first_tmp = first; if(first_tmp == last) {
853  CLEAN_RXBUFS();}
854  )
855 #else
856  CLEAN_RXBUFS();
857 #endif
858 
859  return len;
860 }
861 /*---------------------------------------------------------------------------*/
862 short
863 last_packet_rssi()
864 {
865  return last_rssi;
866 }
867 /** @} */
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
Definition: radio.h:193
void ST_RadioEnableAutoAck(boolean enable)
This function enables or disables automatic transmission of ACKs in response to received packets whic...
void ST_RadioMacTimerCompareIsrCallback(void)
This function is called by the library in response to MAC timer comparison event. ...
Definition: stm32w-radio.c:813
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:667
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
A timer.
Definition: timer.h:86
802.15.4 frame creation and parsing functions
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
u8 * ST_RadioGetEui64(void)
This function get the EUI 64 of the node.
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Definition: timer.c:64
Header file for the Rime buffer (packetbuf) management
void __attribute__((interrupt))
This ISR handles most of the business interacting with the 1-wire bus.
Definition: onewire.c:174
STM32W radio driver header file
#define NULL
The null pointer.
The structure of a device driver for a radio in Contiki.
Definition: radio.h:225
boolean ST_RadioAddressFilteringEnabled(void)
This function gets the address filtering status of the device.
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
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:200
u16 ST_RadioGetNodeId(void)
This function gets the short address of the node.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define TRUE
An alias for one, used for clarity.
u16 ST_RadioGetPanId(void)
This function gets the PAN id of the node.
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:754
Header file for the real-time timer module.
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:747
int(* on)(void)
Turn the radio on.
Definition: radio.h:252
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
Definition: radio.h:258
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
Definition: radio.h:268
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
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:701
Generic set of HAL includes for all platforms.
boolean ST_RadioAutoAckEnabled(void)
This function gets the automatic acknowledgement status of the device.
Return codes for API functions and module definitions.
void ST_RadioSetNodeId(u16 nodeId)
This function sets the short address of the node.
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
void ST_RadioEnableAddressFiltering(boolean enable)
This function enables or disables address filtering on PAN ID, node ID, and EUI 64.
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:65
#define FALSE
An alias for zero, used for clarity.
Header file for Rime statistics
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:207
#define ATOMIC(blah)
A block of code may be made atomic by wrapping it with this macro.
Definition: gnu.h:459
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
Definition: radio.h:274
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:808
int timer_expired(struct timer *t)
Check if a timer has expired.
Definition: timer.c:121
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
Definition: radio.h:261
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:802
Include file for the Contiki low-layer network stack (NETSTACK)
void ST_RadioSetPanId(u16 panId)
This function sets the PAN id of the node.
#define CLOCK_SECOND
A second, measured in system clock time.
Definition: clock.h:82