首页 > 其他分享 >UCOS-III 系统移植

UCOS-III 系统移植

时间:2024-07-07 22:59:20浏览次数:20  
标签:R0 R1 UCOS III LDR uC OS CPU 移植

1. 移植前准备

1.1 源码下载

UCOS-III Kernel Source   https://github.com/weston-embedded/uC-OS3.git

Micriμm CPU Source : https://github.com/weston-embedded/uC-CPU.git

Micriμm Lib Source: https://github.com/weston-embedded/uC-LIB.git 

1.2. 源码介绍

1.2.1 源码组织结构图

1.2.2 源码简介

1)应用层模块

2)BSP 与板子相关的BSP模块 (需要移植) 主要为系统时钟、时间戳相关API

3)µC-OS3/Source 内核源码 与CPU无关的模块

4)µC-OS3/Ports 与CPU相关的模块 (需要移植 )

5)uC-CPU 与特定平台CPU相关的模块(由uc-cpu提供)

6)uC-LIB 与CPU无关的库函数模块

7) µC-OS3/Cfg 配置头文件(需要配置的部分)

调用关系: UC/OS-III/Ports-->uC-CPU --> CPU_BSP

2. 移植配置列表

1)移植 uC-OS3 CPU 相关部分: os_cpu.h, os_cpu_a.asm,  os_cpu_c.c

2)移植 uC/CPU 相关部分: cpu_a.asm , cpu_c.c

3)移植板级支持包(BSP) 部分: bsp.c ,bsp.h

4)配置UC/OS-III 以下部分:

 µC/OS-III 功能配置 (os_cfg.h)

µC/OS-III 堆栈、系统任务和其他数据大小 (os_cfg_app.h)

µC/OS-III 数据类型 (os_type.h)

具体配置参考: http://t.csdnimg.cn/GNZcY

3. 移植 uC-OS3 CPU

3.1 找到MCU使用的CPU架构

以GD32F303为例,翻阅其手册,查找CPU对应的架构信息如下:

3.2 找到CPU架构对应的文件

        在uC-OS3/Ports目录下查找ARMv7-M,找到 ARMv7-M路径: ARM-Cortex-M/ARMv7-M

3.3 开发编译环境列表

ARM-Cortex-M/ARMv7-M 目录下有4个文件夹,分别对应不同的编译器

  • ARM: ARM公司提供的编译器,如Keil MDK开发环境。
  • CCS: TI的Code Composer Studio编译器。
  • GNU: GNU工具链(如GCC)
  • IAR: IAR 开发环境

3.4 使用Keil MDK编译器

uC-OS3/Template/bsp_os_dt.c , 有以下系统时钟相关接口需要移植:

BSP_OS_TickInit()     //初始化系统时钟滴答定时器     
BSP_OS_TickISR()      //系统时钟滴答中断服务程序

uC-OS3/Ports/Template目录里的os_cpu.h ,有以下上下文切换相关接口需要实现:   

void  OSCtxSw              (void);  // 任务级上下文切换,触发PendSV异常
void  OSIntCtxSw           (void);  // 中断上下文中进行任务切换,触发PendSV异常
void  OSStartHighRdy       (void);  // 启动最高优先级的就绪任务
void  OS_CPU_PendSVHandler (void);  // PendSV 异常处理程序,用切换当前任务的上下文到下一个准备就绪的任务 

查看MCU的CPU架构及所选开发环境对应的文件

uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c

uC-OS3/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm

已实现上述的所有接口,如果原厂没有实现的接口,则需要实现以上接口

3.4.1 BSP_OS_TickInit 接口实现

此函数接口用于初始化系统滴答定时器,设置操作系统时钟中断,该函数必须在 OSStart() 调用之后,并且在处理器初始化完成后调用。

优先级设置需要考虑系统中其他中断的优先级配置,确保实时操作系统的滴答计时器中断能够按期触发。

以下是伪代码描述:

void BSP_OS_TickInit(CPU_INT32U freq) {
    Install the interrupt vector for the timer used to generate tick interrupts; // 安装定时器中断向量
    Configure the timer to generate interrupts at 'freq' Hz; // 配置定时器以产生指定频率的中断
    Enable timer interrupts; // 启用定时器中断
}

