自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(27)
  • 收藏
  • 关注

原创 C语言中的全局变量,局部变量,include,extern, static, volatile详解

对Include的理解就是它会把头文件中的内容全部复制到使用include的地方,我们知道,在使用一个函数之前,必须要对其声明,不一定需要赋值。函数也是这样,头文件中只是声明。这是我对C语言语法系列的一些博客收集,现整理起来。建议花20分钟阅读,大有收获。这篇文章从底层讲了 voltaile的由来,很不错。首先是变量(全局变量,局部变量)的分类。了解了这些就再看看include的解析。voltaile的用法。

2023-12-22 14:55:58 617

原创 STM32底层(ARM芯片)启动全过程。(编译,链接,启动)

这些是我慢慢收集来的博客,集中做个整理,建议慢慢阅读,了解STM32的整个底层。

2023-12-21 19:54:00 924

原创 学习(线性、拓展 、无迹)卡尔曼滤波的完整总结

这篇文章是根据 Kalman Filter from froun up 这本书来总结的。这本书写的是真的太棒了!强烈推荐,虽然是英文,但完全不影响阅读。作者通过一些巧妙的叙述过程,避开了那些特别难的推导,有一些难的部分,作者也说可以跳过,不影响理解,真的不像中文的书籍写的无趣且晦涩,要不试读一下前50页试试感觉?没有任何废话。

2023-12-11 19:07:24 1366

原创 STM32 启动文件

这是栈的初始化函数,但是在上面的里面这里面没有说清楚,我的理解就是,__user_initial_stackheap作为初始化堆栈的函数,就只是往R0,R1,R2装入参数的,然后一个跳转指令 BX,就实现了,在_main函数应该会调用这个初始化函数。这个里面对于启动文件的讲解很透彻了,就说下最后我的里面,

2023-11-27 22:00:45 345

原创 FreeRTOS 第21-23章

算了,后面的不说了,看了下没什么说的,就是预先定义好一个数组,这个数组在编译的时候就会预留好空间,堆就是用来实现动态分配内存的,它和启动文件中的堆不一样,如果函数中没有使用malco函数,就算启动文件中的堆尺寸为0也可以。FreeRTOS内核与内存管理是分开的,其只提供函数原型,内存的管理的实现可不同定义。在一般的实时嵌入式系统中,由于实时性的要求,都是直接操作物理内存,而没有引入虚拟内存,而且内存申请的时间也很苛刻,不同的申请函数使得耗费时间不同,这样的不确定性对于实时系统不允许的。

2023-11-27 16:50:46 319

原创 FreeRTOS 第20章 任务通知

case3:eSetValueWithOverwrite(可替代xQueueoverwrite()函数,这里用在队列),case4: eSetValueWithoutOverwrite(不覆盖写入,判断一下被通知任务是不是已经收到通知了,收到了通知就不能覆盖写入,返回pdfalse). case5:eNoaction(只是发送通知,没有使用值,那就是更改被通知任务状态为已经收到通知)。任务通知也是一种通信机制,可替代二值信号量,计数信号量,事件组,也可以替代长度为1,大小为4字节地消息队列。

2023-11-22 18:56:57 840

原创 FreeRTOS 第十九章 软件定时器

软件定时器的实现机理:当创建一个软件定时器时,会申请一块内存,这块内存就是软件定时器TCB,同时会根据系统当前时间和传入的定时时间参数做一个加法确定定时器的唤醒时间,并将软件定时器的TCB加入到软件定时器列表,而列表就是双向链表,它可以实现对空间上离散的内存进行管理,一个个软件定时器虽然它们的内存不连续,但是链表把它们勾结在了一起。而在FreeRTOS中,是需要在创建软件定时器的时候指定回调函数(类似于中断函数),到期了才去执行回调函数,此时回调函数的上下文是用户线程模式,在中断则是特权处理模式。

2023-11-21 16:43:41 63

原创 FreeRTOS 第十八章 事件

在互斥量中,既没有释放信号量的中断版本函数,也没有获取信号量的中断版本,因为互斥量是拥有了才能释放,而且查看源码可知,在互斥量的创建函数下调用了一个互斥量初始化函数prvInitialiseMutex()函数,其中通过一个宏定义。它需要传入事件的句柄,以及置哪个位置置1,而且,它的源码除了置位外,还检查了等待列表的各任务在等什么,是逻辑与还是逻辑或,以及当任务等到了事件时,需不需要清除事件位,最后返回uxEventBits的值,这个值是不断累积的,并不是当前传入的设置值就会完全决定。清除事件指定的位函数。

2023-11-20 16:51:11 37 1

原创 FreeRTOS 第十7章 互斥量

看看xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) 函数,它的函数中就是一个if-else结构,如果提出申请的是当前正在拥有互斥量的任务,那么只需要把结构体中联合体的变量uxRecursiveCallCount加一,如果不是(互斥量不被谁占有或者已被占用,但是该次申请不是由获得互斥量的任务提出),则去执行xQueueGenericReceive函数,获取成功了,则把uxRecursiveCallCount加一,没有获取成功,就去阻塞。

2023-11-19 16:30:41 40 1

原创 FreeRTOS 第十六章 信号量

同步是指,假设需要任务2在任务1之后马上执行,那么就可以在任务1执行完了特定目标之后释放信号量(往消息队列发送一个消息,二值信号量(消息)变为1,可以获取信号量(消息),则可以解除等待读任务),而只需要在任务2函数中加个获取二值信号量函数而阻塞,当任务1释放信号量,其就会马上得到信号量被加入就序列表,如果优先级高,则直接运行。递归信号量是可以重复调用的信号量。,而信号量释放函数是默认阻塞时间为0,也就是如果信号量满了且没有其它任务获取信号量,是不能一直释放的,会马上返回err_QUEUE_FULL.

2023-11-18 15:55:47 53 1

原创 FreeRTOS 第15章 消息队列

如果满足当然最好,如果不满足就会进入阻塞列表,这个列表会被放到相应的等待读列表和等待写列表,如果用户指定了阻塞的时间,那么在这段时间用户阻塞在相应的列表中,CPU去做其它的事情,在该期间内,条件满足,比如有消息了或者有空间了,就马上得到消息解除阻塞进入就绪队列,但是不一定马上执行,其优先级不一定是最高的,如果超过这段时间还没有满足条件,也直接从阻塞列表移除并加入就绪列表,也不一定马上执行,并返回的是errQUEUE,假如多个任务阻塞在同一个队列中,会按照恩威的优先级排序,优先级的高的先获得消息。

2023-11-17 17:17:09 27

原创 FreeRTOS 第十四章 任务管理

设计时候的注意:在中断中一定不能使用使中断阻塞的函数,比如挂起当前任务,因为挂起当前任务没有中断保护版本,其执行了就有可能任务切换,就会导致阻塞,而解除阻塞有中断保护版本,在一个普通中断使用了解除阻塞的中断版本并确定该解除阻塞的任务优先级最高,当该中断退出后,马上执行PendSV中断,然后任务切换。vTaskSuspendAll()是挂起所有的任务,其就是把调度器锁定,不能实现上下文切换,也就不能执行中断函数,但是可以记录中断挂起,当退出挂起的时候,执行中断。,如果其优先级最高,则任务切换。

2023-11-16 17:30:22 33 2

原创 FreeRTOS 第13章 FreeRTOS的启动流程

首先明确,在运行的时候,一些全局变量是保存在堆中的,堆是一块很大的区域,这个由宏定义来明确大小,在最后几章的时候有内存管理会涉及到这个内容,当调用动态任务创建函数的时候,会调用一个pvPortMalloc()函数,是申请内存函数,在这个函数中加个判断,如果是第一次调用,则初始化堆,堆的初始化其实就是根据一个宏定义(堆的大小)把某个内存空间规定为堆。初始化后才能申请内存。如果调用的是动态任务创建函数,那么在开启调度的时候,也会创建动态空闲任务并且加入就绪列表。

