Contiki操作系统移植STM32F103基于Keil编程软件

Tips:实现了contiki移植到stm32f103上,并实现了流水灯

一、contiki简介

  刚开始当然是先简单介绍下contiki了。Contiki 是一个小型的,开源的,极易移植的多任务操作系统。它专门设计以适用于一系列的内存优先的网络系统,包括从8位电脑到微型控制器的嵌入系统。它的名字来自于托尔·海尔达尔的康提基号。Contiki只需几kilobyte的代码和几百字节的内存就能提供多任务环境和内建TCP/IP支持——维基百科。

二、移植前准备

  • 基础stm32f103的开发板、下载器等。我用的是原子的stm32f103的开发板。
  • keil软件。我的是mdk5。
  • contiki源码。我用的版本是3.0。github上直接克隆就好了,地址我就不放了,相信都能找到。

三、开始移植

首先自己建立一个stm32f103的基本模板,要确保能够正常使用。
先上我自己的工程模板的图
工程模板
我的keil打开文件放在USER中。

  • 工程根目录新建文件夹contiki用于存放contiki移植相关源码
  • contiki文件夹下新建文件夹core、cpu
  • contiki源码文件夹下core所有文件copy到工程目录/contiki/core
  • contiki源码文件夹下cpu/arm/stm32f103所有文件copy到工程目录/contiki/cpu下
  • contiki源码文件夹下platform/stm32test文件下下的contiki-conf.h、contiki-main.c文件copy到工程目录/USER,将原本的main.c删除,相当于替换
  • 打开工程,添加相应文件和include路径。
    contiki_cpu的文件在cpu文件夹下
    contiki_core的文件在contiki/core/sys下
    我自己的目录和路径如下图
    这里写图片描述
    这里写图片描述

按照常规,移植需要修改相应的时钟文件和中断服务,contiki相对简单一点,需要把clock.c修改一下,先在clock源文件中添加头文件

include “stm32f10x.h”
include “stm32f10x_it.h”
删除原来的
include<stm32f10x_map.h>
include <nvic.h>
把systick初始化改成

void
clock_init()
{
    if (SysTick_Config(SystemCoreClock / CLOCK_SECOND))
    {
        while(1);
    }
//    SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}

把systick中断改为

void
SysTick_Handler(void)
{
    current_clock++;
    if(etimer_pending()&& etimer_next_expiration_time()<= current_clock) {
        etimer_request_poll();
        // printf("%d,%d\n",clock_time(),etimer_next_expiration_time     ());
    }
    if (--second_countdown== 0) {
        current_seconds++;
        second_countdown = CLOCK_SECOND;
    }
}

最后,把stm32f10x_it.c的void SysTick_Handler(void){}删除
clock.c就变成了这样

#include "stm32f10x.h"
#include "stm32f10x_it.h"
#include <sys/clock.h>
#include <sys/cc.h>
#include <sys/etimer.h>

static volatile clock_time_t current_clock = 0;
static volatile unsigned long current_seconds = 0;
static unsigned int second_countdown = CLOCK_SECOND;

//void
//SysTick_handler(void) __attribute__ ((interrupt));

void
SysTick_Handler(void)
{
    current_clock++;
    if(etimer_pending()&& etimer_next_expiration_time()<= current_clock) {
        etimer_request_poll();
        // printf("%d,%d\n",clock_time(),etimer_next_expiration_time     ());
    }
    if (--second_countdown== 0) {
        current_seconds++;
        second_countdown = CLOCK_SECOND;
    }
}


void
clock_init()
{
    if (SysTick_Config(SystemCoreClock / CLOCK_SECOND))
    {
        while(1);
    }
//    SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}

clock_time_t
clock_time(void)
{
  return current_clock;
}

#if 0
/* The inner loop takes 4 cycles. The outer 5+SPIN_COUNT*4. */

#define SPIN_TIME 2 /* us */
#define SPIN_COUNT (((MCK*SPIN_TIME/1000000)-5)/4)

#ifndef __MAKING_DEPS__

void
clock_delay(unsigned int t)
{
#ifdef __THUMBEL__ 
  asm volatile("1: mov r1,%2\n2:\tsub r1,#1\n\tbne 2b\n\tsub %0,#1\n\tbne 1b\n":"=l"(t):"0"(t),"l"(SPIN_COUNT));
#else
#error Must be compiled in thumb mode
#endif
}
#endif
#endif /* __MAKING_DEPS__ */

unsigned long
clock_seconds(void)
{
  return current_seconds;
}

观察contiki-main.c的源码。发现头件#include<stm32f10x_map.h>、#include <gpio.h>、include<nvic.h>,替换成#include <stm32f10x.h>,如果使用debug-uart.c就把头文件一样替换掉,不使用直接删除debug-uart.c即可。我没有使用它的DMA方式,所以直接重写了debug文件。但是串口还没使用,所以不知道对不对。

//#include <stm32f10x_map.h>
#include <stm32f10x.h>
//#include <stm32f10x_dma.h>
//#include <gpio.h>
//#include <nvic.h>
#include <stdint.h>
#include <stdio.h>
#include <debug-uart.h>
#include <sys/process.h>
#include <sys/procinit.h>
#include <etimer.h>
#include <sys/autostart.h>
#include <clock.h>

unsigned int idle_count = 0;

int
main()
{
  dbg_setup_uart();
  printf("Initialising\n");

  clock_init();
  process_init();
  process_start(&etimer_process, NULL);
  autostart_start(autostart_processes);
  printf("Processes running\n");
  while(1) {
    do {
    } while(process_run() > 0);
    idle_count++;
    /* Idle! */
    /* Stop processor clock */
    /* asm("wfi"::); */ 
  }
  return 0;
}
#include <debug-uart.h>
#include <string.h>
#include <stm32f10x.h>
#include <stm32f10x_it.h>
#include <stdint.h>
#include <stdio.h>

void  
dbg_setup_uart(void)  
{  
    USART_InitTypeDef USART_InitStructure;  
    GPIO_InitTypeDef GPIO_InitStructure;  

    //使能GPIOA时钟  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA
                          | RCC_APB2Periph_USART1 ,ENABLE);  

      //PA9 TX1 复用推挽输出  
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_9;  
    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;  
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;  
    GPIO_Init(GPIOA,&GPIO_InitStructure);  
    //PA10 RX1 浮动输入  
    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_10;  
    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;     
    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IN_FLOATING;  
    GPIO_Init(GPIOA,&GPIO_InitStructure);  

    USART_InitStructure.USART_BaudRate= 9600;  
    USART_InitStructure.USART_WordLength= USART_WordLength_8b;  
    USART_InitStructure.USART_StopBits= USART_StopBits_1;  
    USART_InitStructure.USART_Parity= USART_Parity_No;  
    USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None;  
    USART_InitStructure.USART_Mode= USART_Mode_Rx | USART_Mode_Tx;  
    USART_Init(USART1,&USART_InitStructure);  

    //使能USART1  
    USART_Cmd(USART1,ENABLE);  
  }  

int fputc(int ch, FILE* f)  
{
    USART_SendData(USART1,(uint8_t)ch);  
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)== RESET );  
    return ch;  
}  

