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://blog.csdn.net/qq_23898287/article/details/79363010?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-79363010-blog-105673775.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-79363010-blog-105673775.pc_relevant_default&utm_relevant_index=1

 

posted @ 2023-03-13 09:38  伽椰子真可爱  阅读(195)  评论(0编辑  收藏  举报