双任务延时原理与空闲任务

NVIC_EnableIRQ(SysTick_IRQn) I'm using a Cortex-M3 LPC1548 from NXP with uVision IDE. In themain()function, if I use: SysTick_Config(SystemCoreClock * SYSTICK_INT_FREQ); NVIC_EnableIRQ(SysTick_IRQn); // <--- HardFault happens in this line. I got a HardFault exception every.. 阅读详情

1 双任务延时原理与空闲任务

1.1 设计目标

目标:提供一个任务延时接口,使得延时过程中可放弃CPU而转而运行其它任务,提高CPU利用率。
在这里插入图片描述

1.2 任务延时原理

在整个延时过程中,任务暂停运行,释放CPU的控制权给其它任务:

  • 开始时,启动定时器,暂停任务运行:
    在这里插入图片描述
  • 计时结束,关闭计时器,恢复任务运行。
    在这里插入图片描述
    任务数量不限,而硬件计时器资源数量非常有限,不得不采用“软计时器”,如下:
    在这里插入图片描述
    对于硬件定时器:
  • 使用SysTick,RTOS启动后立即启动。
  • 周期性的中断修改计时器计数值。
  • 中断处理需要时间,所以不能太过频繁,如10ms。

对于软计时器:

  • 递减计数。
  • 每个任务包含1个软计时器。

延时精度问题:

  • 由于使用“软计时器”,加之延时处理需要时间,所以延时精度有限,使用时需要注意场合。

在这里插入图片描述
空闲任务的引入:

  • 如果所有任务都进入延时状态,那么RTOS应该运行什么呢?我们可以设计一个空闲任务,可以简化RTOS的代码结构,可以在空闲任务中方便的添加自定义代码。

1.3 设计实现

为任务添加计时器:
在这里插入图片描述
添加空闲任务:
在这里插入图片描述
在时钟节拍中断中递减计时器,并调用tTaskSched()切换任务:
在这里插入图片描述
最后修改tTaskSched(),仅切换到delayTicks数为0的任务运行。

添加延时接口taskDelay():
在这里插入图片描述
核心代码如下:

/*************************************** Copyright (c)******************************************************
** File name            :   main.c
** Latest modified Date :   2016-06-01
** Latest Version       :   0.1
** Descriptions         :   主文件,包含应用代码
**
**--------------------------------------------------------------------------------------------------------
** Created by           :   01课堂 lishutong
** Created date         :   2016-06-01
** Version              :   1.0
** Descriptions         :   The original version
**
**--------------------------------------------------------------------------------------------------------
** Copyright            :   版权所有,禁止用于商业用途
** Author Blog          :   http://ilishutong.com
**********************************************************************************************************/
#include "tinyOS.h"
#include "ARMCM3.h"

// 当前任务:记录当前是哪个任务正在运行
tTask * currentTask;

// 下一个将即运行的任务:在进行任务切换前,先设置好该值,然后任务切换过程中会从中读取下一任务信息
tTask * nextTask;

// 空闲任务
tTask * idleTask;

// 所有任务的指针数组:简单起见,只使用两个任务
tTask * taskTable[2];

/**********************************************************************************************************
** Function name        :   tTaskInit
** Descriptions         :   初始化任务结构
** parameters           :   task        要初始化的任务结构
** parameters           :   entry       任务的入口函数
** parameters           :   param       传递给任务的运行参数
** Returned value       :   无
***********************************************************************************************************/
void tTaskInit (tTask * task, void (*entry)(void *), void *param, uint32_t * stack)
{
    // 为了简化代码,tinyOS无论是在启动时切换至第一个任务,还是在运行过程中在不同间任务切换
    // 所执行的操作都是先保存当前任务的运行环境参数(CPU寄存器值)的堆栈中(如果已经运行运行起来的话),然后再
    // 取出从下一个任务的堆栈中取出之前的运行环境参数,然后恢复到CPU寄存器
    // 对于切换至之前从没有运行过的任务,我们为它配置一个“虚假的”保存现场,然后使用该现场恢复。

    // 注意以下两点:
    // 1、不需要用到的寄存器,直接填了寄存器号,方便在IDE调试时查看效果;
    // 2、顺序不能变,要结合PendSV_Handler以及CPU对异常的处理流程来理解
    *(--stack) = (unsigned long)(1<<24);                // XPSR, 设置了Thumb模式,恢复到Thumb状态而非ARM状态运行
    *(--stack) = (unsigned long)entry;                  // 程序的入口地址
    *(--stack) = (unsigned long)0x14;                   // R14(LR), 任务不会通过return xxx结束自己,所以未用
    *(--stack) = (unsigned long)0x12;                   // R12, 未用
    *(--stack) = (unsigned long)0x3;                    // R3, 未用
    *(--stack) = (unsigned long)0x2;                    // R2, 未用
    *(--stack) = (unsigned long)0x1;                    // R1, 未用
    *(--stack) = (unsigned long)param;                  // R0 = param, 传给任务的入口函数
    *(--stack) = (unsigned long)0x11;                   // R11, 未用
    *(--stack) = (unsigned long)0x10;                   // R10, 未用
    *(--stack) = (unsigned long)0x9;                    // R9, 未用
    *(--stack) = (unsigned long)0x8;                    // R8, 未用
    *(--stack) = (unsigned long)0x7;                    // R7, 未用
    *(--stack) = (unsigned long)0x6;                    // R6, 未用
    *(--stack) = (unsigned long)0x5;                    // R5, 未用
    *(--stack) = (unsigned long)0x4;                    // R4, 未用

    task->stack = stack;                                // 保存最终的值
    task->delayTicks = 0;
}