完成后发现编译有错误
编译错误
从contiki-main.c头文件进入autostart.h文件,添加#define AUTOSTART_ENABLE 1 ,宏定义。修改procinit.c,extern const struct process *procinit[];修改为const struct process *procinit[];
编译后发现还有autostart错误,暂时先不管,先编写自己的led功能,经过编写后contiki-main.c文件如下:

#include <stm32f10x.h>
#include <stm32f10x_dma.h>
#include <stdint.h>
#include <stdio.h>
#include <debug-uart.h>
#include <sys/process.h>
#include <sys/procinit.h>
#include <etimer.h>
#include <sys/autostart.h>
#include <clock.h>

#define Contiki_etimer_DelayMS(MS) \
    etimer_set(&et, MS/(1000/CLOCK_SECOND)); \
    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et))

unsigned int idle_count = 0;

static void led_init(void);
PROCESS(led_blink_process, "Led");
PROCESS_THREAD(led_blink_process, ev, data);
AUTOSTART_PROCESSES(&led_blink_process);

int main()
{
    dbg_setup_uart();
    led_init();
    clock_init();
    process_init();
    process_start(&etimer_process, NULL);
    autostart_start(autostart_processes);
    process_start(&led_blink_process, NULL);
    while(1) {
        do {
        } while(process_run() > 0);
        idle_count++;
        /* Idle! */
        /* Stop processor clock */
        /* asm("wfi"::); */
    }
    return 0;
}

void led_init(void)
{
    GPIO_InitTypeDef GPIO_Initstructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);
    GPIO_Initstructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_Initstructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Initstructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_Initstructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_8);

    GPIO_Initstructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOD, &GPIO_Initstructure);
    GPIO_SetBits(GPIOD, GPIO_Pin_2);
}

PROCESS_THREAD(led_blink_process, ev, data)
{
    static struct etimer et;
    PROCESS_BEGIN();
    while(1)
    {
        GPIO_ResetBits(GPIOA, GPIO_Pin_8);
        GPIO_SetBits(GPIOD, GPIO_Pin_2);
        Contiki_etimer_DelayMS(500);
        GPIO_SetBits(GPIOA, GPIO_Pin_8);
        GPIO_ResetBits(GPIOD, GPIO_Pin_2);
        Contiki_etimer_DelayMS(500);
    }
    PROCESS_END();
}

编译后发现没错,下载到单片机,led成功点亮并跑马灯了!!! 移植还是很简单的吧?!!!

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值