Kista sweden 26 27 march 2007
Download
1 / 54

Porting Contiki to new hardware platforms - PowerPoint PPT Presentation


  • 4228 Views
  • Uploaded on

Kista, Sweden 26-27 March 2007 Porting Contiki Crash Course 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

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Porting Contiki to new hardware platforms' - niveditha


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Kista sweden 26 27 march 2007 l.jpg

Kista, Sweden

26-27 March 2007

Porting ContikiCrash Course


Porting contiki l.jpg
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


This presentation l.jpg
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


Overview l.jpg
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



Directory structure6 l.jpg
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



The native port8 l.jpg
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/


The native port contd l.jpg
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


Other subdirectories used in platform subdirs l.jpg
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



The clock module12 l.jpg
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()


Clock init l.jpg
clock_init()

  • Initializes the clock module

    • Called by the boot-up code

    • Configures hardware timers, interrupts


Clock time l.jpg
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()


Example cpu msp430 clock c l.jpg
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 */

}


Clock delay l.jpg
clock_delay()

  • Delay for a platform-specific amount of time

  • This function is only used by device drivers and other low-level code


Example cpu msp430 clock c17 l.jpg
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");

}


Workplan l.jpg
Workplan

  • Copy exiting clock.c (cpu/msp430/dev/clock.c)

    • Modify

  • Look at application notes for CPU to see how timer interrupt works


The future of the clock module l.jpg
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



Contiki conf h21 l.jpg
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



Network device drivers23 l.jpg
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


Example core dev simple cc2420 c l.jpg
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);


Example core dev simple cc2420 c25 l.jpg
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


Example core dev simple cc2420 rime c l.jpg
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


Core dev simple cc2420 rime c l.jpg
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());

}


The equivalent uip driver l.jpg
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);

}


Overall comments l.jpg
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



Sensor drivers in contiki l.jpg
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


Example platform sky dev button sensor c l.jpg
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);


In platform sky contiki sky main c l.jpg
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();

/* … */

}


Workplan34 l.jpg
Workplan

  • Copy platform/sky/dev/button-dev.c

  • Modify


The future of the sensor api l.jpg
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



Platform specific makefile l.jpg
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


Example platform sky makefile sky l.jpg
Example: platform/sky/Makefile.sky

# …

CONTIKI_TARGET_DIRS = . dev apps net

# …

CONTIKI_TARGET_SOURCEFILES +=

# …

include $(CONTIKI)/cpu/msp430/Makefile.msp430

# …


Cpu specific makefile l.jpg
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


Example cpu x86 makefile x86 l.jpg
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

# …


Integrating into build system l.jpg
Integrating into build system

  • Keep things simple

  • Copy entire platform/native directory

    • Modify

  • Copy entire cpu/x86 directory

    • Modify



Elf loader43 l.jpg
ELF loader

  • Only needs porting for new CPUs

  • Designed for portability

  • Ported to MSP430, AVR, x86, ARM7


Elf loader architecture specific interface l.jpg
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);


Workplan45 l.jpg
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


The future of the elf loader l.jpg
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



Multi threading library48 l.jpg
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


Mtarch api l.jpg
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);


Example cpu msp430 mtarch c l.jpg
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();

}


Example cpu msp430 mtarch c51 l.jpg
Example: cpu/msp430/mtarch.c

static void sw(void) {

sptmp = running->sp;

__asm__("push r4"); /* Push all registers on the current stack */

__asm__("push r5");

__asm__("push r6");

__asm__("push r7");

__asm__("push r8");

__asm__("push r9");

__asm__("push r10");

__asm__("push r11");

__asm__("push r12");

__asm__("push r13");

__asm__("push r14");

__asm__("push r15");

__asm__("mov.w r1,%0" : "=r" (running->sp)); /* Switch stack pointer to new stack */

__asm__("mov.w %0,r1" : : "m" (sptmp));

__asm__("pop r15"); /* Pop all registers from the new stack */

__asm__("pop r14");

__asm__("pop r13");

__asm__("pop r12");

__asm__("pop r11");

__asm__("pop r10");

__asm__("pop r9");

__asm__("pop r8");

__asm__("pop r7");

__asm__("pop r6");

__asm__("pop r5");

__asm__("pop r4");

}


Potential problems with mtarch c l.jpg
Potential problems with mtarch.c

  • C compiler specific

    • Different compilers behave differently

    • Different compiler versions behave differently


Workplan53 l.jpg
Workplan

  • Copy cpu/msp430/mtarch.c

    • Modify

  • Google and see how existing threading libraries for your CPU push and pop the stack


Conclusions l.jpg
Conclusions

  • Contiki designed to be portable

  • No architecture-specific code out in Contiki base

    • Two directories: cpu/ and platform/

  • To begin porting, copy & modify the platform/native code


ad