contiki移植到STM32(細節篇)


【 開始 】

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM