1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
uC/OS-III移植到STM32F103
4.4新建一个工程文件夹 本教程以uC/OS-III移植到正点原子STM31F103为例,首先将一个STM32的例程文件夹重命名为“STM32_UCOSIII_LED”,先以最基础的点亮LED例程来验证。 图1-1新建工程文件 4.2 向工程中添加相应的文件 (1)下载Micrium官方移植源码 下载好以后我们打开这个“Micrium官方移植”->Sofeware的文件夹,可以看到这里只有四个子文件夹,选择“uC-xxx”的三个文件夹copy到我们所建立的工程文件夹“STM32_UCOSIII_LED”中。 (2)新建“APP”、“BSP”两个空文件夹。 图1-2.1复制UCOSIII相关文件到工程中 (3)向BSP添加文件 复制官方移植好的工程中的相关文件到BSP中,路径: Micrium官方移植SoftwareEvalBoardsMicriumuC-Eval-STM32F107BSP 图1-2.2向BSP添加文件 (4)向APP添加文件 复制官方移植好的工程中的相关文件到BSP中,路径: Micrium官方移植SoftwareEvalBoardsMicriumuC-Eval-STM32F107uCOS-III 图1-2.3向APP添加文件 4.3向工程中添加分组以及相应的头文件路径 (1)向工程中添加分组以及文件 打开KEIL工程,新建如下图的分组。 图1-3.1工程添加分组 工程中分组建立完成后,向新建的各个分组添加相应的文件,要选择“All files”全部添加。 图1-3.2向工程中添加分组以及文件 1、APP分组的路径: STM32_UCOSIII_LEDAPP; 2、BSP分组的路径: STM32_UCOSIII_LEDBSP; 3、UCOSIII-LIB分组的路径: STM32_UCOSIII_LEDuC-LIB(包括Port文件夹的 STM32_UCOSIII_LEDuC-LIBPortsARM-Cortex-M3RealView); 3、UCOSIII-CPU分组的路径: STM32_UCOSIII_LEDuC-CPU(包括ARM-Cortex-M3文件夹的 STM32_UCOSIII_LEDuC-CPUARM-Cortex-M3RealView); 4、UCOSIII-Source分组的路径: STM32_UCOSIII_LEDuCOS-IIISource 6、UCOSIII_Port分组的路径: STM32_UCOSIII_LEDuCOS-IIIPortsARM-Cortex-M3GenericRealView (2)添加相应的头文件路径 图1-3.3添加相应的头文件路径 4.4具体的工程文件修改 4.4.1删除main.c文件 因为APP文件夹中的app.c文件包含main函数,所以打开USR文件夹,删除main.c文件。 4.4.2修改bsp.c和bsp.h文件 bsp.h以及includes.h文件中,源码中使用的头文件是#include 将bsp.c中的BSP_Init()函数的内容删掉(因为我并没有使用BSP部分函数),在里面添加自己写的外设初始化函数,如LED_Init(),将该文件中没有用到的函数都删掉。 添加时钟周期数转换为us所需要的代码: #define BSP_REG_DEM_CR (*(CPU_REG32 *)0xE000EDFC) //DEMCR寄存器 #define BSP_REG_DWT_CR (*(CPU_REG32 *)0xE0001000) //DWT控制寄存器 #define BSP_REG_DWT_CYCCNT (*(CPU_REG32 *)0xE0001004) //DWT时钟计数寄存器 #define BSP_REG_DBGMCU_CR (*(CPU_REG32 *)0xE0042004) //DEMCR寄存器的第24位,如果要使用DWT ETM ITM和TPIU的话DEMCR寄存器的第24位置1 #define BSP_BIT_DEM_CR_TRCENA DEF_BIT_24 //DWTCR寄存器的第0位,当为1的时候使能CYCCNT计数器,使用CYCCNT之前应当先初始化 #define BSP_BIT_DWT_CR_CYCCNTENA DEF_BIT_00 //CPU_TS32_to_uSec()和CPU_TS64_to_uSec()是将读取到时钟周期数,转换为us #if (CPU_CFG_TS_32_EN == DEF_ENABLED) CPU_INT64U CPU_TS32_to_uSec (CPU_TS32 ts_cnts) { CPU_INT64U ts_us; CPU_INT64U fclk_freq; fclk_freq = BSP_CPU_ClkFreq(); ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC); return (ts_us); } #endif #if (CPU_CFG_TS_64_EN == DEF_ENABLED) CPU_INT64U CPU_TS64_to_uSec (CPU_TS64 ts_cnts) { CPU_INT64U ts_us; CPU_INT64U fclk_freq; fclk_freq = BSP_CPU_ClkFreq(); ts_us = ts_cnts / (fclk_freq / DEF_TIME_NBR_uS_PER_SEC); return (ts_us); } #endif 4.4.3、修改os_cpu_a.asm文件(UCOSIII-Port分组) SysTick_Handler和PendSV_Handler两个函数: SysTick_Handler是滴答定时器中断,这个中断相当于操作系统的心脏,在它的中断服务函数中,提供进程/任务的上下文切换和任务调度的工作; PendSV_Handler函数作用是当操作系统(OS)检测到某IRQ正在活动,并且被SysTick抢占,它将触发一个PendSV异常,以便缓期执行上下文切换。 打开os_cpu_a.s文件,将OS_CPU_PendSVHandler修改为PendSV_Handler 添加任务切换器,任务级切换以及中断级切换的代码 代码如下: ;任务级切换,从任务A切换到任务B OSCtxSw LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, [R0] BX LR ;中断级切换,从中断退出时切换到一个任务时,从中断切换到任务时,CPU的寄存器入栈工作已完成,无需做第二次 OSIntCtxSw LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) LDR R1, =NVIC_PENDSVSET STR R1, [R0] BX LR 修改系统优先级寄存器4 打开stm32f10x_it.c文件(USER分组中),注释掉PendSV_Handler()以及SysTick_Handler()函数; 4.4.4修改os_cpu_c.c文件(UCOSIII-Port分组) 在os_cpu_c.c文件中,添加#include 4.4.5修改sys.h文件(SYSTEM分组) 定义系统文件支持UCOS,将0改为1; 4.4.6 修改os_cfg_app.h文件(UCOSIII-Source) 根据自己需要修改系统任务的优先级,一般情况下,系统任务的优先级(由高到低): 中断服务管理任务–>时钟节拍任务–>定时任务->统计任务–>空闲任务 4.5测试验证移植 APP分组中的main函数全部删除替换,使用LED以及串口测试移植是否成功,代码如下: #include "led.h" #include "delay.h" #include "sys.h" #include "usart.h" #include "includes.h" /************************************************ ALIENTEK战舰STM32开发板UCOS实验 技术支持:www.openedv.com 淘宝店铺:http://eboard.taobao.com 关注微信公众平台微信号:"正点原子",免费获取STM32资料。 广州市星翼电子科技有限公司 作者:正点原子 @ALIENTEK ************************************************/ //UCOSIII中以下优先级用户程序不能使用,ALIENTEK //将这些优先级分配给了UCOSIII的5个系统内部任务 //优先级0:中断服务服务管理任务 OS_IntQTask() //优先级1:时钟节拍任务 OS_TickTask() //优先级2:定时任务 OS_TmrTask() //优先级OS_CFG_PRIO_MAX-2(倒数第二):统计任务 OS_StatTask() //优先级OS_CFG_PRIO_MAX-1(最后一个):空闲任务 OS_IdleTask() //技术支持:www.openedv.com //淘宝店铺:http://eboard.taobao.com //广州市星翼电子科技有限公司 //作者:正点原子 @ALIENTEK //任务优先级 #define START_TASK_PRIO 3 //任务堆栈大小 #define START_STK_SIZE 512 //任务控制块 用来保存任务的信息 OS_TCB StartTaskTCB; //任务堆栈 用来在切换任务和调用其他函数的时候保存现场,每个任务都应该有自己的堆栈 CPU_STK START_TASK_STK[START_STK_SIZE]; //任务函数 void start_task(void *p_arg); //任务优先级 #define LED0_TASK_PRIO 4 //任务堆栈大小 #define LED0_STK_SIZE 128 //任务控制块 OS_TCB Led0TaskTCB; //任务堆栈 CPU_STK LED0_TASK_STK[LED0_STK_SIZE]; void led0_task(void *p_arg); //任务优先级 #define LED1_TASK_PRIO 5 //任务堆栈大小 #define LED1_STK_SIZE 128 //任务控制块 OS_TCB Led1TaskTCB; //任务堆栈 CPU_STK LED1_TASK_STK[LED1_STK_SIZE]; //任务函数 void led1_task(void *p_arg); //任务优先级 #define FLOAT_TASK_PRIO 6 //任务堆栈大小 #define FLOAT_STK_SIZE 128 //任务控制块 OS_TCB FloatTaskTCB; //任务堆栈 __align(8) CPU_STK FLOAT_TASK_STK[FLOAT_STK_SIZE]; //任务函数 void float_task(void *p_arg); int main(void) { OS_ERR err; CPU_SR_ALLOC(); delay_init(); //延时初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置 uart_init(115200); //串口波特率设置 LED_Init(); //LED初始化 OSInit(&err); //*初始化UCOSIII OS_CRITICAL_ENTER();//*进入临界区 //*创建开始任务,使用OSTaskCreate函数创建任务必须让OS_CRITICAL_ENTER()进入临界区,任务创建完后OS_CRITICAL_ENTER()退出临界区 OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块 (CPU_CHAR * )"start task", //任务名字 (OS_TASK_PTR )start_task, //任务函数 (void * )0, //传递给任务函数的参数 (OS_PRIO )START_TASK_PRIO, //任务优先级 (CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址 (CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位,,通常为堆栈大小的1/10,用来检测堆栈是否为空 (CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小 (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度, (void * )0, //用户补充的存储区 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项 (OS_ERR * )&err); //存放该函数错误时的返回值 OS_CRITICAL_EXIT(); //*退出临界区 OSStart(&err); //*开启UCOSIII,使用OSStart()之前一定要至少创建一个任务,在调用OSSInit()函数初始化时已经创建一个空闲任务了 while(1); } //开始任务函数 void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //统计任务 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //进入临界区 //创建LED0任务 OSTaskCreate((OS_TCB * )&Led0TaskTCB, (CPU_CHAR * )"led0 task", (OS_TASK_PTR )led0_task, (void * )0, (OS_PRIO )LED0_TASK_PRIO, (CPU_STK * )&LED0_TASK_STK[0], (CPU_STK_SIZE)LED0_STK_SIZE/10, (CPU_STK_SIZE)LED0_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建LED1任务 OSTaskCreate((OS_TCB * )&Led1TaskTCB, (CPU_CHAR * )"led1 task", (OS_TASK_PTR )led1_task, (void * )0, (OS_PRIO )LED1_TASK_PRIO, (CPU_STK * )&LED1_TASK_STK[0], (CPU_STK_SIZE)LED1_STK_SIZE/10, (CPU_STK_SIZE)LED1_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建浮点测试任务 OSTaskCreate((OS_TCB * )&FloatTaskTCB, (CPU_CHAR * )"float test task", (OS_TASK_PTR )float_task, (void * )0, (OS_PRIO )FLOAT_TASK_PRIO, (CPU_STK * )&FLOAT_TASK_STK[0], (CPU_STK_SIZE)FLOAT_STK_SIZE/10, (CPU_STK_SIZE)FLOAT_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务 OS_CRITICAL_EXIT(); //进入临界区 } //led0任务函数 void led0_task(void *p_arg) { OS_ERR err; p_arg = p_arg; while(1) { LED0=0; OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延时200ms LED0=1; OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms } } //led1任务函数 void led1_task(void *p_arg) { OS_ERR err; p_arg = p_arg; while(1) { LED1=~LED1; OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms } } //浮点测试任务 void float_task(void *p_arg) { CPU_SR_ALLOC(); static float float_num=0.01; while(1) { float_num+=0.01f; OS_CRITICAL_ENTER(); //进入临界区 printf("float_num的值为: %.4frn",float_num); OS_CRITICAL_EXIT(); //退出临界区 delay_ms(500); //延时500ms } } 效果图:LED灯交替闪烁,串口显示数字 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1763 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1617 浏览 1 评论
1059 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
723 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1670 浏览 2 评论
1933浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
726浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
567浏览 3评论
592浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
550浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 16:03 , Processed in 2.300965 second(s), Total 75, Slave 59 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号