Contiki 2.5
cc2430_rf_intr.c
Go to the documentation of this file.
1 /**
2  * \file
3  * CC2430 RF driver
4  * \author
5  * Zach Shelby <zach@sensinode.com>
6  *
7  * Non-bankable code for cc2430 rf driver.
8  * Interrupt routine and code called through function pointers
9  * must be placed into the HOME bank.
10  *
11  */
12 
13 #include <stdio.h>
14 
15 #include "contiki.h"
16 #include "dev/radio.h"
17 #include "dev/cc2430_rf.h"
18 #include "cc2430_sfr.h"
19 #ifdef RF_LED_ENABLE
20 #include "dev/leds.h"
21 #endif
22 #include "sys/clock.h"
23 
24 #include "net/packetbuf.h"
25 #include "net/rime/rimestats.h"
26 #define DEBUG 0
27 #if DEBUG
28 #define PRINTF(...) printf(__VA_ARGS__)
29 #else
30 #define PRINTF(...) do {} while (0)
31 #endif
32 
33 #ifdef RF_LED_ENABLE
34 #define RF_RX_LED_ON() leds_on(LEDS_RED);
35 #define RF_RX_LED_OFF() leds_off(LEDS_RED);
36 #define RF_TX_LED_ON() leds_on(LEDS_GREEN);
37 #define RF_TX_LED_OFF() leds_off(LEDS_GREEN);
38 #else
39 #define RF_RX_LED_ON()
40 #define RF_RX_LED_OFF()
41 #define RF_TX_LED_ON()
42 #define RF_TX_LED_OFF()
43 #endif
44 
45 #ifdef HAVE_RF_ERROR
46 uint8_t rf_error = 0;
47 #endif
48 
49 
50 /*---------------------------------------------------------------------------*/
51 PROCESS(cc2430_rf_process, "CC2430 RF driver");
52 
53 /*---------------------------------------------------------------------------*/
54 /**
55  * RF interrupt service routine.
56  *
57  */
58 void
59 cc2430_rf_ISR( void ) __interrupt (RF_VECTOR)
60 {
61  EA = 0;
62  if(RFIF & IRQ_TXDONE) {
63  RF_TX_LED_OFF();
64  RFIF &= ~IRQ_TXDONE;
65  cc2430_rf_command(ISFLUSHTX);
66  }
67  if(RFIF & IRQ_FIFOP) {
68  if(RFSTATUS & FIFO) {
69  RF_RX_LED_ON();
70  /* Poll the RF process which calls cc2430_rf_read() */
71  process_poll(&cc2430_rf_process);
72  } else {
73  cc2430_rf_command(ISFLUSHRX);
74  cc2430_rf_command(ISFLUSHRX);
75  RFIF &= ~IRQ_FIFOP;
76  }
77  }
78  S1CON &= ~(RFIF_0 | RFIF_1);
79  EA = 1;
80 }
81 /*---------------------------------------------------------------------------*/
82 /**
83  * RF error interrupt service routine.
84  *
85  */
86 void
87 cc2430_rf_error_ISR( void ) __interrupt (RFERR_VECTOR)
88 {
89  EA = 0;
90  TCON_RFERRIF = 0;
91 #ifdef HAVE_RF_ERROR
92  rf_error = 254;
93 #endif
94  cc2430_rf_command(ISRFOFF);
95  cc2430_rf_command(ISFLUSHRX);
96  cc2430_rf_command(ISFLUSHRX);
97  cc2430_rf_command(ISRXON);
98  RF_RX_LED_OFF();
99  RF_TX_LED_OFF();
100  EA = 1;
101 }
102 
103 void (* receiver_callback)(const struct radio_driver *);
104 
105 void
106 cc2430_rf_set_receiver(void (* recv)(const struct radio_driver *))
107 {
108  receiver_callback = recv;
109 }
110 /*---------------------------------------------------------------------------*/
111 /*
112  * non-banked functions called through function pointers then call banked code
113  */
114 int
115 cc2430_rf_off(void)
116 {
117  return cc2430_rf_rx_disable();
118 }
119 /*---------------------------------------------------------------------------*/
120 int
121 cc2430_rf_on(void)
122 {
123  return cc2430_rf_rx_enable();
124 }
125 /*---------------------------------------------------------------------------*/
126 int
127 cc2430_rf_send(void *payload, unsigned short payload_len)
128 {
129  return cc2430_rf_send_b(payload, payload_len);
130 }
131 /*---------------------------------------------------------------------------*/
132 int
133 cc2430_rf_read(void *buf, unsigned short bufsize)
134 {
135  return cc2430_rf_read_banked(buf, bufsize);
136 }
137 /*---------------------------------------------------------------------------*/
138 /*---------------------------------------------------------------------------*/
139 PROCESS_THREAD(cc2430_rf_process, ev, data)
140 {
141  PROCESS_BEGIN();
142  while(1) {
143  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
144 
145  if(receiver_callback != NULL) {
146  PRINTF("cc2430_rf_process: calling receiver callback\n");
147  receiver_callback(&cc2430_rf_driver);
148  } else {
149  PRINTF("cc2430_rf_process: no receiver callback\n");
150  cc2430_rf_command(ISFLUSHRX);
151  }
152  }
153 
154  PROCESS_END();
155 }