00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include PLATFORM_HEADER
00044 #include "hal/error.h"
00045 #include "hal/hal.h"
00046
00047 #include "contiki.h"
00048
00049 #include "net/mac/frame802154.h"
00050
00051 #include "dev/stm32w-radio.h"
00052 #include "net/netstack.h"
00053
00054 #include "net/packetbuf.h"
00055 #include "net/rime/rimestats.h"
00056
00057
00058
00059 #define DEBUG 0
00060 #include "dev/leds.h"
00061 #define LED_ACTIVITY 0
00062
00063
00064 #if DEBUG > 0
00065 #include <stdio.h>
00066 #define PRINTF(...) printf(__VA_ARGS__)
00067 #else
00068 #define PRINTF(...) do {} while (0)
00069 #endif
00070
00071 #if LED_ACTIVITY
00072 #define LED_TX_ON() leds_on(LEDS_GREEN)
00073 #define LED_TX_OFF() leds_off(LEDS_GREEN)
00074 #define LED_RX_ON() leds_on(LEDS_RED)
00075 #define LED_RX_OFF() leds_off(LEDS_RED)
00076 #else
00077 #define LED_TX_ON()
00078 #define LED_TX_OFF()
00079 #define LED_RX_ON()
00080 #define LED_RX_OFF()
00081 #endif
00082
00083 #ifndef MAC_RETRIES
00084 #define MAC_RETRIES 1
00085 #endif
00086
00087 #if MAC_RETRIES
00088
00089 int8_t mac_retries_left;
00090
00091 #define INIT_RETRY_CNT() (mac_retries_left = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS))
00092 #define DEC_RETRY_CNT() (mac_retries_left--)
00093 #define RETRY_CNT_GTZ() (mac_retries_left > 0)
00094
00095 #else
00096
00097 #define INIT_RETRY_CNT()
00098 #define DEC_RETRY_CNT()
00099 #define RETRY_CNT_GTZ() 0
00100
00101 #endif
00102
00103
00104
00105
00106 #ifndef RADIO_WAIT_FOR_PACKET_SENT
00107 #define RADIO_WAIT_FOR_PACKET_SENT 1
00108 #endif
00109
00110 #define TO_PREV_STATE() { \
00111 if(onoroff == OFF){ \
00112 ST_RadioSleep(); \
00113 ENERGEST_OFF(ENERGEST_TYPE_LISTEN); \
00114 } \
00115 }
00116
00117 const RadioTransmitConfig radioTransmitConfig = {
00118 TRUE,
00119 TRUE,
00120 4,
00121 2,
00122 6,
00123 TRUE
00124 };
00125
00126
00127
00128
00129 #ifndef RADIO_RXBUFS
00130 #define RADIO_RXBUFS 1
00131 #endif
00132
00133 static uint8_t stm32w_rxbufs[RADIO_RXBUFS][STM32W_MAX_PACKET_LEN+1];
00134
00135 #if RADIO_RXBUFS > 1
00136 static volatile int8_t first = -1, last=0;
00137 #else
00138 static const int8_t first=0, last=0;
00139 #endif
00140
00141 #if RADIO_RXBUFS > 1
00142 #define CLEAN_RXBUFS() do{first = -1; last = 0;}while(0)
00143 #define RXBUFS_EMPTY() (first == -1)
00144
00145 int RXBUFS_FULL(){
00146
00147 int8_t first_tmp = first;
00148 return first_tmp == last;
00149 }
00150
00151 #else
00152 #define CLEAN_RXBUFS() (stm32w_rxbufs[0][0] = 0)
00153 #define RXBUFS_EMPTY() (stm32w_rxbufs[0][0] == 0)
00154 #define RXBUFS_FULL() (stm32w_rxbufs[0][0] != 0)
00155 #endif
00156
00157 static uint8_t __attribute__(( aligned(2) )) stm32w_txbuf[STM32W_MAX_PACKET_LEN+1];
00158
00159
00160 #define CLEAN_TXBUF() (stm32w_txbuf[0] = 0)
00161 #define TXBUF_EMPTY() (stm32w_txbuf[0] == 0)
00162
00163 #define CHECKSUM_LEN 2
00164
00165
00166
00167
00168 #define ON 0
00169 #define OFF 1
00170
00171 static volatile uint8_t onoroff = OFF;
00172 static uint8_t receiving_packet = 0;
00173 static s8 last_rssi;
00174 static volatile StStatus last_tx_status;
00175
00176
00177 PROCESS(stm32w_radio_process, "STM32W radio driver");
00178
00179
00180 static int stm32w_radio_init(void);
00181 static int stm32w_radio_prepare(const void *payload, unsigned short payload_len);
00182 static int stm32w_radio_transmit(unsigned short payload_len);
00183 static int stm32w_radio_send(const void *data, unsigned short len);
00184 static int stm32w_radio_read(void *buf, unsigned short bufsize);
00185 static int stm32w_radio_channel_clear(void);
00186 static int stm32w_radio_receiving_packet(void);
00187 static int stm32w_radio_pending_packet(void);
00188 static int stm32w_radio_on(void);
00189 static int stm32w_radio_off(void);
00190
00191 static int add_to_rxbuf(uint8_t * src);
00192 static int read_from_rxbuf(void * dest, unsigned short len);
00193
00194
00195 const struct radio_driver stm32w_radio_driver =
00196 {
00197 stm32w_radio_init,
00198 stm32w_radio_prepare,
00199 stm32w_radio_transmit,
00200 stm32w_radio_send,
00201 stm32w_radio_read,
00202 stm32w_radio_channel_clear,
00203 stm32w_radio_receiving_packet,
00204 stm32w_radio_pending_packet,
00205 stm32w_radio_on,
00206 stm32w_radio_off,
00207 };
00208
00209 static int stm32w_radio_init(void)
00210 {
00211
00212
00213 ST_RadioSetChannel(RF_CHANNEL);
00214
00215
00216
00217 ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
00218 onoroff = OFF;
00219 ST_RadioSetNodeId(STM32W_NODE_ID);
00220 ST_RadioSetPanId(IEEE802154_PANID);
00221
00222 CLEAN_RXBUFS();
00223 CLEAN_TXBUF();
00224
00225 process_start(&stm32w_radio_process, NULL);
00226
00227 return 0;
00228 }
00229
00230 int stm32w_radio_set_channel(u8_t channel)
00231 {
00232 if (ST_RadioSetChannel(channel) == ST_SUCCESS)
00233 return 0;
00234 else
00235 return 1;
00236 }
00237
00238 static int wait_for_tx(void){
00239
00240 struct timer t;
00241
00242 timer_set(&t, CLOCK_SECOND/10);
00243 while(!TXBUF_EMPTY()){
00244 if(timer_expired(&t)){
00245 PRINTF("stm32w: tx buffer full.\r\n");
00246 return 1;
00247 }
00248
00249 halSleepWithOptions(SLEEPMODE_IDLE,0);
00250 }
00251 return 0;
00252 }
00253
00254 static int stm32w_radio_prepare(const void *payload, unsigned short payload_len)
00255 {
00256 if(payload_len > STM32W_MAX_PACKET_LEN){
00257 PRINTF("stm32w: payload length=%d is too long.\r\n", payload_len);
00258 return RADIO_TX_ERR;
00259 }
00260
00261 #if !RADIO_WAIT_FOR_PACKET_SENT
00262
00263
00264
00265
00266 if(wait_for_tx()){
00267 PRINTF("stm32w: tx buffer full.\r\n");
00268 return RADIO_TX_ERR;
00269 }
00270 #endif
00271
00272
00273
00274
00275 CLEAN_TXBUF();
00276 memcpy(stm32w_txbuf + 1, payload, payload_len);
00277
00278 return RADIO_TX_OK;
00279
00280 }
00281
00282 static int stm32w_radio_transmit(unsigned short payload_len)
00283 {
00284 stm32w_txbuf[0] = payload_len + CHECKSUM_LEN;
00285
00286 INIT_RETRY_CNT();
00287
00288 if(onoroff == OFF){
00289 PRINTF("stm32w: Radio is off, turning it on.\r\n");
00290 ST_RadioWake();
00291 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00292 }
00293
00294 LED_TX_ON();
00295 if(ST_RadioTransmit(stm32w_txbuf)==ST_SUCCESS){
00296
00297 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00298 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00299
00300 PRINTF("stm32w: sending %d bytes\r\n", payload_len);
00301
00302 #if DEBUG > 1
00303 for(u8_t c=1; c <= stm32w_txbuf[0]-2; c++){
00304 PRINTF("%x:",stm32w_txbuf[c]);
00305 }
00306 PRINTF("\r\n");
00307 #endif
00308
00309 #if RADIO_WAIT_FOR_PACKET_SENT
00310
00311 if(wait_for_tx()){
00312 PRINTF("stm32w: unknown tx error.\r\n");
00313 TO_PREV_STATE();
00314 LED_TX_OFF();
00315 return RADIO_TX_ERR;
00316 }
00317
00318 TO_PREV_STATE();
00319 if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED){
00320 return RADIO_TX_OK;
00321 }
00322 LED_TX_OFF();
00323 return RADIO_TX_ERR;
00324
00325 #else
00326
00327 TO_PREV_STATE();
00328 LED_TX_OFF();
00329 return RADIO_TX_OK;
00330
00331 #endif
00332
00333 }
00334
00335 TO_PREV_STATE();
00336
00337 PRINTF("stm32w: transmission never started.\r\n");
00338
00339
00340 CLEAN_TXBUF();
00341 LED_TX_OFF();
00342 return RADIO_TX_ERR;
00343
00344 }
00345
00346 static int stm32w_radio_send(const void *payload, unsigned short payload_len)
00347 {
00348 if(stm32w_radio_prepare(payload, payload_len) == RADIO_TX_ERR)
00349 return RADIO_TX_ERR;
00350
00351 return stm32w_radio_transmit(payload_len);
00352
00353 }
00354
00355 static int stm32w_radio_channel_clear(void)
00356 {
00357 return ST_RadioChannelIsClear();
00358 }
00359
00360 static int stm32w_radio_receiving_packet(void)
00361 {
00362 return receiving_packet;
00363 }
00364
00365 static int stm32w_radio_pending_packet(void)
00366 {
00367 return !RXBUFS_EMPTY();
00368 }
00369
00370 static int stm32w_radio_off(void)
00371 {
00372
00373
00374
00375 if(onoroff == ON){
00376 ST_RadioSleep();
00377 onoroff = OFF;
00378 CLEAN_TXBUF();
00379 CLEAN_RXBUFS();
00380
00381 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00382 }
00383
00384 return 1;
00385 }
00386
00387 static int stm32w_radio_on(void)
00388 {
00389 if(onoroff == OFF){
00390 ST_RadioWake();
00391 onoroff = ON;
00392
00393 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00394 }
00395
00396 return 1;
00397 }
00398
00399
00400
00401
00402 void ST_RadioReceiveIsrCallback(u8 *packet,
00403 boolean ackFramePendingSet,
00404 u32 time,
00405 u16 errors,
00406 s8 rssi)
00407 {
00408 LED_RX_ON();
00409 receiving_packet = 0;
00410
00411 if(add_to_rxbuf(packet)){
00412 process_poll(&stm32w_radio_process);
00413 last_rssi = rssi;
00414 }
00415 LED_RX_OFF();
00416 }
00417
00418
00419 void ST_RadioTransmitCompleteIsrCallback(StStatus status,
00420 u32 txSyncTime,
00421 boolean framePending)
00422 {
00423
00424 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
00425 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
00426 LED_TX_OFF();
00427
00428 last_tx_status = status;
00429
00430 if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED){
00431 CLEAN_TXBUF();
00432 }
00433 else {
00434
00435 if(RETRY_CNT_GTZ()){
00436
00437 LED_TX_ON();
00438 if(ST_RadioTransmit(stm32w_txbuf)==ST_SUCCESS){
00439
00440 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
00441 ENERGEST_ON(ENERGEST_TYPE_TRANSMIT);
00442
00443 PRINTF("stm32w: retransmission.\r\n");
00444
00445 DEC_RETRY_CNT();
00446 }
00447 else {
00448 CLEAN_TXBUF();
00449 LED_TX_OFF();
00450 PRINTF("stm32w: retransmission failed.\r\n");
00451 }
00452 }
00453 else {
00454 CLEAN_TXBUF();
00455 }
00456 }
00457
00458
00459 if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED){
00460 PRINTF("TX_END");
00461 }
00462 else if (status == ST_MAC_NO_ACK_RECEIVED){
00463 PRINTF("TX_END_NOACK!!!");
00464 }
00465 else if (status == ST_PHY_TX_CCA_FAIL){
00466 PRINTF("TX_END_CCA!!!");
00467 }
00468 else if(status == ST_PHY_TX_UNDERFLOW){
00469 PRINTF("TX_END_UFL!!!");
00470 }
00471 else {
00472 PRINTF("TX_END_INCOMPL!!!");
00473 }
00474 }
00475
00476
00477 boolean ST_RadioDataPendingShortIdIsrCallback(int16u shortId) {
00478 receiving_packet = 1;
00479 return FALSE;
00480 }
00481
00482 boolean ST_RadioDataPendingLongIdIsrCallback(int8u* longId) {
00483 receiving_packet = 1;
00484 return FALSE;
00485 }
00486
00487 PROCESS_THREAD(stm32w_radio_process, ev, data)
00488 {
00489 int len;
00490
00491 PROCESS_BEGIN();
00492
00493 PRINTF("stm32w_radio_process: started\r\n");
00494
00495 while(1) {
00496
00497 PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
00498
00499 PRINTF("stm32w_radio_process: calling receiver callback\r\n");
00500
00501 #if DEBUG > 1
00502 for(u8_t c=1; c <= RCVD_PACKET_LEN; c++){
00503 PRINTF("%x",stm32w_rxbuf[c]);
00504 }
00505 PRINTF("\r\n");
00506 #endif
00507
00508 packetbuf_clear();
00509 len = stm32w_radio_read(packetbuf_dataptr(), PACKETBUF_SIZE);
00510 if(len > 0) {
00511 packetbuf_set_datalen(len);
00512 NETSTACK_RDC.input();
00513 }
00514 if(!RXBUFS_EMPTY()){
00515
00516
00517 process_poll(&stm32w_radio_process);
00518 }
00519 }
00520
00521 PROCESS_END();
00522 }
00523
00524 static int stm32w_radio_read(void *buf, unsigned short bufsize)
00525 {
00526 return read_from_rxbuf(buf,bufsize);
00527 }
00528
00529
00530 void ST_RadioOverflowIsrCallback(void)
00531 {
00532 PRINTF("OVERFLOW\r\n");
00533 }
00534
00535 void ST_RadioSfdSentIsrCallback(u32 sfdSentTime)
00536 {
00537 }
00538
00539 void ST_RadioMacTimerCompareIsrCallback(void)
00540 {
00541 }
00542
00543 static int add_to_rxbuf(uint8_t * src)
00544 {
00545 if(RXBUFS_FULL()){
00546 return 0;
00547 }
00548
00549 memcpy(stm32w_rxbufs[last], src, src[0] + 1);
00550 #if RADIO_RXBUFS > 1
00551 last = (last + 1) % RADIO_RXBUFS;
00552 if(first == -1){
00553 first = 0;
00554 }
00555 #endif
00556
00557 return 1;
00558 }
00559
00560 static int read_from_rxbuf(void * dest, unsigned short len)
00561 {
00562
00563 if(RXBUFS_EMPTY()){
00564 return 0;
00565 }
00566
00567 if(stm32w_rxbufs[first][0] > len){
00568 len = 0;
00569 }
00570 else {
00571 len = stm32w_rxbufs[first][0];
00572 memcpy(dest,stm32w_rxbufs[first]+1,len);
00573 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
00574 }
00575
00576 #if RADIO_RXBUFS > 1
00577 ATOMIC(
00578 first = (first + 1) % RADIO_RXBUFS;
00579 int first_tmp = first;
00580 if(first_tmp == last){
00581 CLEAN_RXBUFS();
00582 }
00583 )
00584 #else
00585 CLEAN_RXBUFS();
00586 #endif
00587
00588 return len;
00589 }
00590
00591 short last_packet_rssi(){
00592 return last_rssi;
00593 }
00594