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成功点亮并跑马灯了!!! 移植还是很简单的吧?!!!
上一篇: POI通过模板导出EXCEL文件的实例
下一篇: python实现的多线程端口扫描功能示例