平台描述:
MCU -- Stm32F100CB cotex-M3架构,128KB ROM,8KB SRAM。
Ethernet Controller –ENC28J60 10Mb 以太网控制器,使用SPI总线与MCU交互。
802.15.4 Controller –cc2500 802.15.4 网络控制芯片,使用SPI总线与MCU交互。
移植前准备工作
准备编译调试工具集
这里我们使用GNU编译工具集,最少要包括编译器(GCC),链接器(LD),调试器(GDB),实用工具集(ReadELF,ObjCopy)。
编译器的选择:能编译出thumb2指令集的编译器即可,这里选用gcc版本号4.5.2。也可以使用第三方提供的编译好的GNU编译工具链,其中Mentor提供的就不错,可以到如下网站下载:
http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/platforms/arm-eabi
准备下载调试环境
硬件:JLink调试器,version 8.
与硬件连接软件: SEGGERJLINK或者使用OpenOCD都行,我们这里使用的是SEGGERJLINK,以后会试试OpenOCD。
准备相关代码
Contiki2.5源码:http://sourceforge.net/projects/contiki/?source=directory
Enc28J60示例代码,可以从Microchip网站上下载,这里不列出。
CC2500示例代码,还没写CC2500的Contiki驱动但这不是重点,示例可以从TI网站上获得。
移植开始
首先我们的目标是让Contiki操作系统运行起来,关键部分就是启动系统时钟,对应到Contiki进程就是启动Etimer进程。但只启动一个etimer进程没有意思,我们加上一个LED闪烁进程,使用etimer来定时亮灭。所以综上,我们最原始的Contiki系统包含一个系统进程(只是比喻,Contiki中进程不分系统与用户)etimer_process,与一个用户进程led_twinkling_process。而etimer_process由Contiki系统提供,我们这里只需对系统时钟进行初始化并定时更新系统时钟(用户自定义current_clock),并判断etimer的下一个定时时刻是否已到(通过比较current_clock与etimer的定时时刻来判定)如果时钟等待序列中有等待时钟的进程那么就调度etimer进程执行,通过其来唤醒相关进程。相关代码如下:
#include <stm32f10x_map.h>
#include <nvic.h>
#include <sys/clock.h>
#include <sys/cc.h>
#include <sys/etimer.h>
#include <debug-uart.h>
static volatile clock_time_t current_clock= 0;
static volatile unsigned longcurrent_seconds = 0;
static unsigned int second_countdown =CLOCK_SECOND;
void SysTick_handler(void) __attribute__((interrupt));
void SysTick_handler(void) {
(void)SysTick->CTRL;
SCB->ICSR= SCB_ICSR_PENDSTCLR;
current_clock++;
if(etimer_pending()&& etimer_next_expiration_time() <= current_clock) {
etimer_request_poll();
}
if(--second_countdown == 0) {
current_seconds++;
second_countdown= CLOCK_SECOND;
}
}
void clock_init() {
NVIC_SET_SYSTICK_PRI(8);
SysTick->LOAD= ((unsigned int)24000000) / 8 / CLOCK_SECOND;
SysTick->CTRL= SysTick_CTRL_ENABLE | SysTick_CTRL_TICKINT;
}
clock_time_t clock_time(void) {
returncurrent_clock;
}
unsigned long clock_seconds(void) {
returncurrent_seconds;
}
接下来就是针对Contiki编写准备以太网卡enc28j60的驱动,包含spi驱动,照着芯片厂商提供的示例代码编写就差不多了。
驱动有了,还要实现驱动与Contiki之间的接口,这一步还是比较容易的可以参照Contiki提供的文档中的例子“example-packet-drv.c”来编写,值得注意就是ethernet链路层头有14个字节大小,要在“contiki-conf.h”中指出来,具体来说就是定义宏“#defineUIP_CONF_LLH_LEN 14”。当然因为ethernet的MTU为1500所以我们定义uip buffer的大小就为1500.
再来,最主要的一个与移植相关的文件就是contiki-conf.h了,其位于platform/my_platform/文件夹下,用于定制Contiki的功能。
最后就是编写相应platform的Makefile了,将“CONTIKI_TARGET_DIRS”,“CONTIKI_TARGET_SOURCEFILES”附上相应的值,并包含相应cpu的Makefile即可。
最后的最后LD使用连接脚本也需要自己编写,指明各段的位置(位于ROM还是SRAM)。
OK,编译下载。