/**********************************************************************************************************
** Function name        :   tTaskSched
** Descriptions         :   任务调度接口。tinyOS通过它来选择下一个具体的任务,然后切换至该任务运行。
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
void tTaskSched () 
{       
    // 空闲任务只有在所有其它任务都不是延时状态时才执行
    // 所以,我们先检查下当前任务是否是空闲任务
    if (currentTask == idleTask) 
    {
        // 如果是的话,那么去执行task1或者task2中的任意一个
        // 当然,如果某个任务还在延时状态,那么就不应该切换到他。
        // 如果所有任务都在延时,那么就继续运行空闲任务,不进行任何切换了
        if (taskTable[0]->delayTicks == 0) 
        {
            nextTask = taskTable[0];
        }           
        else if (taskTable[1]->delayTicks == 0) 
        {
            nextTask = taskTable[1];
        } else 
        {
            return;
        }
    } 
    else 
    {
        // 如果是task1或者task2的话,检查下另外一个任务
        // 如果另外的任务不在延时中,就切换到该任务
        // 否则,判断下当前任务是否应该进入延时状态,如果是的话,就切换到空闲任务。否则就不进行任何切换
        if (currentTask == taskTable[0]) 
        {
            if (taskTable[1]->delayTicks == 0) 
            {
                nextTask = taskTable[1];
            }
            else if (currentTask->delayTicks != 0) 
            {
                nextTask = idleTask;
            } 
            else 
            {
                return;
            }
        }
        else if (currentTask == taskTable[1]) 
        {
            if (taskTable[0]->delayTicks == 0) 
            {
                nextTask = taskTable[0];
            }
            else if (currentTask->delayTicks != 0) 
            {
                nextTask = idleTask;
            }
            else 
            {
                return;
            }
        }
    }
    
    tTaskSwitch();
}

/**********************************************************************************************************
** Function name        :   tTaskSystemTickHandler
** Descriptions         :   系统时钟节拍处理。
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
void tTaskSystemTickHandler () 
{
    // 检查所有任务的delayTicks数,如果不0的话,减1。
    int i;
    for (i = 0; i < 2; i++) 
    {
        if (taskTable[i]->delayTicks > 0)
        {
            taskTable[i]->delayTicks--;
        }
    }
    
    // 这个过程中可能有任务延时完毕(delayTicks = 0),进行一次调度。
    tTaskSched();
}

/**********************************************************************************************************
** Function name        :   tTaskDelay
** Descriptions         :   使当前任务进入延时状态。
** parameters           :   delay 延时多少个ticks
** Returned value       :   无
***********************************************************************************************************/
void tTaskDelay (uint32_t delay) {
    // 配置好当前要延时的ticks数
    currentTask->delayTicks = delay;

    // 然后进行任务切换,切换至另一个任务,或者空闲任务
    // delayTikcs会在时钟中断中自动减1.当减至0时,会切换回来继续运行。
    tTaskSched();
}

