木子剑
生命不熄,学习不止!

【 开始 】

今天移植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 ====

 

posted on 2021-10-16 15:53  木子剑  阅读(1783)  评论(2编辑  收藏  举报