Contiki 3.x
contiki-main.c
1 #include "contiki.h"
2 #include "soc.h"
3 #include "stack.h"
4 #include "sys/clock.h"
5 #include "sys/autostart.h"
6 #include "dev/serial-line.h"
7 #include "dev/slip.h"
8 #include "dev/leds.h"
9 #include "dev/io-arch.h"
10 #include "dev/dma.h"
11 #include "dev/cc2530-rf.h"
12 #include "dev/radio.h"
13 #include "dev/watchdog.h"
14 #include "dev/clock-isr.h"
15 #include "dev/port2.h"
16 #include "dev/lpm.h"
17 #include "dev/button-sensor.h"
18 #include "dev/adc-sensor.h"
19 #include "dev/leds-arch.h"
20 #include "net/rime/rime.h"
21 #include "net/netstack.h"
22 #include "net/mac/frame802154.h"
23 #include "debug.h"
24 #include "cc253x.h"
25 #include "sfr-bits.h"
26 #include "contiki-lib.h"
27 #include "contiki-net.h"
28 /*---------------------------------------------------------------------------*/
29 #if VIZTOOL_CONF_ON
30 PROCESS_NAME(viztool_process);
31 #endif
32 /*---------------------------------------------------------------------------*/
33 #if STARTUP_CONF_VERBOSE
34 #define PUTSTRING(...) putstring(__VA_ARGS__)
35 #define PUTHEX(...) puthex(__VA_ARGS__)
36 #define PUTBIN(...) putbin(__VA_ARGS__)
37 #define PUTCHAR(...) putchar(__VA_ARGS__)
38 #else
39 #define PUTSTRING(...)
40 #define PUTHEX(...)
41 #define PUTBIN(...)
42 #define PUTCHAR(...)
43 #endif
44 /*---------------------------------------------------------------------------*/
45 #if CLOCK_CONF_STACK_FRIENDLY
46 extern volatile uint8_t sleep_flag;
47 #endif
48 /*---------------------------------------------------------------------------*/
49 extern linkaddr_t linkaddr_node_addr;
50 static CC_AT_DATA uint16_t len;
51 /*---------------------------------------------------------------------------*/
52 #if ENERGEST_CONF_ON
53 static unsigned long irq_energest = 0;
54 #define ENERGEST_IRQ_SAVE(a) do { \
55  a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0)
56 #define ENERGEST_IRQ_RESTORE(a) do { \
57  energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0)
58 #else
59 #define ENERGEST_IRQ_SAVE(a) do {} while(0)
60 #define ENERGEST_IRQ_RESTORE(a) do {} while(0)
61 #endif
62 /*---------------------------------------------------------------------------*/
63 static void
64 fade(int l) CC_NON_BANKED
65 {
66  volatile int i, a;
67  int k, j;
68  for(k = 0; k < 400; ++k) {
69  j = k > 200 ? 400 - k : k;
70 
71  leds_on(l);
72  for(i = 0; i < j; ++i) {
73  a = i;
74  }
75  leds_off(l);
76  for(i = 0; i < 200 - j; ++i) {
77  a = i;
78  }
79  }
80 }
81 /*---------------------------------------------------------------------------*/
82 static void
83 set_rf_params(void) CC_NON_BANKED
84 {
85  char i;
86  uint16_t short_addr;
87  uint8_t ext_addr[8];
88 
89 #if CC2530_CONF_MAC_FROM_PRIMARY
90  __xdata unsigned char *macp = &X_IEEE_ADDR;
91 #else
92  __code unsigned char *macp = (__code unsigned char *)0xFFE8;
93 #endif
94 
95  PUTSTRING("Rime is 0x");
96  PUTHEX(sizeof(linkaddr_t));
97  PUTSTRING(" bytes long\n");
98 
99 #if CC2530_CONF_MAC_FROM_PRIMARY
100  PUTSTRING("Reading MAC from Info Page\n");
101 #else
102  PUTSTRING("Reading MAC from flash\n");
103 
104  /*
105  * The MAC is always stored in 0xFFE8 of the highest BANK of our flash. This
106  * maps to address 0xFFF8 of our CODE segment, when this BANK is selected.
107  * Load the bank, read 8 bytes starting at 0xFFE8 and restore last BANK.
108  * Since we are called from main(), this MUST be BANK1 or something is very
109  * wrong. This code can be used even without a bankable firmware.
110  */
111 
112  /* Don't interrupt us to make sure no BANK switching happens while working */
114 
115  /* Switch to the BANKn,
116  * map CODE: 0x8000 - 0xFFFF to FLASH: 0xn8000 - 0xnFFFF */
117  FMAP = CC2530_LAST_FLASH_BANK;
118 #endif
119 
120  /*
121  * Read IEEE address from flash, store in ext_addr.
122  * Invert endianness (from little to big endian)
123  */
124  for(i = 7; i >= 0; --i) {
125  ext_addr[i] = *macp;
126  macp++;
127  }
128 
129 #if !CC2530_CONF_MAC_FROM_PRIMARY
130  /* Remap 0x8000 - 0xFFFF to BANK1 */
131  FMAP = 1;
132  ENABLE_INTERRUPTS();
133 #endif
134 
135  short_addr = ext_addr[7];
136  short_addr |= ext_addr[6] << 8;
137 
138  /* Populate linkaddr_node_addr. Maintain endianness */
139  memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE);
140 
141  /* Now the address is stored MSB first */
142 #if STARTUP_CONF_VERBOSE
143  PUTSTRING("Rime configured with address ");
144  for(i = 0; i < LINKADDR_SIZE - 1; i++) {
145  PUTHEX(linkaddr_node_addr.u8[i]);
146  PUTCHAR(':');
147  }
148  PUTHEX(linkaddr_node_addr.u8[i]);
149  PUTCHAR('\n');
150 #endif
151 
152  /* Write params to RF registers */
153  NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID);
154  NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr);
155  NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC2530_RF_CHANNEL);
156  NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8);
157  return;
158 }
159 /*---------------------------------------------------------------------------*/
160 int
161 main(void) CC_NON_BANKED
162 {
163  /* Hardware initialization */
164  clock_init();
165  soc_init();
166  rtimer_init();
167 
168  stack_poison();
169 
170  /* Init LEDs here */
171  leds_init();
172  leds_off(LEDS_ALL);
173  fade(LEDS_GREEN);
174 
175  /* initialize process manager. */
176  process_init();
177 
178 #if DMA_ON
179  dma_init();
180 #endif
181 
182  io_arch_init();
183 
184 #if SLIP_ARCH_CONF_ENABLE
185  slip_arch_init(0);
186 #else
187  io_arch_set_input(serial_line_input_byte);
188  serial_line_init();
189 #endif
190  fade(LEDS_RED);
191 
192  PUTSTRING("##########################################\n");
193  putstring(CONTIKI_VERSION_STRING "\n");
194  putstring(MODEL_STRING);
195  switch(CHIPID) {
196  case 0xA5:
197  putstring("cc2530");
198  break;
199  case 0xB5:
200  putstring("cc2531");
201  break;
202  case 0x95:
203  putstring("cc2533");
204  break;
205  case 0x8D:
206  putstring("cc2540");
207  break;
208  }
209 
210  putstring("-" CC2530_FLAVOR_STRING ", ");
211  puthex(CHIPINFO1 + 1);
212  putstring("KB SRAM\n");
213 
214  PUTSTRING("\nSDCC Build:\n");
215 #if STARTUP_CONF_VERBOSE
216 #ifdef HAVE_SDCC_BANKING
217  PUTSTRING(" With Banking.\n");
218 #endif /* HAVE_SDCC_BANKING */
219 #ifdef SDCC_MODEL_LARGE
220  PUTSTRING(" --model-large\n");
221 #endif /* SDCC_MODEL_LARGE */
222 #ifdef SDCC_MODEL_HUGE
223  PUTSTRING(" --model-huge\n");
224 #endif /* SDCC_MODEL_HUGE */
225 #ifdef SDCC_STACK_AUTO
226  PUTSTRING(" --stack-auto\n");
227 #endif /* SDCC_STACK_AUTO */
228 
229  PUTCHAR('\n');
230 
231  PUTSTRING(" Net: ");
232  PUTSTRING(NETSTACK_NETWORK.name);
233  PUTCHAR('\n');
234  PUTSTRING(" MAC: ");
235  PUTSTRING(NETSTACK_MAC.name);
236  PUTCHAR('\n');
237  PUTSTRING(" RDC: ");
238  PUTSTRING(NETSTACK_RDC.name);
239  PUTCHAR('\n');
240 
241  PUTSTRING("##########################################\n");
242 #endif
243 
244  watchdog_init();
245 
246  /* Initialise the H/W RNG engine. */
247  random_init(0);
248 
249  /* start services */
250  process_start(&etimer_process, NULL);
251  ctimer_init();
252 
253  /* initialize the netstack */
254  netstack_init();
255  set_rf_params();
256 
257 #if BUTTON_SENSOR_ON || ADC_SENSOR_ON
258  process_start(&sensors_process, NULL);
259  BUTTON_SENSOR_ACTIVATE();
260  ADC_SENSOR_ACTIVATE();
261 #endif
262 
263 #if UIP_CONF_IPV6
264  memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));
265  queuebuf_init();
266  process_start(&tcpip_process, NULL);
267 #endif /* UIP_CONF_IPV6 */
268 
269 #if VIZTOOL_CONF_ON
270  process_start(&viztool_process, NULL);
271 #endif
272 
273  energest_init();
274  ENERGEST_ON(ENERGEST_TYPE_CPU);
275 
276  autostart_start(autostart_processes);
277 
278  watchdog_start();
279 
280  fade(LEDS_YELLOW);
281 
282  while(1) {
283  uint8_t r;
284  do {
285  /* Reset watchdog and handle polls and events */
287 
288 #if CLOCK_CONF_STACK_FRIENDLY
289  if(sleep_flag) {
290  if(etimer_pending() &&
291  (etimer_next_expiration_time() - clock_time() - 1) > MAX_TICKS) {
293  }
294  sleep_flag = 0;
295  }
296 #endif
297  r = process_run();
298  } while(r > 0);
299  len = NETSTACK_RADIO.pending_packet();
300  if(len) {
301  packetbuf_clear();
302  len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
303  if(len > 0) {
305  NETSTACK_RDC.input();
306  }
307  }
308 
309 #if LPM_MODE
310 #if (LPM_MODE==LPM_MODE_PM2)
311  SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */
312  while(!(SLEEP & HFRC_STB)); /* Wait for RCOSC to be stable */
313  CLKCON |= OSC; /* Switch to the RCOSC */
314  while(!(CLKCON & OSC)); /* Wait till it's happened */
315  SLEEP |= OSC_PD; /* Turn the other one off */
316 #endif /* LPM_MODE==LPM_MODE_PM2 */
317 
318  /*
319  * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM
320  * Sleep Timer will wake us up in no more than 7.8ms (max idle interval)
321  */
322  SLEEPCMD = (SLEEPCMD & 0xFC) | (LPM_MODE - 1);
323 
324 #if (LPM_MODE==LPM_MODE_PM2)
325  /*
326  * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or
327  * no interrupt occurred and we can safely power down
328  */
329  __asm
330  nop
331  nop
332  nop
333  __endasm;
334 
335  if(SLEEPCMD & SLEEP_MODE0) {
336 #endif /* LPM_MODE==LPM_MODE_PM2 */
337 
338  ENERGEST_OFF(ENERGEST_TYPE_CPU);
339  ENERGEST_ON(ENERGEST_TYPE_LPM);
340 
341  /* We are only interested in IRQ energest while idle or in LPM */
342  ENERGEST_IRQ_RESTORE(irq_energest);
343 
344  /* Go IDLE or Enter PM1 */
345  PCON |= PCON_IDLE;
346 
347  /* First instruction upon exiting PM1 must be a NOP */
348  __asm
349  nop
350  __endasm;
351 
352  /* Remember energest IRQ for next pass */
353  ENERGEST_IRQ_SAVE(irq_energest);
354 
355  ENERGEST_ON(ENERGEST_TYPE_CPU);
356  ENERGEST_OFF(ENERGEST_TYPE_LPM);
357 
358 #if (LPM_MODE==LPM_MODE_PM2)
359  SLEEPCMD &= ~SLEEP_OSC_PD; /* Make sure both HS OSCs are on */
360  while(!(SLEEPCMD & SLEEP_XOSC_STB)); /* Wait for XOSC to be stable */
361  CLKCONCMD &= ~CLKCONCMD_OSC; /* Switch to the XOSC */
362  /*
363  * On occasion the XOSC is reported stable when in reality it's not.
364  * We need to wait for a safeguard of 64us or more before selecting it
365  */
366  clock_delay_usec(65);
367  while(CLKCONCMD & CLKCONCMD_OSC); /* Wait till it's happened */
368  }
369 #endif /* LPM_MODE==LPM_MODE_PM2 */
370 #endif /* LPM_MODE */
371  }
372 }
373 /*---------------------------------------------------------------------------*/
int serial_line_input_byte(unsigned char c)
Get one byte of input from the serial driver.
Definition: serial-line.c:60
linkaddr_t linkaddr_node_addr
The Rime address of the node.
Definition: linkaddr.c:48
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Definition: uip6.c:115
802.15.4 frame creation and parsing functions
#define OSC
Peripheral OSC base pointer.
Definition: MK60D10.h:6025
#define LEDS_RED
LED1 (Red) -&gt; PC0.
Definition: board.h:89
void watchdog_start(void)
Starts the WDT in watchdog mode if enabled by user configuration, maximum interval.
Definition: watchdog.c:49
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94
Header file for the radio API
void rtimer_init(void)
Initialize the real-time scheduler.
Definition: rtimer.c:61
#define PROCESS_NAME(name)
Declare the name of a process.
Definition: process.h:286
Header file for debugging functions used by the sensinode port.
#define NULL
The null pointer.
Definitions for TI/Chipcon cc2530, cc2531 and cc2533 SFR registers.
void clock_init(void)
Initialize the clock library.
Definition: clock.c:76
Declaration of the Sleep timer ISR, used by the clock module
int main(void)
This is main...
Definition: ethconfig.c:49
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:200
void process_init(void)
Initialize the process module.
Definition: process.c:208
Header file for the Rime stack
Header file with definitions of bit masks for some cc2530 SFRs
Header file for platform-specific led functionality
#define LEDS_YELLOW
LED2 (Yellow) -&gt; PC1.
Definition: board.h:80
#define LEDS_GREEN
LED3 (Green) -&gt; PC2.
Definition: board.h:81
CCIF clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
void random_init(unsigned short seed)
Seed the cc2430 random number generator.
Definition: random.c:41
void slip_arch_init(unsigned long ubr)
Initalize the RS232 port and the SLIP driver.
Definition: slip-arch.c:56
Generic serial I/O process header filer.
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
Header file for module for automatically starting and exiting a list of processes.
void ctimer_init(void)
Initialize the callback timer library.
Definition: ctimer.c:91
clock_time_t etimer_next_expiration_time(void)
Get next event timer expiration time.
Definition: etimer.c:229
Platform-specific header file which switches between UART and USB input/output, depending on whether we are building for the cc2531 USB dongle or the SmartRF
void etimer_request_poll(void)
Make the event timer aware that the clock has changed.
Definition: etimer.c:145
#define SLEEP
Constant SLEEP for sub-register SR_TRX_STATUS.
int etimer_pending(void)
Check if there are any non-expired event timers.
Definition: etimer.c:223
Implementation of the cc2530 RF driver
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
int process_run(void)
Run the system once - call poll handlers and process one event.
Definition: process.c:302
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:65
Header file with cc253x SoC-specific defines and prototypes
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:207
#define DISABLE_INTERRUPTS()
Disable interrupts, saving the previous state so it can be later restored with RESTORE_INTERRUPTS().
Definition: gnu.h:405
void watchdog_init(void)
Copyright (c) 2014, Analog Devices, Inc.
Definition: watchdog.c:42
Include file for the Contiki low-layer network stack (NETSTACK)