/*********************************************************************************************************
** 系统时钟节拍定时器System Tick配置
** 在我们目前的环境(模拟器)中,系统时钟节拍为12MHz
** 请务必按照本教程推荐配置,否则systemTick的值就会有变化,需要查看数据手册才了解
**********************************************************************************************************/
void tSetSysTickPeriod(uint32_t ms)
{
  SysTick->LOAD  = ms * SystemCoreClock / 1000 - 1; 
  NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
  SysTick->VAL   = 0;                           
  SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |
                   SysTick_CTRL_TICKINT_Msk   |
                   SysTick_CTRL_ENABLE_Msk; 
}

/**********************************************************************************************************
** Function name        :   SysTick_Handler
** Descriptions         :   SystemTick的中断处理函数。
** parameters           :   无
** Returned value       :   无
***********************************************************************************************************/
void SysTick_Handler () 
{
    tTaskSystemTickHandler();
}

/**********************************************************************************************************
** 应用示例
** 有两个任务,分别执行task1Entry和task2Entry。功能是分别对相应的变量进行周期性置0置1.
** 每个任务都可以占用一段时间的CPU,一旦用完了,就会被强制暂停,切换到另一个任务中去。
**********************************************************************************************************/
int task1Flag;
void task1Entry (void * param) 
{
    tSetSysTickPeriod(10);
    for (;;) 
    {
        task1Flag = 1;
        tTaskDelay(1);
        task1Flag = 0;
        tTaskDelay(1);
    }
}

int task2Flag;
void task2Entry (void * param) 
{
    for (;;) 
    {
        task2Flag = 1;
        tTaskDelay(1);
        task2Flag = 0;
        tTaskDelay(1);
    }
}

// 任务1和任务2的任务结构,以及用于堆栈空间
tTask tTask1;
tTask tTask2;
tTaskStack task1Env[1024];
tTaskStack task2Env[1024];

// 用于空闲任务的任务结构和堆栈空间
tTask tTaskIdle;
tTaskStack idleTaskEnv[1024];

void idleTaskEntry (void * param) {
    for (;;)
    {
        // 空闲任务什么都不做
    }
}

int main () 
{
    // 初始化任务1和任务2结构,传递运行的起始地址,想要给任意参数,以及运行堆栈空间
    tTaskInit(&tTask1, task1Entry, (void *)0x11111111, &task1Env[1024]);
    tTaskInit(&tTask2, task2Entry, (void *)0x22222222, &task2Env[1024]);
    
    // 接着,将任务加入到任务表中
    taskTable[0] = &tTask1;
    taskTable[1] = &tTask2;

    // 创建空闲任务
    tTaskInit(&tTaskIdle, idleTaskEntry, (void *)0, &idleTaskEnv[1024]);
    idleTask = &tTaskIdle;
    
    // 我们期望先运行tTask1, 也就是void task1Entry (void * param) 
    nextTask = taskTable[0];

    // 切换到nextTask, 这个函数永远不会返回
    tTaskRunFirst();
    return 0;
}


参考资料:

  1. 【李述铜】从0到1自己动手写嵌入式操作系统
RTOS任务切换原理与实践:从TCB到PendSV的嵌入式多任务实现 在嵌入式系统开发中,实时操作系统(RTOS)是实现多任务并发的核心技术,它解决了传统超级循环模式在复杂应用中的响应瓶颈。RTOS通过任务定义与切换机制,允许多个任务看似同时运行,其核心原理在于任务控制块(TCB)的管理与上下文切换。TCB作为任务的身份证,存储了栈指针、优先级等关键信息,而上下文切换则依赖于处理器架构的异常机制,如在Cortex-M中利用PendSV中断实现现场保存与恢复。这一机制的技术价值在于提升了系统的实时性与资源利用率,广泛应用于物联网设备、工业控制等场景。本文以任务定义与切换为切入点 阅读详情

相关推荐

自己动手从0到1写嵌入式操作系统-李述铜-专题视频课程

这不是rtos源码分析的课程,而是为初级的同学设计,从基础原理讲师,一步步不断迭代设计rtos的课程! 用不到【2000行代码,汇编代码仅18行】(不含注释)实现一个精巧的可以运行在ARM Cortex-M内核芯片上的RTOS! 该RTOS功能与ucos类似,具体实现不同。学习之后,再去学习ucos之类的系统将没有什么问题。...

李述铜的笔记 4971

【C#】51. Await 处理并行任务(WhenAll)以及Task.Delay()

