TrueStudio开发环境下移植UCOSII(stm32f103c8t6)
记录该篇文章的原因在于,在使用“正点原子”的“UCOSII移植”示例程序时,发现将UCOSII直接复制进Truestudio目录下其汇编文件(os_cpu_a.asm)报错。其原因为keil与Truestdio所使用编译器不同而导致,找到适合Trestdio编译器所适用的汇编文件替换即可。
一、相关资料准备
①、先去Micrium官网下载UCOSII的源程序文件(下载方式可见文末“参考链接”)
百度网盘分享资料:
链接:https://pan.baidu.com/s/1_4C-08hOOjnpiNgMZ5SgWQ
提取码:9jvu
二、在工程目录下新建UCOSII文件夹,并在目录下新建CONFIG、CORE、PORT等三个文件夹
三、将 uCOS-II移植准备目录\Micrium_uC-Eval-STM32F107_uCOS-II\Software\uCOS-II\Source 路径下所有文件复制到CORE目录下;
四、将 uCOS-II移植准备目录\Micrium_uC-Eval-STM32F107_uCOS-II\Software\uCOS-II\Ports\ARM-Cortex-M3\Generic\GNU 路径下所以文件复制到PORT目录下
五、参考了正点原子 ”UCOSII移植“,复制”includes.h“ 、”os_cfg.h“ 到 CONFIG 目录下
六、将UCOSII.h下的头文件进行修改
七、编译无报错,即移植成功;
八、编写时基(滴答时钟)
#include "LibFunDefine.h"
//SysTick
#define SYSTEM_SUPPORT_OS 1 //定义系统文件夹是否支持UCOS
#define SysTickdelay_osrunning OSRunning //OS是否运行标记,0,不运行;1,在运行
#define SysTickdelay_ostickspersec OS_TICKS_PER_SEC //OS时钟节拍,即每秒调度次数
#define SysTickdelay_osintnesting OSIntNesting //中断嵌套级别,即中断嵌套次数
static u8 fac_us=0; //us延时倍乘数 static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数 /* * 函数名称:SysTickDelay_Osschedlock * 函数功能:微妙级延时时,关闭任务调度 * 输入参数:无 * 输出参数:无 * */ void SysTickDelay_Osschedlock(void) { OSSchedLock(); } /* * 函数名称:SysTickDelay_OsschedUnlock * 函数功能:微妙级延时时,恢复任务调度 * 输入参数:无 * 输出参数:无 * */ void SysTickDelay_OsschedUnlock(void) { OSSchedUnlock(); } /* * 函数名称:SysTickDelay_OsTimeDly * 函数功能:调用OS自带的延时函数 * 输入参数:ticks 延时节拍数 * 输出参数:无 * */ void SysTickDelay_OsTimeDly(uint32_t ticks) { OSTimeDly(ticks); } /* * 函数名称:LibDelayInit * 函数功能:滴答时钟初始化 * 输入参数: * 输出参数: * */ void LibSysTickDelayInit(void) { #if SYSTEM_SUPPORT_OS //如果需要支持OS. u32 reload; #endif SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8 fac_us = SystemCoreClock / 8000000; //为系统时钟的1/8 #if SYSTEM_SUPPORT_OS //如果需要支持OS. reload = SystemCoreClock / 8000000; //每秒钟的计数次数 单位为K reload *= 1000000 / SysTickdelay_ostickspersec;//根据delay_ostickspersec设定溢出时间 //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右 fac_ms = 1000 / SysTickdelay_ostickspersec; //代表OS可以延时的最少单位 SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; //开启SYSTICK中断 SysTick->LOAD = reload; //每1/delay_ostickspersec秒中断一次 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //开启SYSTICK #else fac_ms = (u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数 #endif } #if SYSTEM_SUPPORT_OS //如果需要支持OS. /* * 函数名称:LibSysTickDelayms * 函数功能:带OS毫秒延时 * 输入参数: * 输出参数: * */ void LibSysTickDelayms(uint16_t ms) { if(SysTickdelay_osrunning && SysTickdelay_osintnesting==0) //如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度) { if(ms >= fac_ms) //延时的时间大于OS的最少时间周期 { SysTickDelay_OsTimeDly(ms / fac_ms); //OS延时 } ms %= fac_ms; //OS已经无法提供这么小的延时了,采用普通方式延时 } LibSysTickDelayus((u32)(ms*1000)); //普通方式延时 } /* * 函数名称:LibSysTickDelayus * 函数功能:带OS为微妙延时 * 输入参数: * 输出参数: * */ void LibSysTickDelayus(uint32_t us) { u32 ticks; u32 told,tnow,tcnt = 0; u32 reload = SysTick->LOAD; //LOAD的值 ticks = us*fac_us; //需要的节拍数 tcnt = 0; SysTickDelay_Osschedlock(); //阻止OS调度,防止打断us延时 told = SysTick->VAL; //刚进入时的计数器值 while(1) { tnow = SysTick->VAL; if(tnow != told) { if(tnow < told)tcnt += told - tnow; //这里注意一下SYSTICK是一个递减的计数器就可以了. else tcnt += reload-tnow + told; told = tnow; if(tcnt >= ticks)break; //时间超过/等于要延迟的时间,则退出. } }; SysTickDelay_OsschedUnlock(); //恢复OS调度 } #else /* * 函数名称:LibSysTickDelayms * 函数功能:毫秒延时 * 输入参数: * 输出参数: * */ void LibSysTickDelayms(uint16_t ms) { u32 temp; SysTick->LOAD=(u32)ms*fac_ms; //时间加载(SysTick->LOAD为24bit) SysTick->VAL =0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while ((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } /* * 函数名称:LibSysTickDelayus * 函数功能:为微妙延时 * 输入参数: * 输出参数: * */ void LibSysTickDelayus(uint32_t us) { u32 temp; SysTick->LOAD=us*fac_us; //时间加载 SysTick->VAL=0x00; //清空计数器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数 do { temp=SysTick->CTRL; }while ((temp&0x01)&&!(temp&(1<<16))); //等待时间到达 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } #endif /* * 函数名称:SysTick_Handler * 函数功能:滴答时钟中断 * 输入参数: * 输出参数: * */ void SysTick_Handler(void) { if(SysTickdelay_osrunning == 1) //OS开始跑了,才执行正常的调度处理 { OSIntEnter(); //进入中断 OSTimeTick(); //调用ucos的时钟服务程序 OSIntExit(); //触发任务切换软中断 } }
八、程序编写完成后,发现UCOSII在运行到OSStart() - > OSStartHighRdy()时执行不下去
解决方法:
①、屏蔽stm32f1xx_it.c下的PendSV_Handler;
②、将os_cpu_a.asm下的OS_CPU_PendSVHandler修改为PendSV_Handler,
参考:
https://blog.csdn.net/qq_29344757/article/details/77096149
https://www.cnblogs.com/myguaiguai/p/12454642.html
本文来自博客园,作者:伽椰子真可爱,转载请注明原文链接:https://www.cnblogs.com/jiayezi/p/17210272.html