2023-11-16 16:13:51 43 1

原创 FeeRTOS 第十二章 任务

可以看到:pxCurrentTCB为空的时候,表示这还是第一次创建任务,就把这个传入的TCB赋给这个pxCurrentTCB,而如果pxCurrentTCB 不为空,且调度器还没有开始运行,即(xSchedulerRunning=pdFalse), 说明这是第二次创建任务,或者第三次,反正不是第一次,并且还没开始调度。至此,就确定好了最先执行的任务。任务分静态任务和动态任务,静态任务需要自定义栈空间,还需要包括任务栈,以及定时器的栈,软件定时器是依靠一个叫做定时器任务来维持的,因此需要一个栈空间。

2023-11-15 22:40:58 28

原创 FreeRTOS 第十一章 移植

这章没什么好说的,照着做。

2023-11-15 21:56:42 16

原创 FreeRTOS 第十章 时间片

在taskSELECT_HIGHEST_PRIORITY_TASK()函数中实现了时间片,该函数是在vTaskSwitchContext()函数中(切换上下文函数,在PendSV中断函数中调用寻找最高优先级的任务和TCB,寻找的算法有优化算法和普通算法)。节点的OWNER,在相同优先级下,几个任务并存,在根节点中有个PxIndex指针还没有用过,当每次调用这个函数,这个指针就向后移动一下,并赋给这个传入的参数pxCurrentTCB)。时间片调度是指多个任务在相同的最高优先级下,轮流占用CPU。

2023-11-15 21:53:10 65

原创 FeeRTOS 第九章 任务延时列表

这个函数的参数是xTicksToDelay,延时时间,其具体做了1;首先当延时到期后,进入一个for循环,当延时列表不为空时,调用一个获取延时列表头部的TCB的函数,再获取辅助排序值也就是计数到期的Tick,其不会进如下一个if语句,然后直接把任务移除阻塞列表再添加就绪列表,不断地for循环,把所有到期地任务移除(也许在一个计时Tick下有多个任务),直到辅助排序值的时间大于当前总的计时Tick,说明不能再移除了,把下个最快到期任务的时间给xNextTaskUnblockTime。//当前计数Tick。

2023-11-14 21:03:18 30 1

原创 FreeRTOS 第八章 多优先级

因此在Systick的中断时基函数中,就要把这个延时到期的任务的优先级加入到这个uxTopReadyPriority中,其具体调用了taskRECORD_READY_PRIORITY()这个函数,在85页可以看到,如果这个计时到期的任务的优先级高于uxTopReadyPriority,则把uxTopReadyPriority变成这个到期的任务的任务,如果小于,则不更改,毕竟到期了任务的优先级低,任务不需要切换。在中断中,配置的优先级数越小,则优先级越高,在任务中,配置的优先级数越小,任务的优先级就越低。

2023-11-14 19:57:50 60 1

原创 FreeRTOS 第七章 空闲任务与阻塞延时

该函数修改了代码实现了在空闲任务存在的时候任务切换的选择。这个函数很简单,就是把一个表示当前计算的总的计数Tick加1,并且把各TCB的xTicksToDelay减一,然后执行一次taskYIELD(),又去开启任务调度,挂起PendSV,当Systick中断退出的时候,又执行任务切换,又调用vTaskSwitchContext函数。任务开启调度函数中,这说明空闲任务控制块的名字,栈空间的命名,空闲任务的实现函数这些应该都是固定好了的,该函数还把空闲任务加入了就绪列表。当然,动态空闲任务的创建也是在这里。

2023-11-14 19:00:31 72 1

原创 FreeRTOS 第六章 临界段的保护

