UCOS-III 系统移植

news2025/7/11 7:35:48

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 编译验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1899399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Intellj idea无法启动

个人电脑上安装的是2024.01版本的intellj idea作为开发工具&#xff0c;引入了javaagent作为工具包 但是在一次invaliad cache操作后&#xff0c;intellj idea就无法启动了&#xff0c;双击无响应。 重装了idea后也无效&#xff08;这个是有原因的&#xff0c;下面会讲&#…

java项目总结4

1.正则表达式 用于验证字符串是否满足自己所需要的规则。方法&#xff1a;matches 注意&#xff1a;\在Java中有特殊涵义&#xff0c;是将其它的意思本来化&#xff0c;假设"是用来引用字符串的&#xff0c;但是你如果想要输出它&#xff0c;那是不是就变成了System.out…

机器学习---线性回归

1、线性回归 例如&#xff1a;对于一个房子的价格&#xff0c;其影响因素有很多&#xff0c;例如房子的面积、房子的卧室数量、房子的卫生间数量等等都会影响房子的价格。这些影响因子不妨用 x i x_{i} xi​表示&#xff0c;那么房价 y y y可以用如下公式表示&#xff1a; y …

基于Qt实现的PDF阅读、编辑工具

记录一下实现pdf工具功能 语言&#xff1a;c、qt IDE&#xff1a;vs2017 环境&#xff1a;win10 一、功能演示&#xff1a; 二、功能介绍&#xff1a; 1.基于saribbon主体界面框架&#xff0c;该框架主要是为了实现类似word导航项 2.加载PDF放大缩小以及预览功能 3.pdf页面跳转…

01--SpringAI接入大模型,chatgpt,Java接入人工智能大模型

01–SpringAI接入大模型,chatgpt,Java接入人工智能大模型 文章目录 01--SpringAI接入大模型,chatgpt,Java接入人工智能大模型一、准备工作&#xff1f;①&#xff1a;环境准备 二、创建一个springAI项目①&#xff1a;创建一个根项目②&#xff1a;创建一个SpringAI模块01.解决…

Dos(命令符窗口)命令

目录 1. 常用Windows组合键 2. 常用DOS命令 3. 复制操作 4. 当前路径 5. 查看电脑ip地址 6. 切换盘符: 7. 目录 8. 自动补齐 8. 进入某路径&#xff1a;cd 路径 9. 直接进入某个位置 10. 新建文件 11. 查看文件内容 12. 关机 13. 强行终止命令的执行&#xff1a;C…

python conda查看源,修改源

查看源 conda config --show-sources 修改源 可以直接vim .condarc修改源&#xff0c;

查看java版本和安装位置-cnblog

查看java位置 进入设置&#xff0c;高级系统设置 打开环境变量 找到path双击 查看java版本 java -version

中电金信:加快企业 AI 平台升级,构建金融智能业务新引擎

在当今数字化时代的浪潮下&#xff0c;人工智能&#xff08;AI&#xff09;技术的蓬勃发展正为各行业带来前所未有的变革与创新契机。尤其是在金融领域&#xff0c;AI 模型的广泛应用已然成为提升竞争力、优化业务流程以及实现智能化转型的关键驱动力。然而&#xff0c;企业在积…

刷代码随想录有感(126):动态规划——不相交的线

题干&#xff1a; 代码&#xff1a; class Solution { public:int maxUncrossedLines(vector<int>& nums1, vector<int>& nums2) {vector<vector<int>>dp(nums1.size() 1, vector<int>(nums2.size() 1, 0));for(int i 1; i < num…

Github与本地仓库建立链接、Git命令(或使用Github桌面应用)

一、Git命令&#xff08;不嫌麻烦可以使用Github桌面应用&#xff09; git clone [] cd [] git branch -vv #查看本地对应远程的分支对应关系 git branch -a #查看本地和远程所有分支 git checkout -b [hongyuan] #以当前的本地分支作为基础新建一个【】分支,命名为h…

矢量绘图设计Sketch中文 Sketch直装安装包

Sketch是一款专为UI设计师和UX专家打造的矢量图形设计软件&#xff0c;以其简洁的界面、强大的功能和高效的协作能力而闻名。Sketch支持快速创建高质量的UI界面、图标、图形和插画&#xff0c;其矢量绘图工具让设计细节更加精准。同时&#xff0c;Sketch内置丰富的插件和组件库…

AI文字图片人脸生成原创视频文生图生肖生小程序开发

AI文字图片人脸生成原创视频文生图生肖生小程序开发 无限开 0.12生成 图生视频 AI技术在生成文字、图片、人脸以及视频方面已经取得了显著的进步。以下是一些可能包含在AI文字图片人脸生成原创视频小程序中的功能列表&#xff1a; 文字转视频&#xff1a; 输入文字或文章&…

使用flask的web网页部署介绍

使用flask的web网页部署介绍 文章目录 前言一、网页介绍二、数据库设计介绍总结 前言 flaskbootstrapjquerymysql搭建三叶青在线识别网站&#xff0c;使用nginxgunicorn将网站部署在腾讯云上&#xff0c;配置SSL证书。网站地址&#xff1a;https://www.whtuu.cn 三叶青图像识…

Open3D 在点云中构建八叉树

目录 一、概述 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2构建后点云 一、概述 八叉树&#xff08;Octree&#xff09;是一种树状数据结构&#xff0c;用于递归地将3D空间分割成较小的立方体。八叉树特别适用于3D计算机图形学、点云处理和空间…

uniapp实现可拖动悬浮按钮(最新版2024-7月)

此章主要介绍如何使用uniapp跨平台开发&#xff0c;实现悬浮按钮&#xff0c;移动端经常会有所这样的需求&#xff0c;那么功能如下&#xff1a; 1.圆圈悬浮球&#xff0c;上下左右靠边显示 2.可以界面任何拖动&#xff0c;不会超出界面 3.单击悬浮球的点击事件 效果&#xf…

Flash存储器解析:从原理到应用,全面了解其与缓存的区别

Flash存储器解析&#xff1a;从原理到应用&#xff0c;全面了解其与缓存的区别 Flash存储器是一种非易失性存储器技术&#xff0c;广泛应用于各种电子设备中&#xff0c;如USB闪存盘、固态硬盘&#xff08;SSD&#xff09;、智能手机、数码相机和嵌入式系统。它能够在断电情况下…

1-3 NLP为什么这么难做

1-3 NLP为什么这么难做 主目录点这里 字词结构的复杂性 中文以汉字为基础单位&#xff0c;一个词通常由一个或多个汉字组成&#xff0c;而不像英语词汇单元由字母构成。这使得中文分词&#xff08;切分句子为词语&#xff09;成为一个具有挑战性的任务。语言歧义性 中文中常…

day04-matplotlib入门

matplotlib Matplotlib 提供了一个套面向绘图对象编程的 API接口 是一款用于数据可视化的 Python 软件包&#xff0c;支持跨平台运行 它能够根据 NumPyndarray 数组来绘制 2D(3D) 图像&#xff0c;它使用简单、代码清晰易懂&#xff0c;深受广大技术爱好 者喜爱。 实列&…

Chapter11让画面动起来——Shader入门精要学习笔记

Chapter11让画面动起来 一、Unity Shader中的内置变量&#xff08;时间篇&#xff09;二、纹理动画1.序列帧动画2.滚动背景 三、顶点动画1.流动的河流2.广告牌3.注意事项①批处理问题②阴影投射问题 一、Unity Shader中的内置变量&#xff08;时间篇&#xff09; Unity Shader…