新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 關于contiki系統到STM32的移植

        關于contiki系統到STM32的移植

        作者: 時間:2016-11-13 來源:網絡 收藏
        1.contiki簡介

        “Contiki是一個小型的,開源的,極易移植的多任務操作系統。它專門設計以適用于一系列的內存優先的網絡系統,包括從8位電腦到微型控制器的嵌入系統。它的名字來自于托爾·海爾達爾的康提基號。Contiki只需幾kilobyte的代碼和幾百字節的內存就能提供多任務環境和內建TCP/IP支持。

        本文引用地址:http://www.104case.com/article/201611/316108.htm

        2.移植前的準備

        首先建立一個最簡單工程。一個最簡單的任務莫過于LED閃爍了,從學習51單片機開始,到AVR,到ARM,從移植uCOS到移植contiki。LED閃爍無疑是最棒的任務。假設這個任務就是LED點亮1秒,然后LED熄滅1秒。Contiki的采用事件驅動機制,那么如何才能夠產生“事件“呢。答案只有兩個:第一,通過時鐘定時,定時事件到就產生一個事件;第二,通過某種中斷,某個中斷發生,就產生某個事件例如外部中斷。那么移植contiki到底要做哪些工作呢。先來回顧一下uCOS在STM32移植,uCOS的移植也就是做了兩件事情,第一,在PendSV這個異常中斷中,保存上下文;第二,使用systick提供系統時鐘。由于contiki是非搶占的操作系統,所以移植時并不需要PendSV中保存上下文。那么時鐘一定是必要的,移植contiki的移植重點就應該在systick上。

        先上全部的代碼,給大家一個整體的印象。

        1. #include"stm32f10x.h"
        2. #include
        3. #include
        4. #includeuart.h>
        5. #include
        6. #include
        7. #include
        8. #include
        9. #include
        10. unsignedintidle_count=0;
        11. voidled_init();
        12. PROCESS(blink_process,"Blink");
        13. AUTOSTART_PROCESSES(&blink_process);
        14. PROCESS_THREAD(blink_process,ev,data)
        15. {
        16. PROCESS_BEGIN();
        17. while(1)
        18. {
        19. staticstructetimeret;
        20. etimer_set(&et,CLOCK_SECOND);
        21. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
        22. //打開LED
        23. GPIO_ResetBits(GPIOC,GPIO_Pin_6);
        24. printf("LEDONrn");
        25. etimer_set(&et,CLOCK_SECOND);
        26. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
        27. //關閉LED
        28. GPIO_SetBits(GPIOC,GPIO_Pin_6);
        29. printf("LEDOFFrn");
        30. }
        31. PROCESS_END();
        32. }
        33. intmain()
        34. {
        35. dbg_setup_uart();
        36. led_init();
        37. printf("Initialisingrn");
        38. clock_init();
        39. process_init();
        40. process_start(&etimer_process,NULL);
        41. autostart_start(autostart_processes);
        42. //process_start(&blink_process,NULL);
        43. printf("Processesrunningrn");
        44. while(1){
        45. do
        46. {
        47. }
        48. while(process_run()>0);
        49. idle_count++;
        50. /*Idle!*/
        51. /*Stopprocessorclock*/
        52. /*asm("wfi"::);*/
        53. }
        54. return0;
        55. }
        56. voidled_init()
        57. {
        58. GPIO_InitTypeDefGPIO_InitStructure;
        59. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
        60. //PC6推挽輸出
        61. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
        62. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        63. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        64. GPIO_Init(GPIOC,&GPIO_InitStructure);
        65. }

        3.尋找一些線索

        閱讀contiki-2.5 源碼中,stm32移植的相關內容分散在兩個文件夾中,第一, cpuarmstm32f103,這個文件夾存放的stm32移植的相關文件;第二,platformstm32test,這個文件夾中有一個不是那么完整的例子。具體的源碼如下:

        1. #include
        2. #include
        3. #include
        4. #include
        5. #include
        6. #include
        7. #include
        8. #include
        9. #include
        10. #include
        11. #include
        12. #include
        13. unsignedintidle_count=0;
        14. int
        15. main()
        16. {
        17. dbg_setup_uart();
        18. printf("Initialisingn");
        19. clock_init();
        20. process_init();
        21. process_start(&etimer_process,NULL);
        22. autostart_start(autostart_processes);
        23. printf("Processesrunningn");
        24. while(1){
        25. do{
        26. }while(process_run()>0);
        27. idle_count++;
        28. /*Idle!*/
        29. /*Stopprocessorclock*/
        30. /*asm("wfi"::);*/
        31. }
        32. return0;
        33. }

        簡單分析一下,首先文件中包含了一些頭文件。看著有點熟悉,應該是V2.0庫的頭文件,后面的移植工作會全部替換掉,使用V3.4的庫文件。在main函數中,第一步初始化串口并通過串口發送某些信息。接著,初始化時鐘,通過跟蹤源代碼,發現clock_init函數位于cpuarmstm32f103文件夾中的clock文件夾中。具體的函數如下:

        1. void
        2. clock_init()
        3. {
        4. NVIC_SET_SYSTICK_PRI(8);
        5. SysTick->LOAD=MCK/8/CLOCK_SECOND;
        6. SysTick->CTRL=SysTick_CTRL_ENABLE|SysTick_CTRL_TICKINT;
        7. }

        這段代碼的原理也非常的簡單,初始化systick定時器。其功能是每秒發生CLOCK_SECOND次溢出。配置了systick也少不了systick中斷了,systick的中斷的源碼如下: 在systick中斷中不斷更新了etimer,有了時鐘contiki就可以運行了。

        4.開始移植 先在clock源文件中添加頭文件

        #include "stm32f10x.h"

        #include "stm32f10x_it.h"

        刪除原來的

        #include

        #include

        把systick初始化改成

        1. void
        2. clock_init()
        3. {
        4. if(SysTick_Config(SystemCoreClock/CLOCK_SECOND))
        5. {
        6. while(1);
        7. }
        8. }

        把systick中斷改為

        1. voidSysTick_Handler(void)
        2. {
        3. current_clock++;
        4. if(etimer_pending()&&etimer_next_expiration_time()<=current_clock){
        5. etimer_request_poll();
        6. //printf("%d,%dn",clock_time(),etimer_next_expiration_time());
        7. }
        8. if(--second_countdown==0){
        9. current_seconds++;
        10. second_countdown=CLOCK_SECOND;
        11. }
        12. }

        最后,把stm32f10x_it.c的void SysTick_Handler(void){}刪除。。 再來配置一下debug接口。配置串口位于debug_uart文件中,我把原代碼中的DMA相關代碼刪除,只剩串口初始化和fputc函數。具體的代碼如下:

        1. void
        2. dbg_setup_uart_default()
        3. {
        4. USART_InitTypeDefUSART_InitStructure;
        5. GPIO_InitTypeDefGPIO_InitStructure;
        6. //使能GPIOA時鐘
        7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
        8. |RCC_APB2Periph_USART1,ENABLE);
        9. //PA9TX1復用推挽輸出
        10. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
        11. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        12. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
        13. GPIO_Init(GPIOA,&GPIO_InitStructure);
        14. //PA10RX1浮動輸入
        15. GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
        16. GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        17. GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        18. GPIO_Init(GPIOA,&GPIO_InitStructure);
        19. USART_InitStructure.USART_BaudRate=9600;
        20. USART_InitStructure.USART_WordLength=USART_WordLength_8b;
        21. USART_InitStructure.USART_StopBits=USART_StopBits_1;
        22. USART_InitStructure.USART_Parity=USART_Parity_No;
        23. USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
        24. USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
        25. USART_Init(USART1,&USART_InitStructure);
        26. //使能USART1
        27. USART_Cmd(USART1,ENABLE);
        28. }
        29. intfputc(intch,FILE*f)
        30. {
        31. USART_SendData(USART1,(uint8_t)ch);
        32. while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
        33. returnch;
        34. }

        5.新建一個任務

        通過上網搜索和閱讀書籍,我寫了以下任務。

        1. PROCESS(blink_process,"Blink");
        2. AUTOSTART_PROCESSES(&blink_process);
        3. PROCESS_THREAD(blink_process,ev,data)
        4. {
        5. PROCESS_BEGIN();
        6. while(1)
        7. {
        8. staticstructetimeret;
        9. etimer_set(&et,CLOCK_SECOND);
        10. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
        11. //打開LED
        12. GPIO_ResetBits(GPIOC,GPIO_Pin_6);
        13. printf("LEDONrn");
        14. etimer_set(&et,CLOCK_SECOND);
        15. PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
        16. //關閉LED
        17. GPIO_SetBits(GPIOC,GPIO_Pin_6);
        18. printf("LEDOFFrn");
        19. }
        20. PROCESS_END();
        21. }

        該任務是從contiki-2.5中例子修改而來的。任務非常的簡單,打開LED,通過串口發送提示信息,然后關閉LED,通過串口發送提示信息。

        【1】PROCESS(blink_process,"Blink");相關于函數的聲明

        【2】AUTOSTART_PROCESSES(&blink_process);是指該任務自動啟動,也可以調用process_start函數啟動任務。AUTOSTART_PROCESSES其實也是一個宏東定義:

        1. #if!CC_NO_VA_ARGS
        2. #ifAUTOSTART_ENABLE
        3. #defineAUTOSTART_PROCESSES(...)
        4. structprocess*constautostart_processes[]={__VA_ARGS__,NULL}
        5. #else//AUTOSTART_ENABLE
        6. #defineAUTOSTART_PROCESSES(...)
        7. externint_dummy
        8. #endif//AUTOSTART_ENABLE
        9. #else
        10. #error"Ccompilermustsupport__VA_ARGS__macro"
        11. #endif

        要想使用它的話,還需要添加AUTOSTART_ENABLE定義。

        #define AUTOSTART_ENABLE 1

        最后請大家不要忘記LED相關IO口的初始化操作。請查看前文代碼。

        6.實驗結果

        先給出contiki的IAR 工程目錄和文件目錄

        再來一個頭文件包含路徑:

        $PROJ_DIR$CMSIS

        $PROJ_DIR$StdPeriph_Driverinc

        $PROJ_DIR$User

        $PROJ_DIR$contiki-2.5core

        $PROJ_DIR$contiki-2.5coresys

        $PROJ_DIR$contiki-2.5corelib

        $PROJ_DIR$contiki-2.5cpu

        【小技巧】在編譯文件的時候會發生一些莫名奇妙的警告,這個警告產生的原因是 linux的文件換行和window文件換行不同! 采用以下方法可以屏蔽這個警告,如下圖所示:

        如果移植順利的話,就可以看到以下實驗結果。

        寫到這里你會發現,contiki的移植還是非常簡單的。



        關鍵詞: contiki系統STM32移

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 富宁县| 唐海县| 正定县| 苍南县| 苏尼特左旗| 扶绥县| 囊谦县| 榆树市| 陆河县| 当雄县| 乃东县| 瓦房店市| 凤台县| 天门市| 建宁县| 常德市| 平顶山市| 顺昌县| 宁德市| 南汇区| 区。| 绥宁县| 邢台市| 澄迈县| 武川县| 灵台县| 仙桃市| 山丹县| 克什克腾旗| 临西县| 自治县| 定州市| 张家港市| 通海县| 罗城| 通山县| 商城县| 夹江县| 达尔| 额敏县| 措勤县|