Contiki-Inga 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 const struct radio_driver stm32w_radio_driver = {
269  stm32w_radio_init,
270  stm32w_radio_prepare,
271  stm32w_radio_transmit,
272  stm32w_radio_send,
273  stm32w_radio_read,
274  stm32w_radio_channel_clear,
275  stm32w_radio_receiving_packet,
276  stm32w_radio_pending_packet,
277  stm32w_radio_on,
278  stm32w_radio_off,
279 };
280 /*---------------------------------------------------------------------------*/
281 static int
282 stm32w_radio_init(void)
283 {
284  /* A channel also needs to be set. */
285  ST_RadioSetChannel(RF_CHANNEL);
286 
287  /* Initialize radio (analog section, digital baseband and MAC). */
288  /* Leave radio powered up in non-promiscuous rx mode. */
289  ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
290 
291  onoroff = OFF;
292  ST_RadioSetPanId(IEEE802154_PANID);
293 
294  CLEAN_RXBUFS();
295  CLEAN_TXBUF();
296 
297 #if ST_RADIO_AUTOACK && !(UIP_CONF_LL_802154 && LINKADDR_CONF_SIZE==8)
298 #error "Autoack and address filtering can only be used with EUI 64"
299 #endif
300  ST_RadioEnableAutoAck(ST_RADIO_AUTOACK);
301  ST_RadioEnableAddressFiltering(ST_RADIO_AUTOACK);
302 
303  locked = 0;
304  process_start(&stm32w_radio_process, NULL);
305 
306  return 0;
307 }
308 /*---------------------------------------------------------------------------*/
309 void
310 stm32w_radio_set_promiscous(uint8_t on)
311 {
312  if(on) {
313  ST_RadioEnableAddressFiltering(0);
314  } else {
315  ST_RadioEnableAddressFiltering(ST_RADIO_AUTOACK);
316  }
317 }
318 /*---------------------------------------------------------------------------*/
319 int
320 stm32w_radio_set_channel(uint8_t channel)
321 {
322  if (ST_RadioSetChannel(channel) == ST_SUCCESS) {
323  return 0;
324  } else {
325  return 1;
326  }
327 }
328 /*---------------------------------------------------------------------------*/
329 static int
330 wait_for_tx(void)
331 {
332  struct timer t;
333  timer_set(&t, CLOCK_SECOND / 10);
334  while(!TXBUF_EMPTY()) {
335  if(timer_expired(&t)) {
336  PRINTF("stm32w: tx buffer full.\r\n");
337  return 1;
338  }
339  /* Put CPU in sleep mode. */
340  halSleepWithOptions(SLEEPMODE_IDLE, 0);
341  }
342  return 0;
343 }
344 /*---------------------------------------------------------------------------*/
345 static int
346 stm32w_radio_prepare(const void *payload, unsigned short payload_len)
347 {
348  if(payload_len > STM32W_MAX_PACKET_LEN) {
349  PRINTF("stm32w: payload length=%d is too long.\r\n", payload_len);
350  return RADIO_TX_ERR;
351  }
352 #if !RADIO_WAIT_FOR_PACKET_SENT
353  /*
354  * Check if the txbuf is empty. Wait for a finite time.
355  * This should not occur if we wait for the end of transmission in
356  * stm32w_radio_transmit().
357  */
358  if(wait_for_tx()) {
359  PRINTF("stm32w: tx buffer full.\r\n");
360  return RADIO_TX_ERR;
361  }
362 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
363 
364  /*
365  * Copy to the txbuf.
366  * The first byte must be the packet length.
367  */
368  CLEAN_TXBUF();
369  memcpy(stm32w_txbuf + 1, payload, payload_len);
370 
371  return RADIO_TX_OK;
372 }
373 /*---------------------------------------------------------------------------*/
374 static int
375 stm32w_radio_transmit(unsigned short payload_len)
376 {
377  stm32w_txbuf[0] = payload_len + CHECKSUM_LEN;
378  INIT_RETRY_CNT();
379 
380  if(onoroff == OFF) {
381  PRINTF("stm32w: Radio is off, turning it on.\r\n");
382  ST_RadioWake();
383  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
384  }
385 #if RADIO_WAIT_FOR_PACKET_SENT
386  GET_LOCK();
387 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
388  last_tx_status = -1;
389  LED_TX_ON();
390  if(ST_RadioTransmit(stm32w_txbuf) == ST_SUCCESS) {
391  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
392  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
393  PRINTF("stm32w: sending %d bytes\r\n", payload_len);
394 
395 #if DEBUG > 1
396  for(uint8_t c = 1; c <= stm32w_txbuf[0] - 2; c++) {
397  PRINTF("%x:", stm32w_txbuf[c]);
398  }
399  PRINTF("\r\n");
400 #endif
401 
402 #if RADIO_WAIT_FOR_PACKET_SENT
403 
404  if(wait_for_tx()) {
405  PRINTF("stm32w: unknown tx error.\r\n");
406  TO_PREV_STATE();
407  LED_TX_OFF();
408  RELEASE_LOCK();
409  return RADIO_TX_ERR;
410  }
411 
412  TO_PREV_STATE();
413  if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED ||
414  last_tx_status == ST_MAC_NO_ACK_RECEIVED) {
415  RELEASE_LOCK();
416  if(last_tx_status == ST_PHY_ACK_RECEIVED) {
417  return RADIO_TX_OK; /* ACK status */
418  } else if(last_tx_status == ST_MAC_NO_ACK_RECEIVED ||
419  last_tx_status == ST_SUCCESS) {
420  return RADIO_TX_NOACK;
421  }
422  }
423  LED_TX_OFF();
424  RELEASE_LOCK();
425  return RADIO_TX_ERR;
426 
427 #else /* RADIO_WAIT_FOR_PACKET_SENT */
428  TO_PREV_STATE();
429  LED_TX_OFF();
430  return RADIO_TX_OK;
431 
432 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
433  }
434 
435 #if RADIO_WAIT_FOR_PACKET_SENT
436  RELEASE_LOCK();
437 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
438  TO_PREV_STATE();
439 
440  PRINTF("stm32w: transmission never started.\r\n");
441  /* TODO: Do we have to retransmit? */
442 
443  CLEAN_TXBUF();
444  LED_TX_OFF();
445  return RADIO_TX_ERR;
446 }
447 /*---------------------------------------------------------------------------*/
448 static int
449 stm32w_radio_send(const void *payload, unsigned short payload_len)
450 {
451  if (stm32w_radio_prepare(payload, payload_len) == RADIO_TX_ERR) {
452  return RADIO_TX_ERR;
453  }
454  return stm32w_radio_transmit(payload_len);
455 }
456 /*---------------------------------------------------------------------------*/
457 static int
458 stm32w_radio_channel_clear(void)
459 {
460  return ST_RadioChannelIsClear();
461 }
462 /*---------------------------------------------------------------------------*/
463 static int
464 stm32w_radio_receiving_packet(void)
465 {
466  return receiving_packet;
467 }
468 /*---------------------------------------------------------------------------*/
469 static int
470 stm32w_radio_pending_packet(void)
471 {
472  return !RXBUFS_EMPTY();
473 }
474 /*---------------------------------------------------------------------------*/
475 static int
476 stm32w_radio_off(void)
477 {
478  /* Any transmit or receive packets in progress are aborted.
479  * Waiting for end of transmission or reception have to be done.
480  */
481  if(locked) {
482  PRINTF("stm32w: try to off while sending/receiving (lock=%u).\r\n",
483  locked);
484  return 0;
485  }
486  /* off only if there is no transmission or reception of packet. */
487  if(onoroff == ON && TXBUF_EMPTY() && !receiving_packet) {
488  LED_RDC_OFF();
489  ST_RadioSleep();
490  onoroff = OFF;
491  CLEAN_TXBUF();
492  CLEAN_RXBUFS();
493 
494  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
495  }
496 
497  return 1;
498 }
499 /*---------------------------------------------------------------------------*/
500 static int
501 stm32w_radio_on(void)
502 {
503  PRINTF("stm32w: turn radio on\n");
504  if(onoroff == OFF) {
505  LED_RDC_ON();
506  ST_RadioWake();
507  onoroff = ON;
508 
509  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
510  }
511 
512  return 1;
513 }
514 /*---------------------------------------------------------------------------*/
515 int
516 stm32w_radio_is_on(void)
517 {
518  return onoroff == ON;
519 }
520 /*---------------------------------------------------------------------------*/
521 void
522 ST_RadioReceiveIsrCallback(uint8_t *packet,
523  boolean ackFramePendingSet,
524  uint32_t time, uint16_t errors, int8_t rssi)
525 {
526  LED_RX_ON();
527  PRINTF("stm32w: incomming packet received\n");
528  receiving_packet = 0;
529 
530  /* Copy packet into the buffer. It is better to do this here. */
531  if(add_to_rxbuf(packet)) {
532  process_poll(&stm32w_radio_process);
533  last_rssi = rssi;
534  }
535  LED_RX_OFF();
536  GET_LOCK();
537  is_transmit_ack = 1;
538  /* Wait for sending ACK */
539  BUSYWAIT_UNTIL(!is_transmit_ack, RTIMER_SECOND / 1500);
540  RELEASE_LOCK();
541 }
542 /*--------------------------------------------------------------------------*/
543 void
544 ST_RadioTxAckIsrCallback(void)
545 {
546  /*
547  * This callback is for simplemac 1.1.0.
548  * Till now we block (RTIMER_SECOND / 1500)
549  * to prevent radio off during ACK transmission.
550  */
551  is_transmit_ack = 0;
552  /* RELEASE_LOCK(); */
553 }
554 /*--------------------------------------------------------------------------*/
555 void
556 ST_RadioTransmitCompleteIsrCallback(StStatus status,
557  uint32_t txSyncTime, boolean framePending)
558 {
559  ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
560  ENERGEST_ON(ENERGEST_TYPE_LISTEN);
561  LED_TX_OFF();
562 
563  last_tx_status = status;
564 
565  if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED) {
566  CLEAN_TXBUF();
567  } else {
568  if(RETRY_CNT_GTZ()) {
569 
570  /* Retransmission */
571  LED_TX_ON();
572  if(ST_RadioTransmit(stm32w_txbuf) == ST_SUCCESS) {
573  ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
574  ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
575  PRINTF("stm32w: retransmission.\r\n");
576  DEC_RETRY_CNT();
577  } else {
578  CLEAN_TXBUF();
579  LED_TX_OFF();
580  PRINTF("stm32w: retransmission failed.\r\n");
581  }
582  } else {
583  CLEAN_TXBUF();
584  }
585  }
586 
587  /* Debug outputs. */
588  if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED) {
589  PRINTF("stm32w: return status TX_END\r\n");
590  } else if(status == ST_MAC_NO_ACK_RECEIVED) {
591  PRINTF("stm32w: return status TX_END_NOACK\r\n");
592  } else if(status == ST_PHY_TX_CCA_FAIL) {
593  PRINTF("stm32w: return status TX_END_CCA_FAIL\r\n");
594  } else if(status == ST_PHY_TX_UNDERFLOW) {
595  PRINTF("stm32w: return status TX_END_UNDERFLOW\r\n");
596  } else {
597  PRINTF("stm32w: return status TX_END_INCOMPLETE\r\n");
598  }
599 }
600 /*--------------------------------------------------------------------------*/
601 boolean
603 {
604  receiving_packet = 1;
605  return FALSE;
606 }
607 /*--------------------------------------------------------------------------*/
608 boolean
610 {
611  receiving_packet = 1;
612  return FALSE;
613 }
614 /*---------------------------------------------------------------------------*/
615 PROCESS_THREAD(stm32w_radio_process, ev, data)
616 {
617  int len;
618  PROCESS_BEGIN();
619  PRINTF("stm32w_radio_process: started\r\n");
620 
621  while(1) {
622  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
623  PRINTF("stm32w_radio_process: calling receiver callback\r\n");
624 
625 #if DEBUG > 1
626  for(uint8_t c = 1; c <= RCVD_PACKET_LEN; c++) {
627  PRINTF("%x", stm32w_rxbuf[c]);
628  }
629  PRINTF("\r\n");
630 #endif
631 
632  packetbuf_clear();
633  len = stm32w_radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
634  if(len > 0) {
636  NETSTACK_RDC.input();
637  }
638  if(!RXBUFS_EMPTY()) {
639  /*
640  * Some data packet still in rx buffer (this happens because process_poll
641  * doesn't queue requests), so stm32w_radio_process needs to be called
642  * again.
643  */
644  process_poll(&stm32w_radio_process);
645  }
646  }
647  PROCESS_END();
648 }
649 /*---------------------------------------------------------------------------*/
650 static int
651 stm32w_radio_read(void *buf, unsigned short bufsize)
652 {
653  return read_from_rxbuf(buf, bufsize);
654 }
655 /*---------------------------------------------------------------------------*/
656 void
658 {
659  PRINTF("stm32w: radio overflow\r\n");
660 }
661 /*---------------------------------------------------------------------------*/
662 void
663 ST_RadioSfdSentIsrCallback(uint32_t sfdSentTime)
664 {
665 }
666 /*---------------------------------------------------------------------------*/
667 void
669 {
670 }
671 /*---------------------------------------------------------------------------*/
672 static int
673 add_to_rxbuf(uint8_t *src)
674 {
675  if(RXBUFS_FULL()) {
676  return 0;
677  }
678 
679  memcpy(stm32w_rxbufs[last], src, src[0] + 1);
680 #if RADIO_RXBUFS > 1
681  last = (last + 1) % RADIO_RXBUFS;
682  if(first == -1) {
683  first = 0;
684  }
685 #endif
686 
687  return 1;
688 }
689 /*---------------------------------------------------------------------------*/
690 static int
691 read_from_rxbuf(void *dest, unsigned short len)
692 {
693  if(RXBUFS_EMPTY()) { /* Buffers are all empty */
694  return 0;
695  }
696 
697  if(stm32w_rxbufs[first][0] > len) { /* Too large packet for dest. */
698  len = 0;
699  } else {
700  len = stm32w_rxbufs[first][0];
701  memcpy(dest, stm32w_rxbufs[first] + 1, len);
702  packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
703  }
704 
705 #if RADIO_RXBUFS > 1
706  ATOMIC(first = (first + 1) % RADIO_RXBUFS;
707  int first_tmp = first; if(first_tmp == last) {
708  CLEAN_RXBUFS();}
709  )
710 #else
711  CLEAN_RXBUFS();
712 #endif
713 
714  return len;
715 }
716 /*---------------------------------------------------------------------------*/
717 short
718 last_packet_rssi()
719 {
720  return last_rssi;
721 }
722 /** @} */