以下是ARM-Cortex-M/ARMv7-M/os_cpu_c.c已实现的接口:

voidOS_CPU_SysTickInit(CPU_INT32U  cnts)
{

    CPU_INT32U  prio;
    CPU_INT32U  basepri;

    // 设置 BASEPRI 边界
    basepri = (CPU_INT32U)(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS));
    CPU_REG_SYST_RVR = cnts - 1u;  // 设置重载寄存器// 设置 SysTick 处理程序的优先级
    prio = CPU_REG_SCB_SHPRI3;
    prio &= 0x00FFFFFFu;
    prio |= (basepri << 24u);
    CPU_REG_SCB_SHPRI3 = prio;

    // 启用计时器
    CPU_REG_SYST_CSR |= CPU_REG_SYST_CSR_CLKSOURCE | CPU_REG_SYST_CSR_ENABLE;

    // 启用计时器中断
    CPU_REG_SYST_CSR |= CPU_REG_SYST_CSR_TICKINT;

}

3.4.2 BSP_OS_TickISR 接口实现

此接口函数用于处理系统时钟滴答(SysTick)中断

以下是该函数的伪代码描述:

BSP_OS_TickISR:
    OS_CTX_SAVE                ; 保存当前任务的上下文
    Disable Interrupts         ; 禁用中断
    OSIntNestingCtr++          ; 增加中断嵌套计数器
    if (OSIntNestingCtr == 1) {
        OSTCBCurPtr->StkPtr = SP ; 如果这是第一个中断,保存任务堆栈指针
    }
    Clear tick interrupt       ; 清除滴答中断标志
    OSTimeTick()               ; 调用OSTimeTick,通知发生了一个滴答
    OSIntExit()                ; 通知µC/OS-III中断处理结束
    OS_CTX_RESTORE             ; 恢复任务的上下文
    Return from Interrupt/Exception ; 返回到被中断的任务

以下是ARM-Cortex-M/ARMv7-M/os_cpu_c.c已实现的接口:

void OS_CPU_SysTickHandler(void)
{
    CPU_SR_ALLOC();
    CPU_CRITICAL_ENTER();
    OSIntEnter();  /* 通知uC/OS-III我们正在进入一个ISR */
    CPU_CRITICAL_EXIT();
    OSTimeTick();  /* 调用uC/OS-III的OSTimeTick() */
    OSIntExit();  /* 通知uC/OS-III我们正在离开ISR */
}

3.4.3 OSCtxSw 接口移植

该函数接口实现任务级上下文切换,以下是该函数的汇编实现伪代码:

                             ; (1) 通过软中断调用OSCtxSw
OSCtxSw:
    OS_CTX_SAVE              ; (2) 保存当前任务的CPU上下文
    LDR     R0, =OSTCBCurPtr
    LDR     R0, [R0]
    STR     SP, [R0]         ; (3) 将当前任务的堆栈指针保存到其TCB
    BL      OSTaskSwHook
    LDR     R0, =OSPrioHighRdy
    LDR     R0, [R0]
    STR     R0, =OSPrioCur
    LDR     R0, =OSTCBHighRdyPtr
    LDR     R0, [R0]
    LDR     SP, [R0]         ; (4) 从新任务的TCB中获取堆栈指针
    OS_CTX_RESTORE           ; (5) 恢复新任务的CPU上下文
    BX      LR               ; (6) 从中断返回,恢复PC和SR

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已实现的接口:

OSCtxSw
OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL      ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

3.4.4 OSIntCtxSw 接口移植

此函数用于在中断上下文中进行任务切换,以下为该函数的汇编实现伪代码:

在所有嵌套的ISR结束时由 OSIntExit() 调用
OSIntCtxSw:
    BL      OSTaskSwHook
    LDR     R0, =OSPrioHighRdy
    LDR     R0, [R0]
    STR     R0, =OSPrioCur
    LDR     R0, =OSTCBHighRdyPtr
    LDR     R0, [R0]
    LDR     SP, [R0]
    OS_CTX_RESTORE
    BX      LR

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已实现的接口:

OSCtxSw
OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL      ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]
    BX      LR

3.4.5 OSStartHighRdy 接口移植

此函数用于启动最高优先级的就绪任务,以下是该函数的汇编实现伪代码:

OSStartHighRdy:
    BL      OSTaskSwHook                                      ; 调用任务切换钩子函数
    LDR     R0, =OSTCBHighRdyPtr                              ; 获取最高优先级任务的TCB指针
    LDR     R0, [R0]
    LDR     SP, [R0]                                          ; (1) 获取最高优先级任务的堆栈指针
    OS_CTX_RESTORE                                            ; (2) 恢复新任务的CPU上下文
    BX      LR                                                ; (3) 从中断返回,恢复PC和SR

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已实现的接口:

OSStartHighRdy
    CPSID   I                                                   ; Prevent interruption during context switch
    MOV32   R0, NVIC_SYSPRI14                                   ; Set the PendSV exception priority
    MOV32   R1, NVIC_PENDSV_PRI
    STRB    R1, [R0]
    MOVS    R0, #0                                              ; Set the PSP to 0 for initial context switch call
    MSR     PSP, R0
    MOV32   R0, OS_CPU_ExceptStkBase                            ; Initialize the MSP to the OS_CPU_ExceptStkBase
    LDR     R1, [R0]
    MSR     MSP, R1
    BL      OSTaskSwHook                                        ; Call OSTaskSwHook() for FPU Push & Pop
    MOV32   R0, OSPrioCur                                       ; OSPrioCur   = OSPrioHighRdy;
    MOV32   R1, OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]
    MOV32   R0, OSTCBCurPtr                                     ; OSTCBCurPtr = OSTCBHighRdyPtr;
    MOV32   R1, OSTCBHighRdyPtr
    LDR     R2, [R1]
    STR     R2, [R0]
    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
    MSR     PSP, R0                                             ; Load PSP with new process SP
    MRS     R0, CONTROL
    ORR     R0, R0, #2
    BIC     R0, R0, #4                                          ; Clear FPCA bit to indicate FPU is not in use
    MSR     CONTROL, R0
    ISB                                                         ; Sync instruction stream
    LDMFD    SP!, {R4-R11, LR}                                  ; Restore r4-11, lr from new process stack
    LDMFD    SP!, {R0-R3}                                       ; Restore r0, r3
    LDMFD    SP!, {R12, LR}                                     ; Load R12 and LR
    LDMFD    SP!, {R1, R2}                                      ; Load PC and discard xPSR
    CPSIE    I
    BX       R1

3.4.6 OS_CPU_PendSVHandler 接口实现

此接口函数用于引发上下文切换,以下是该函数的实现步骤和详细代码

获取进程堆栈指针:将进程堆栈指针(PSP)保存到R0

保存剩余寄存器:将寄存器R4-R11和R14保存到进程堆栈

保存进程堆栈指针:将进程堆栈指针保存到当前任务的TCB中

调用OSTaskSwHook:执行任务切换钩子函数

更新当前任务和准备就绪任务:更新当前任务的优先级和TCB指针

获取新任务堆栈指针:从准备就绪任务的TCB中获取堆栈指针,并将其加载到PSP中

恢复寄存器:从新任务堆栈恢复寄存器R4-R11和R14

恢复上下文:从异常返回,恢复剩余上下文

以下是ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm已实现的接口:

