欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-02-22 18:48:52
...
Tips:实现了contiki移植到stm32f103上,并实现了流水灯

一、contiki简介

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

二、移植前准备

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

三、开始移植

首先自己建立一个stm32f103的基本模板,要确保能够正常使用。
先上我自己的工程模板的图
Contiki操作系统移植STM32F103基于Keil编程软件
我的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操作系统移植STM32F103基于Keil编程软件
    Contiki操作系统移植STM32F103基于Keil编程软件

按照常规,移植需要修改相应的时钟文件和中断服务,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操作系统移植STM32F103基于Keil编程软件
从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成功点亮并跑马灯了!!! 移植还是很简单的吧?!!!

相关标签: 移植 操作系统