uc/OS-II操作系统移植:uc/OS-II移植到STM32流程(文章末尾附实例)

一、实验目的

1、掌握在STM32上移植嵌入式实时操作系统uC/OS-II的方法
2、掌握在STM32上移植uC/OS-II的基本步骤
3、掌握uC/OS-II的文件OS_CPU.H编写
4、掌握uC/OS-II的文件OS_CPU_C.C编写
5、掌握uC/OS-II的文件OS_CPU_A.S的编写

二、实验原理

uCOS也叫uC/OS-II,它是由美国人Jean .J.Labrosse在1992年编写的一个嵌入式多任务实时操作系统。它具有以下特点:
(1)微型化。嵌入式系统芯片内部存储器的容量通常不会很大,一般也不配置外存,加之电源的容量较小以及外部设备的多样性,因而不允许嵌入式操作系统占用较多的资源,所以在保证应用功能的前提下,嵌入式操作系统的规模越小越好
(2)可裁剪性。嵌入式操作系统的运行平台多种多样,其宿主对象更是五花八门,所以要求嵌入式操作系统中提供的各个功能模块可以让用户根据需要选择使用,即要求它具有良好的可裁剪性
(3)实时性。目前嵌入式系统广泛应用于生产过程控制、数据采集、传输通信等场合,这些应用的共同特点就是要求系统能快速响应事件,因此要求嵌入式操作系统要有较强的实时性
(4)高可靠性。嵌入式系统广泛地应用于军事武器、航空航天、交通运输等重要领域,所以要求嵌入式操作系统必须有极高的可靠性,对关键、要害的应用还要提供必要的容错和防错措施,以进一步提高系统的可靠性
(5)易移植性。为了适应多种多样的硬件平台,嵌入式操作系统应可在不做大量修改的情况下稳定地运行于不同地平台

由于uC/OS-II基本全部是用C语言写的,只有和微处理器相关的部分是用汇编语言写的,但是汇编所占比例很小,从而使得uC/OS-II很容易移植到各种微处理器上,事实上现在的uC/OS-II已经应用在了大部分的8位、16位以及32位的MCU中了,本次实验是将uC/OS-II移植到STM32上,只需要编写文件《OS_CPU.H》、《OS_CPU_C.C》以及《OS_CPU_A.S》即可。

三、实验要求

在STM32f103上移植uC/OS-II,并能成功运行。

四、实验步骤

移植第一步:
1、定义编译器相关的数据类型(在OS_CPU.H中定义)
2、定义允许和禁止中断宏(在OS_CPU.H中定义)
3、定义栈的增长方向(在OS_CPU.H中定义)
移植的第二步:
1、系统堆栈的初始化OSTaskStkInit()(在OS_CPU_C.C中定义)
移植的第三步:
1、最高优先级任务的调度(在OS_CPU_A.S中定义)
2、任务级的任务切换(在OS_CPU_A.S中定义)
3、中断级的任务切换(在OS_CPU_A.S中定义)
移植的第四步:
1、关于时钟节拍中断的操作
2、钩子函数

五、实验步骤截图展示

注:我已经创建好了STM32工程目录
1、首先去官网下载移植代码

在这里插入图片描述
在这里插入图片描述

2、在工程目录下创建一个UCOS-II目录,并在该目录下创建三个文件用来存放移植代码

在这里插入图片描述
在这里插入图片描述

3、然后将UCOS-II目录下的三个文件加入到STM32工程中来在这里插入图片描述
4、将UCOS-II目录下的三个文件加入到STM32头文件目录下

在这里插入图片描述

5、修改startup_stm32f10x_hd.s文件中的参数

在这里插入图片描述
6、注释掉stm32f10x_it.c文件中的如下内容
在这里插入图片描述

7、注释掉UCOSII-Ports目录下的os_cpu.h中的如下内容

在这里插入图片描述

8、在UCOSII-Ports目录下的os_cpu.a.asm中添加如下所示代码

在这里插入图片描述
在这里插入图片描述

9、注释掉UCOSII-Ports目录下的os_cpu_c.c文件下的如下内容

在这里插入图片描述

10、删掉UCOSII-Ports目录下os_dbg.c文件中的“_root”代码

在这里插入图片描述

11、注释掉UCOSII-Source目录下ucos_ii.h文件中“#include<app_cfg.h>”头文件

在这里插入图片描述

12、仿真结果如下