OS_CPU_PendSVHandler:
    CPSID   I                               ; 禁止中断
    MOV32   R2, OS_KA_BASEPRI_Boundary      ; 设置BASEPRI优先级
    LDR     R1, [R2]
    MSR     BASEPRI, R1
    DSB
    ISB
    CPSIE   I
    MRS     R0, PSP                         ; 获取进程堆栈指针
    IF {FPU} != "SoftVFP"
        TST       R14, #0x10
        IT        EQ
        VSTMDBEQ  R0!, {S16-S31}            ; 如果任务使用FPU,保存高位FPU寄存器
    ENDIF
    STMFD   R0!, {R4-R11, R14}              ; 保存R4-R11和R14寄存器
    MOV32   R5, OSTCBCurPtr                 ; 保存当前任务的堆栈指针
    LDR     R1, [R5]
    STR     R0, [R1]
    MOV     R4, LR                          ; 保存LR寄存器值
    BL      OSTaskSwHook                    ; 调用任务切换钩子函数
    MOV32   R0, OSPrioCur                   ; 更新当前任务优先级
    MOV32   R1, OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]
    MOV32   R1, OSTCBHighRdyPtr             ; 更新当前任务的TCB指针
    LDR     R2, [R1]
    STR     R2, [R5]
    ORR     LR, R4, #0x04                   ; 确保异常返回使用进程堆栈
    LDR     R0, [R2]                        ; 获取新任务的堆栈指针
    LDMFD   R0!, {R4-R11, R14}              ; 恢复R4-R11和R14寄存器
    IF {FPU} != "SoftVFP"
        TST       R14, #0x10
        IT        EQ
        VLDMIAEQ  R0!, {S16-S31}            ; 恢复高位FPU寄存器
    ENDIF
    MSR     PSP, R0                         ; 加载新的进程堆栈指针
    MOV32   R2, #0                          ; 恢复BASEPRI优先级
    CPSID   I
    MSR     BASEPRI, R2
    DSB
    ISB
    CPSIE   I
    BX      LR                              ; 异常返回,将恢复剩余上下文
    ALIGN
    END

4. 移植 uC/CPU

uC-CPU/BSP/Template/bsp_cpu.c 有以下CPU时间戳相关接口需要实现:

CPU_TS_TmrInit()   //CPU 时间戳计时器初始化
CPU_TS_TmrRd()     //获取当前 CPU 时间戳计时器的计数值 
CPU_TS32_to_uSec() //将时间戳计数转换为微秒
如果启用了 CPU 时间戳或 CPU 中断禁用时间测量功能,必须实现这些接口

uC-CPU/Template/cpu_a.asm 有以下接口需要实现:

CPU_IntDis     ;禁用中断
CPU_IntEn      ;启用中断
CPU_SR_Save    ;保存CPU状态寄存器
CPU_SR_Restore ;恢复CPU状态寄存器
CPU_CntLeadZeros;计数前导零

uC-CPU/ARM-Cortex-M/ARMv7-M/ARM/cpu_a.asm 已实现上述接口

4.1 CPU_TS_TmrInit() 接口移植

该接口是CPU 时间戳计时器初始化函数 , 该计时器用于记录精确的时间戳或测量 CPU 禁用中断的时间。以下是基于GD32F303的实现代码:

void  CPU_TS_TmrInit (void)
{
    CPU_INT32U  fclk_freq;
    fclk_freq = BSP_CPU_ClkFreq();
    BSP_REG_DEM_CR     |= (CPU_INT32U)BSP_BIT_DEM_CR_TRCENA;    /* Enable Cortex-M4's DWT CYCCNT reg.                   */
    BSP_REG_DWT_CYCCNT  = (CPU_INT32U)0u;
    BSP_REG_DWT_CR     |= (CPU_INT32U)BSP_BIT_DWT_CR_CYCCNTENA;
    CPU_TS_TmrFreqSet((CPU_TS_TMR_FREQ)fclk_freq);
}

4.2 CPU_TS_TmrRd 接口移植

该 函数用于获取当前 CPU 时间戳计时器的计数值,以下是基于GD32F303的实现代码:

CPU_TS_TMR  CPU_TS_TmrRd (void)
{
    CPU_TS_TMR  ts_tmr_cnts;
    ts_tmr_cnts = (CPU_TS_TMR)BSP_REG_DWT_CYCCNT;
    return (ts_tmr_cnts);
}

4.3 CPU_TS32_to_uSec 接口移植

该函数用于将时间戳计数转换为微秒,以下是基于GD32F303的实现代码:

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);
}

5. 移植验证

5.1. 构建工程目录

├── app // 应用程序

├── bsp // 板级支持包,包含系统需要移植的接口及硬件相关库文件及接口

        └── gd32f30x

                ├── bsp.c //需要移植的接口

                ├── bsp.h

                ├── gd32f30x_it.c

                ├── gd32f30x_it.h

                ├── gd32f30x_libopt.h

                ├── Library

                ├── mdk-project

