Contiki 3.x
contiki-sensinode-main.c
1 #include "contiki.h"
2 #include "sys/clock.h"
3 #include "sys/autostart.h"
4 
5 #include "dev/serial-line.h"
6 #include "dev/slip.h"
7 #include "dev/bus.h"
8 #include "dev/leds.h"
9 #include "dev/uart1.h"
10 #include "dev/dma.h"
11 #include "dev/models.h"
12 #include "dev/cc2430_rf.h"
13 #include "dev/watchdog.h"
14 #include "dev/lpm.h"
15 #include "net/rime/rime.h"
16 #include "net/netstack.h"
17 #include "net/mac/frame802154.h"
18 #include "debug.h"
19 #include "stack.h"
20 #include "dev/watchdog-cc2430.h"
21 #include "dev/sensinode-sensors.h"
22 #include "disco.h"
23 #include "contiki-lib.h"
24 #include "contiki-net.h"
25 
26 unsigned short node_id = 0; /* Manually sets MAC address when > 0 */
27 
28 #if VIZTOOL_CONF_ON
29 PROCESS_NAME(viztool_process);
30 #endif
31 
32 #if BATMON_CONF_ON
33 PROCESS_NAME(batmon_process);
34 #endif
35 
36 #if NETSTACK_CONF_SHORTCUTS
37 static CC_AT_DATA uint16_t len;
38 #endif
39 
40 #ifdef STARTUP_CONF_VERBOSE
41 #define STARTUP_VERBOSE STARTUP_CONF_VERBOSE
42 #else
43 #define STARTUP_VERBOSE 0
44 #endif
45 
46 #if STARTUP_VERBOSE
47 #define PUTSTRING(...) putstring(__VA_ARGS__)
48 #define PUTHEX(...) puthex(__VA_ARGS__)
49 #define PUTBIN(...) putbin(__VA_ARGS__)
50 #define PUTCHAR(...) putchar(__VA_ARGS__)
51 #else
52 #define PUTSTRING(...) do {} while(0)
53 #define PUTHEX(...) do {} while(0)
54 #define PUTBIN(...) do {} while(0)
55 #define PUTCHAR(...) do {} while(0)
56 #endif
57 
58 #if CLOCK_CONF_STACK_FRIENDLY
59 extern volatile uint8_t sleep_flag;
60 #endif
61 
62 extern linkaddr_t linkaddr_node_addr;
63 #if ENERGEST_CONF_ON
64 static unsigned long irq_energest = 0;
65 #define ENERGEST_IRQ_SAVE(a) do { \
66  a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0)
67 #define ENERGEST_IRQ_RESTORE(a) do { \
68  energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0)
69 #else
70 #define ENERGEST_IRQ_SAVE(a) do {} while(0)
71 #define ENERGEST_IRQ_RESTORE(a) do {} while(0)
72 #endif
73 /*---------------------------------------------------------------------------*/
74 static void
75 fade(int l) CC_NON_BANKED
76 {
77  volatile int i, a;
78  int k, j;
79  for(k = 0; k < 400; ++k) {
80  j = k > 200 ? 400 - k : k;
81 
82  leds_on(l);
83  for(i = 0; i < j; ++i) {
84  a = i;
85  }
86  leds_off(l);
87  for(i = 0; i < 200 - j; ++i) {
88  a = i;
89  }
90  }
91 }
92 /*---------------------------------------------------------------------------*/
93 static void
94 set_rime_addr(void) CC_NON_BANKED
95 {
96  uint8_t *addr_long = NULL;
97  uint16_t addr_short = 0;
98  char i;
99  __code unsigned char *macp;
100 
101  PUTSTRING("Rime is 0x");
102  PUTHEX(sizeof(linkaddr_t));
103  PUTSTRING(" bytes long\n");
104 
105  if(node_id == 0) {
106  PUTSTRING("Reading MAC from flash\n");
107  /*
108  * The MAC is always stored in 0x1FFF8 of our flash. This maps to address
109  * 0xFFF8 of our CODE segment, when BANK3 is selected.
110  * Switch to BANK3, read 8 bytes starting at 0xFFF8 and restore last BANK
111  * Since we are called from main(), this MUST be BANK1 or something is very
112  * wrong. This code can be used even without banking
113  */
114 
115  /* Don't interrupt us to make sure no BANK switching happens while working */
117 
118  /* Switch to BANK3, map CODE: 0x8000 - 0xFFFF to FLASH: 0x18000 - 0x1FFFF */
119  FMAP = 3;
120 
121  /* Set our pointer to the correct address and fetch 8 bytes of MAC */
122  macp = (__code unsigned char *)0xFFF8;
123 
124  for(i = (LINKADDR_SIZE - 1); i >= 0; --i) {
125  linkaddr_node_addr.u8[i] = *macp;
126  macp++;
127  }
128 
129  /* Remap 0x8000 - 0xFFFF to BANK1 */
130  FMAP = 1;
131  ENABLE_INTERRUPTS();
132 
133  } else {
134  PUTSTRING("Setting manual address from node_id\n");
135  linkaddr_node_addr.u8[LINKADDR_SIZE - 1] = node_id >> 8;
136  linkaddr_node_addr.u8[LINKADDR_SIZE - 2] = node_id & 0xff;
137  }
138 
139  /* Now the address is stored MSB first */
140 #if STARTUP_VERBOSE
141  PUTSTRING("Rime configured with address ");
142  for(i = 0; i < LINKADDR_SIZE - 1; i++) {
143  PUTHEX(linkaddr_node_addr.u8[i]);
144  PUTCHAR(':');
145  }
146  PUTHEX(linkaddr_node_addr.u8[i]);
147  PUTCHAR('\n');
148 #endif
149 
150  /* Set the cc2430 RF addresses */
151 #if (LINKADDR_SIZE==8)
152  addr_short = (linkaddr_node_addr.u8[6] * 256) + linkaddr_node_addr.u8[7];
153  addr_long = (uint8_t *) &linkaddr_node_addr;
154 #else
155  addr_short = (linkaddr_node_addr.u8[0] * 256) + linkaddr_node_addr.u8[1];
156 #endif
157  cc2430_rf_set_addr(IEEE802154_PANID, addr_short, addr_long);
158 }
159 /*---------------------------------------------------------------------------*/
160 int
161 main(void)
162 {
163 
164  /* Hardware initialization */
165  bus_init();
166  rtimer_init();
167 
168  stack_poison();
169 
170  /* model-specific h/w init. */
171  model_init();
172 
173  /* Init LEDs here */
174  leds_init();
175  fade(LEDS_GREEN);
176 
177  /* initialize process manager. */
178  process_init();
179 
180  /* Init UART1 */
181  uart1_init();
182 
183 #if DMA_ON
184  dma_init();
185 #endif
186 
187 #if SLIP_ARCH_CONF_ENABLE
188  /* On cc2430, the argument is not used */
189  slip_arch_init(0);
190 #else
191  uart1_set_input(serial_line_input_byte);
192  serial_line_init();
193 #endif
194 
195  PUTSTRING("##########################################\n");
196  putstring(CONTIKI_VERSION_STRING "\n");
197  putstring(SENSINODE_MODEL " (CC24");
198  puthex(((CHIPID >> 3) | 0x20));
199  putstring("-" FLASH_SIZE ")\n");
200 
201 #if STARTUP_VERBOSE
202 #ifdef HAVE_SDCC_BANKING
203  PUTSTRING(" With Banking.\n");
204 #endif /* HAVE_SDCC_BANKING */
205 #ifdef SDCC_MODEL_LARGE
206  PUTSTRING(" --model-large\n");
207 #endif /* SDCC_MODEL_LARGE */
208 #ifdef SDCC_MODEL_HUGE
209  PUTSTRING(" --model-huge\n");
210 #endif /* SDCC_MODEL_HUGE */
211 #ifdef SDCC_STACK_AUTO
212  PUTSTRING(" --stack-auto\n");
213 #endif /* SDCC_STACK_AUTO */
214 
215  PUTCHAR('\n');
216 
217  PUTSTRING(" Net: ");
218  PUTSTRING(NETSTACK_NETWORK.name);
219  PUTCHAR('\n');
220  PUTSTRING(" MAC: ");
221  PUTSTRING(NETSTACK_MAC.name);
222  PUTCHAR('\n');
223  PUTSTRING(" RDC: ");
224  PUTSTRING(NETSTACK_RDC.name);
225  PUTCHAR('\n');
226 
227  PUTSTRING("##########################################\n");
228 #endif
229 
230  watchdog_init();
231 
232  /* Initialise the cc2430 RNG engine. */
233  random_init(0);
234 
235  /* start services */
236  process_start(&etimer_process, NULL);
237  ctimer_init();
238 
239  /* initialize the netstack */
240  netstack_init();
241  set_rime_addr();
242 
243 #if BUTTON_SENSOR_ON || ADC_SENSOR_ON
244  process_start(&sensors_process, NULL);
245  sensinode_sensors_activate();
246 #endif
247 
248 #if UIP_CONF_IPV6
249  memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));
250  queuebuf_init();
251  process_start(&tcpip_process, NULL);
252 
253 #if DISCO_ENABLED
254  process_start(&disco_process, NULL);
255 #endif /* DISCO_ENABLED */
256 
257 #if VIZTOOL_CONF_ON
258  process_start(&viztool_process, NULL);
259 #endif
260 
261 #if (!UIP_CONF_IPV6_RPL)
262  {
263  uip_ipaddr_t ipaddr;
264 
265  uip_ip6addr(&ipaddr, 0x2001, 0x630, 0x301, 0x6453, 0, 0, 0, 0);
266  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
267  uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
268  }
269 #endif /* UIP_CONF_IPV6_RPL */
270 #endif /* UIP_CONF_IPV6 */
271 
272  /*
273  * Acknowledge the UART1 RX interrupt
274  * now that we're sure we are ready to process it
275  */
276  model_uart_intr_en();
277 
278  energest_init();
279  ENERGEST_ON(ENERGEST_TYPE_CPU);
280 
281  fade(LEDS_RED);
282 
283 #if BATMON_CONF_ON
284  process_start(&batmon_process, NULL);
285 #endif
286 
287  autostart_start(autostart_processes);
288 
289  watchdog_start();
290 
291  while(1) {
292  uint8_t r;
293  do {
294  /* Reset watchdog and handle polls and events */
296 
297 #if CLOCK_CONF_STACK_FRIENDLY
298  if(sleep_flag) {
299  if(etimer_pending() &&
300  (etimer_next_expiration_time() - clock_time() - 1) > MAX_TICKS) {
302  }
303  sleep_flag = 0;
304  }
305 #endif
306  r = process_run();
307  } while(r > 0);
308 #if NETSTACK_CONF_SHORTCUTS
309  len = NETSTACK_RADIO.pending_packet();
310  if(len) {
311  packetbuf_clear();
312  len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
313  if(len > 0) {
315  NETSTACK_RDC.input();
316  }
317  }
318 #endif
319 
320 #if LPM_MODE
321 #if (LPM_MODE==LPM_MODE_PM2)
322  SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */
323  while(!(SLEEP & HFRC_STB)); /* Wait for RCOSC to be stable */
324  CLKCON |= OSC; /* Switch to the RCOSC */
325  while(!(CLKCON & OSC)); /* Wait till it's happened */
326  SLEEP |= OSC_PD; /* Turn the other one off */
327 #endif /* LPM_MODE==LPM_MODE_PM2 */
328 
329  /*
330  * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM
331  * Sleep Timer will wake us up in no more than 7.8ms (max idle interval)
332  */
333  SLEEP = (SLEEP & 0xFC) | (LPM_MODE - 1);
334 
335 #if (LPM_MODE==LPM_MODE_PM2)
336  /*
337  * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or
338  * no interrupt occurred and we can safely power down
339  */
340  __asm
341  nop
342  nop
343  nop
344  __endasm;
345 
346  if(SLEEP & SLEEP_MODE0) {
347 #endif /* LPM_MODE==LPM_MODE_PM2 */
348 
349  ENERGEST_OFF(ENERGEST_TYPE_CPU);
350  ENERGEST_ON(ENERGEST_TYPE_LPM);
351 
352  /* We are only interested in IRQ energest while idle or in LPM */
353  ENERGEST_IRQ_RESTORE(irq_energest);
354 
355  /* Go IDLE or Enter PM1 */
356  PCON |= IDLE;
357 
358  /* First instruction upon exiting PM1 must be a NOP */
359  __asm
360  nop
361  __endasm;
362 
363  /* Remember energest IRQ for next pass */
364  ENERGEST_IRQ_SAVE(irq_energest);
365 
366  ENERGEST_ON(ENERGEST_TYPE_CPU);
367  ENERGEST_OFF(ENERGEST_TYPE_LPM);
368 
369 #if (LPM_MODE==LPM_MODE_PM2)
370  SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */
371  while(!(SLEEP & XOSC_STB)); /* Wait for XOSC to be stable */
372  CLKCON &= ~OSC; /* Switch to the XOSC */
373  /*
374  * On occasion the XOSC is reported stable when in reality it's not.
375  * We need to wait for a safeguard of 64us or more before selecting it
376  */
377  clock_delay_usec(65);
378  while(CLKCON & OSC); /* Wait till it's happened */
379  }
380 #endif /* LPM_MODE==LPM_MODE_PM2 */
381 #endif /* LPM_MODE */
382  }
383 }
384 /*---------------------------------------------------------------------------*/
void uart1_init(unsigned long ubr)
Initalize the RS232 port.
Definition: uart1.c:143
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
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
Definition: uip-ds6.c:535
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 the Disco server (embedded part of the DISCOBALL project) ...
CC2430 RF driver header file
#define NULL
The null pointer.
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
A brief description of what this file is.
#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
Hardware-dependent header file for the cc2430 watchdog timer.
void cc2430_rf_set_addr(unsigned pan, unsigned addr, const uint8_t *ieee_addr)
Set MAC addresses.
Definition: cc2430_rf.c:252
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
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
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
Definition: uip-ds6.h:123
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
Defines for the sensors on the various Sensinode models.
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
Header file for debugging functions used by the sensinode port.
#define uip_ip6addr(addr, addr0, addr1, addr2, addr3, addr4, addr5, addr6, addr7)
Construct an IPv6 address from eight 16-bit words.
Definition: uip.h:969
void watchdog_init(void)
Copyright (c) 2014, Analog Devices, Inc.
Definition: watchdog.c:42
Include file for the Contiki low-layer network stack (NETSTACK)