这章没什么好说的,临界段就是为了在操作一些代码的时候一次性操作完,不能被打扰。通过控制几个中断屏蔽寄存器实现。

2023-11-14 16:41:16 29 1

原创 FreeRTOS 第五章的任务的定义和切换

1 任务控制块区分一下FreeRTOS中的任务,在RTOS中的任务是指拥有TCB,任务栈,以及把任务函数(任务具体的实现函数)这些融合在一起后才叫任务。首先就是定义任务控制块,在后面的使用中,任务控制块(TCB)是每个任务的身份,在创建任务的时候必须传入,是一个结构体。第一个栈顶是任务栈的栈顶,在静态创建的时候是指向那个预先定义好的一个全局数组的最高位。第二个是任务节点,此处数据类型不是指针,就是一个节点,之后把任务加入列表就是利用这个节点。

2023-11-14 16:35:40 52 1

原创 FeeRTOS 第四章 列表与列表项

插入末尾,由于MiniListItem_t结构体中的成员在普通成员都有,所以可以用指向一个普通成员的指针指向MiniListItem_t,这其中存在一个隐式转换。列表是实现FreeRTOS最底层的任务排列的数据结构,列表节点就是列表中的一项。使用的是双向链表,也就是一个节点有指向下一个节点和指向上一个节点的指针。除此之外,因为它不属于任务任务以及列表(自己属于自己),所以这个省去了普通节点中的pvOwner 和pvContainer。(列表初始化函数,对根节点的初始化相当于列表的初始化)

2023-11-14 14:57:00 26 1

原创 FreeRTOS-1-3章

这部分没什么好讲的,看书为主。

2023-11-14 14:21:46 20 1

原创 CMSIS 的构成

第三个是core_cm3.h 其中有内核内设的寄存器地址(内核外设的配置结构体定义),然后是内在函数的声明以及NVIC的函数,尤其NVIC的配置函数是标准的,不容许修改。启动文件startup_stm32f10x_md.s 是有关中断向量表的配置,复位启动函数,然后堆栈的配置。第四个 stm32f10x.h 设备外设访问的头文件,其中定义了各个外设的寄存器地址,还有配置的数据结构,第七八个是stm32f10x_it.c 以及声明文件,这是中断函数的具体实现。

2023-11-13 21:57:32 126

原创 ARM中字对齐和半字对齐,以及小尾模式

展开成32位地址表示最低的四位分别是0000b,0100b,这就是字对齐,最后两位是0,如果是八字节对齐,则最后的三位都是0.比如存放0x12345678在地址0x0000 00000 中,实际上会把0x78放在地址0x0000 0001处,把0x12放在地址0x0000 0004处。这样外部访问一个字的时候就可以 mov R0, [0x0000 0000],以字的低地址作为字的地址。在Cortex-M3中,默认的小端模式,就是一个word型数据是32位,低八位存放在低地址中。

2023-11-12 21:28:52 414

原创 大小端模式

在Cortex-M3中一个地址处存一个字节,对于一个32位的字型数据,其最低的八位存低地址,最高的八位存在高地址,这种叫做小端模式,这样比较方便人的思维。Cortex-M3内核默认是小端模式。

2023-11-12 21:09:38 20

转载 ARM 重映射和映射

图中可以看出把0x00000000地址上的存储单元映射到了新的地址0x00000007上(重映射)。寄存器映射:对外设的操作原本是对外设的某些寄存器配置配置,但是把这个寄存器“链接”到地址上,就相当于对这个地址处的存储器操作就等价于对外设的操作,叫寄存器映射。在ARM微控制器设计中,给物理存储器分配逻辑地址的过程就称为存储器映射。把某个存储器(系统最开始默认的地址的存储器)重映射(重新分配)到一个新地址,对新地址的访问就相当于对系统最开始默认地址访问。ARM芯片中有些物理存储单元的地址可以根据设置变换。

2023-11-12 20:33:32 257

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除