RTOS知识点

RTOS任务创建:

       如果栈向下增长,则首先分配栈内存,然后分配任务控制块(TCB),这样栈就不会增长到TCB的内存区域。同样地,如果栈向上增长,则首先分配TCB,然后分配栈内存。

  • 栈向下增长:在这种情况下,先为任务栈分配内存,再为TCB分配内存。这样做可以确保栈向下扩展时不会覆盖到TCB的内存区域。
  • 栈向上增长:在这种情况下,先为TCB分配内存,再为任务栈分配内存。这样可以防止栈向上扩展时覆盖到TCB。
  • 这种内存分配策略有助于避免栈溢出错误,确保每个任务的栈和TCB之间有正确的内存布局。

         pxNewTCB->pxStack表示将分配的栈内存基地址赋值给TCB 指针

        pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB表示标记任务的内存分配状态,以便 FreeRTOS 能够在任务生命周期结束时正确地管理内存。

信号量:

1、信号量与队列的区别:

 

互斥量:

  1、队列和信号量都可以完成互斥访问,但是效果不完美。

2、互斥量是一种特殊的二进制信号量,但是互斥量无法在ISR中使用。主要区别如下:

事件组:

任务通知:

定义:多对一的方式,与其他队列、信号量等都不一样,并且知道谁接收通知,无需中间通信结构体。

缺点:ISR无法接收数据

           无法缓冲数据,接受任务结构体中只有一个通知值

           接收方任务独享资源,因为数据直接存到其结构体内部

          发送方无法进入堵塞状态,无法发送通知给接受任务时会返回错误

          无法给多个任务发送数据

         通知值为32位无符号整形

任务结构体:通知状态和通知值

任务通知常用函数:

简化版:任务A为发送通知任务,任务B为接收任务。

任务A调用xTASKNotifyGive给任务B发送通知,它会使任务B中的val++。如果任务B处于调用ulTaskNotifyTake函数,则其处于等待通知状态,任务B会被唤醒,val--。如果任务B未调用Take函数,则其处于接收数据状态,当其调用take函数后会立刻接收通知(不会进入阻塞等待),val--。专业版:任务A为发送通知任务,任务B为接收任务。

相较于简化版,专业版需要考虑参数。

其中,第一个参数为要接收数据的任务,第二个参数为要传的值,第三个参数是如何用。其中4表示如果存在通知值,新的通知值被舍弃,5与其相反直接进行覆盖。

其中,第一个参数表示如果通知状态不是接收数据,清楚某些位,本意是等待某些事件产生,把之前旧数据的某些位请0。

软件定时器:

        RTOS中的软件定时器都是基于tick interupt,定时器可以当作一个结构体(包括超时时间、一次性/周期性、period、回调函数、参数、链表等等)。

        因为其和tick中断有关,但是并不会在中断函数中执行定时器。这是因为RTOS不允许内核/中断中执行不确定的代码,并且如果定时器函数消耗很多时间,会影响整个系统。故将其放入任务中运行,此任务在初始化调度器时候就会自动创建(若想使用定时器,需要将FreeRTOS的配置项configUSE_TIMERS被设置为1)。

        整个定时器运行流程:通过调用定时器函数,进行写队列(通知唤醒定时器任务),之后读队列,并处理定时器回调函数。需要注意的是,如果任务在t1时刻就调用了定时器函数(命令被写入队列,但是由于其他任务优先级高,定时器任务进入阻塞状态),在t4时刻内核才读队列,定时器在tx时刻超时,超时时间为tx-t1(超时时间-定时器函数被调用时间)。

软件和中断两套函数:

根本原因:中断需要尽快处理,否则(1、低优先级的中断无法执行,实时性较差2、中断的优先级永远大于任务优先级,故程序会卡顿)

任务写队列函数,写队列存在两种情况

1、队列满,无法继续写入,自己变阻塞态

2、队列空,写队列,唤醒等待接收的任务(若唤醒的任务优先级更高,写队列所需时间可能无穷大;唤醒任务的优先级低于自己,则写队列时间为0)。

中断写队列函数

假设硬件中断函数里面有个大的循环,执行写队列操作时,若队列为空,则会唤醒接收任务,接收任务将从阻塞态变为就绪态,当接收任务的优先级高于发送任务,会切换到接受任务,这时程序需要保留发送任务的现场,包括寄存器的值等等,恢复新任务的现场,多次循环的话耗费相当多时间,与中断应尽快完成的理论不符合。因此,在中断函数里面写队列,若接收任务优先级比发送任务高,会标记下这个接收任务,在中断函数退出前调度 。

资源管理:

        前文中通过全局变量可以解决临界资源访问,但是并不是非常完美,如果出现下图情况,还是会出现多任务访问同意共享资源时出现冲突。

        针对上述问题,常见的方法引入信号量/互斥量,当一个任务拥有钥匙的时候,即使发生任务切换,其他任务没得钥匙也无法访问共享资源(公平竞争)。除此之外引入另外种方法,若是任务来抢资源就关闭调度器,中断抢资源就关闭中断。

1、屏蔽中断

①任务中屏蔽中断

左边的函数代表屏蔽中断,右边的函数代表重新使能中断。

②ISR中屏蔽中断

关于ISR中屏蔽中断,在屏蔽终端前会通过函数

获得中断的状态(因为ISR中中断可能是使能也能是禁止状态,所以要记录中断状态,便于访问完临界资源后恢复),调用taskenter保存中断状态、关闭中断,访问临界资源,调用taskexit恢复中断。

2、关闭调度器

        如果存在优先级比你高的任务来抢夺资源,无需关闭中断,仅需暂停调度器即可。通过下面函数实现调度器关闭开启

关闭调度器的实质:判断uxSchedulerSuspended是否为0,若为非0则会关闭调度器。

        关于队列和事件组如何实现临界资源保护:

1、队列

任务/中断:写队列都是通过关中断实现临界资源保护;

2、事件组

任务/中断:关调度器

在中断中设置事件组->写定时器队列,实质上是触发定时器任务,在定时器任务里面写事件值 。所以对事件组的保护没必要关中断,其在任务中实现,通过开关调度器即可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值