在这里插入图片描述

六、实例

将uC/OS-II移植到STM32上以后,我编写了两个任务分别是点亮LED0和点亮LED1,他们的亮灭的时间不同,由于没有硬件所以只在Keil5平台上验证其正确性,最后仿真结果完全正确,仿真结果如下:
在这里插入图片描述

七、实验总结

》此次实验是移植uC/OS-II到STM32f103上,通过结合书中的知识可以知道,在ARM上移植uC/OS-II时,为使在不同的ARM工作模式下调用uC/OS-II底层接口函数不受访问权限的限制,在移植时使用了ARM的软中断技术。根据ARM核的特点和移植目标,移植时在uC/OS-II中增加了4个系统函数,其中,两个是用来转换处理器模式的函数ChangeToSYSMode()和ChangeToUSRMode();两个设置任务的初试指令集的函数TaskIsARM()和TaskIsTHUMB()。而且为了使用户可用C语言编写中断服务程序时不必为处理器的硬件区别而困扰,根据uC/OS-II对中断服务程序的要求以及以及ARM7体系结构特点,编写了一个适用于所有基于ARM7核处理器的汇编宏。这个宏实现了uC/OS-II for ARM7中断服务程序的汇编语言代码与C语言函数代码之间的通用接口。
》并且通过此次实验我相信在座的各位大佬学会了将uC/OS-II移植到STM32的基本步骤与方法,虽然在移植过程中你们还会出现很多错误,但是我相信你们经过和同学讨论以及上网查阅把出现的错误都会一一解决,在写代码的时候巩固了你们在实时操作系统上所学的相关代码,实现了实时操作系统中的代码和ARM中的代码的结合,也给你们的专业能力打下了一定的基础。

八、源代码

#include"stm32f10x.h"
#include"stm32f10x_conf.h"
#include"ucos_ii.h"

#define	TASK_STK_SIZE	 64	      //定义堆栈长度
OS_STK LED0_TASK_STK[TASK_STK_SIZE];
OS_STK LED1_TASK_STK[TASK_STK_SIZE];  
#define ON 0
#define OFF 1
#define LED0(a)	if (a)	\
					GPIO_SetBits(GPIOA,GPIO_Pin_0);\
					else		\
					GPIO_ResetBits(GPIOA,GPIO_Pin_0)
#define LED1(a)	if (a)	\
					GPIO_SetBits(GPIOA,GPIO_Pin_1);\
					else		\
					GPIO_ResetBits(GPIOA,GPIO_Pin_1) 

void GPIO_configuration(void)						     
{		
	 GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;  
    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_0);
	GPIO_SetBits(GPIOA, GPIO_Pin_1);	 
}

void BSP_Init(void)	       
{  
    GPIO_configuration();  
}

void SysTick_init(void)	      
{
    SysTick_Config(SystemCoreClock/OS_TICKS_PER_SEC);   
}

void Task_LED0(void *pada)
{
    pada=pada;					

    SysTick_init();                    
              	
    while (1)
    {
        LED0( ON );
        OSTimeDlyHMSM(0, 0,0,100);
        LED0( OFF);
		OSTimeDlyHMSM(0, 0,0,100);       
    }
}
void Task_LED1(void *pada)
{
    pada=pada;					 	

             while (1)
    {
        LED1( ON );
        OSTimeDlyHMSM(0, 0,0,500);
        LED1( OFF);
		OSTimeDlyHMSM(0, 0,0,500);       
    }
}


