Porting Contiki Crash Course - PowerPoint PPT Presentation

niveditha
kista sweden 26 27 march 2007 l.
Skip this Video
Loading SlideShow in 5 Seconds..
Porting Contiki Crash Course PowerPoint Presentation
Download Presentation
Porting Contiki Crash Course

play fullscreen
1 / 54
Download Presentation
Porting Contiki Crash Course
4295 Views
Download Presentation

Porting Contiki Crash Course

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Kista, Sweden 26-27 March 2007 Porting ContikiCrash Course

  2. Porting Contiki • Contiki is designed to be easy to port • Porting the base system is instant • No architecture-dependent code • Stuff that needs porting: • The clock module • I/O (network drivers, serial driver, sensors, …) • ELF loader • Multi-threading • Possible C compiler-quirks • Makefiles

  3. This presentation • I will present the ideal Contiki port • Not all ports look exacly like this • Ports under development typically do not look like this • However, we should aim for it • Having this structure in mind during porting makes things easier

  4. Overview • Directory structure • The native port • The clock module • contiki-conf.h • Network drivers • Sensors • Integrating into the Contiki build system • ELF loader • Multi-threading

  5. Directory structure

  6. Directory structure • Two directories are of importance • cpu/ • platform/ • cpu/ contains code common to all platforms with the same microcontroller • platform/ contains platform specific code • Example: platform/sky, platform/esb, and cpu/msp430

  7. The native port

  8. The native port • The simplest port; can be used as a template • ls platform/native • Makefile.native • clock.c • contiki-conf.h • contiki-main.c • dev/

  9. The native port (contd) • Makefile.native • For integration into the Contiki build system, must have the name Makefile.(platform name) • clock.c • Architecture-specific clock code • contiki-conf.h • Configuration options • contiki-main.c • main(): boot-up code and the main loop • dev/ • Device drivers

  10. Other subdirectories used in platform/ subdirs • apps/ • Platform-specific applications • Example: platform/sky/apps/burn-nodeid.c • net/ • Platform-specific network code/drivers • Example: platform/esb/net/tr1001-rime.c

  11. The clock module

  12. The clock module • The clock module is hardware-specific • Generic header file in core/sys/clock.h • clock.c can be either in platform/ or in cpu/ • Example: platform/ for native, cpu/ for MSP430 ports • Three functions • clock_init() • clock_time() • clock_delay()

  13. clock_init() • Initializes the clock module • Called by the boot-up code • Configures hardware timers, interrupts

  14. clock_time() • Should return an increasing tick counter • The tick typically is increased in an interrupt handler • Implemented in clock.c • Interrupt handler must wake up CPU if there are etimers pending • etimer_request_poll()

  15. Example: cpu/msp430/clock.c static volatile clock_time_t count = 0; interrupt(TIMERA1_VECTOR) timera1 (void) { if(TAIV == 2) { TACCR1 += INTERVAL; /* Set next hw interrupt */ ++count; /* Increase tick counter */ /* If there are pending etimers, poll etimer process, wake up CPU. */ if(etimer_pending() && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { etimer_request_poll(); LPM4_EXIT; } } } clock_time_t clock_time(void) { return count; /* Return tick count */ }

  16. clock_delay() • Delay for a platform-specific amount of time • This function is only used by device drivers and other low-level code

  17. Example: cpu/msp430/clock.c /** * Delay the CPU for a multiple * of 2.83 us. */ void clock_delay(unsigned int i) { asm("add #-1, r15"); asm("jnz $-2"); }

  18. Workplan • Copy exiting clock.c (cpu/msp430/dev/clock.c) • Modify • Look at application notes for CPU to see how timer interrupt works

  19. The future of the clock module • Periodic ticking is inefficient • The clock module might be replaced by the rtimer module in the future • The rtimer code will have to be backed by code similar to the current clock.c code

  20. contiki-conf.h

  21. contiki-conf.h • Found in platform/(name of platform) • Example: platform/native/contiki-conf.h • Contains platform-specific configuration options • C compiler configuration • C types • uIP configuration • Clock configuration: clock_time_t, CLOCK_CONF_SECOND • Sometimes used as a kitchen sink • Workplan: copy platform/native/contiki-conf.h

  22. Network device drivers

  23. Network device drivers • Two operations: • Send out packet • Receive packets • Driver design: • Split code into three files • Hardware-specific code • Interface between uIP and hw specific code • Interface between Rime and hw specific code

  24. Example: core/dev/simple-cc2420.c /* Initialize driver */ void simple_cc2420_init(void); /* Setup a function to be called when a packet has arrived */ void simple_cc2420_set_receiver(void (* recv)(void)); /* Read arrived packet into a buffer */ int simple_cc2420_read(u8_t *buf, u8_t bufsize); /* Send a packet from a buffer */ int simple_cc2420_send(const u8_t *data, u8_t len);

  25. Example: core/dev/simple-cc2420.c • Hardware driver does not add any headers • Only handles reception/sending of raw bytes • Any 802.15.4 headers (optional) could be handled by upper layer module • Add function for switching on CC2420 address decoding

  26. Example: core/dev/simple-cc2420-rime.c • Uses the hardware-specific code in simple-cc2420.c to send and receive packets • No hardware-specific code outside of lowest level driver

  27. core/dev/simple-cc2420-rime.c static void receiver(void) { u8_t len; rimebuf_clear(); len = simple_cc2420_read(rimebuf_dataptr(), RIMEBUF_SIZE); if(len > 0) { rimebuf_set_datalen(len); rime_input(); } } void simple_cc2420_rime_init(void) { simple_cc2420_set_receiver(receiver); } void rime_driver_send(void) { simple_cc2420_send(rimebuf_hdrptr(), rimebuf_totlen()); }

  28. The equivalent uIP driver static void receiver(void) { u8_t len; len = simple_cc2420_read(uip_buf, UIP_BUFSIZE); if(len > 0) { uip_len = len; tcpip_input(); } } void simple_cc2420_rime_init(void) { simple_cc2420_set_receiver(receiver); } int simple_cc2420_uip_send(void) { simple_cc2420_send(&uip_buf[UIP_LLH_LEN], uip_len); }

  29. Overall comments • Keep things simple • Keep low-level code in a seprate file • As little low-level code as possible • Create simple interfaces between the low-level code and Rime/uIP driver • Workplan: • Copy existing driver (simple-cc2420, tr1001) • Modify

  30. Sensors

  31. Sensor drivers in Contiki • When a sensor changes an event is broadcast to all processes • Button press, PIR movement detected, … • Generic code for sending events in core/lib/sensors.c • Low-level code in separate file

  32. Example: platform/sky/dev/button-sensor.c HWCONF_PIN(BUTTON, 2, 7); /* Button is on port 2, pin 7 */ HWCONF_IRQ(BUTTON, 2, 7); /* Connect this to an interrupt */ static void init(void) { timer_set(&debouncetimer, 0); BUTTON_IRQ_EDGE_SELECTD(); /* Trigger interrupt on down flank */ BUTTON_SELECT(); /* Select this pin */ BUTTON_MAKE_INPUT(); /* Make button pin an input pin */ } static int irq(void) { if(BUTTON_CHECK_IRQ()) { /* Is this why we got an interrupt? */ if(timer_expired(&debouncetimer)) { timer_set(&debouncetimer, CLOCK_SECOND / 4); sensors_changed(&button_sensor); /* Send event to all processes */ return 1; } } return 0; } /* … more stuff here … */ SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, init, irq, activate, deactivate, active, value, configure, status);

  33. In platform/sky/contiki-sky-main.c #include "dev/button-sensor.h" SENSORS(&button_sensor); /* … */ int main(void) { /* … */ process_start(&sensors_process, NULL); button_sensor.activate(); /* … */ }

  34. Workplan • Copy platform/sky/dev/button-dev.c • Modify

  35. The future of the sensor API • Works well for digital sensors • Does not work that well for analog sensors • May need to be updated in the future

  36. Integrating into the Contiki build system

  37. Platform-specific Makefile • platform/name/Makefile.name • Included by top-level Makefile.include • Never invoked directly • Not supposed to run “make” in platform directory • Makefile specifies source files, directories, … • Usually includes CPU-specific Makefile • cpu/name/Makefile.name

  38. Example: platform/sky/Makefile.sky # … CONTIKI_TARGET_DIRS = . dev apps net # … CONTIKI_TARGET_SOURCEFILES += # … include $(CONTIKI)/cpu/msp430/Makefile.msp430 # …

  39. CPU-specific Makefile • cpu/name/Makefile.name • Definitions for CPU-specific source files • Definitions for rules for C compiler • CFLAGS, CC • Definition of vpath • Where (GNU) make looks for .c files

  40. Example: cpu/x86/Makefile.x86 CONTIKI_SOURCEFILES += mtarch.c elfloader-stub.c ### Compiler definitions CC = gcc LD = gcc AS = as OBJCOPY = objcopy STRIP = strip CFLAGSNO = -I. -I$(CONTIKI) -I$(CONTIKI)/core \ -I$(CONTIKI_CPU) \ -I$(CONTIKI)/platform/$(TARGET) \ ${addprefix -I,$(APPDIRS)} $(APP_INCLUDES) \ -DWITH_UIP -DWITH_ASCII \ -Wall -g -I. -I/usr/local/include CFLAGS += $(CFLAGSNO) -O LDFLAGS = -Wl,-Map=contiki.map,-export-dynamic # …

  41. Integrating into build system • Keep things simple • Copy entire platform/native directory • Modify • Copy entire cpu/x86 directory • Modify

  42. ELF loader

  43. ELF loader • Only needs porting for new CPUs • Designed for portability • Ported to MSP430, AVR, x86, ARM7

  44. ELF loader architecture-specific interface /* Allocate RAM for data and bss segments */ void *elfloader_arch_allocate_ram(int size); /* Allocate ROM for text segment (code) */ void *elfloader_arch_allocate_rom(int size); /* Relocate one relocation entry. */ void elfloader_arch_relocate(int fd, unsigned int sectionoffset, char *sectionaddr, struct elf32_rela *rela, char *addr); /* Write code to previously allocated ROM */ void elfloader_arch_write_rom(int fd, unsigned short textoff, unsigned int size, char *mem);

  45. Workplan • Copy core/loader/elfloader-stub.c • Modify • Look at core/loader/elfloader-msp430.c, elfloader-avr.c, elfloader-x86.c • Need knowledge of the ELF format for the CPU

  46. The future of the ELF loader • The current interface cannot nicely hold multiple allocations • But Contiki itself supports it • API change will be needed • Current ELF loader does not properly process relocation entries • New ELF loader code on the way

  47. Multi-threading library

  48. Multi-threading library • Must be ported to new CPUs • But: not used very often • Porting often not required • Split into two parts (Contiki-style) • mt.c • mtarch.c

  49. mtarch API /* Thread structure */ struct mtarch_thread; /* Initialize the architecture-specific code */ void mtarch_init(void); /* Remove & clean up */ void mtarch_remove(void); /* “Start” a thread (setup its stack) */ void mtarch_start(struct mtarch_thread *thread, void (* function)(void *data), void *data); /* Switch to the specified thread */ void mtarch_exec(struct mtarch_thread *thread); /* Yield the current thread */ void mtarch_yield(void); /* Stop preemption */ void mtarch_pstop(void); /* Start preemption */ void mtarch_pstart(void);

  50. Example: cpu/msp430/mtarch.c void mtarch_start(struct mtarch_thread *t, void (*function)(void *), void *data) { t->sp = &t->stack[MTARCH_STACKSIZE - 1]; *t->sp = (unsigned short)mt_exit; --t->sp; *t->sp = (unsigned short)function; --t->sp; /* Space for registers. */ t->sp -= 11; } static struct mtarch_thread *running; void mtarch_exec(struct mtarch_thread *t) { running = t; sw(); running = NULL; } void mtarch_yield(void) { sw(); }