这篇文章主要说明两个问题:1、await如何替代ContinueWith来处理WhenAll之类的并行多任务;2、Task.Delay()的原理。 async static Task GetInfoAsync(string name, int seconds) { await Task.Delay(TimeSpan.FromSeconds(seconds)); //await Task.Run(

huiwuhuiwu的专栏 9026

TinyOs系统---第2章 基本任务切换实现

TinyOs系统---第2章 基本任务切换实现

weixin_42162924的博客 388

1277_FreeRTOS中vTaskDelay的实现分析

全部学习汇总: https://github.com/GreyZhang/g_FreeRTOS之前用FreeRTOS的时候,感觉很方便的一点就是vTaskDelay()接口提供了一个非阻塞的延时。这样,就很容易把一些等待或者延时的时间解放出来去做一些更有价值的事情。当时我对这个接口的认识就是这个接口会触发一次任务调度,但是我并没有去做深入的分析甚至去看相应的接口说明。因为这样的观念是从ucos ii的时候就建立了的。不过,说真的,我对ucos的理解也并不深。前一段时间,项目中使用了一个封闭的RTOS。为了能

小灰笔记 2335

FreeRTOS源码下载与STM32移植:从官网下载到任务切换源码阅读

在嵌入式开发中,实时操作系统(RTOS)是提升多任务处理效率的关键技术,而FreeRTOS作为一款开源、轻量级的内核,凭借稳定的调度机制和丰富的生态,成为STM32等MCU平台的主流选择。其核心原理是通过优先级抢占和时间片轮转实现任务切换,由内核管理任务状态、队列和内存。理解这一机制,有助于开发者构建可靠的多任务应用。在实际工程中,从官网正确获取FreeRTOS源码包、理解目录结构、定制FreeRTOSConfig.h并完成基础移植,是入门的第一步。进一步深入任务切换流程、堆栈溢出检测机制,能有效避免运行时

weixin_30313409的博客 238

esp32c6 开发实战:低功耗蓝牙(BLE)开发

蓝牙栈在此程序流程中已经启动并运行,但是应用程序的功能尚未定义。功能的定义是通过响应事件来实现的,当其他设备尝试读取或写入参数以及建立连接时就会触发事件回调函数处理。BT控制器在控制器端实现主机控制器接口(HCI),链路层(LL)和物理层(PHY)。BT控制器对用户应用程序不可见,并处理BLE堆栈的较低层。蓝牙堆栈(Bluedroid stack)定义了经典蓝牙(BT Classic)和低功耗蓝牙(BLE)的通用定义和API。的判断)等对于启动低功耗蓝牙来说不重要的代码,函数初始化和启用BT控制器。

月入鱼饵的博客 2742

同优先级时间片运行

文章目录1 同优先级时间片运行1.1 设计目标1.2 设计原理1.3 设计实现 1 同优先级时间片运行 1.1 设计目标 构建一个允许多任务具备相同优先级,且同优先级任务按时间片占用CPU运行的系统。 1.2 设计原理 当前设计:每个优先级只允许一个任务。 新的设计: 1.3 设计实现 配置优先级列表: 任务链接结点: 修改获取最高优先级任务的方式: 时钟节拍处理:增加时间片轮转。 ...

木子皿--啥都不会的菜鸟 688

更换光猫的原理与方法

当你给装维打电话说你需要更换光猫时,对于装维来说,他并不需要知道怎么更换,他只需要生成一张工单,由后台进行业务操作后,在去用户家把新光猫给装好即可,此时装维到底起到了什么作用呢?我想可能只是运输员吧,把一个设备从一个地方运到另一个地方罢了,此时并不能指望装维做什么,因为本质上来说装维的能力真的很差很差,我是不知道那些装维哪来的勇气做视频,还说自己什么什么能力很强?很强吗?吹牛的技术确实很强。 更换光猫之前,需要先明白为什么要更换光猫,怎么更换光猫,更换后不能用怎么办?怎么才能更换成功,换光猫以后被限速了怎么

qq_34146290的博客 1万+

gd32的SysTick_IRQn 中断开启,报warning

而 SysTick_IRQn 的宏是-1. 所以会报warning。最终解决办法:还是会报警,不过 中断可以正常进入。

weixin_46131386的博客 1161

【雷达通信】雷达信号处理仿真【含Matlab源码 2509期】

雷达信号处理仿真 完整的代码,方可运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 904

李宏毅2025《机器学习》第一讲-生成式AI:技术突破和未来发展

