stm32w-radio.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010, STMicroelectronics.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above
00011  *    copyright notice, this list of conditions and the following
00012  *    disclaimer in the documentation and/or other materials provided
00013  *    with the distribution.
00014  * 3. The name of the author may not be used to endorse or promote
00015  *    products derived from this software without specific prior
00016  *    written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00019  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00020  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00022  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00024  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00026  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00027  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * This file is part of the Contiki OS
00031  *
00032  * $Id: stm32w-radio.c,v 1.2 2010/10/27 14:05:23 salvopitru Exp $
00033  */
00034 /*---------------------------------------------------------------------------*/
00035 /**
00036 * \file
00037 *                                       Machine dependent STM32W radio code.
00038 * \author
00039 *                                       Salvatore Pitrulli
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 /* If set to 1, a send() returns only after the packet has been transmitted.
00105   This is necessary if you use the x-mac module, for example. */
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,  // waitForAck;
00119   TRUE, // checkCca;     // Set to FALSE with low-power MACs.
00120   4,     // ccaAttemptMax;
00121   2,     // backoffExponentMin;
00122   6,     // backoffExponentMax;
00123   TRUE   // appendCrc;
00124 };
00125 
00126 /*
00127  * The buffers which hold incoming data.
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]; // +1 because of the first byte, which will contain the length of the packet.
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 /* RADIO_RXBUFS > 1 */
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 /* RADIO_RXBUFS > 1 */
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  * The transceiver state.
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   // A channel needs also to be setted.
00213   ST_RadioSetChannel(RF_CHANNEL);
00214 
00215   // Initialize radio (analog section, digital baseband and MAC).
00216   // Leave radio powered up in non-promiscuous rx mode.
00217   ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
00218   onoroff = OFF;
00219   ST_RadioSetNodeId(STM32W_NODE_ID);   // To be deleted.
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     /* Put CPU in sleep mode. */
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     /* Check if the txbuf is empty.
00263      *  Wait for a finite time.
00264      * This sould not occur if we wait for the end of transmission in stm32w_radio_transmit().
00265     */
00266     if(wait_for_tx()){
00267       PRINTF("stm32w: tx buffer full.\r\n");
00268       return RADIO_TX_ERR;
00269     }
00270 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
00271     
00272     /* Copy to the txbuf. 
00273      * The first byte must be the packet length.
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 /* RADIO_WAIT_FOR_PACKET_SENT */      
00326       
00327       TO_PREV_STATE();
00328       LED_TX_OFF();
00329       return RADIO_TX_OK;    
00330       
00331 #endif /* RADIO_WAIT_FOR_PACKET_SENT */
00332       
00333     }
00334     
00335     TO_PREV_STATE();
00336     
00337     PRINTF("stm32w: transmission never started.\r\n");
00338     /* TODO: Do we have to retransmit? */
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   /* Any transmit or receive packets in progress are aborted.
00373    * Waiting for end of transmission or reception have to be done.
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   /* Copy packet into the buffer. It is better to do this here. */
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           // Retransmission
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   /* Debug outputs. */
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       // Some data packet still in rx buffer (this appens because process_poll doesn't queue requests),
00516       // so stm32w_radio_process need to be called again.
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()){ // Buffers are all empty
00564         return 0;
00565     }        
00566     
00567     if(stm32w_rxbufs[first][0] > len){  // Too large packet for dest.
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 

Generated on Mon Apr 11 14:23:39 2011 for Contiki 2.5 by  doxygen 1.6.1