int main(void)
{
	BSP_Init();

	OSInit();
	OSTaskCreate(Task_LED0,(void *)0, &LED0_TASK_STK[TASK_STK_SIZE-1], 4);
    OSTaskCreate(Task_LED1,(void *)0, &LED1_TASK_STK[TASK_STK_SIZE-1], 5);
	OSStart();
    return 0;
}
如果大家还不知道怎么移植,请大家联系我邮箱:Zhangyc_Engineer@qq.com,我给大家直接发移植好的工程,然后大家再对着这篇笔记,自己私下里动手去移植移植,有助于提高大家的能力!
/*********************** (C) COPYLEFT 2010 Leafgrass *************************/ This project runs on uC/OS-II V2.52 and is based on STM32F103RBT6(ARM Cortex-M3 Core) Take care of the configuration of project. There're some Include Paths while linking which cannot be modified. Procedure of driving a device(IMPORTANT!!!): 1.Connect hardware correctly. 2.Prepare DEVICE_NAME.h and DEVICE_NAME.c. 3.Enable clock of related components. 4.Enable related interrupt while configure NVIC. 5.Configure related IO pins. 6.Finish test code and begin testing. 2010-06-10( original ): Sucessfully port uCOS-II V2.52. 2010-06-11: Add code "SysTick_CounterCmd(SysTick_Counter_Enable);" in SysTick_Configuration(), solve the problem that the program can't get into SysTickHandler(), as below: /******************************************************************************* * Function Name : SysTick_Config * Description : Configures SysTick * Input : None * Output : None * Return : None *******************************************************************************/ void SysTick_Configuration(void) { NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 0, 1); /* Configure HCLK clock as SysTick clock source */ SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); /* SysTick interrupt each 1000 Hz with HCLK equal to 72MHz */ SysTick_SetReload(9000); /* Enable the SysTick Interrupt */ SysTick_ITConfig(ENABLE); SysTick_CounterCmd(SysTick_Counter_Enable); //Important!! Solve "the program can't get into SysTickHandler()!! } 2010-06-12( updates to V1.0 ): 1. Add EXTI8, EXTI9 on PC8, PC9, only for EXTI test. 2. Modify some comments in LCD5110_lib. 3. (in main.c) Modifiy tasks' priority LED_TASK_Prio 1 -> 5 START_TASK_Prio 2 -> 10 4. (in main.c) Modify code "OSTaskDel(START_TASK_Prio);" to "OSTaskSuspend(START_TASK_Prio);" 2010-07-13 1.Drive LTM022A69B LCD ok. Just use I/O to imitate SPI. Still cannot use internal SPI to drive it. 2.Move LCD library of LTM022A69B into "LCD_lib.c". 2010-07-15: Add color bar display in LCD_test(). 2010-07-16( updates to V1.1 ): 1.Solve problem about position error and color error, when display a set of 16-bit color data. Mainly resulted from CPU type, big endian or little endian. STM32F103RBT6 is little endian while in default set. 2.Add Draw_img(); 3.Add colorful characters and strings, add parameters about colors in display functions.(colors are defined in LTM022A69B.h) 2010-07-17: 1.Add comments in LCD_Init(). 2.Add parameter "color" to function Draw_dot(). 3.Add function SetCursor(). 4.Unify LCD related functions' name. Add prefix "LCD_". 2010-07-19: Modify data type in LCD_Lib. normal --> const. At one time, modify the pointers type to const. 2010-07-20: 1.Correct the error that OSTimeDlyHMSM() can't delay an accurate time, by modifying SysTick_Configuration() to get an correct clock frequency. 2010-07-31: Add STM32_Init.c but is not referenced, for future use of Configuration Wizard. 2010-08-01: Configure SPI ok, and do some test(SPI2 tx -> SPI1 rx, display on LCD). 2010-08-03: 1.Add SPI test code in main.c, SPI2 send data, SPI1 receive data , display info on LCD, use soft SPI. 2.Add exported macro "USESPI" to choose if use SPI to drive LCD or not. 3.After several days researching about hard SPI to drive LCD, failed. So switch to use a faster GPIO method, as below: Replace "#define LCD_RST_H() GPIO_SetBits(LCD_CTRL_PORT, LCD_RST)" in ST library with "#define LCD_RST_H() ( LCD_CTRL_PORT->BSRR = LCD_RST )" for a faster LCD refresh speed. 4.Modify name "LCD_SCI" to "LCD_SI", 'cause it means Serial Interface. 5.Modify function name "LCD_test()" to "LCD_Test()". 2010-08-06: Comment off "typedef enum {FALSE = 0, TRUE = !FALSE} bool;" in stm32f10x.type.h in order to avoid warning. 2010-08-09: Prepare to update to v2.0. 2010-08-10( Update to v2.0, use ST's FWLib3.1.2 ): 1. Set project(Keil RealView MDK). (1) RO memory area : IROM1 -- start at 0x08000000, size 0x20000. (2) RW memory area : IRAM1 -- start at 0x20000000, size 0x5000. (3) Output setup. (4) Listing setup, no assembler list. (5) C/C++ setup. Preprocessor Symbols : Define -- USE_STDPERIPH_DRIVER, STM32F10X_MD. Include Paths : ..\; ..\..\Libraries\CMSIS\Core\CM3; ..\..\Libraries\STM32F10x_StdPeriph_Driver\inc; ..\..\App; ..\..\Driver; ..\..\OS; ..\..\OS\port (6) Linker, Use memory layout from target dialog. (7) Debug and Utilities, Cortex-M/R J-Link/J-Trace. Disable Trace. 2. Modify code in "includes.h". 3. Modify startup code, did not use the st original one. Port those used in FWLib2.0 instead. Of course, some code are revised for FWLib3.1.2(StdPeriph_Driver and CMSIS). Mainly rewrite the names of the ISR. The most important two are : "PendSV_Handler" and "SysTick_Handler". ---> "OSPendSV" and "SysTick_Handler". (in "os_cpu_a.asm") (in "stm32f10x_it.c") 4. Modify initial code for SysTick in "SysTick_Configuration()" in "CPU_Init.c" because of the changing of library. Note : A general problem is that program always go into "B OSStartHang" in "OSStartHighRdy" in "os_cpu_a.asm", and will die in there... That's caused by program hasn't step into the correct ISR yet. Enable the SysTick interrupt, check if the name of Interrupt Service Routines are right, then all will be OK. 5. Still some problem with retargeting "printf()". If use "printf()" in program, system wouldn't run. 6. Change Project name to "RTOS_STM32". 2010-08-11( Update to v2.1, use ST's FWLib3.3.0 ): 1. Modify Include Path in Target Options. 2. Comment "typedef enum {FALSE = 0, TRUE = !FALSE} bool;" off in order to avoid error: "..\stm32f10x.h(454): error: #40: expected an identifier". 2010-08-12( Update to v2.2 ): 1. Remove the incorrect use of SPI in LCD display, add a new schedule( maily used SPI busy flag ). 2. Commen off code "assert_param(IS_SPI_ALL_PERIPH(SPIx));" in "SPI_I2S_SendData()", "SPI_I2S_ReceiveData()", and "SPI_I2S_GetFlagStatus" in "stm32f10x_spi.h", in order to improve LCD refresh frequency. 3. Finish to retarget C library printf() to UART. As a foundation, change the setup of KEIL in "Target Options" --> "Code Generation" --> tick "Use MicroLIB". There are still some problem with building, modify a few lines in "stm32f10x_startup.s" : ================================ IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap ================================ Then rebuild. Add retarget code in main.c : ================================================================ #ifdef __GNUC__ // With GCC/RAISONANCE, small printf // (option LD Linker->Libraries->Small printf set to 'Yes') // calls __io_putchar() #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif // __GNUC__ ---------------------------------------------------------------- PUTCHAR_PROTOTYPE { // Place your implementation of fputc here // e.g. write a character to the USART USART_SendData(USARTx, (u8)ch); // Loop until the end of transmission while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} return ch; } ================================================================ 2010-08-14(update to v2.3): 1. Rewrite the different part of code into its C file. 2. Drive TIM3 output PWM wave successfully. 3. Add "servo" file, for servo control. 2010-08-19(update to v2.4, GPS data receive ok): 1. Add "gps" file. 2. Add code in "USART3_IRQHandler()", mainly to receive data from GPS. But there's still someting confusing, that the pair "USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);" and "USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);" cannot work well. Because once use them, some data will be lost. 2010-08-22: Refresh firmware of GPS, modify to Baudrate 9600, China timezone, WGS-84 coordinate. 2010-09-02: Replace those two old startup files "cortexm3_macro.s" and "stm32f10x_startup.s" with the one "startup_stm32f10x_md.s" which is created by MCD Application Team in FWLib3.3.0. 2010-09-13: 1. Add general_task.h and .c for miscellaneous experimental purpose. 2. Add uart output infomation in booting stage. 3. Add macro "LED_TOGGLE()" use "(GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1))" 4. Create Logo: _ _ / / | | ___ __ _ _| |_ __ _ _ __ __ _ _ _ | | / _ \/ _` |_ _/ _` | \/ _)/ _` | / / / / | |_ _ __( (_| | | | (_| | | | ( (_| | \ \ \ \ |_ _ _\___|\__,_| | | \__, / | | \__,_| /_/ /_/ /_/ \_ _/ 5. EXTI again. setup procedure: GPIO IN FLOATING -> NVIC IRQ -> EXTI Config -> _it.c /*********************** (C) COPYLEFT 2010 Leafgrass *************************/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheems_Pak Choi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值