Skip to content

xupenghu/learning_tinyOS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RTOS知识点简要概括

3.1 临界区保护 1、为什么需要临界区保护

临界区保护的目的是为了防止共享资源(包括全局变量等)被同时访问。比如任务1正在进行一个count++的操作,此时调度系统强行切换到任务2运行,任务2中也有count++的操作,那么 我们的count++操作就没有按照我们的设计目的来完成,就会出现原来的修改值被覆盖的问题。或者我们在一个任务中使用count++操作时发生了一个中断,在中断服务程序中操作count也会 出现同样的问题,所以,就需要引入临界区保护的措施。

2、怎么进行临界区的保护

先搞清楚发生共享资源访问冲突的两个种情况:1、任务切换时会发生访问冲突。2、中断发生时会发生访问冲突。 我们知道任务切换时是在PendSV中断中完成的,其本质也是发生了中断,那么在访问一些可能引发冲突的变量时,我们可以暂时关闭所有可屏蔽中断,这样就可以解决资源访问冲突的 问题。

3、这样操作有何缺点

1、关闭可屏蔽中断,使得系统的实时响应变差。 2、关闭可屏蔽中断,系统不能进行任务切换调度,只能执行当前任务中的代码,使得系统实时性变差。

3.2 调度锁保护

1、问什么需要调度锁的保护

1.1 为了解决临界区保护屏蔽所有中断使得系统实时性变差的问题 1.2 有些共享资源访问冲突只是在任务切换中体现,不设计中断中使用,此时我们应该让中断响应正常执行。

2、什么是调度锁保护

调度锁保护顾名思义就是上了调度锁后,调度系统暂时失效,必须要等当前任务被保护部分执行完毕解锁后才能继续进行任务调度。

3、怎么实现调度锁保护

调度锁保护的实现机制很简单,我们定义一个全局变量,当需要使用调度锁的时候,让该全局变量+1,然后再调度函数中判断该全局变量是否为0,如果为0,说明所有的调度锁都已 解锁,那么我们就执行调度算法,如果不为0,那么就有任务上锁了,直接退出。 注意:上锁资源中尽量不要出现延时函数,否则会影响延时效果。

FCARM - Output Name not specified, please check 'Options for Target - Utilities' 错误原因:引入了不知名的文件类型,需要查看文件属性来解决。

3.3 位图

引入位图的概念是为了引入优先级的概念

3.5 双向链表

引入双向链表是为了管理各种数据结构,也是为了方便扩展

3.6 延时队列的实现

之前的延时,实现的方式都是循环扫描各个task的delayTicks,如果delayTicks==0 那么就将该任务就绪,这样操作有一个缺点就是太耗时,taskTable中的有些task我们并没有定义 但是在扫描的时候我们还是扫描了delayTicks 这么操作就使得多做了一些无用功,需要优化。

我们优化的方式就是加入延时队列,将需要延时等待的任务加入到延时队列中来,将不需要延时等待的任务不加入。那么在systick中断中,我们只需要扫描对应的延时任务就行了。

3.7 相同优先级时间片轮流运行

我们之前提到的任务管理方式是使用tTask * taskTable[];来管理的,这种管理方式下,每个优先级只能有一个任务来运行。那么我们想让两个任务占用相同的优先级该怎么办呢? 方法和实现延时队列一样,使用list来管理taskTable,这样我们可以在这个任务队列中加入很多子任务。

4.1 任务的挂起和恢复

我们上节课已经将任务加入到任务队列中中去了,任务的挂起就是将该任务从任务队列中删除,任务恢复就是将该任务从任务队列中恢复。

本节内容还会将代码结构做一下调整,将对应的模块放在对应的文件中,这样后续的代码更好管理。

4.2 任务的删除

任务删除的关键是释放掉该任务所占用的资源。

有两种任务的删除操作:1) 别的任务强制删除其他任务。 2) 别的任务请求删除其他任务,其他任务检测到自己要被删除时,在调用删除自己任务的接口。

4.3 获取任务状态信息

我们定义了一个专门获取任务状态信息的函数,需要获取什么信息可以在task_info结构体中直接添加,调用也比较简单。

5.1 事件控制块

事件控制块有什么作用呢? 可以进行事件的同步 事件之间的通讯等等 事件控制块的实现是使用一个结构体将需要等待的事件和等待队列封装在一起,比如我们要实现任务的同步运行,可以将一个信号量封装成一个任务控制块,然后把需要同步的任务放在 等待队列中,当信号量清0时,等待队列中的任务就加入到就绪队列中去,这样就可以实现任务的同步了。同理还可以采集中断,置中断标志位来实现特定的任务的运行。

5.2 事件的等待与通知

我们需要在任务的结构体中加入等待事件的相关字段,当把等待事件加入到等待列表中时,我们需要把任务的等待相关字段设置,当把任务从等待列表中移除时,同样也需要配置任务 的等待相关字段,这样我们获取任务信息时,就可以得到该任务等待相关的字段。也就知道了任务是被什么唤醒的等等。

5.3 事件控制块的清空与状态查询

清空事件控制块列表就是将事件控制列表中的所有节点都释放掉,只需一个函数完成就行。

6.1 信号量的原理与创建

信号量的组成包括事件控制块和计数器,我们可以用信号量来实现资源的访问和任务同步等。本节主要完成了信号量的创建和初始化任务。

6.2 计数信号量的获取与释放

计数信号量可以看成是阻塞的,我们在当前任务中等待一个信号量时,如果这个信号量没有等到,我们就阻塞当前任务,然后切换到其他任务去运行。 如果其他任务通知了这个信号量,那么我们再将阻塞的任务从信号量列表中释放出来,加入到调度任务中去,这样就完成了信号量的获取和释放。

7.1 邮箱结构体的定义和初始化

我们使用邮箱来在各个任务之间传递信息,邮箱里面应该有一个任务控制块用来实现当任务没有获取到想要的信息且加入到等待队列中去,然后定义一个环形的数据缓冲区, 包括读索引、写索引、数据缓冲区的地址以及最大信息量和当前信息量等字段。

7.2 邮箱的等待和通知

我们使用邮箱的目的是为了在各个任务之间传递信息,其用法不同于信号量的是,我们在等待的时候,会等待一个信息出来。

7.3 邮箱的清空和销毁

邮箱清空就是将邮箱的信息字段全部清空,邮箱的销毁就是将邮箱中的等待队列全部移除,加入到调度列表中。

7.4 邮箱状态信息查询

定义一个状态信息结构体,然后将需要获取的邮箱状态拷贝出来就行了。

8.1 存储块的原理与创建

我们知道C库函数中有malloc和free两个函数专门用来内存的申请和创建的函数,但是在RTOS中,我们不希望这么做。因为RTOS运行的硬件环境中没有很多的RAM资源供我们管理,其次 malloc和free的RAM申请与释放本身就占用比较多的系统资源。我们采用另外一种方式来对内存进行申请和释放,那就是存储块。

存储块的原理是:我先划分固定大小的存储空间,然后将存储空间加入到存储队列中去,当有任务向我这里申请存储空间时,我就给它一个,当存储空间用完时,任务就进入等待 队列,当有新的存储块释放时,就让任务重新获取该存储队列并加入到任务调度系统。

About

从0到1开始入门RTOS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published