- 博客(104)
- 收藏
- 关注
原创 嵌入式学习笔记 - C语言访问地址的方式,以及指针的进一步理解
/将结构体变量的地址赋值给指针,结构体的名字不能作为地址,需使用&符号。如果不使用类型转换,自增的步长会默认为指针变量的类型大小,因为定义指针的时候肯定要定义类型。//将数组a的地址赋值给指针,数组名可以代表地址,或者p=&a[0];嵌入式系统中对一个具体内存地址的访问,通常需要使用指针(指针变量)的方式进行。如果你强制类型转换的对象是一个地址,那么必须使用的方式,以上语句是c语言中定义一个指针(指针变量)的方式。这种直接给指针赋绝对地址值的写法是合法的语法,//将变量a的地址赋值给指针。
2025-06-11 19:58:44
277
原创 嵌入式学习笔记 - C语言中结构体的定义,以及结构体变量的内存空间的分配
定义结构体:在C语言中,通过struct关键字定义结构体。char name;int age;这个定义只是声明了一个名为Student的结构体类型,并没有分配内存空间。通常所说的结构体是指结构体类型。结构体变量才是真正的结构体。分配内存:创建结构体变量时,系统会为其分配内存空间。// 分配内存空间给stu1此时,stu1占用的内存空间包括name数组和age变量所需的空间。
2025-06-11 19:17:27
153
转载 从keil官网下载DFP(芯片支持包)的方法
Database 的意思是数据库,资料库,Device Database就是设备资料库。DFP的意思是Devices Family Packs 设备系列包。5.选择我们使用的芯片(我这里使用的是STM32L051系列)3.选择MDK-ARM会进入到MDK下载页面。2.点击右上角的下载按钮,进入下一页面。4.选择左下角的芯片列表按钮(7.在右上角选择下载DFP文件。这里我们不用下载MDK。6.然后选择DFP(
2025-06-10 14:33:26
7
原创 嵌入式学习笔记 - freeRTOS为什么中断中不能使用互斥量
如上图,任务①,②,③优先级依次升高,任务①与任务③共用一个信号量资源,入过某一时刻任务①拥有了这个共享资源,任务③要处于阻塞状态等待任务①,假设此时不需要共享资源的任务②时间到了,则会打断任务①,那么任务①的释放信号量的时间将会更长,那么高优先级的任务③就很长时间得不到执行,这显然不符合优先级机制。任务③会将任务①的优先级提升到任务③一样的值,那么任务①会一直运行不会被中间级别优先级的任务打断,这就大大缩短了任务①释放共享资源的时间,如下图。关键就在发起人,就是提升优先级的那个时刻是谁要求的。
2025-06-08 12:01:30
278
原创 freeRTOS 互斥量优先级继承机制函数实现xQueueGenericReceive()
以下为函数接收互斥量,互斥量不为空(未被别的任务持有),去除互斥量,并且将互斥量的持有者付志伟当前任务,紫色字体函数peeked. *//*lint!else。
2025-06-07 20:55:52
691
原创 嵌入式学习笔记 - freeRTOS vTaskPlaceOnEventList()函数解析
/将当前任务的事件属性插入消息队列等待插入链表。//将当前任务的状态属性部分插入延时链表。函数第一个参数为消息队列等待插入链表,这种设计实现了事件与状态管理的分离。也就是说一个任务有两个属性,就绪列表,延时列表,挂起列表。另一个是事件属性,可能位于。一个是状态属性,可能位于。
2025-06-07 13:00:00
433
原创 嵌入式学习笔记 - freeRTOS xTaskResumeAll( )函数解析
如果configUSE_PREEMPTION 定义为 0,就不进行任务切换同时xAlreadyYielded也不赋值为1,就是记录为没切换过,可能是因为这种情况下taskYIELD_IF_USING_PREEMPTION()未定义(如下图所示),默认为taskYIELD_IF_USING_PREEMPTION()不起作用,所以不对xAlreadyYielded。// 返回是否切换过的标志,如果未切换过,出去后是一定要切换的,因为将当前任务加到等待插入列表,以及延时列表之后,是一定要切换任务的。
2025-06-07 12:13:46
979
转载 freeRTOS 函数xTaskCheckForTimeOut解析
否则,如果`xElapsedTime < *pxTicksToWait`:(如果`xConstTickCount < pxTimeOut->xTimeOnEntering`,那么`xElapsedTime`必定会大于`*pxTicksToWait`,所以不会选择这条分支)(仅开启vTaskSuspend)如果等待时限为无限时长(`*pxTicksToWait == portMAX_DELAY`),则应该返回`pdFALSE`(`xReturn = pdFALSE`)。
2025-06-07 10:03:14
15
原创 嵌入式学习笔记 - FreeRTOS 信号量以及释放函数
二值信号量:主要用于任务同步和互斥访问。它只有两个状态:信号量被占用(0)和信号量未被占用(1)。二值信号量没有优先级继承机制,适用于同步任务或中断12。互斥量:也称为互斥信号量,主要用于互斥访问共享资源。互斥量的初始值为1,表示资源可用。互斥量具有优先级继承机制,适用于需要保护共享资源的场景,确保同一时间只有一个任务可以访问该资源45。
2025-06-06 23:17:27
477
原创 嵌入式学习笔记-freeRTOS taskENTER_CRITICAL(_FROM_ISR)跟taskEXIT_CRITICAL(_FROM_ISR)函数解析
第①处按照系统设定的configMAX_SYSCALL_INTERRUPT_PRIORITY值对中断进行屏蔽第②处调用一次自增一次第③处检查中断状态寄存器位,如果有任何中断位置1,说明是在中断中,那么报错,因为此函数不允许中断中使用。第①处如果前面有过一次以上调用taskENTER_CRITICAL,那么仍然禁止中断configMAX_SYSCALL_INTERRUPT_PRIORITY值以上的中断都不能开启,直到最后一次退出才真正退出,
2025-06-06 23:16:02
1185
原创 嵌入式学习笔记- freeRTOS 带FromISR后缀的函数
因为中断中等待的,一般都是任务给予的,比如消息队列,信号量,而isr中断运行优先级又高于任何任务,要尽早结束中断让系统任务运行起来才有可能尽可能快的得到想要的消息,不然任务中断都会很被动的运行甚至拖死,任务得不到运行发不出消息,中断得不到消息。其实没有必须,只是因为合适,中断中不可能进行任务切换,放在中间也可以但是也不会立即切换,放在末尾能够确保中断尽快完整的运行结束,确保对信号量消息队列的关键操作全部完成再判断是否进行切换,比较符合逻辑,可能造成上下文混乱,这个只是猜测,这个问题有答案的欢迎留言。
2025-06-06 14:04:58
159
原创 freeRTOS xQueueGenericSend以及xQueueGenericReceive函数疑问
freeRTOS 将当前任务添加到队列的等待接收列表以及阻塞延时列表后当前任务会立刻停止吗,会立即进行任务调度吗,按照逻辑道理上来说应该会立即进行任务切换。但是源代码里面队列写入以及读取代码里面没有立即切换任务的实现,是有条件的。是不满足条件的情况下进行调度,这个地方很多教程都是错的。
2025-06-06 14:00:41
170
原创 freeRTOS在ISR中断中切换任务为什么会造成堆栈错乱
在 ISR 中直接切换任务会破坏中断上下文与任务上下文的隔离性,主要原因包括中断嵌套导致的栈帧覆盖、临界区保护失效及 PendSV 机制被绕过。,而非任务的专用栈空间。中断退出时,CPU 尝试从中断栈帧恢复寄存器,但该位置已被新任务的数据覆盖,导致寄存器错乱或硬错误。,由 FreeRTOS 内核在中断退出后安全执行切换操作。若在 ISR 内直接调用任务切换函数(如。),系统可能错误地将新任务的上下文保存到。中断返回时,CPU 无法正确恢复到预定任务。
2025-06-05 16:33:26
429
原创 freeRTOS中断中为什么不能进行任务切换2
:FreeRTOS 禁止在中断中直接进行任务切换,是为了保护被中断任务的上下文完整性、维护正确的堆栈管理、保证系统的实时响应能力以及确保内核操作的原子性。(个人理解是进入ISR中断之前,要利用MSP保护上下文,那么如果ISR里面进行任务切换,任务切换时也要利用MSP对任务上下文进行切换,而freeRTOS的对MSP的保存机制,跟ISR对MSP的保存机制可能不同,很有可能会造成错乱)后缀的 API,这些 API 在需要时内部会安全地触发 PendSV 请求,而不是直接切换任务。
2025-06-05 16:23:37
361
原创 freeRTOS中断中为什么不能进行任务切换1
场景能否切换任务实现方式中断服务程序(ISR)内部❌ 禁止仅标记切换请求(中断退出后✅ 允许通过PendSV等软中断执行实际切换此设计保障了中断响应的实时性,同时确保任务切换在安全上下文进行56。
2025-06-05 16:23:35
391
原创 freeRTOS 消息队列之一个事件添加到消息队列超时怎么处理
在使用FreeRTOS时,如果你需要将一个事件添加到消息队列中,并且希望在特定时间内完成,可以通过几种方式来处理超时情况。
2025-06-05 12:13:48
138
原创 为什么freertos 放在xPendingReadyList里面的是xEventListItem而不是xStateListItem
在FreeRTOS的任务调度机制中,xPendingReadyList用于管理即将从事件中解除阻塞并准备就绪的任务。这种分离设计提高了系统效率,使事件处理和状态管理可以并行操作而互不干扰。
2025-06-05 11:06:15
171
原创 嵌入式学习笔记 - freeRTOS任务设计要点
优先级越高的任务执行时间尽量短一些间隔时间长一些,这样给低优先级的任务多一些运行的机会。或者说处理时间短的任务可以设置的优先级高一些。因为中断函数使用的上下文环境是MSP环境,而非PSP环境,不允许挂起任务,不允许阻塞任务的任何操作。空闲任务的优先级最低,不允许出现阻塞,包括空闲任务的钩子函数,否则cpu指令将停止,造成硬件错误。中断的处理时间要远低于任务的运行时间,不然将会一直执行中断。高优先级任务尽量频率低一些,否则低优先级得不到运行。可以使用FromISR函数进行操作。
2025-06-04 20:58:59
285
原创 嵌入式学习笔记 - freeRTOS关于删除自身任务函数 void vTaskDelete
当删除的任务是自身时,不会当下立即删除当前任务,因为任务切换时还需要当前任务的堆栈进行相关操作,存放pxCurrentTCB的指针的R3就得需要当前任务的堆栈暂存,而是将自身任务插入到等待删除列表,由空闲任务删除。下图为void vTaskDelete函数的内部实现,
2025-06-04 15:50:12
97
原创 嵌入式学习笔记 - freeRTOS的两种临界禁止
数组)是全局共享的关键数据结构,存储了所有可运行任务的信息。多个任务或中断服务程序(ISR)可能并发访问该列表。若不进行保护,可能导致链表节点损坏、优先级错乱等数据竞争问题。与临界区(关中断)不同,vTaskSuspendAll()仅暂停调度器,中断仍可响应,适用于需长时间保护临界区但需响应中断的场景。更改就绪列表时,通常是通过禁止中断的方式,进入临界段,因为systick中断中有可以更改就绪列表的权利,暂停所有任务调度(但允许中断),确保当前任务独占执行权,
2025-06-04 12:45:07
173
原创 嵌入式学习笔记 - freeRTOS创建一个任务的具体过程
若是第一次创建任务,先初始化所有列表,再将任务添加到列表,添加到列表的过程就是将任务控制块的任务节点信息的前后节点指针赋值,插入到就绪列表的相应优先级的链表。包含了任务的全部信息,包括任务栈的起始地址(用户定义的任务栈地址),栈顶地址,任务堆栈,任务优先级,
2025-06-03 17:08:10
90
原创 嵌入式学习笔记 - freeRTOS任务栈在初始化以及任务切换时的压栈出栈过程分析
比如定义一个任务栈为Task2Stack[N],那么任务栈的在ARM内存中的排列如下图示所,数组Task2Stack代表的起始是任务栈的最低地址,当栈为空时,就是栈内不存任何内容时,栈顶地址SP=Task2Stack+N-1,Task2Stack 为定义的任务栈的起始地址,也就是定义的任务栈数组的地址,N为定义的任务栈的总大小(长度)。
2025-06-03 16:30:01
843
原创 嵌入式学习笔记 - FreeRTOS关于vApplicationGetIdleTaskMemory
* 任务堆栈大小 */ /*指针pulIdleTaskStackSize指向的地址存放的是变量configMINIMAL_STACK_SIZE*//* 任务堆栈内存 */ /*指针ppxIdleTaskStackBuffer指向的地址里存放的是数组IdleTaskStack的地址,数组名字直接可以代表地址*//* 任务控制块内存 *//*指针ppxIdleTaskTCBBuffer指向的地址里存放的是结构体IdleTaskTCB的地址,结构体名字必须加&代表地址*/
2025-06-02 12:58:56
309
原创 嵌入式学习笔记 - freeRTOS动态创建任务时传入的任务句柄参数
以下是函数内部使用这个参数的具体部分,如果这个参数被赋值过,也是就是参数(这个参数是一个指针地址)里面有指针,也就是用户定义过这个指针,就进行赋值操作,否则无任何操作,后续程序也不能使用这个任务。xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */(const char* )"AppTaskCreate",/* 任务名字 */(void* )NULL,/* 任务入口函数参数 */任务控制块指针的地址。
2025-06-02 12:40:59
383
原创 嵌入式学习笔记 - freeRTOS在程序开始在任务内创建任务的好处是什么
在FreeRTOS中,程序启动后优先在初始任务(而非函数)内创建其他任务是一种常见且推荐的设计模式,其主要优势包括以下几点:以下来自deepseek的回答,很全面很正确:函数通常使用启动文件分配的有限栈空间。若在其中密集创建任务、队列等对象可能导致栈溢出❌1。将任务创建移至独立任务的函数栈中(默认更大且可配置),可显著降低风险。允许根据运行时状态(如硬件检测结果、配置参数)动态决定创建哪些任务及其优先级、栈大小等属性,提升系统灵活性🛠️7。例如:cCopy CodeFreeRTOS需通过启动内核调
2025-06-02 10:19:02
277
原创 嵌入式学习笔记 - FreeRTOS v9.0.0 与v10.0.1不同版本占用资源对比,以及TOTAL_HEAP_SIZE设置大小
以下为用示例对比freeRTOS v9.0.0版本以及v10.0.1版本占用资源的境况,两者均在运行完全相同的任务包括任务内容与数量的情况进行对比,任务的创建均使用静态内存方式创建,每个任务的任务堆栈均设置相同大小,并且freeRTOSconfig.h文件使用基本相同的配置。可以看出两者ROM占用基本一致,RAM占用方面10.0.1版本比9.0.0版本多出接近一倍。下图为用移植方式使用freeRTOS,版本v9.0.0,运行的任务编译后如下。v9.0.0版本: ROM:20520+396+144=
2025-06-01 17:36:25
205
原创 嵌入式学习笔记 - vAssertCalled(__FILE__, __LINE__)
是预处理宏,分别表示当前文件的名称和行号。函数会被调用,打印错误信息并停止程序执行。
2025-05-31 18:12:10
120
原创 嵌入式学习笔记 - STM32 HAL库以及标准库内核以及外设头文件区别问题
两个文件,stm32f103xe.h为stm10系列底层文件如总线以及各片上外设模块寄存器地址,stm2f1xx.h仅为底层配置文件stm32f103xe.h提供配置选择的宏定义,相当于一个入口文件,虽然HAL库中已不含stm32f10x.h头文件,但是KEIL安装根目录下,ARM编译器目录下依然有标准库的驱动源文件,包括头文件STM32F10x.h,而keil默认包含根目录下的头文件,标准库中CMSIS内核驱动文件夹中,仅包含两个.h文件,其中。HAL库中CMSIS内核驱动文件夹中,改为如下三个文件,
2025-05-31 16:44:16
448
原创 嵌入式学习笔记 - keil安装目录下的头文件自动包含问题
可在工程选项中确认自动包含的路径。进入“Options for Target” → “C/C++”选项卡 → “Include Paths”栏,通常能看到类似。Keil MDK/MDK-ARM(ARM编译器)默认情况下会自动包含其安装目录下的标准头文件路径(如CMSIS库、设备头文件等)。新建工程或使用设备数据库选择芯片型号后,Keil会自动将必需的标准库头文件路径(如。目录下的CMSIS相关头文件路径)添加到项目的。(CMSIS核心)等由Keil自动添加的路径。中,无需用户手动添加。
2025-05-31 11:56:20
369
原创 嵌入式学习笔记 - freeRTOS任务优先级抢占,时间片抢占的实现机制
如果是大于的情况,那么使用listGET_OWNER_OF_NEXT_ENTRY也是指向当前到期的任务,因为taskSELECT_HIGHEST_PRIORITY_TASK()函数实现里关于listGET_OWNER_OF_NEXT_ENTRY()的函数实现里( pxConstList )->pxIndex总是指向end节点之前,而时间到期插入就绪任务时使用的是insertEnd();第564行是判断如果延时时间到的任务比当前任务优先级高,使能切换,这个自然是正常逻辑。函数返回为1,这个函数如下图,
2025-05-29 21:54:55
385
原创 嵌入式学习笔记 - freeRTOS 阻塞延时的实现机制,同时避免在中断中扫描停留
systick中断只需根据NextTaskUnlockTime激活延时列表的第一个节点即可(激活是通过删除延时列表节点并添加到就绪列表的的方式,有可能不止一个节点但是肯定靠在前面),按大小插入延时列表肯定要排序,注意这里定义两个延时链表的方式也很巧妙,分别定义了两个链表变量,然后定义了两个链表指针,分别指向两个链表,这样可以灵活的运用两个指针,当想要操作的对象改变时只需要对指针交换指针指向的地址即可。加入延时列表时,扫描延时列表,根据延时值顺序插入延时列表,
2025-05-29 13:56:13
230
原创 嵌入式学习笔记 - 用typedef定义函数指针
定义了函数指针类型后,你可以像使用其他数据类型一样使用它。例如,声明一个函数指针变量,并将它指向。是一个关键字,用于为已有的数据类型定义一个新的名称(别名),同样它也可以为函数定义别名。// 使用函数名初始化指针。定义一个指向【返回int且接受两个int参数的】函数指针。ptr(2, 3);// 通过指针调用函数,输出 5。// 定义函数指针类型。就是函数指针的类型,它指向一个接受两个。
2025-05-28 16:01:55
348
原创 嵌入式学习笔记 - 新版Keil软件模拟时钟Xtal灰色不可更改的问题
这是因为Keil MDK从5.36版本开始,参数配置界面不再支持修改系统XTAL频率,XTAL选项变为灰色,无法修改。这会导致在软件仿真时出现时间错误的问题,特别是对于调试实时操作系统(RTOS)来说非常不便。:由于Keil软件默认使用12MHz时钟,可以直接使用这个设置进行仿真,这样虽然不是最优解,但可以避免时间错误的问题。如果优更优的解决办法请指正。
2025-05-28 12:53:05
608
原创 嵌入式学习笔记 - 数组名,结构体名与地址的关系
printf("成员地址: %p (id), %p (name)\n", (void*)&stu.id, (void*)&stu.name);// 输出整个数组的地址(值与 arr 相同,但类型不同)// 输出首元素地址(等价于 &arr[0])printf("结构体首地址: %p\n", (void*)&stu);// struct Student 只是一个类型名,没有地址。运算符获取地址,不能隐式转换。
2025-05-27 20:08:59
286
原创 嵌入式学习笔记 - freeRTOS关于空闲任务的理解
空闲任务是 FreeRTOS 内存管理、低功耗、稳定调度及功能扩展的核心支撑组件,其缺失将直接导致系统不可用。由于freeRTOS的任务延时都是阻塞延时,阻塞延时是当任务进入延时后,该任务的CPU使用权被剥夺进入阻塞状态(阻塞状态可以理解为保持状态不变),可以理解为任务不运行时PC停止了。使用阻塞延时的好处就是可以让CPU充分的得到利用,不会空耗在软件延时上。但是所有任务都处在阻塞延时时,相当于PC停止了,很明显这是不合理的,而且会产生硬件错误,所以会有一个空闲任务,作为保底空闲任务的优先级是最低的。
2025-05-27 18:06:38
98
原创 嵌入式学习笔记 -函数嵌套时以及异常响应时,LR使用的具体过程
最后一层函数在返回时,是先执行BX lr指令返回,然后在执行出栈操作恢复包括上一层函数返回地址寄存器LR在内的所有栈内容。当使用BL指令调用函数时,处理器在进行跳转之前,会将当前函数的下一条地址,即(PC+4)的地址,存入LR寄存器,被调函数执行完毕函数返回时,通过MOV pc,lr 指令加载LR寄存器的值到PC寄存器,实现函数返回。中断返回时,BX R14的执行逻辑,通常不是直接将LR寄存器的值赋值给PC寄存器,而是通过。异常返回模式:标识返回后使用MSP(主栈指针)还是PSP(进程栈指针);
2025-05-27 09:38:55
449
原创 嵌入式学习笔记 - 关于freeRTOS下的系统模式,用户模式,SVC模式
指令或软件中断触发。RISC-V 架构:FreeRTOS 可运行于 RISC-V 的 S 模式(监管模式) 或 U 模式(用户模式),具体取决于内核配置和硬件支持8。ARM Cortex-M 架构:通常运行于 特权模式(系统模式),直接管理硬件资源(如 SysTick 定时器、中断向量表)以实现高效调度。指令触发 SVC 异常(软件指令写寄存器触发方式进入特权模式),进入特权模式(内核态)后,在 SVC 的 Handler 中手动设置。显式设置PSP,实现从特权模式到任务上下文的切换。
2025-05-26 10:45:24
375
原创 嵌入式 学习笔记 - freeRTOS启动第一个任务的过程
首先将PENDSV 跟SYSTICK的中断优先级设置为最低,如下图,就是对控制PENDSV 跟SYSTICK的中断优先级的寄存器进行设置,都设置为255第100至105行,就是再设置MSP主堆栈寄存器的值,最终将主堆栈寄存器的值设置为0x00000000地址里面的值,因为0X00000000是向量表首地址,它存放的就是主堆栈指针的值。第114行,调SVC命令开启SVC中断第125到128行,将之前保存(在创建任务时,初始化堆栈时会将堆栈设置的值搬运到寄存器,像被调度打断了)的现场恢复出来,
2025-05-26 10:42:02
810
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人