【 开始 】
今天移植CONTIKI NG内核调度,用上简单事件驱动,先自报一下PC的环境:
1_> WINDOWS 7, 64bit
2_> IAR v7.7
3_> STM32F103vet6核心板
4_> CONTIKI NG源码,推荐使用V4.6版本 ,V4.7以后,ARM-CMSIS是空的,可以到 https://github.com/ARM-software/CMSIS_5/releases 下载
第一步:
先下载contiki-NG源码,并解压后如下图:
裁剪掉暂时不用文件,留下OS核心文件,如下图:
第二步:
进入contiki_v4.7\examples内,只留下"hello-world"这个文件夹:
推介,用户所有的应用工程都在examples里面,新建_stm32f10x及几个备用文件夹:
碰到HK32F MM32F GD32F,都按照这个思路处理就好,这样会比较精炼 简洁。。。
第三步:
进入contiki_v4.7\os内,把一些高大上的,暂时又用不着的文件先裁剪掉,如下图所示:
上图的 “contiki-main.c” 也可裁剪掉的,因为在我们STM32单片机代码中,有自己main.c文件;
剩下文件夹不要裁剪了,基本都是os核心了.后期都是按照工程实际要求,加入必要的
contiki_v4.7\os\lib或contiki_v4.7\os\dev的文件,也有可能用不上。。
第四步:
进入contiki_v4.7\arch内,裁剪掉"dev"这个文件夹 :
arch是用户要实现的内容,俩个文件cpu和platform, 就是告诉我们,实现这俩文件后,可以快乐使用OS了
打开contiki_v4.7\arch\cpu目录,也要裁剪掉一些暂时无用的文件:
arm是标准文件,留下CC2358是因为有一些系统必要的配置文件,可以复制或参考。。
我们进入ARM文件夹,如下图:
这里要就说明一下,common 和 openocd我们暂时使不用的文件,但不打算裁剪掉它们.
打开CMSIS,会发现是空的,因为在github的contiki-ng-release-v4.7中,要链接到ARM软件哪边去下载了.......
我没有去ARM哪边下载CMSIS核心文件,打开已下载好的contiki-ng-release-v4.6,从里面提取现成的CMSIS.当然
也可以去STM32固件库里去提取过来,基本套路都一样。。
这样CMSIS文件夹就有内容了,如下图所示:
然后回到arch\cpu下,新建一个“stm32”文件,后放入一些与CPU相关文件,比如CPU的ADC IIC UART
这些库函数(基于芯片手册,官方STDP库)。。。这样contiki_v4.7\arch\cpu规划完成了。。
接下来打开contiki_v4.7\arch\platform,裁剪掉暂时不用的文件,如下图:
新建一个“stm32”,就是我们的对应平台,主要放入一些类似,按键, LED, LCD等
实现函数,与硬件平台相关文件,(开发人员要实现的)。同理cc2538dk只是
参考信息,因OS要配备系统文件,会方便一点。
OK,今天就处理到这里,NG的源码整理就是这些了,接下来就是移植进IAR跑STM32。
时间:2021-10-17
预准备好STM32官方的标准固件库,或者基于固件库的DEMO测试OK例程。
此时,要认真思考一下,如何将【标准固件库】信息加入到CONTIKI中,最为合理。
第一步:
将官方一些固定的,基本不会改 变的,放在arch\cpu\stm32中,选择STM32F10x_StdPeriph_Driver
内的inc, src就可以了,如下图:
再提取STM32固件库对IAR的启动文件,也放在arch\cpu\stm32中,如下图:
提取stm32f10x.h, system_stm32f10x.h, system_stm32f10x.c, 放在arch\cpu\stm32中:
以上就是提取STM32固件库放到OS的CPU/STM32内的所有内容了,
将一些应用文件,平台上可能经常更改的放在\arch\platform\stm32里面,暂时把
stm32f10x_it.h, stm32f10x_it.c, stm32f10x_conf.h放进platform\stm32,下图示:
以上就是提取STM32固件库放到OS的platform/STM32内的所有内容。STM32固件库不要了,
可以丢弃了。
第二步:
现在开始思考一些CONTIKI必要系统文件,一般从OS文件名可以大该看出,带xx_conf的文件,
就是给用户配置的文件;而带xx_arch的,就是用户自己实现的文件。一个配置文件和实现文件的过程。
(如果少这一步,很多OS功能无法正常使用,或者没有真正使用CONTIKI进行工作)
因为第一次移植,我们会全部从CC2538里面进行提取。。后期自行进一步精简。
先找到board.h contiki-conf.h platform.c,放入到arch\platform\stm32中
继续从CC2538里面进行提取文件,这次去找clock.c cc2538-conf.h cc2538-def.h
将它们放入arch\cpu\stm32中,并改名为如下图:
到此为止,contiki_v4.7\arch下的cpu和platform全部实现了,OS内CC2538已没有价值,可以丢弃了。
第三步:
把contiki_v4.7\os下的contiki-main.c, 复制到contiki_v4.7\examples\_stm32f10x里面,
在_stm32f10x内建立基于STM32F的空项目:
打开IAR v7.x,点击Project-->create new project...选择Empty project:
取名为contiki并保存在contiki_v4.7\examples\_stm32f10x里面,如下图:
(注:上图中,请选择Debug,后文会提及到原因)
简单配置一下IAR,其他的暂时默认就好,可以后期再调整:
接下来就是在IAR建立对应的文件夹,加入对应的.H .C文件,I配置所有OS的工程路径,
这个过程很无聊。。要有耐心。。不要错心大意。。
第四步:
移植CONTIKI有三大部份:contiki_v4.7\os, contiki_v4.7\examples, contiki_v4.7\arch
还是比较简单的,你会发现都是2个或3个文件夹事情,这个OS算是很精炼了。。。
先移植contiki_v4.7\os部份,移植了我认为要使用到的具体文件,如下图:
这份contiki_v4.7\os全部移植完了,
接下来移植contiki_v4.7\arch部份,如下图:
arch/platform部份,如下图:
arch/examples部份,如下图:
算是移植完了三大文件contiki_v4.7\os, contiki_v4.7\examples, contiki_v4.7\arch,
第五步:
先加入OS所有工程路经,改动一些C实现文件,IAR中进行编译,出错后再进行修正,
以下是IAR工程路经:
$PROJ_DIR$ $PROJ_DIR$\user $PROJ_DIR$\user\inc $PROJ_DIR$\user\src $PROJ_DIR$\user\dev $PROJ_DIR$\..\..\os $PROJ_DIR$\..\..\os\sys $PROJ_DIR$\..\..\os\lib $PROJ_DIR$\..\..\os\dev $PROJ_DIR$\..\..\arch $PROJ_DIR$\..\..\arch\cpu $PROJ_DIR$\..\..\arch\cpu\arm $PROJ_DIR$\..\..\arch\cpu\arm\CMSIS $PROJ_DIR$\..\..\arch\cpu\arm\cortex-m $PROJ_DIR$\..\..\arch\cpu\arm\cortex-m\cm3 $PROJ_DIR$\..\..\arch\cpu\stm32 $PROJ_DIR$\..\..\arch\cpu\stm32\inc $PROJ_DIR$\..\..\arch\cpu\stm32\src $PROJ_DIR$\..\..\arch\cpu\stm32\starup_iar $PROJ_DIR$\..\..\arch\platform $PROJ_DIR$\..\..\arch\platform\stm32 $PROJ_DIR$\..\..\examples $PROJ_DIR$\..\..\examples\hello-world $PROJ_DIR$\..\..\examples\_stm32f10x $PROJ_DIR$\..\..\examples\_stm32f10x\inc $PROJ_DIR$\..\..\examples\_stm32f10x\src $PROJ_DIR$\..\..\examples\_stm32f10x\dev
另外设置STM32的内存容量如下图:
把examples\_stm32f10x下的contiki-main.c改为如下内容:
#include "contiki.h" #include "platform.h" #include <stdio.h> #include <stdint.h> /*---------------------------------主MAIN入口--------------------------------*/ void main (void) { platform_init_stage_one(); //platform-1 //rtimer_init(); //未实现功能 process_init(); process_start(&etimer_process, NULL); ctimer_init(); platform_init_stage_two(); //platform-2 platform_init_stage_three(); //platform-3 autostart_start(autostart_processes); //自动启动 //process_start(&xx_xx, NULL); //手动启动 /*---------------------------------主循环体----------------------------------*/ char ch; while(1){ do{ ch = process_run(); //runing } while(ch > 0); //platform_idle(); //sleep未实现功能 } }
把\arch\platform\stm32下的platform.c改为如下内容,后期进行补全:
#include "contiki.h" #include "lib/sensors.h" #include "sys/platform.h" #include <stdint.h> #include <string.h> #include <stdio.h> /*---------------------------------------------------------------------------*/ void platform_init_stage_one(void) { } /*---------------------------------------------------------------------------*/ void platform_init_stage_two() { } /*---------------------------------------------------------------------------*/ void platform_init_stage_three() { } /*---------------------------------------------------------------------------*/ void platform_idle() { }
然后第一次进行IAR编译,收获28个ERROR,找不到CC2538_XXX,把相关文件改为stm32_xxx
在arch\cpu\stm32下,补充rtimer-arch.h文件,这个系统配置之前漏了吧,改为如下:
/* * \file * Real-timer header file for stm32 * \author * lijian */ #ifndef RTIMER_ARCH_H_ #define RTIMER_ARCH_H_ //#define RTIMER_ARCH_RES_341US 0 //#define RTIMER_ARCH_RES_171US 1 //#define RTIMER_ARCH_RES_85US 2 #define RTIMER_ARCH_RES_100US 3 // stm32新加的 #include "contiki-conf.h" #include "clock.h" #ifdef RTIMER_ARCH_CONF_RESOLUTION #define RTIMER_ARCH_RESOLUTION RTIMER_ARCH_CONF_RESOLUTION // CONF 配置值arm-def.h处 #else /* RTIMER_ARCH_CONF_RESOLUTION */ #define RTIMER_ARCH_RESOLUTION RTIMER_ARCH_RES_100US // 默认值,可以更改 #endif /* RTIMER_ARCH_CONF_RESOLUTION */ #if RTIMER_ARCH_RESOLUTION == RTIMER_ARCH_RES_100US #define RTIMER_ARCH__PRESCALER 10 // #define RTIMER_ARCH_SECOND 12760 // 示波器实测为xxx us #endif rtimer_clock_t rtimer_arch_now(void); void rtimer_arch_disable_irq(void); void rtimer_arch_enable_irq(void); #endif /* RTIMER_ARCH_H_ */
经过上面的处理后,再进行编译,这时候只有7个ERRORS了:
将stm32-def.h的LINE:66行注示掉,这是CC2538的信息:
将contiki_v4.7\arch\cpu\stm32下的clock.c进行更改,先改成如下图:
#include <stdint.h> #include <stdio.h> #include "contiki.h" #include "clock.h" #include "etimer.h" #include "rtimer.h" #include "stm32f10x.h" #include "stm32f10x_conf.h" static volatile clock_time_t current_clock; static volatile unsigned long current_seconds = 0; static unsigned int second_current_clockdown = CLOCK_SECOND; /*---------------------------------------------------------------------------*/ 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_current_clockdown == 0) { current_seconds++; second_current_clockdown = CLOCK_SECOND; } } /*---------------------------------------------------------------------------*/ void clock_init(void) { if (SysTick_Config(SystemCoreClock / CLOCK_SECOND)) { while(1); } } /*---------------------------------------------------------------------------*/ clock_time_t clock_time(void) { return current_clock; } /*-----------------将CPU延迟i*j的倍数NOP--------------------------------------*/ void clock_delay(unsigned int i) { for(; i > 0; i--) { /* 需要修改成XXX值 */ unsigned j; for(j = 50; j > 0; j--) { asm("nop"); } } } /*---------等待1*N毫秒。------------------------------------------------------*/ void clock_wait(clock_time_t i) { clock_time_t start; start = clock_time(); while(clock_time() - start < (clock_time_t) i); } /*---------------------------------------------------------------------------*/ unsigned long clock_seconds(void) { return current_seconds; }
再一次进行IAR编译,这时候只有5个ERRORS了:
在contiki_v4.7\os\dev下的slip.c,是网络功能的驱动,我们也把它从IAR裁剪掉。。
再一次进行IAR编译,只有1个ERRORS了:
在把stm32f10x_it.c内的void SysTick_Handler(void)屏蔽掉或进行弱定义,因为我们在clock.c已经定义了。
LOG.h报个错,也是关与NET网络联连的,我们给它也 // 屏蔽掉:
最后打开IAR,确认设置一下工程选项,如下图:
再一次进行IAR编译,这时候只有0个ERRORS了:
报谦了,又粗心大意了,哎,日常纠正错误了,。。
就是重新配置芯片型号,路经什么的,也很简单。搞起来。。。
这是arch\platform\stm32的platform.c更新内容,先这样改:
最后进行IAR编译,没有毛病了吧 ! !
在hello-world.c的测试源码加上断点,然后接上开发板进行仿真,1秒一次断点,正常了。。。。
最后,我们改一下hello-world.c文件内容,驱动一个IO口吧:
#include "contiki.h" #include <stdio.h> /* For printf() */ ///////////////////////////GPIO测试PC6 PC7 //////////////////////////////////// void GPIOB_Initt()//引脚的 { //启用GPIOB外设时钟,设置IO口时要选配置好,要不后面无用。 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_DeInit(GPIOC);//为上电初始值 //匿名结构体别名, 段变量名, 直接设置参数(3个数据) GPIO_InitTypeDef GPIO_InitStructure = { GPIO_Pin_7|GPIO_Pin_6, //1 参数PIN8 GPIO_Speed_2MHz, //2 参数2M速度 GPIO_Mode_Out_PP }; //3 参数推挽输出 GPIO_Init(GPIOC, &GPIO_InitStructure);// 将3个参数初始化到GPIOB_PIN8,是指针,要放入地址。 } /*---------------------------------------------------------------------------*/ PROCESS(hello_world_process, "Hello world process"); AUTOSTART_PROCESSES(&hello_world_process); /*---------------------------------------------------------------------------*/ PROCESS_THREAD(hello_world_process, ev, data) { static struct etimer timer; static bool aa; // 测试值 GPIOB_Initt(); // 初始化GPIOC_7 PROCESS_BEGIN(); /* Setup a periodic timer that expires after 1 seconds. */ etimer_set(&timer, CLOCK_SECOND * 1); while(1) { //printf("Hello, world\n"); GPIO_WriteBit(GPIOC, GPIO_Pin_7,aa=!aa); // 测试值在变化,PC7在取反 /* Wait for the periodic timer to expire and then restart the timer. */ PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer)); etimer_reset(&timer); } PROCESS_END(); } /*---------------------------------------------------------------------------*/
烧入STM32开发板后,PC7脚的LED正在1秒一次的闪烁,STM32移植CONTIKI结束了,伙伴们 再见!!!
==== END ====