├── uC-CFG //把 uC-CPU 及uC-OS3 需要配置的文件集中到此文件夹

├── uC-CPU

├── uC-LIB

└── uC-OS3

5.2  构建Keil工程 

5.3 编译验证

标签:R0,R1,UCOS,III,LDR,uC,OS,CPU,移植
From: https://blog.csdn.net/sensorfeng/article/details/140220427

相关文章

  • QT移植到imx6ull ARM板子上面
    目录前言:1.资料准备:2.编译tslib库3.编译qt库源码4.配置arm板子qt和tslib环境5.qt安装和配置6.新建QT工程7.arm板子运行第一个qt程序8.关闭arm板子出厂gui程序前言:本文章是移植qt库到imx6ull上面能够运行,同时移植tslib库(触摸屏)到imx6ull上面,适用于大部分arm板......
  • 计算器III
    给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。你可以假设给定的表达式总是有效的。所有中间结果将在 [-231,231 -1] 的范围内。注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。 提示:1<=......
  • LeetCode 算法:路径总和 III c++
    原题链接......
  • OpenHarmony移植小型系统exynos4412(二)
    产品配置规则1、概述产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、部件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:vendor/{产品解决方案厂商}/{产品名称}_。产品解决方案的目录树规则如下:vendor└──company#产品解决方案厂......
  • FreeRTOS移植到STM32
    本内容主要是讲解关于如果把FreeRTOS移植到STM32中去的操作。明白各部分的作用以及打通思路,具体操作按照下列进行相应的操作。第一:早一个STM32的裸机程序我们这里用的是STM32F103的芯片为例。 二、去官网上下载FreeRTOSV9.0.0源码在移植之前,我们首先要获取到......
  • 在使用基于Pytorch的DeeplabV3+模型(Bubbliiiing)训练以及预测时遇到的问题
    原博:憨批的语义分割重制版9——Pytorch搭建自己的DeeplabV3+语义分割平台-CSDN博客github:https://github.com/bubbliiiing/deeplabv3-plus-pytorch最近在使用Bubbliiing的deeplabv3+模型对自己的数据集进行训练时,使用博主提供的json_to_dataset.py对labelme标注的数据进行......
  • 【STM32F1例程10】UCOSII系统实验
      那么这个实验,从项目的工程结构来看,其实稍微稍微有一丢丢,有一丢丢比之前几个实验复杂,但是还是老话,既然能读到这篇文章,证明能力还是得到认可的。实验简介  那么在STM32上进行uC/OS-II系统实验是一种常见的实践,可以帮助大家了解和应用实时操作系统(RTOS)在嵌入式系统开......
  • esp32-s3+GC9A01基于vs code+PlatformIO+ardunio框架+Squareline UI 移植
    文章目录前言一、SquarelineStudio是什么?二、使用步骤1.创建测试的UI2.工程导出3.工程移植总结前言本节描述了使用SquarelineStudio创建简单UI,导出文件后如何与LVGL集成并在PlatformIO环境中进行编译和下载过程。环境如下:platform=espressif32board=esp32-s......
  • UCOS-III 系统配置
    1.µC/OS-III功能配置(os_cfg.h)os_cfg.h用于确定应用程序所需的µC/OS-III功能,详细如下: 1.1杂项OS_CFG_APP_HOOKS_EN:启用/禁用应用程序特定的钩子。OS_CFG_ARG_CHK_EN:启用/禁用参数检查。OS_CFG_CALLED_FROM_ISR_CHK_EN:启用/禁用中断服务程序(ISR)检查。OS_CFG_DB......
  • 040【GD32F470】 灰度传感器移植成功示例
    【1TB嵌入式学习资料免费领取:https://link3.cc/sgzy】2.40灰度传感器2.40.1模块来源2.40.2规格参数工作电压:3.3V-5V工作电流:<20mA输出格式:模拟信号输出控制接口:ADC管脚数量:3Pin(2.54mm间距排针)2.40.3移植过程我们的目标是在梁山派GD32F470上能够判断当前环境......