本文基于台湾大学李宏毅教授的“一堂课搞懂生成式人工智慧的技术突破与未来发展”课程内容,系统性地梳理了生成式AI的核心概念、技术原理、发展演进以及未来趋势。文章从AI的“行为”入手,通过生动的实例展示了其强大的生成与推理能力;进而深入剖析其底层运作机制,阐释了“万物皆为令牌(Token)”、自回归生成、Transformer架构等核心原理;接着,文章追溯了通用AI模型从“专才”到“通才”的演进历程;最后,探讨了如何通过微调(Fine-tuning)、模型编辑(Model Editing)等技术赋予AI新的能力

木鱼时刻的专栏 2295

ucos学习笔记---003双任务延时原理与空闲任务

双任务延时原理与空闲任务 设计目标:提供一个任务延时接口,使得延时过程中可放弃CPU转而运行其他任务,提高CPU运行效率 任务延时原理:任务数量不限,而硬件计数器资源数量非常有限,不得不采用“软件计时器” 延时精度问题:精度有限 void tTaskSched() { if(currentTask == idleTask) { if(taskTable[0]->delayT...

qq_39353165的博客 281

刷机维修进阶教程-----adb禁用错了系统app导致无法开机 如何保数据无损恢复机型

在刷机维修过程中 。我们会遇到一些由于客户使用adb指令来禁用手机app而导致手机无法开机进入系统的故障机型。通常此类问题机型有好几种解决方法。但如果客户需要保数据来恢复机型。其实操作也是很简单的.还有类似误删除应用导致不开机等等如何保数据。  通过博文了解💝💝💝    1💝💝💝----adb禁用或者删除系统app导致无法开机的几种解决方法 2💝💝💝----如何保数据来无损恢复机型 3💝💝💝----其他保数据解决系统类故障无法开机的步骤解析

小马哥的专栏 1352

自己动手写从0到1写嵌入式操作系统 源代码学习笔记<3>

本文主要介绍了嵌入式操作系统中双时间片运行原理和双任务延时原理。首先,SysTick定时器作为系统滴答定时器,用于定期产生中断,其配置涉及LOAD、VAL、CTRL等寄存器,用于设置中断间隔和使能定时器。其次,SystemInit函数中的条件编译代码用于处理未对齐内存访问的异常。在任务管理方面,空闲任务在所有其他任务阻塞时运行,主要用于防止CPU空转和统计任务负荷。空闲任务钩子函数可用于执行低优先级功能、测试系统处理裕量和配置低功耗模式,但需遵守不阻塞和快速返回的规则,以确保系统资源的有效回收。

flyflyfly12345的博客 698

【IPC】ONVIF Device Manager 测试工具

介绍onvif 协议测试工具

以实战经验介绍行业知识 1961

三维空间刚体运动4-3:四元数线性插值方法:Squad

摘要:四元数插值三个方法Slerp、Squad和Spring既复杂又很重要,为了详细阐述,故每个方法独立成一篇博文讲解,没有插值的四元数是没有灵魂的,插值的重要性不言而喻。Slerp是经典的两点间一阶连续可导插值方法,Squad方法在Slerp的基础上实现多点间的一阶连续可导,而Spring则可以实现多点间的二阶连续可导,更适合复杂的曲线,此系列博文也是国内首篇介绍Spring的中文资料。

shao918516的博客 9217

手写RTOS嵌入式操作系统(2)

时间片轮转,共享资源保护

weixin_44923666的博客 621

【深度学习基础】一篇弄懂训练集、验证集和测试集(呕心沥血版)

在深度学习中,训练集、验证集和测试集是构建和评估模型的核心组成部分。训练集用于模型的学习和参数优化,验证集帮助调整超参数和防止过拟合,而测试集则用于最终评估模型的泛化性能。正确划分和使用这三类数据集,对于开发高效、可靠的深度学习模型至关重要。本文将深入解析它们的作用、划分方法以及在实际应用中的注意事项,帮助你全面理解并掌握数据集的科学使用方法,从而提升模型的实际表现。

十二月的猫 3792

FreeRTOS学习(三)——任务状态和调度器运行过程

启动FreeRTOS任务调度器。任务调度器的作用是判断当前有哪些任务可以运行,并从中选择一个任务交给CPU执行。当调度器启动后,task1和task2进入FreeRTOS的任务调度过程。调度器会根据任务的优先级和当前状态,决定CPU接下来执行哪个任务。这一节学习了FreeRTOS任务的四种基本状态:运行态表示任务正在占用CPU;就绪态表示任务已经可以运行,正在等待CPU;阻塞态表示任务正在等待延时或者某个事件;挂起态表示任务被人为暂停。在LED点灯程序中,任务执行。

hsjiasb的博客 451

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

FreeRTOS任务状态详解:运行、就绪、阻塞、挂起与删除

在嵌入式实时系统中,任务状态是操作系统实现并发调度的核心抽象。它源于对时间片、资源竞争和事件驱动等基础概念的建模,通过运行态(Running)、就绪态(Ready)、阻塞态(Blocked)、挂起态(Suspended)和删除态(Deleted)五种状态,精准刻画任务在CPU占用、内存驻留及内核干预层面的行为特征。这种状态机设计不仅支撑了上下文切换与优先级调度等关键机制,更赋予开发者解耦逻辑与时序的能力——例如用vTaskDelay()替代轮询,以阻塞态实现精确延时;或借助就绪列表O(1)查找保障高实时性。

cuda7parallel的博客 947

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

从裸机到FreeRTOS:嵌入式任务调度与移植实战指南

嵌入式开发中,裸机程序随着代码规模膨胀,前后台系统的串行执行模式逐渐暴露实时性差、CPU空转、模块耦合严重等问题。实时操作系统(RTOS)通过任务调度器将大循环拆分为独立小循环,利用优先级抢占和时间片轮转机制合理分配CPU资源,从根本上重构程序执行模型。FreeRTOS作为轻量级开源RTOS,以任务状态机、队列通信、信号量互斥等核心机制,帮助开发者构建高可靠、可维护的嵌入式软件架构。本文从任务调度原理出发,结合STM32平台的最小系统移植实战,讲解任务创建、调度器启动、常见坑点及任务间通信技巧,为从裸机迁移

weixin_30896825的博客 439

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

FreeRTOS嵌入式实时操作系统入门:从多任务管理到实战应用

实时操作系统(RTOS)是嵌入式开发中实现多任务管理的核心技术,它通过任务调度器在单核MCU上模拟并行处理,确保系统对外部事件的响应具有确定性。其核心原理基于任务状态机(运行态、就绪态、阻塞态、挂起态)和优先级调度机制,通过抢占式或时间片轮转策略分配CPU时间。在物联网和工业控制等场景中,RTOS的技术价值在于提升系统响应可靠性、简化复杂逻辑设计。FreeRTOS作为一款开源、可裁剪的RTOS,提供了任务、队列、信号量等内核对象,便于实现任务间通信与同步。本文以STM32平台为例,详解FreeRTOS的环境

weixin_34174105的博客 392

深度剖析Arduino IDE中ESP32开发的FreeRTOS任务调度机制

剖析Arduino IDE下esp32开发中FreeRTOS的任务调度机制,揭示多任务并行处理的底层逻辑与实际应用技巧,帮助开发者更好地掌握esp32开发中的实时性控制与资源分配。

weixin_32102617的博客 320

RTOS任务调度核心机制:从PendSV异常到优先级就绪列表详解

实时操作系统(RTOS)是现代嵌入式系统实现多任务并发与实时响应的核心技术。其核心原理在于任务调度机制,通过调度器(Scheduler)作为中央决策单元,基于优先级和就绪状态动态分配CPU时间片,从而在单核处理器上模拟出多任务并行执行的假象。这一机制的技术价值在于显著提升了复杂嵌入式系统的模块化程度、可维护性及实时响应能力,广泛应用于物联网设备、工业控制、消费电子等领域。具体实现依赖于硬件底层支持,例如在Cortex-M内核中,通过PendSV(可挂起的系统调用)这一低优先级异常来实现“延迟”的上下文切换,

weixin_34221276的博客 376

ClimateGuard CG-Anem传感器I²C驱动设计与嵌入式集成

I²C传感器驱动是嵌入式系统中实现高可靠性外设通信的关键技术,其核心在于协议适配、时序容错与资源约束优化。针对无寄存器映射、命令-响应式交互的特殊I²C设备(如热式风速风温传感器),需摒弃传统寄存器读写范式,转而构建基于状态机与CRC校验的纯事务型驱动架构。此类设计显著提升在FreeRTOS等实时环境下的确定性,并支持STOP低功耗唤醒、DMA零拷贝等工业级特性。本文以ClimateGuard CG-Anem为例,详解恒温差(CTA)原理传感器的I²C协议解析、静态内存驱动实现及多传感器总线仲裁方案,覆盖S

weixin_26907223的博客 575
上一篇: 算法的复杂度分析
下一篇: 软件开发流程简介
SlowIsFastLemon
博客等级 码龄8年 265粉丝 790原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值