一.μCOS-II源码文件结构介绍
下载地址:
https://www.micrium.com/download/micrium_stm32xxx_ucos-ii/
这个地址下载的时候需要注册Micrium账号才能下载,源码是Micrium官方提供给移植内核ARM Cortex-M3的例子,我们所要移植的STM32F103VC芯片的内核是ARM Cortex-M3,因此我们下载这个源码文件。
下载成功之后是一个Micrium_STM32xxx_uCOS-II.exe可执行文件的压缩文件(图1)需要我们解压缩(图2)得到(图3)。
图1:
图2:
图3:
树形展开结构:
其中文件夹简单介绍:
AppNotes:
在这个文件夹下有两个子文件夹,里面内容都是移植时的说明文件,我们只关心
MicriumAppNotesAN1xxx-RTOSAN1018-uCOS-II-Cortex-M3AN-1018.pdf因为这个是针对ARM Cortex-M3移植的说明。
Licensing:
这个文件夹下是μCOS-II使用的许可证。
Software:
CPU:STM32标准外设库。
EvalBoards: Micrium官方评估板相关代码。
uC-CPU: 基于Micrium官方评估板的uCOS-II移植代码。
uC-LCD: Micrium官方评估板LCD驱动代码。
uC-LIB: Micrium官方的一个库代码。
uCOS-II: μC/OS-II源代码。
uC-Probe: 和uC-Probe相关代码。
在这个文件夹下有好多文件夹,我们只关心μCOS-II这个文件夹下的内容,在uCOS-II这个文件夹下分别有:Doc,Ports,Source三个文件夹,我们需要的是
MicriumSoftwareuCOS-IIPortsARM-Cortex-M3GenericRealView 下os_cpu_c.c,os_cpu.h,os_cpu_a.asm这三个文件(图4)和MicriumSoftwareuCOS-IISource下的所有文件(图5),在之后创建工程目录结构的时候会将这些文件复制到相应目录下,并且在工程里面会添加进去相关文件。
图4:
图5:
二.STM32固件库V3.5.0文件结构介绍
上面的图示只是简单的将大部分内容的文件夹展现了出来,接下来介绍一下这些文件夹都存放的什么文件:
STM32F10x_StdPeriph_LibV3.5.0——————ST公司针对STM32提供的函数接口
_htmresc——————CMSIS内核和ST公司Logo
Libraries——————固件库
CMSIS——————Cortex内核软件接口标准
Core_Support——————为采用Cortex-M3核设计SOC的芯片商设计的芯片外设提供一个进入M3内核的接口
STM32F10x——————定义寄存器的地址及使用的结构封装,设备外设访问层,配置时钟频率相应的头文件
startup——————由汇编编写的系统启动文件,不同的文件对应不同的芯片型号
arm————————ARM编译器启动文件
gcc_ride7——————GCC编译器启动文件
iar——————IAR编译器启动文件
TrueSTUDIO——————TrueSTUDIO编译器启动文件
STM32F10x_StdPeriph_Driver——————CMSIS的设备外设函数,由stm32f10x_ppp.c或stm32f10x_ppp.h文件组成,ppp表示外设名称,每个外设驱动库函数对应一个头文件和源文件
STM32F10x_StdPeriph_Example——————标准外设库驱动的完整例程
STM32F10x_StdPeriph_Template————————官方的一个库工程模板
Utilities————————包含了用于STM3210B-EVAL和STM3210E-EVAL评估板的专用驱动
三.移植环境和准备工作
我这里移植的环境:
硬件:STM32F103VC芯片,ARM Cortex-M3内核
软件:μCOS-II源码版本V2.86
STM32固件库版本V3.5.0
Keil uvision5集成开发环境
准备工作:
创建UCOS-II_Project工程存放文件的文件夹目录结构,树形结构见(图6)
图6:
创建好存放源码文件的文件夹结构之后,现在我们开始复制源码到创建好的文件夹里面:
CMSIS:在这个文件夹下面存放内核硬件抽象层文件,复制(图7)文件到该目录下
图7:
MDK:该文件夹下存放创建好的keil工程相关文件,在之后创建工程的时候会用到。
CPU:在这个文件夹下存放的是μCOS-II和CPU架构之间的文件,复制uCOS-IICpu目录下文件(图8)到该目录下
图8:
STM32:
inc:在这个文件夹下存放STM32固件库的.h文件,复制STM32F10x_StdPeriph_Lib_V3.5.0LibrariesSTM32F10x_StdPeriph_Driverinc目录下文件(图9)到该目录下
图9:
src:在这个目录下存放STM32固件库的.c文件,复制STM32F10x_StdPeriph_Lib_V3.5.0LibrariesSTM32F10x_StdPeriph_Driversrc目录下文件(图10)到该目录下
图10:
UCOSII:
src:在这个文件夹下存放μCOS-II的源码,复制uCOS-IISource目录下文件(图11)到该目录下
图11:
USER:该文件夹用来存放创建好keil工程之后我们自己所写的板级硬件初始化文件和main函数文件等相关应用文件。
好了,基本的准备工作就做好了。
四.创建STM32的keil工程
点击keil开发软件的Project,选择下面的New μVision Project...(图12)
图12:
新建工程地址选为:UCOS-II_ProjectMDK (图13)
图13:
芯片选择(图14)
图14:
修改工程名称(图15)
图15:
创建工程目录和向工程目录下添加文件(图16)
图16:
修改编译输出文件目录路径(图17)
图17:
创建完成之后的工程总体目录结构(图18),在这里创建好的工程里面cpu,ucosii工程目录里面没有文件,在之后的移植过程里会将关于ucosii的文件添加进去。
图18:
创建好工程之后,需要加入main函数主文件和板级硬件初始化函数的文件,在这里我将已经写好的bsp.c,debug-uart.c,ucos-main.c文件已经加入工程里了,在下面贴出代码:
/*bsp.c*/
#include
#include
#include
#include "stm32f10x.h"
static void bsp_rcc_init (void)
{
uint32_t rcc_to;
RCC_DeInit(); /* Reset the RCC clock config to the default reset state */
RCC_HSEConfig(RCC_HSE_ON); /* HSE Oscillator ON*/
rcc_to = BSP_RCC_TO_VAL;
while ((rcc_to > 0) && (RCC_WaitForHSEStartUp() != SUCCESS)) { /* Wait until the oscilator is stable */
rcc_to--;
}
FLASH_SetLatency(FLASH_Latency_2);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* Fcpu = (PLL_src * PLL_MUL) = (8 Mhz / 1) * (9) = 72Mhz*/
RCC_PLLCmd(ENABLE);
rcc_to = BSP_RCC_TO_VAL;
while ((rcc_to > 0) &&
(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)) {
rcc_to--;
}
RCC_HCLKConfig(RCC_SYSCLK_Div1); /* Set system clock dividers*/
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
FLASH_SetLatency(FLASH_Latency_2); /* Embedded Flash Configuration*/
FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
}
static void bsp_led_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
//PE8,9 ÍÆÍìÊä³ö
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
}
void bsp_led_on (uint8_t led_id)
{
switch (led_id) {
case 0:
GPIO_ResetBits(GPIOE, GPIO_Pin_8|GPIO_Pin_9);
break;
case 1:
GPIO_ResetBits(GPIOE, GPIO_Pin_8);
break;
case 2:
GPIO_ResetBits(GPIOE, GPIO_Pin_9);
break;
default:
break;
}
}
void bsp_led_off (uint8_t led_id)
{
switch (led_id) {
case 0:
GPIO_SetBits(GPIOE, GPIO_Pin_8|GPIO_Pin_9);
break;
case 1:
GPIO_SetBits(GPIOE, GPIO_Pin_8);
break;
case 2:
GPIO_SetBits(GPIOE, GPIO_Pin_9);
break;
default:
break;
}
}
void bsp_led_toggle (uint8_t led_id)
{
uint16_t reg_val;
switch (led_id) {
case 0:
reg_val = GPIO_ReadOutputData(GPIOE);
reg_val ^= (GPIO_Pin_8|GPIO_Pin_9);
reg_val &= (GPIO_Pin_8|GPIO_Pin_9);
GPIO_SetBits(GPIOE, reg_val);
reg_val = (~reg_val);
reg_val &= (GPIO_Pin_8|GPIO_Pin_9);
GPIO_ResetBits(GPIOE, reg_val);
break;
case 1:
reg_val = GPIO_ReadOutputData(GPIOE);
reg_val ^= GPIO_Pin_8;
GPIO_SetBits(GPIOE,reg_val&GPIO_Pin_8);
GPIO_ResetBits(GPIOE,(~reg_val)&GPIO_Pin_8);
break;
case 2:
reg_val = GPIO_ReadOutputData(GPIOE);
reg_val ^= GPIO_Pin_9;
GPIO_SetBits(GPIOE,reg_val&GPIO_Pin_9);
GPIO_ResetBits(GPIOE,(~reg_val)&GPIO_Pin_9);
break;
default:
break;
}
}
void SysTickInit(void)
{
//every msec got int
if (SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC))
{
/* Capture error */
while (1);
}
}
void bsp_init(void){
bsp_rcc_init();
bsp_led_init();
/* Set the Vector Table base address at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
}
#include
#include
#include "stm32f10x.h"
void dbg_uart_gpio_init(void){
GPIO_InitTypeDef gpio_init;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* Configure GPIOA.9 as push-pull */
gpio_init.GPIO_Pin = GPIO_Pin_9;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &gpio_init);
/* Configure GPIOA.10 as input floating */
gpio_init.GPIO_Pin = GPIO_Pin_10;
gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &gpio_init);
}
void dbg_uart_init(void){
USART_InitTypeDef usart_init;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
usart_init.USART_BaudRate = 115200;
usart_init.USART_WordLength = USART_WordLength_8b;
usart_init.USART_StopBits = USART_StopBits_1;
usart_init.USART_Parity = USART_Parity_No ;
usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usart_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &usart_init);
USART_Cmd(USART1, ENABLE);
}
void dbg_uart_int_init(void){
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1, USART_IT_TC, DISABLE);
}
void
dbg_setup_uart(){
dbg_uart_gpio_init();
dbg_uart_init();
dbg_uart_int_init();
}
int fputc(int ch, FILE * f)
{
USART_SendData(USART1, (uint8_t)ch);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );
return ch;
}
void uart1_sendstring(uint8_t* cp)
{
while((*cp)!='