Contiki 2.5
contiki-mc1322x-main.c
1 /*
2  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
3  * to the MC1322x project (http://mc1322x.devl.org) and Contiki.
4  *
5  * Copyright (c) 2006, Technical University of Munich
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the Institute nor the names of its contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * This file is part of the Contiki operating system.
33  *
34  * @(#)$$
35  */
36 
37 #include <signal.h>
38 #include <stdio.h>
39 #include <string.h>
40 
41 #include "contiki.h"
42 
43 #include "dev/leds.h"
44 #include "dev/serial-line.h"
45 #include "dev/slip.h"
46 #include "dev/xmem.h"
47 #include "dev/button-sensor.h"
48 #include "lib/random.h"
49 #include "net/netstack.h"
50 #include "net/mac/frame802154.h"
51 
52 #if WITH_UIP6
53 #include "net/sicslowpan.h"
54 #include "net/uip-ds6.h"
55 #include "net/mac/sicslowmac.h"
56 #endif /* WITH_UIP6 */
57 
58 #include "net/rime.h"
59 
60 #include "sys/autostart.h"
61 #include "sys/profile.h"
62 
63 /* from libmc1322x */
64 #include "mc1322x.h"
65 #include "default_lowlevel.h"
66 #include "contiki-maca.h"
67 #include "contiki-uart.h"
68 
69 #define DEBUG 1
70 #if DEBUG
71 #include <stdio.h>
72 #define PRINTF(...) printf(__VA_ARGS__)
73 #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
74 #define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5])
75 #else
76 #define PRINTF(...)
77 #define PRINT6ADDR(addr)
78 #define PRINTLLADDR(addr)
79 #endif
80 
81 #ifndef RIMEADDR_NVM
82 #define RIMEADDR_NVM 0x1E000
83 #endif
84 
85 #ifndef RIMEADDR_NBYTES
86 #define RIMEADDR_NBYTES 8
87 #endif
88 
89 #define PLATFORM_DEBUG 1
90 #if PLATFORM_DEBUG
91 #define PRINTF(...) printf(__VA_ARGS__)
92 #else
93 #define PRINTF(...)
94 #endif
95 
96 
97 #if UIP_CONF_ROUTER
98 
99 #ifndef UIP_ROUTER_MODULE
100 #ifdef UIP_CONF_ROUTER_MODULE
101 #define UIP_ROUTER_MODULE UIP_CONF_ROUTER_MODULE
102 #else /* UIP_CONF_ROUTER_MODULE */
103 #define UIP_ROUTER_MODULE rimeroute
104 #endif /* UIP_CONF_ROUTER_MODULE */
105 #endif /* UIP_ROUTER_MODULE */
106 
107 extern const struct uip_router UIP_ROUTER_MODULE;
108 
109 #endif /* UIP_CONF_ROUTER */
110 
111 #if DCOSYNCH_CONF_ENABLED
112 static struct timer mgt_timer;
113 #endif
114 
115 #ifndef WITH_UIP
116 #define WITH_UIP 0
117 #endif
118 
119 #if WITH_UIP
120 #include "net/uip.h"
121 #include "net/uip-fw.h"
122 #include "net/uip-fw-drv.h"
123 #include "net/uip-over-mesh.h"
124 static struct uip_fw_netif slipif =
125  {UIP_FW_NETIF(192,168,1,2, 255,255,255,255, slip_send)};
126 static struct uip_fw_netif meshif =
127  {UIP_FW_NETIF(172,16,0,0, 255,255,0,0, uip_over_mesh_send)};
128 
129 #endif /* WITH_UIP */
130 
131 #define UIP_OVER_MESH_CHANNEL 8
132 #if WITH_UIP
133 static uint8_t is_gateway;
134 #endif /* WITH_UIP */
135 
136 /*---------------------------------------------------------------------------*/
137 void uip_log(char *msg) { printf("%c",msg); }
138 /*---------------------------------------------------------------------------*/
139 #ifndef RF_CHANNEL
140 #define RF_CHANNEL 26
141 #endif
142 /*---------------------------------------------------------------------------*/
143 #if WITH_UIP
144 static void
145 set_gateway(void)
146 {
147  if(!is_gateway) {
148 // leds_on(LEDS_RED);
149  printf("%d.%d: making myself the IP network gateway.\n\n",
151  printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n",
152  uip_ipaddr_to_quad(&uip_hostaddr));
153  uip_over_mesh_set_gateway(&rimeaddr_node_addr);
154  uip_over_mesh_make_announced_gateway();
155  is_gateway = 1;
156  }
157 }
158 #endif /* WITH_UIP */
159 /*---------------------------------------------------------------------------*/
160 static void
161 print_processes(struct process * const processes[])
162 {
163  /* const struct process * const * p = processes;*/
164  printf("Starting");
165  while(*processes != NULL) {
166  printf(" '%s'", (*processes)->name);
167  processes++;
168  }
169  printf("\n");
170 }
171 /*--------------------------------------------------------------------------*/
172 
173 SENSORS(&button_sensor);
174 
175 void
176 init_lowlevel(void)
177 {
178  /* led direction init */
179  set_bit(*GPIO_PAD_DIR0,8);
180  set_bit(*GPIO_PAD_DIR0,9);
181  set_bit(*GPIO_PAD_DIR0,10);
182  set_bit(*GPIO_PAD_DIR0,23);
183  set_bit(*GPIO_PAD_DIR0,24);
184  set_bit(*GPIO_PAD_DIR0,25);
185 
186  /* button init */
187  /* set up kbi */
188  enable_irq_kbi(4);
189  kbi_edge(4);
190  enable_ext_wu(4);
191 // kbi_pol_neg(7);
192 // kbi_pol_pos(7);
193 // gpio_sel0_pullup(29);
194 // gpio_pu0_disable(29);
195 
196  trim_xtal();
197 
198  /* uart init */
199  uart_init(BRINC, BRMOD, SAMP);
200 
201  default_vreg_init();
202 
203  maca_init();
204 
205  set_channel(RF_CHANNEL - 11); /* channel 11 */
206  set_power(0x12); /* 0x12 is the highest, not documented */
207 
208  /* control TX_ON with the radio */
209  *GPIO_FUNC_SEL2 = (0x01 << ((44-16*2)*2));
210  gpio_pad_dir_set( 1ULL << 44 );
211 
212  enable_irq(CRM);
213 
214 #if USE_32KHZ_XTAL
215  enable_32khz_xtal();
216 #else
217  cal_ring_osc();
218 #endif
219 
220 #if USE_32KHZ_XTAL
221  *CRM_RTC_TIMEOUT = 32768 * 10;
222 #else
223  *CRM_RTC_TIMEOUT = cal_rtc_secs * 10;
224 #endif
225 
226  /* XXX debug */
227  /* trigger periodic rtc int */
228 // clear_rtc_wu_evt();
229 // enable_rtc_wu();
230 // enable_rtc_wu_irq();
231 }
232 
233 #if RIMEADDR_SIZE == 1
234 const rimeaddr_t addr_ff = { { 0xff } };
235 #else /*RIMEADDR_SIZE == 2*/
236 #if RIMEADDR_SIZE == 2
237 const rimeaddr_t addr_ff = { { 0xff, 0xff } };
238 #else /*RIMEADDR_SIZE == 2*/
239 #if RIMEADDR_SIZE == 8
240 const rimeaddr_t addr_ff = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
241 #endif /*RIMEADDR_SIZE == 8*/
242 #endif /*RIMEADDR_SIZE == 2*/
243 #endif /*RIMEADDR_SIZE == 1*/
244 
245 void iab_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint16_t iab, uint32_t ext) {
246  /* OUI for IABs */
247  eui64->u8[0] = 0x00;
248  eui64->u8[1] = 0x50;
249  eui64->u8[2] = 0xc2;
250 
251  /* EUI64 field */
252  eui64->u8[3] = 0xff;
253  eui64->u8[4] = 0xfe;
254 
255  /* IAB */
256  eui64->u8[5] = (iab >> 4) & 0xff;
257  eui64->u8[6] = (iab & 0xf) << 4;
258 
259  /* EXT */
260  eui64->u8[6] |= ((ext >> 8) & 0xf);
261  eui64->u8[7] = ext & 0xff;
262 }
263 
264 void oui_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint32_t ext) {
265  /* OUI */
266  eui64->u8[0] = (oui >> 16) & 0xff;
267  eui64->u8[1] = (oui >> 8) & 0xff;
268  eui64->u8[2] = oui & 0xff;
269 
270  /* EUI64 field */
271  eui64->u8[3] = 0xff;
272  eui64->u8[4] = 0xfe;
273 
274  /* EXT */
275  eui64->u8[5] = (ext >> 16) & 0xff;
276  eui64->u8[6] = (ext >> 8) & 0xff;
277  eui64->u8[7] = ext & 0xff;
278 }
279 
280 void
281 set_rimeaddr(rimeaddr_t *addr)
282 {
283  nvmType_t type=0;
284  nvmErr_t err;
285  volatile uint8_t buf[RIMEADDR_NBYTES];
286  rimeaddr_t eui64;
287  int i;
288 
289  err = nvm_detect(gNvmInternalInterface_c, &type);
290 
291  err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, RIMEADDR_NVM, RIMEADDR_NBYTES);
292 
294 
295  for(i=0; i<RIMEADDR_CONF_SIZE; i++) {
296  addr->u8[i] = buf[i];
297  }
298 
299  if (memcmp(addr, &addr_ff, RIMEADDR_CONF_SIZE)==0) {
300 
301  //set addr to EUI64
302 #ifdef IAB
303  #ifdef EXT_ID
304  PRINTF("address in flash blank, setting to defined IAB and extension.\n\r");
305  iab_to_eui64(&eui64, OUI, IAB, EXT_ID);
306  #else /* ifdef EXT_ID */
307  PRINTF("address in flash blank, setting to defined IAB with a random extension.\n\r");
308  iab_to_eui64(&eui64, OUI, IAB, *MACA_RANDOM & 0xfff);
309  #endif /* ifdef EXT_ID */
310 
311 #else /* ifdef IAB */
312 
313  #ifdef EXT_ID
314  PRINTF("address in flash blank, setting to defined OUI and extension.\n\r");
315  oui_to_eui64(&eui64, OUI, EXT_ID);
316  #else /*ifdef EXT_ID */
317  PRINTF("address in flash blank, setting to defined OUI with a random extension.\n\r");
318  oui_to_eui64(&eui64, OUI, *MACA_RANDOM & 0xffffff);
319  #endif /*endif EXTID */
320 
321 #endif /* ifdef IAB */
322 
323  rimeaddr_copy(addr, &eui64);
324 #ifdef FLASH_BLANK_ADDR
325  PRINTF("flashing blank address\n\r");
326  err = nvm_write(gNvmInternalInterface_c, type, &(eui64.u8), RIMEADDR_NVM, RIMEADDR_NBYTES);
327 #endif /* ifdef FLASH_BLANK_ADDR */
328  } else {
329  PRINTF("loading rime address from flash.\n\r");
330  }
331 
333 }
334 
335 int
336 main(void)
337 {
338  volatile uint32_t i;
339  rimeaddr_t addr;
340 
341  /* Initialize hardware and */
342  /* go into user mode */
343  init_lowlevel();
344 
345  /* Clock */
346  clock_init();
347 
348  /* Process subsystem */
349  process_init();
350  process_start(&etimer_process, NULL);
351  process_start(&contiki_maca_process, NULL);
352 
353  ctimer_init();
354 
355  set_rimeaddr(&addr);
356 
357  printf("Rime started with address ");
358  for(i = 0; i < sizeof(addr.u8) - 1; i++) {
359  printf("%02X:", addr.u8[i]);
360  }
361  printf("%02X\n", addr.u8[i]);
362 
363 
364 #if WITH_UIP6
365  memcpy(&uip_lladdr.addr, &addr.u8, sizeof(uip_lladdr.addr));
366  /* Setup nullmac-like MAC for 802.15.4 */
367 /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */
368 /* printf(" %s channel %u\n", sicslowmac_driver.name, RF_CHANNEL); */
369 
370  /* Setup X-MAC for 802.15.4 */
371  queuebuf_init();
372  NETSTACK_RDC.init();
373  NETSTACK_MAC.init();
374  NETSTACK_NETWORK.init();
375 
376  printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
377  NETSTACK_MAC.name, NETSTACK_RDC.name,
378  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
379  NETSTACK_RDC.channel_check_interval()),
380  RF_CHANNEL);
381 
382  process_start(&tcpip_process, NULL);
383 
384  printf("Tentative link-local IPv6 address ");
385  {
386  int i, a;
387  for(a = 0; a < UIP_DS6_ADDR_NB; a++) {
388  if (uip_ds6_if.addr_list[a].isused) {
389  for(i = 0; i < 7; ++i) {
390  printf("%02x%02x:",
391  uip_ds6_if.addr_list[a].ipaddr.u8[i * 2],
392  uip_ds6_if.addr_list[a].ipaddr.u8[i * 2 + 1]);
393  }
394  printf("%02x%02x\n",
395  uip_ds6_if.addr_list[a].ipaddr.u8[14],
396  uip_ds6_if.addr_list[a].ipaddr.u8[15]);
397  }
398  }
399  }
400 
401  if(1) {
403  int i;
404  uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
405  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
406  uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
407  printf("Tentative global IPv6 address ");
408  for(i = 0; i < 7; ++i) {
409  printf("%02x%02x:",
410  ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]);
411  }
412  printf("%02x%02x\n",
413  ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]);
414  }
415 
416 
417 #else /* WITH_UIP6 */
418 
419  NETSTACK_RDC.init();
420  NETSTACK_MAC.init();
421  NETSTACK_NETWORK.init();
422 
423  printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
424  NETSTACK_MAC.name, NETSTACK_RDC.name,
425  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1:
426  NETSTACK_RDC.channel_check_interval()),
427  RF_CHANNEL);
428 #endif /* WITH_UIP6 */
429 
430 #if PROFILE_CONF_ON
431  profile_init();
432 #endif /* PROFILE_CONF_ON */
433 
434 #if TIMESYNCH_CONF_ENABLED
435  timesynch_init();
437 #endif /* TIMESYNCH_CONF_ENABLED */
438 
439 #if WITH_UIP
440  process_start(&tcpip_process, NULL);
441  process_start(&uip_fw_process, NULL); /* Start IP output */
442  process_start(&slip_process, NULL);
443 
444  slip_set_input_callback(set_gateway);
445 
446  {
447  uip_ipaddr_t hostaddr, netmask;
448 
449  uip_init();
450 
451  uip_ipaddr(&hostaddr, 172,16,
453  uip_ipaddr(&netmask, 255,255,0,0);
454  uip_ipaddr_copy(&meshif.ipaddr, &hostaddr);
455 
456  uip_sethostaddr(&hostaddr);
457  uip_setnetmask(&netmask);
458  uip_over_mesh_set_net(&hostaddr, &netmask);
459  /* uip_fw_register(&slipif);*/
460  uip_over_mesh_set_gateway_netif(&slipif);
461  uip_fw_default(&meshif);
462  uip_over_mesh_init(UIP_OVER_MESH_CHANNEL);
463  printf("uIP started with IP address %d.%d.%d.%d\n",
464  uip_ipaddr_to_quad(&hostaddr));
465  }
466 #endif /* WITH_UIP */
467 
468  process_start(&sensors_process, NULL);
469 
470  print_processes(autostart_processes);
471  autostart_start(autostart_processes);
472 
473  /* Main scheduler loop */
474  while(1) {
475  check_maca();
476 
477  /* TODO: replace this with a uart rx interrupt */
478  if(uart1_input_handler != NULL) {
479  if(uart1_can_get()) {
480  uart1_input_handler(uart1_getc());
481  }
482  }
483 
484  process_run();
485  }
486 
487  return 0;
488 }
489 
490 /*---------------------------------------------------------------------------*/
491 #if LOG_CONF_ENABLED
492 void
493 log_message(char *m1, char *m2)
494 {
495  printf("%s%s\n", m1, m2);
496 }
497 #endif /* LOG_CONF_ENABLED */