- 博客(57)
- 资源 (5)
- 收藏
- 关注
原创 基于OSAL的嵌入式裸机事件驱动框架——内存管理osal_memory
如果使用外部RAM,theHeap被定义为一个指向外部RAM起始地址的指针. 反之则定义一个静态数组_theHeap,数组的大小为,halDataAlign_t类型。静态数组意味着其生命周期从程序开始一直持续到程序结束,且其存储空间在静态存储区,而不是在栈上。这使得_theHeap可以在整个程序运行期间保持其值。: 这是一个GCC编译器的扩展属性,用于指定变量的对齐方式。在这种情况下,_theHeap数组将被对齐到32字节的边界。这意味着_theHeap的起始地址将是32的倍数。
2025-02-08 15:57:35
619
原创 FreeRTOS学习——heap4
如果 configSUPPORT_DYNAMIC_ALLOCATION 为0,则不得使用此文件==0if0如果这个宏为0,在free内存函数中,并没有将内存空间清0,只是将其插入到空闲内存块链表中。此宏为1,才清00heapMINIMUM_BLOCK_SIZE 宏size_t<<1这个宏定义了一个最小的块大小,即乘以2。表示存储堆信息的数据结构()的大小。确保内存分配的最小单位至少能够存储两个这样的数据结构,这样即使在最坏的情况下,内存也能被有效管理,避免过小的内存块导致碎片化严重。
2025-02-06 15:05:13
783
原创 基于OSAL的嵌入式裸机事件驱动框架——DEMO
DEMO演示,使用OSAL的任务事件,定时器以及消息队列功能进行一个简单的使用演示有两个任务LED任务- 定时器1事件:500ms闪烁一次- 定时器2事件:1000ms发送消息给打印任务打印任务- 按键按下事件:打印" button pressed "- 系统消息事件:打印" msg test received "
2025-01-26 20:27:14
296
原创 基于OSAL的嵌入式裸机事件驱动框架——整体架构调度机制
参考B站up主任务ID : TASK_XXXTASK_XXX 在系统中每个任务的ID是唯一的,范围是 0 to 0xFFFE,0xFFFE保留为SYS_TSK_INIT。同时任务ID的大小也充当任务调度的优先级,ID越大,优先级越高,越排在任务链表的最前面事件ID :EVE_XXXEVE_XXX和任务绑定,对于一个任务来说,一个任务的事件集有16位,最高位1<<15 保留为系统消息事件SYS_EVE_MSG,剩下的1<<0 到 1<<14由用户定义。
2025-01-26 20:04:33
1708
1
原创 基于OSAL的嵌入式裸机事件驱动框架——软件定时器osal_timer
参考B站up主软件定时器定时器使用链表将所有定时器连接起来需要将定时器更新函数osal_timer_update放在Systick中断中。
2025-01-26 19:59:35
389
原创 基于OSAL的嵌入式裸机事件驱动框架——消息队列osal_msg
参考B站up主消息队列消息分为hdr和bdy,把消息的头dhr和内容bdy做了一个分离的设计dhr包括指向下一个消息的指针next,len在创建消息的时候使用,dest_id即目标任务,将消息和任务进行绑定。bdy是消息的主体,包括数据data,还有事件id。(注:这里的event_id和任务里的event_id 是不一样的,在任务中有个属性是事件集,表示对应于这个认为的事件集合,有16位,即一个任务最多可以对应16个事件,当有事件触发时,会将事件集对应位置1,通过按位或的方式。
2025-01-26 19:54:51
697
原创 基于OSAL的嵌入式裸机事件驱动框架——事件及任务osal_task
参考B站up主用户任务通过单向链表连接起来,最后一项指向NULLtask_id 唯一且充当优先级的作用,task_id越大,优先级越高每个任务最多可以对应16个独立事件,最高位对应消息队列事件,留给用户设置0-14位。(注:事件集这16个事件只针对于此一个任务)
2025-01-26 19:49:19
463
原创 FreeRTOS学习——Systick中断、SVC中断、PendSV中断
当SVC指令被执行后,处理器会根据中断向量表中的信息跳转到相应的SVC中断处理函数,执行SVC指令时,处理器会自动保存当前的上下文,并将处理器的模式切换为特权模式,从而允许执行受限的操作。ldr r3, pxCurrentTCBConst2:将pxCurrentTCBConst2的值(即pxCurrentTCB的地址)加载到寄存器r3中。配置系统的滴答定时器,以允许操作系统根据配置的频率生成定时中断,从而支持任务的调度和管理。msr psp, r0:将恢复后的任务栈指针r0存入PSP(进程栈指针)。
2024-09-23 20:56:10
2973
原创 FreeRTOS学习——接口宏portmacro.h
原子操作是指在多线程或多任务环境中,**一个操作要么完全执行成功,要么完全不执行,不会在中间被挂起或打断。**对于时间片操作,若标识为原子,在此期间所有对时间片的修改和读取都是一个不可分割的动作。
2024-09-18 20:04:59
1523
原创 FreeRTOS学习——链表list
FreeRTOS学习——链表(列表)list,仅用于记录自己阅读与学习源码*list_t只能存储指向list_item_t的指针。每个list_item_t都包含一个数值(xItemValue)。大多数时候,列表是按项目值升序排列的。*创建的列表已包含一个列表项。此项的值是可以存储的最大值,因此它始终位于列表的末尾,并充当标记。列表成员pxHead始终指向此标记,即使它位于列表的末尾。这是因为尾部包含一个返回指针,指向列表的真正头部。
2024-09-16 22:26:14
1234
原创 FreeRTOS学习——代码覆盖率测试宏mt
在代码中使用 mtCOVERAGE_TEST_MARKER() 时,预处理器会直接移除这个宏调用,不会留下任何代码。mtCOVERAGE_TEST_DELAY特意放在代码的一个关键部分,通常是为了确保通过操作函数时,所有逻辑判断和指针操作都能被仔细测试。#define mtCOVERAGE_TEST_MARKER() ((void)0) 表示宏展开为一个空操作,保留一个空语句。它的主要目的是确保在某些特定情况下,代码的所有可能路径都能被测试到。它确保在某些特定情况下,代码的所有可能路径都能被测试到。
2024-09-14 14:46:43
689
原创 使用Clion开发STM32——移植FreeRTOS
其实在STM32cubeMX中就可以直接配置FreeRTOS,rtthread等操作系统,而且使用接口封装过的,很方便。但我还是想手动一直一遍,肯定有不一样的收获。
2024-08-16 15:22:14
1974
4
原创 FreeModbus学习——接收状态机xMBRTUReceiveFSM
当接收状态机状态为初始化态,接收到一个数据,进入接收状态机,不存储这个数据,而是重启定时器。再接收,再重启,直到这一帧完成(帧与帧之间会有个时间间隔),然后进入定时器中断,将接收状态机变为空闲态,并发布ready事件,代表协议栈就绪。协议栈使能后,会将接收状态机赋值为初始化态,串口接收使能,且定时器也使能(重新计数),定时器进入溢出中断,然后会将接收状态机由初始化态变为空闲态。然后再将接收状态机置为空闲态。当接收状态机为空闲态时,开始接收第一个数据作为帧首,然后将接收状态机置为接收态,重新计数定时器。
2024-08-03 17:20:23
1164
原创 FreeModbus学习——定时器
接收状态机为空闲态时,接收到一个字符,会进入串口接收中断,串口接收中断中会将接收到的字符保存作为帧首,并且把接收状态机变为STATE_RX_RCV。但是万一这个时候串口接收寄存器已经有数据了咋办,那会进入串口接收中断函数,会调用xMBRTUReceiveFSM,当接收状态机为STATE_RX_INIT时,会清空定时器重新计数。当接收状态机为空闲态STATE_RX_IDLE,接收到第一个数据时作为帧首,然后接收状态机进入接收态STATE_RX_RCV,并且使能定时器(重新计数)。说明一帧已经接收完毕。
2024-07-25 19:55:02
1268
原创 Clion开发STM32——移植FreeModbus
网上用keil的比较多,用Clion的比较少,如果你也用Clion,那么希望本文可以给你提供些许参考。
2024-07-25 17:52:11
1518
5
原创 FreeModbus学习——读输入寄存器eMBFuncReadInputRegister
也就是说经过eMBFuncReadInputRegister这个函数处理之后,打包好的帧已经放在了pucFrame,长度放在了usLen。调用回调函数eMBRegInputCB读取寄存器数据,eMBRegInputCB这个函数会把读到的数据继续存放在pucFrameCur 帧里。就是说这个指针pucFrameCur刚开始指向pucFrame这一帧数据的起始位置,然后打包一个数据,pucFrameCur+一个。读寄存器数据,其实就是读数组嘛,寄存器是16位的,所以定义数组也是16位的SHORT型。
2024-07-24 21:20:08
1180
原创 FreeModbus学习——xFuncHandlers功能码处理
这句话就是说,定义了一个变量,这个变量是pxMBFunctionHandler 函数指针类型。在mb.c文件中,有一个数组是static xMBFunctionHandler xFuncHandlers[MB_FUNC_HANDLERS_MAX]首先看这个数组的类型 :xMBFunctionHandler ,也就是说这个数组中的每一个元素都是xMBFunctionHandler。以读输入寄存器为例(首先要在mbconfig.h文件中打开这个功能(默认打开))那么这个读输入寄存器函数在哪?
2024-07-24 18:27:37
550
原创 stm32h7串口发送寄存器空中断
关于stm32串口的发送完成中断UART_IT_TC网上资料挺多的,但是使用发送寄存器空中断UART_IT_TXE的不太多。
2024-07-24 16:16:26
1264
原创 FreeModbus学习——eMBPoll轮询
接收状态机为空闲态时(每次定时器溢出中断会将接收机状态置为空闲态),接收到一个字符,会进入串口接收中断,串口接收中断中会将接收到的字符保存作为帧首,并且把接收状态机变为STATE_RX_RCV。直到一帧结束,也就是距离下个字符超过定时器溢出时间,进入定时器中断,此时接收状态机还为STATE_RX_RCV,这就意味着接受完成了一帧。协议栈使能后,会将接收状态机赋值为初始化态,且定时器也使能,定时器进入溢出中断,会将接收状态机由初始化态变为空闲态,并且发布一个EV_READY事件。
2024-07-23 19:23:54
2275
原创 FreeModbus学习——eMBEnable协议栈使能
先进行协议栈状态判断,若eMBState == STATE_DISABLED即初始化完成了,就激活协议栈。串口接收使能,发送禁止。在定时器第一次溢出后会将接收状态机的状态由STATE_RX_INIT变为STATE_RX_IDLE。Modbus初始化后,协议栈状态由eMBState由未初始化变成了STATE_DISABLED。先将接收状态机赋值为初始化状态 eRcvState = STATE_RX_INIT;eMBRcvState有四个状态:初始化,空闲态,接收中,帧无效(错误)
2024-07-23 17:41:03
520
原创 FreeModbus学习——eMBInit初始化
在调用xMBPortSerialInit进行串口初始化,这个函数在portserial.c文件中,这个函数是留给用户自己实现的,就是初始化函数,实际上串口初始化放在外面自己初始化也可以,反正只要初始化了就行。所以设置Prescaler = 11999;,这样一个时基就是12000/240000000 = 1/20000 = 1/20ms = 1000/20 us = 50us。在mb.c文件中还定义了几个回调函数指针,这里只用到了前三个,分别是字节接收,发送空,定时器溢出回调函数。
2024-07-23 16:05:26
1233
原创 FreeModbus学习——portevent事件
如果队列中有事件,则就将队列中的事件eQueuedEvent赋值给eEvent ,事件被取走了,那么队列里就没有事件了,所以xEventInQueue = FALSE;eEvent 为要发布的事件,将xEventInQueue 置为TRUE,即队列中有事件了,然后将eEvent赋值给eQueuedEvent ,即队列中的事件为eEvent。在mbport.h文件中有事件类型的定义eMBEventType,有事件状态有四种,或者说有四种事件:就绪,帧接收完成,处理,帧发送完成。首先定义了两个静态变量。
2024-07-23 14:46:41
558
原创 STM32H7串口中断服务函数会禁止中断
同时也会禁止发送完成中断,调用UART_EndTransmit_IT来进行操作。在中断服务函数HAL_UART_IRQHandler中,会禁止接收中断。
2024-07-23 14:13:00
325
原创 rtt设备驱动框架学习——内核对象基类object
这个基类是内核所有对象的基类在rt-thread/include/rtdef.h文件里有对内核对象基类object的定义object属性有 内核对象名字 , 内核对象类型 , 内核对象标志,还有一个链表节点。
2024-07-06 00:10:43
702
原创 rtt设备驱动框架学习——链表
这个宏的作用是通过结构体成员的指针 ptr 和成员名 member,计算出包含该成员的结构体的起始地址,并将其转换为 type 类型的指针。_inline函数也称为内联函数或内嵌函数,_inline定义的类的内联函数,函数代码被放入符号调用表,使用时直接展开,不需要调用,即在编译期间将所调用的函数的代码直接嵌入到主调函数中,是一种。(type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)):将计算结果转换回 type 类型的指针。
2024-06-30 17:50:25
1259
原创 嵌入式系统面向对象的程序设计原则
简单地说,就是尽可能让一个子系统(或一个结构体)的功能比较单一,减少对其他子系统(或其他结构体)的依赖。低耦合:一个子系统(或者一个结构体)的实现,尽可能少地调用到另一个子系统 (或另一个结构体)的功能。6.接口函数在C文件中实现,内部函数定义为static函数,内部变量定义为static。高内聚:一个子系统(或者一个结构体),尽可能只完成一个功能,即最大限度地耦合。4.删除一个模块,应当只影响有依赖关系的其他模块,而不应该影响其他无关部分。2.模块只对外暴露最小限度的接口,形成最低的依赖关系。
2024-06-29 17:04:37
239
原创 STM32驱动AD5676R
数据首先装入MSB (DB23),前四位是命令位,C3到C0,其次是4位DAC地址位,A3到A0,最后是16位数据字。这些数据位被传输到SCLK的24个下降沿上的输入寄存器,并在SYNC的上升沿上更新。当 RESET 被激活时,输入寄存器和 DAC 寄存器将更新为零刻度或中刻度,取决于 RSTSEL 引脚的状态。将该引脚脉冲拉低允许任何或全部的DAC寄存器被更新,如果输入寄存器有新数据,这允许同时地更新所有 DAC 输出。寻址输入寄存器和DAC寄存器都在同步的上升沿上更新,输出开始改变。
2024-05-30 00:09:07
1371
4
原创 Clion开发STM32——添加自己文件
发现新加入的文件后CmakeList.txt会自动添加LINKER_SCRIPT。报错clion No such file or directory。修改CMakeLists_template.txt即可。期间还有一个坑,编译进度已经到最后了,但是还是报了错。这样可以是可以,但是每次重新生成代码,会被重新覆盖。有网上有教程,让修改CMakeLists.txt。把下面这行后面的文件删掉即可。
2024-04-14 17:38:14
564
原创 8_正确认识回流路径(参考平面)
(a)直流电路信号回流路径(b)高速信号回流路径对于高速信号当信号源输出一个高频信号(实际上就是信号的沿)时,从信号传输的角度讲,它并不是一下子就能达到信号的接收端。信号的上升沿要逐一通过每一个微小(Δx长度)的等效电路,并且在这个微小的等效电路上建立起稳定的电磁场结构,然后才能继续将这个电磁场能力传递到下一个等效电路上。
2023-08-24 15:00:26
3644
原创 5_串扰的产生与预防
当高速信号沿着某一根导线传播时,其电场和磁场将会通过某种方式耦合(影响)到其他导体线路内。当这种耦合的电磁场强度达到一定量时,就会使邻近线路产生无法预期的信号,这样就导致了串扰串扰是由于变化的电磁场通过耦合的方式引起的分为:感性串扰,容性串扰在实际电路中,容性串扰和感性串扰是同时发生作用的感性串扰的强度随着串扰耦合长度的增加而增加,当然也随着L1上的信号强度增加而增加,在时间上,随着上升沿的消失而消失,极性和入侵者L1上的原始信号极性相反。
2023-08-22 16:04:28
361
原创 3_信号完整性问题分类
所谓信号完整性,是指在不影响系统中其他信号质量的前提下,位于此信号传输路径上的各个负载能够尽最大可能地复原(接收到)驱动端所发出的原始信号的状态”所有的信号完整性以系统正常、稳定工作为目的,而不是以单个信号的“完美波形”为目的。按照Eric博士的观点,所有的信号完整性问题可以分为如下四类:●● Crosstalk——相邻传输线之间的信号串扰问题;● PI Related——与电源和地分布相关的信号及电源完整性问题;
2023-08-22 10:54:39
386
1
原创 2_高速电路中的阻抗理论基础
在高速系统中,所有的现象都可以用如下的阻抗特性来解释:● 由于传输线的阻抗不连续,引起信号的反射,从而引起信号本身的畸变;● 由于传输线的耦合(耦合是阻抗构成的一部分),引起信号间的串扰,造成临近区域信号的畸变;● 由于电源系统的某个区域分布阻抗过大,使得该区电源系统的供电不足、谐振,从而造成相关器件的性能损失,甚至混乱;● 由以上各种阻抗特性的不可控而带来的高速信号畸变或者电源系统混乱,最后都会影响到系统的EMI(电磁干扰)对于高速信号系统的设计最后都会归结为对信号传输阻抗的设计。
2023-08-21 22:42:08
402
1
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人