47 #include PLATFORM_HEADER
65 #define LED_ACTIVITY 0
67 #ifdef ST_CONF_RADIO_AUTOACK
68 #define ST_RADIO_AUTOACK ST_CONF_RADIO_AUTOACK
70 #define ST_RADIO_AUTOACK 0
73 #if RDC_CONF_DEBUG_LED
74 #define LED_RDC RDC_CONF_DEBUG_LED
75 #define LED_ACTIVITY 1
82 #define PRINTF(...) printf(__VA_ARGS__)
84 #define PRINTF(...) do {} while (0)
88 #define LED_TX_ON() leds_on(LEDS_GREEN)
89 #define LED_TX_OFF() leds_off(LEDS_GREEN)
90 #define LED_RX_ON() do { \
95 #define LED_RX_OFF() do { \
100 #define LED_RDC_ON() do { \
105 #define LED_RDC_OFF() do { \
107 leds_off(LEDS_RED); \
116 #define LED_RDC_OFF()
119 #if RDC_CONF_HARDWARE_CSMA
120 #define MAC_RETRIES 0
124 #define MAC_RETRIES 1
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)
133 #define INIT_RETRY_CNT()
134 #define DEC_RETRY_CNT()
135 #define RETRY_CNT_GTZ() 0
141 #ifndef RADIO_WAIT_FOR_PACKET_SENT
142 #define RADIO_WAIT_FOR_PACKET_SENT 1
145 #define TO_PREV_STATE() do { \
146 if(onoroff == OFF){ \
148 ENERGEST_OFF(ENERGEST_TYPE_LISTEN); \
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
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
163 const RadioTransmitConfig radioTransmitConfig = {
166 ST_RADIO_CCA_ATTEMPT_MAX,
172 #define MAC_RETRIES 0
178 #define RADIO_RXBUFS 1
182 static uint8_t stm32w_rxbufs[RADIO_RXBUFS][STM32W_MAX_PACKET_LEN + 1];
185 static volatile int8_t first = -1, last = 0;
187 static const int8_t first = 0, last = 0;
191 #define CLEAN_RXBUFS() do{first = -1; last = 0;}while(0)
192 #define RXBUFS_EMPTY() (first == -1)
196 int8_t first_tmp = first;
197 return first_tmp == last;
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)
206 __attribute__ ((aligned(2))) stm32w_txbuf[STM32W_MAX_PACKET_LEN + 1];
209 #define CLEAN_TXBUF() (stm32w_txbuf[0] = 0)
210 #define TXBUF_EMPTY() (stm32w_txbuf[0] == 0)
211 #define CHECKSUM_LEN 2
219 #define BUSYWAIT_UNTIL(cond, max_time) \
223 while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \
226 #define GET_LOCK() locked++
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;
242 PROCESS(stm32w_radio_process,
"STM32W radio driver");
244 static int stm32w_radio_init(
void);
246 static int stm32w_radio_prepare(
const void *payload,
247 unsigned short payload_len);
248 static int stm32w_radio_transmit(
unsigned short payload_len);
250 static int stm32w_radio_send(
const void *data,
unsigned short len);
252 static int stm32w_radio_read(
void *buf,
unsigned short bufsize);
254 static int stm32w_radio_channel_clear(
void);
256 static int stm32w_radio_receiving_packet(
void);
258 static int stm32w_radio_pending_packet(
void);
260 static int stm32w_radio_on(
void);
262 static int stm32w_radio_off(
void);
264 static int add_to_rxbuf(uint8_t * src);
266 static int read_from_rxbuf(
void *dest,
unsigned short len);
269 static radio_result_t
273 return RADIO_RESULT_INVALID_VALUE;
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:
284 return RADIO_RESULT_OK;
285 case RADIO_PARAM_16BIT_ADDR:
287 return RADIO_RESULT_OK;
288 case RADIO_PARAM_RX_MODE:
294 *value |= RADIO_RX_MODE_AUTOACK;
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;
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;
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;
322 return RADIO_RESULT_NOT_SUPPORTED;
326 static radio_result_t
330 case RADIO_PARAM_POWER_MODE:
331 if(value == RADIO_POWER_MODE_ON) {
333 return RADIO_RESULT_OK;
335 if(value == RADIO_POWER_MODE_OFF) {
337 return RADIO_RESULT_OK;
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;
345 if(ST_RadioSetChannel(value) != ST_SUCCESS) {
346 return RADIO_RESULT_ERROR;
348 return RADIO_RESULT_OK;
349 case RADIO_PARAM_PAN_ID:
351 return RADIO_RESULT_OK;
352 case RADIO_PARAM_16BIT_ADDR:
354 return RADIO_RESULT_OK;
355 case RADIO_PARAM_RX_MODE:
357 RADIO_RX_MODE_AUTOACK)) {
358 return RADIO_RESULT_INVALID_VALUE;
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;
367 if(ST_RadioSetPower((int8_t)value) != ST_SUCCESS) {
368 return RADIO_RESULT_INVALID_VALUE;
370 return RADIO_RESULT_OK;
371 case RADIO_PARAM_CCA_THRESHOLD:
372 ST_RadioSetEdCcaThreshold((int8_t)value);
373 return RADIO_RESULT_OK;
375 return RADIO_RESULT_NOT_SUPPORTED;
379 static radio_result_t
380 get_object(radio_param_t param,
void *dest,
size_t size)
382 const uint8_t *eui64;
386 if(param == RADIO_PARAM_64BIT_ADDR) {
387 if(size < 8 || !dest) {
388 return RADIO_RESULT_INVALID_VALUE;
392 return RADIO_RESULT_ERROR;
395 for(i = 0; i < 8; i++) {
396 target[i] = eui64[7 - i];
398 return RADIO_RESULT_OK;
400 return RADIO_RESULT_NOT_SUPPORTED;
403 static radio_result_t
404 set_object(radio_param_t param,
const void *src,
size_t size)
406 return RADIO_RESULT_NOT_SUPPORTED;
411 stm32w_radio_prepare,
412 stm32w_radio_transmit,
415 stm32w_radio_channel_clear,
416 stm32w_radio_receiving_packet,
417 stm32w_radio_pending_packet,
427 stm32w_radio_init(
void)
430 ST_RadioSetChannel(RF_CHANNEL);
434 ST_RadioInit(ST_RADIO_POWER_MODE_OFF);
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"
455 stm32w_radio_set_promiscous(uint8_t
on)
465 stm32w_radio_set_channel(uint8_t channel)
467 if (ST_RadioSetChannel(channel) == ST_SUCCESS) {
479 while(!TXBUF_EMPTY()) {
481 PRINTF(
"stm32w: tx buffer full.\r\n");
491 stm32w_radio_prepare(
const void *payload,
unsigned short payload_len)
493 if(payload_len > STM32W_MAX_PACKET_LEN) {
494 PRINTF(
"stm32w: payload length=%d is too long.\r\n", payload_len);
497 #if !RADIO_WAIT_FOR_PACKET_SENT
504 PRINTF(
"stm32w: tx buffer full.\r\n");
514 memcpy(stm32w_txbuf + 1, payload, payload_len);
520 stm32w_radio_transmit(
unsigned short payload_len)
522 stm32w_txbuf[0] = payload_len + CHECKSUM_LEN;
526 PRINTF(
"stm32w: Radio is off, turning it on.\r\n");
528 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
530 #if RADIO_WAIT_FOR_PACKET_SENT
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);
541 for(uint8_t c = 1; c <= stm32w_txbuf[0] - 2; c++) {
542 PRINTF(
"%x:", stm32w_txbuf[c]);
547 #if RADIO_WAIT_FOR_PACKET_SENT
550 PRINTF(
"stm32w: unknown tx error.\r\n");
558 if(last_tx_status == ST_SUCCESS || last_tx_status == ST_PHY_ACK_RECEIVED ||
559 last_tx_status == ST_MAC_NO_ACK_RECEIVED) {
561 if(last_tx_status == ST_PHY_ACK_RECEIVED) {
563 }
else if(last_tx_status == ST_MAC_NO_ACK_RECEIVED ||
564 last_tx_status == ST_SUCCESS) {
565 return RADIO_TX_NOACK;
580 #if RADIO_WAIT_FOR_PACKET_SENT
585 PRINTF(
"stm32w: transmission never started.\r\n");
594 stm32w_radio_send(
const void *payload,
unsigned short payload_len)
596 if (stm32w_radio_prepare(payload, payload_len) == RADIO_TX_ERR) {
599 return stm32w_radio_transmit(payload_len);
603 stm32w_radio_channel_clear(
void)
605 return ST_RadioChannelIsClear();
609 stm32w_radio_receiving_packet(
void)
611 return receiving_packet;
615 stm32w_radio_pending_packet(
void)
617 return !RXBUFS_EMPTY();
621 stm32w_radio_off(
void)
627 PRINTF(
"stm32w: try to off while sending/receiving (lock=%u).\r\n",
632 if(onoroff == ON && TXBUF_EMPTY() && !receiving_packet) {
639 ENERGEST_OFF(ENERGEST_TYPE_LISTEN);
646 stm32w_radio_on(
void)
648 PRINTF(
"stm32w: turn radio on\n");
654 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
661 stm32w_radio_is_on(
void)
663 return onoroff == ON;
668 boolean ackFramePendingSet,
669 uint32_t time, uint16_t errors, int8_t rssi)
672 PRINTF(
"stm32w: incomming packet received\n");
673 receiving_packet = 0;
676 if(add_to_rxbuf(packet)) {
684 BUSYWAIT_UNTIL(!is_transmit_ack, RTIMER_SECOND / 1500);
689 ST_RadioTxAckIsrCallback(
void)
702 uint32_t txSyncTime,
boolean framePending)
704 ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT);
705 ENERGEST_ON(ENERGEST_TYPE_LISTEN);
708 last_tx_status = status;
710 if(status == ST_SUCCESS || status == ST_PHY_ACK_RECEIVED) {
713 if(RETRY_CNT_GTZ()) {
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");
725 PRINTF(
"stm32w: retransmission failed.\r\n");
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");
742 PRINTF(
"stm32w: return status TX_END_INCOMPLETE\r\n");
749 receiving_packet = 1;
756 receiving_packet = 1;
764 PRINTF(
"stm32w_radio_process: started\r\n");
768 PRINTF(
"stm32w_radio_process: calling receiver callback\r\n");
771 for(uint8_t c = 1; c <= RCVD_PACKET_LEN; c++) {
772 PRINTF(
"%x", stm32w_rxbuf[c]);
781 NETSTACK_RDC.input();
783 if(!RXBUFS_EMPTY()) {
796 stm32w_radio_read(
void *buf,
unsigned short bufsize)
798 return read_from_rxbuf(buf, bufsize);
804 PRINTF(
"stm32w: radio overflow\r\n");
818 add_to_rxbuf(uint8_t *src)
824 memcpy(stm32w_rxbufs[last], src, src[0] + 1);
826 last = (last + 1) % RADIO_RXBUFS;
836 read_from_rxbuf(
void *dest,
unsigned short len)
842 if(stm32w_rxbufs[first][0] > len) {
845 len = stm32w_rxbufs[first][0];
846 memcpy(dest, stm32w_rxbufs[first] + 1, len);
847 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi);
851 ATOMIC(first = (first + 1) % RADIO_RXBUFS;
852 int first_tmp = first;
if(first_tmp == last) {
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
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. ...
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.
void process_poll(struct process *p)
Request a process to be polled.
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 ...
u8 * ST_RadioGetEui64(void)
This function get the EUI 64 of the node.
#define PROCESS_BEGIN()
Define the beginning of a process.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
Header file for the Rime buffer (packetbuf) management
void __attribute__((interrupt))
This ISR handles most of the business interacting with the 1-wire bus.
STM32W radio driver header file
#define NULL
The null pointer.
The structure of a device driver for a radio in Contiki.
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...
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
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.
#define PROCESS_END()
Define the end of a process.
#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...
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...
int(* on)(void)
Turn the radio on.
radio_result_t(* get_value)(radio_param_t param, radio_value_t *value)
Get a radio parameter value.
radio_result_t(* get_object)(radio_param_t param, void *dest, size_t size)
Get a radio parameter object.
#define PROCESS(name, strname)
Declare a process.
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...
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.
void process_start(struct process *p, process_data_t data)
Start a process.
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.
#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.
#define ATOMIC(blah)
A block of code may be made atomic by wrapping it with this macro.
radio_result_t(* set_object)(radio_param_t param, const void *src, size_t size)
Set a radio parameter object.
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...
int timer_expired(struct timer *t)
Check if a timer has expired.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
radio_result_t(* set_value)(radio_param_t param, radio_value_t value)
Set a radio parameter value.
void ST_RadioOverflowIsrCallback(void)
This function is called by the library in response to a receive overflow event if this notification i...
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.