Contiki-Inga 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/watchdog.h"
13 #include "dev/clock-isr.h"
14 #include "dev/port2.h"
15 #include "dev/lpm.h"
16 #include "dev/button-sensor.h"
17 #include "dev/adc-sensor.h"
18 #include "dev/leds-arch.h"
19 #include "net/rime/rime.h"
20 #include "net/netstack.h"
21 #include "net/mac/frame802154.h"
22 #include "debug.h"
23 #include "cc253x.h"
24 #include "sfr-bits.h"
25 #include "contiki-lib.h"
26 #include "contiki-net.h"
27 /*---------------------------------------------------------------------------*/
28 #if VIZTOOL_CONF_ON
29 PROCESS_NAME(viztool_process);
30 #endif
31 /*---------------------------------------------------------------------------*/
32 #if STARTUP_CONF_VERBOSE
33 #define PUTSTRING(...) putstring(__VA_ARGS__)
34 #define PUTHEX(...) puthex(__VA_ARGS__)
35 #define PUTBIN(...) putbin(__VA_ARGS__)
36 #define PUTCHAR(...) putchar(__VA_ARGS__)
37 #else
38 #define PUTSTRING(...)
39 #define PUTHEX(...)
40 #define PUTBIN(...)
41 #define PUTCHAR(...)
42 #endif
43 /*---------------------------------------------------------------------------*/
44 #if CLOCK_CONF_STACK_FRIENDLY
45 extern volatile uint8_t sleep_flag;
46 #endif
47 /*---------------------------------------------------------------------------*/
48 extern linkaddr_t linkaddr_node_addr;
49 static CC_AT_DATA uint16_t len;
50 /*---------------------------------------------------------------------------*/
51 #if ENERGEST_CONF_ON
52 static unsigned long irq_energest = 0;
53 #define ENERGEST_IRQ_SAVE(a) do { \
54  a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0)
55 #define ENERGEST_IRQ_RESTORE(a) do { \
56  energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0)
57 #else
58 #define ENERGEST_IRQ_SAVE(a) do {} while(0)
59 #define ENERGEST_IRQ_RESTORE(a) do {} while(0)
60 #endif
61 /*---------------------------------------------------------------------------*/
62 static void
63 fade(int l) CC_NON_BANKED
64 {
65  volatile int i, a;
66  int k, j;
67  for(k = 0; k < 400; ++k) {
68  j = k > 200 ? 400 - k : k;
69 
70  leds_on(l);
71  for(i = 0; i < j; ++i) {
72  a = i;
73  }
74  leds_off(l);
75  for(i = 0; i < 200 - j; ++i) {
76  a = i;
77  }
78  }
79 }
80 /*---------------------------------------------------------------------------*/
81 static void
82 set_rime_addr(void) CC_NON_BANKED
83 {
84  char i;
85 
86 #if CC2530_CONF_MAC_FROM_PRIMARY
87  __xdata unsigned char *macp = &X_IEEE_ADDR;
88 #else
89  __code unsigned char *macp = (__code unsigned char *)0xFFE8;
90 #endif
91 
92  PUTSTRING("Rime is 0x");
93  PUTHEX(sizeof(linkaddr_t));
94  PUTSTRING(" bytes long\n");
95 
96 #if CC2530_CONF_MAC_FROM_PRIMARY
97  PUTSTRING("Reading MAC from Info Page\n");
98 #else
99  PUTSTRING("Reading MAC from flash\n");
100 
101  /*
102  * The MAC is always stored in 0xFFE8 of the highest BANK of our flash. This
103  * maps to address 0xFFF8 of our CODE segment, when this BANK is selected.
104  * Load the bank, read 8 bytes starting at 0xFFE8 and restore last BANK.
105  * Since we are called from main(), this MUST be BANK1 or something is very
106  * wrong. This code can be used even without a bankable firmware.
107  */
108 
109  /* Don't interrupt us to make sure no BANK switching happens while working */
111 
112  /* Switch to the BANKn,
113  * map CODE: 0x8000 - 0xFFFF to FLASH: 0xn8000 - 0xnFFFF */
114  FMAP = CC2530_LAST_FLASH_BANK;
115 #endif
116 
117  for(i = (LINKADDR_SIZE - 1); i >= 0; --i) {
118  linkaddr_node_addr.u8[i] = *macp;
119  macp++;
120  }
121 
122 #if !CC2530_CONF_MAC_FROM_PRIMARY
123  /* Remap 0x8000 - 0xFFFF to BANK1 */
124  FMAP = 1;
125  ENABLE_INTERRUPTS();
126 #endif
127 
128  /* Now the address is stored MSB first */
129 #if STARTUP_CONF_VERBOSE
130  PUTSTRING("Rime configured with address ");
131  for(i = 0; i < LINKADDR_SIZE - 1; i++) {
132  PUTHEX(linkaddr_node_addr.u8[i]);
133  PUTCHAR(':');
134  }
135  PUTHEX(linkaddr_node_addr.u8[i]);
136  PUTCHAR('\n');
137 #endif
138 
139  cc2530_rf_set_addr(IEEE802154_PANID);
140  return;
141 }
142 /*---------------------------------------------------------------------------*/
143 int
144 main(void) CC_NON_BANKED
145 {
146  /* Hardware initialization */
147  clock_init();
148  soc_init();
149  rtimer_init();
150 
151  stack_poison();
152 
153  /* Init LEDs here */
154  leds_init();
155  leds_off(LEDS_ALL);
156  fade(LEDS_GREEN);
157 
158  /* initialize process manager. */
159  process_init();
160 
161 #if DMA_ON
162  dma_init();
163 #endif
164 
165  io_arch_init();
166 
167 #if SLIP_ARCH_CONF_ENABLE
168  slip_arch_init(0);
169 #else
170  io_arch_set_input(serial_line_input_byte);
171  serial_line_init();
172 #endif
173  fade(LEDS_RED);
174 
175  PUTSTRING("##########################################\n");
176  putstring(CONTIKI_VERSION_STRING "\n");
177  putstring(MODEL_STRING);
178  switch(CHIPID) {
179  case 0xA5:
180  putstring("cc2530");
181  break;
182  case 0xB5:
183  putstring("cc2531");
184  break;
185  case 0x95:
186  putstring("cc2533");
187  break;
188  case 0x8D:
189  putstring("cc2540");
190  break;
191  }
192 
193  putstring("-" CC2530_FLAVOR_STRING ", ");
194  puthex(CHIPINFO1 + 1);
195  putstring("KB SRAM\n");
196 
197  PUTSTRING("\nSDCC Build:\n");
198 #if STARTUP_CONF_VERBOSE
199 #ifdef HAVE_SDCC_BANKING
200  PUTSTRING(" With Banking.\n");
201 #endif /* HAVE_SDCC_BANKING */
202 #ifdef SDCC_MODEL_LARGE
203  PUTSTRING(" --model-large\n");
204 #endif /* SDCC_MODEL_LARGE */
205 #ifdef SDCC_MODEL_HUGE
206  PUTSTRING(" --model-huge\n");
207 #endif /* SDCC_MODEL_HUGE */
208 #ifdef SDCC_STACK_AUTO
209  PUTSTRING(" --stack-auto\n");
210 #endif /* SDCC_STACK_AUTO */
211 
212  PUTCHAR('\n');
213 
214  PUTSTRING(" Net: ");
215  PUTSTRING(NETSTACK_NETWORK.name);
216  PUTCHAR('\n');
217  PUTSTRING(" MAC: ");
218  PUTSTRING(NETSTACK_MAC.name);
219  PUTCHAR('\n');
220  PUTSTRING(" RDC: ");
221  PUTSTRING(NETSTACK_RDC.name);
222  PUTCHAR('\n');
223 
224  PUTSTRING("##########################################\n");
225 #endif
226 
227  watchdog_init();
228 
229  /* Initialise the H/W RNG engine. */
230  random_init(0);
231 
232  /* start services */
233  process_start(&etimer_process, NULL);
234  ctimer_init();
235 
236  /* initialize the netstack */
237  netstack_init();
238  set_rime_addr();
239 
240 #if BUTTON_SENSOR_ON || ADC_SENSOR_ON
241  process_start(&sensors_process, NULL);
242  BUTTON_SENSOR_ACTIVATE();
243  ADC_SENSOR_ACTIVATE();
244 #endif
245 
246 #if UIP_CONF_IPV6
247  memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));
248  queuebuf_init();
249  process_start(&tcpip_process, NULL);
250 #endif /* UIP_CONF_IPV6 */
251 
252 #if VIZTOOL_CONF_ON
253  process_start(&viztool_process, NULL);
254 #endif
255 
256  energest_init();
257  ENERGEST_ON(ENERGEST_TYPE_CPU);
258 
259  autostart_start(autostart_processes);
260 
261  watchdog_start();
262 
263  fade(LEDS_YELLOW);
264 
265  while(1) {
266  uint8_t r;
267  do {
268  /* Reset watchdog and handle polls and events */
270 
271 #if CLOCK_CONF_STACK_FRIENDLY
272  if(sleep_flag) {
273  if(etimer_pending() &&
274  (etimer_next_expiration_time() - clock_time() - 1) > MAX_TICKS) {
276  }
277  sleep_flag = 0;
278  }
279 #endif
280  r = process_run();
281  } while(r > 0);
282  len = NETSTACK_RADIO.pending_packet();
283  if(len) {
284  packetbuf_clear();
285  len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
286  if(len > 0) {
288  NETSTACK_RDC.input();
289  }
290  }
291 
292 #if LPM_MODE
293 #if (LPM_MODE==LPM_MODE_PM2)
294  SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */
295  while(!(SLEEP & HFRC_STB)); /* Wait for RCOSC to be stable */
296  CLKCON |= OSC; /* Switch to the RCOSC */
297  while(!(CLKCON & OSC)); /* Wait till it's happened */
298  SLEEP |= OSC_PD; /* Turn the other one off */
299 #endif /* LPM_MODE==LPM_MODE_PM2 */
300 
301  /*
302  * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM
303  * Sleep Timer will wake us up in no more than 7.8ms (max idle interval)
304  */
305  SLEEPCMD = (SLEEPCMD & 0xFC) | (LPM_MODE - 1);
306 
307 #if (LPM_MODE==LPM_MODE_PM2)
308  /*
309  * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or
310  * no interrupt occurred and we can safely power down
311  */
312  __asm
313  nop
314  nop
315  nop
316  __endasm;
317 
318  if(SLEEPCMD & SLEEP_MODE0) {
319 #endif /* LPM_MODE==LPM_MODE_PM2 */
320 
321  ENERGEST_OFF(ENERGEST_TYPE_CPU);
322  ENERGEST_ON(ENERGEST_TYPE_LPM);
323 
324  /* We are only interested in IRQ energest while idle or in LPM */
325  ENERGEST_IRQ_RESTORE(irq_energest);
326 
327  /* Go IDLE or Enter PM1 */
328  PCON |= PCON_IDLE;
329 
330  /* First instruction upon exiting PM1 must be a NOP */
331  __asm
332  nop
333  __endasm;
334 
335  /* Remember energest IRQ for next pass */
336  ENERGEST_IRQ_SAVE(irq_energest);
337 
338  ENERGEST_ON(ENERGEST_TYPE_CPU);
339  ENERGEST_OFF(ENERGEST_TYPE_LPM);
340 
341 #if (LPM_MODE==LPM_MODE_PM2)
342  SLEEPCMD &= ~SLEEP_OSC_PD; /* Make sure both HS OSCs are on */
343  while(!(SLEEPCMD & SLEEP_XOSC_STB)); /* Wait for XOSC to be stable */
344  CLKCONCMD &= ~CLKCONCMD_OSC; /* Switch to the XOSC */
345  /*
346  * On occasion the XOSC is reported stable when in reality it's not.
347  * We need to wait for a safeguard of 64us or more before selecting it
348  */
349  clock_delay_usec(65);
350  while(CLKCONCMD & CLKCONCMD_OSC); /* Wait till it's happened */
351  }
352 #endif /* LPM_MODE==LPM_MODE_PM2 */
353 #endif /* LPM_MODE */
354  }
355 }
356 /*---------------------------------------------------------------------------*/