1. μC/OS-Ⅲ是一个可剥夺型内核,它总是运行当前就绪任务中优先级最高的那个
2. ISR通常只是发出一个信号或者一则消息
3. 使用多任务内核提供的功能函数会增加系统的开销
4. μC/OS-Ⅲ需要1~4KB的额外RAM资源,每个任务还需要自己的堆栈RAM空间。
5. μC/OS-Ⅲ提供70多个系统功能函数
6. 内核对象,指任务、信号量、互斥型信号量、事件标记、消息队列、定时器和存储块等。
7. 可剥夺型内核,指操作系统内核可随时剥夺正在运行的任务的CPU使用权,并将其交给刚刚进入就绪态的优先级更高的任务。
8. 每个任务能够单独定义时间片的长度
9. μC/OS-Ⅲ可以采用锁定内核调度的方式而不是关中断的方式来保护这些访问内部数据结构和变量的临界段。
10. 每个任务都需要有自己单独的栈空间,μC/OS-Ⅲ能够实现对堆栈使用情况的实时监测。
11. 互斥型信号量申请可以嵌套,最多可以嵌套250层。
12. 一个任务能够挂起在多个信号量或消息队列上。
13. μC/OS-Ⅲ允许中断或任务直接给另一个任务发信号
14. μC/OS-Ⅲ允许中断服务程序或一个任务直接给另一个任务发消息
15. 优先级相关的关键算法可以用汇编语言编写,以发挥一些CPU的特殊汇编指令的优势,例如位改写指令、计算前导零或发现首位壹等指令。
16. 将延迟处理和超时判断放在任务级代码完成,能极大地减少中断延迟时间。
17. μC/OS-Ⅲ使用了哈希散列表机制,进一步降低了处理延迟和超时判断的开销。
18. 板级支持包(BSP)是操作系统与目标板外设的交互代码。
19. 在创建一个任务时,必须为该任务分配一个任务控制块(OS_TCB)。
20. 任务栈必须声明为CPU_STK数据类型。
21. 任务栈空间可以静态分配,也可使用malloc()函数从堆中动态分配。
22. 一个任务想要访问某共享资源时,必须先获取互斥型信号量。
23. 中断服务程序(ISR)或任务可通过消息队列给其他任务发送消息。
24. 用户需要定义消息队列最多允许接收的消息数目。
25. 临界段代码,也叫临界区,是指那些必须完整连续运行,不可被打断的代码段。
26. 中断处理程序和任务都会访问的临界段代码,需要用关中断的方法加以保护;仅由任务访问的临界段代码,可以通过给调度器上锁的方法来保护。
27. 中断关闭时间受处理器指令执行速度和存储器访问速度的影响。
28. 在大多数嵌入式系统中,任务都采用无限循环的形式。
29. 任务与C函数不同,不允许返回。
30. 只要函数是可重入的,就可以在不同的任务中调用相同的C函数。
31. 除非已为静态变量或全局变量加上多重访问保护机制,否则,在可重入函数中不可以使用静态变量或全局变量。
32. 任务栈永远位于RAM中,可用来保存局部变量、函数调用以及可能的ISR嵌套。
33. 在分配栈空间时,必须考虑该任务调用的函数的嵌套情况、任务调用的嵌套函数所使用的局部变量的数目以及所有嵌套的ISR对堆栈的需求。
34. 在分配栈空间时,应保留一定的安全余量
35. 任务的休眠态是指任务已经存在于存储器中,但还不受μC/OS-Ⅲ的管理。
36. 任务就绪表根据任务优先级对任务进行排序。
37. 任务在等待某个事件发生的时候并不消耗任何CPU时间。
38. 一般来说,ISR应当只是通知任务某个事件已经发生,而事件的处理则交给任务。
39. 任务的TCB由用户在用户存储空间(RAM)中分配。
40. 如果把ASCII字符串声明为常量(const),则该字符串会被放入用户ROM空间中,否则,会被放入RAM空间中。
41. 堆栈基地址通常是任务堆栈存储区的最低地址。
42. 在每个任务的TCB中都建立了一个消息队列。
43. 任务挂起可以嵌套。
44. 空闲任务是一个真正的无限循环,它不得调用任何会使其进入等待态的服务函数。
45. 一般来说,大部分处理器都会在发生中断时退出低功耗模式。
46. 时钟节拍列表由一个数据表和一个计数器构成。
47. 时钟节拍中断服务程序仅需唤醒时钟节拍任务,可大大缩短中断处理时间。
48. 多数开发C应用程序的编译器都会为CPU创建启动代码,引导CPU来执行main()函数。
49. 当创建任务时,必须指定该任务所使用的任务控制块的地址、任务的优先级、任务堆栈所在的RAM区以及一些其他的参数。
50. μC/OS-Ⅲ最多会创建5个系统任务:空闲任务、时钟节拍任务、统计任务、中断服务管理任务和定时器任务。
51. 就绪任务列表的索引号就是任务对应的优先级。
52. 中断处理任务从消息队列中删除发布请求,并执行相应的发布操作。
53. 当消息队列读取完毕时,μC/OS-Ⅲ将中断处理任务从就绪列表中移除,并切换到获得信号量或者消息的任务。
54. 当所有嵌套的中断结束时,会启动调度器来确定这些中断是否使得有更高优先级的任务进入就绪态。
55. μC/OS-Ⅲ允许用户在运行时使能或者禁止时间片轮转调度。
56. μC/OS-Ⅲ采用可剥夺型调度算法,总是执行进入就绪态的优先级最高的任务。
57. 在程序调用某些μC/OS-Ⅲ的服务函数时,调度器会启动
58. μC/OS-Ⅲ有两个调度器:在任务级代码使用OSSched(),而在中断服务程序结束时则调用OSIntExit()。
59. 任务切换的时间取决于有多少寄存器需要保存和恢复。
60. 任务在建立的时候就进入就绪态,它们的堆栈是由软件来初始化的,使得与发生中断后的堆栈相似。
61. 任务堆栈指针指向最后一个入栈的寄存器。
62. 中断堆栈指针指向中断堆栈当前的栈顶
63. 程序计数器和状态寄存器通常是在执行中断返回指令时弹出堆栈的。
64. 中断是一种硬件机制,用于通知CPU一个异步事件发生了。
65. CPU在确认中断后,将其部分或全部寄存器入栈保存,并跳转执行一个特殊的函数,这个函数称为中断服务程序。
66. 中断处理的实时性通常比轮询方式好。
67. 在实时系统中,应尽量减少关中断的时间。
68. 实时多任务内核的一个重要指标是中断关闭总时间。
69. 实时多任务内核在运行临界段代码之前会关闭中断,在临界段代码运行完后重新打开中断。
70. 中断响应时间是指从中断被识别到对应的中断处理代码开始执行的时间
71. CPU处理中断的模式有两种:①所有的中断映射(vector)到一个共用的中断服务程序;②每个中断映射到各自的中断服务程序。
72. μC/OS-Ⅲ的中断服务程序需使用汇编语言编写。
73. 中断服务程序首先需要将CPU的寄存器保存到被中断任务的堆栈中。
74. 清除中断请求以避免重复执行中断服务。
75. 调用用C语言编写的用户中断处理程序(ISR Handler)做进一步的处理。
76. 通常的规则是保持中断服务程序(ISR)尽可能精简,最好在中断服务程序中进给任务发布信号或消息,让任务来完成那些复杂的操作。
77. “中断服务程序”指中断响应到中断返回之间的程序,包括开关中断、CPU寄存器入栈出栈、用户中断处理程序等。
78. μC/OS-Ⅲ的C处理函数查询中断控制器,问道“哪个中断源请求中断了?”,中断控制器提供一个0到N-1的数字,C处理函数会简单地将其作为索引号,在中断向量表(位于ROM或者RAM)中找到对应的中断处理程序的入口地址。
79. μC/OS-Ⅲ对从中断发布消息或信号的处理有两种模式:直接发布和延迟发布。
80. 中断响应时间 = 中断延迟时间 + 中断向量映射时间 + 中断预处理时间
81. 任务延迟时间 = 中断响应时间 + 中断恢复时间 + 任务调度锁定的时间
82. 直接发布模式下,仅在处理定时器的时候才会给任务调度器上锁。
82. 中断服务程序通过调用系统的发布服务函数向任务发布消息或信号。
83. 中断队列处理任务将处理队列处理完,将自身挂起,并重新启动任务调度来运行处于最高优先级的就绪任务。
84. 中断队列处理任务提取出发布函数调用的信息后重新开中断,锁定任务调度器,然后进行发布函数调用,相当于发布函数调用一直是在任务级代码中进行的。
85. 直接发布模式下,μC/OS-Ⅲ通过关闭中断来保护临界段代码。延迟发布模式下,μC/OS-Ⅲ通过锁定任务调度来保护临界段代码。
86. 广播消息或信号量的时候,μC/OS-Ⅲ需要关闭中断。
87. 时钟节拍也是所有定时器的计时基准。
88. μC/OS-Ⅲ通过任务挂起表跟踪正在等待信号量、互斥型信号量、事件标志组和消息队列的任务。
89. OSTimeSet()允许用户改变当前时钟节拍计数器的值。
90. 所谓定时器本质上是递减计数器,当计数器减到零时可以触发某种动作的执行。
91. 定时器在创建以后可以启动(或重启)和停止任意次数,其运行模式包括三种:单次模式、无初始延迟的周期模式和有初始延迟的周期模式。
92. OSTmrTask()是一个周期任务,并采用与产生时钟节拍相同的中断源。
93. 定时器回调函数不允许等待事件,因为这样会占用定时器任务的时间。
94. 调用回调函数时,调度器是上了锁的,所以必须要保证回调函数尽快执行完毕。
95. 每个回调函数执行的顺序是根据它们在定时器列表中的位置决定的。
96. 为了避免更新这些定时器占用过多的CPU资源,系统需要实现定时器列表管理机制。
97. μC/OS-Ⅲ允许应用程序创建任意数量的定时器(其只受可用RAM大小的限制)。
98. 回调函数的执行是在定时器任务内完成的,此时调度器是上了锁的。
99. 回调函数的编写必须尽量简洁以保证快速执行,并且不能有任务阻塞调用。
100. 当不同任务处于同一寻址空间时,任务之间可以简单地共享数据,并能够同时引用全局变量、指针、缓存、链表、环形缓冲区等。
101. 最常用的独占共享资源和创建临界区的方法有以下几种:①关中断;②禁止任务调度;③使用信号量;④使用互斥型信号量。
102. 使用信号量可能导致优先级反转的问题,然而其优点在于它的速度比使用互斥型信号量要略微快一些
103. μC/OS-Ⅲ的互斥型信号量具有一套内建的优先级继承机制,用来避免优先级反转的问题。
104. 关中断和开中断事实上是CPU相关函数,而非系统相关函数。
105. 关中断和开中断是一个任务和一个中断服务程序共享变量或者数据结构的唯一方法。
106. 在使用μC/OS-Ⅲ时,只要关中断的时间不比μC/OS-Ⅲ系统本身的关中断时间长,就不会影响到系统的中断延迟时间。
107. 如果调度器已经上锁了,但并没有关中断,那么一旦中断发生,即便在临界区内,中断服务程序也将被立即执行。
108. 只有当调度器解锁后,μC/OS-Ⅲ才会在那些具有高优先级的任务进入就绪态后,执行任务切换。
109. 在调度器上锁时,μC/OS-Ⅲ会禁止用户进行阻塞型调用。
110. 一旦给调度器上锁,则当前的任务就直接被提升为具有最高优先级的任务了。
111. 信号量原先常被用来控制对共享资源的访问,但现在则基本被用来作任务之间的同步
112. 在共享资源时,只有任务才能使用信号量,中断服务程序则不能使用。
113. 当信号量释放时,μC/OS-Ⅲ会记录一个时间戳,并在OSSemPend()返回时返回该时间戳。
114. μC/OS-Ⅲ支持一种特殊的二进制信号量,其被称做互斥型信号量。用它可以解决无界优先级反转的问题
115. 与信号量一样,只有任务才能使用互斥型信号量(中断服务程序则不可以)。
116. 所有的数据类型都以“OS_”开头,且所有字母大写。
117. 互斥型信号量包含了一个时间戳来记录上一次被释放的时间。
118. 一旦任务被阻塞了,调度器便会介入,调度器会转而运行下一个已就绪的具有最高优先级的任务。
119. 如果没有任务对共享资源的访问有截止时间,那么普通信号量就可以替代互斥型信号量;反之则必须使用互斥型信号量。因为前者会造成无界优先级反转
120. μC/OS-Ⅲ支持任务在请求互斥型信号量时设定了一个超时时间。
121. 使用何种互斥机制取决于代码对共享资源的访问速度
122. μC/OS-Ⅲ中有两种基本的同步机制:信号量和事件标志。
123. 信号量被用来控制存取共享资源。但是,更多被用来实现任务间的同步以及任务和ISR间的同步
124. 当任务需要启动I/O操作并等待信号量时会使用单向同步
125. ISR处理完中断后调用OSSemPost()函数来发布信号量。ISR退出时会调用OSIntExit()函数。
126. μC/OS-Ⅲ使用该计数变量记录信号量被发布的次数,通常情况下,该变量被OSSemCreate()初始化为0。
127. 信号量中包含时间戳,用来记录最近一次发布信号量的时间。
128. 将信号量计数值初始化为非零值,表示资源的初始可用数
129. 任务可以调用OSSemPend()函数来等待ISR或其他任务发布信号
130. 超时时间为零则意味着调用任务将一直等下去,直至信号量被发布。
131. 当ISR或其他任务给任务发布信号量时,需要调用OSSemPost()函数
132. 调用时通过传入信号量的地址作为参数来指定发布哪个信号量。
133. 给任务发布信号量是一种非常常用的同步方法
134. 在μC/OS-Ⅲ中,每个任务都有它自己的内嵌信号量。
135. 两个任务可以使用两个任务信号量同步它们的行为,这种情况被称为双向同步。
136. 双向同步不能用于任务和ISR之间的同步,因为ISR不能等待信号量。
137. 当任务需要与多个事件的发生同步时,可以使用事件标志组。
138. 用户需要在启动μC/OS-Ⅲ之前,或在启动任务中创建事件标志组。
139. 任务和ISR都可以发布事件标志。
140. 如果等待的事件标志组在设定的时间内没有被发布,那么μC/OS-Ⅲ会使挂起的任务进入就绪态并通知它等待超时。
141. 调用OSFlagPend()函数并传入目标事件标志组的地址,来实现等待事件标志组的操作。
142. 当发布事件标志时,μC/OS-Ⅲ会自动读取、保存时间戳。
143. 事件标志通常有两种用途:状态信息监控和瞬时事件监控。
144. 为了处理多个任务等待同一个事件标志组的情况,事件标志组对象中包含了一个任务等待表。
145. 事件标志组中包含时间戳,用来表示最近一次发布事件标志的时间。
146. 进行广播操作的任务必须在所有与待同步任务对应的事件标志都被置位后才可以进行广播操作。
147. ISR和任务都可以通过三种方式向一个或多个任务发信号:信号量、任务信号量和事件标志组。
148. 任务信号量服务函数的执行速度也比信号量服务函数的执行速度要快。
149. 事件标志不支持信用记录功能,因为在事件标志组中每个事件用一个数据位(而不是使用计数器)表示。
150. 任务间的信息传递可以通过两种途径实现:一是通过全局变量,二是通过发布消息。
151. 任务要想与中断服务程序通信,只能通过全局变量。
152. 消息可以通过消息队列作为中介发布给任务,也可以直接发布给任务
153. 在μC/OS-Ⅲ中,每一个任务都有其内建的消息队列。
154. 发布数据采用的是引用传递,是指针传递而不是值传递。也就说,发布的数据本身并不产生拷贝。
155. 消息队列是一种由用户程序分配的内核对象。
156. 用户可以分配任意数量的消息队列,唯一的限制就是可用的RAM区的容量。
157. 发布的数据必须一直保持其可见性,因为数据传递采用的是引用传递,而不是值传递。
158. μC/OS-Ⅲ允许任务同时等待多个内核对象。
159. OSPendMulti()仅允许同时等待多个信号量和消息队列,不允许同时等待事件标志组和互斥型信号量。
160. 调用OSMemCreate()函数可以创建一个存储分区。
161. 调用OSMemPut()函数就可以将存储块归还存储分区。
162. OSMemCreate()函数仅供任务级的代码调用,但是OSMemGet()函数和OSMemPut()函数可以被ISR调用。
163. 因为添加时间戳操作是μC/OS-Ⅲ的内嵌特性,所以没有必要在消息中加时间戳
164. 不要在嵌入式系统中使用malloc()函数和free()函数,因为它们会引起存储空间碎片。
165. 用户可以创建任意多个存储分区(仅受限于RAM空间容量)。
166. μC/OS-Ⅲ中那些操作CPU寄存器的代码,仍只能使用汇编语言编写,除非C编译器支持内嵌汇编语言。
167. 使用的工具链须包含汇编器、C编译器和链接/定位器。
168. R13链接寄存器(LR)中保存函数调用的返回地址。
169. R15是程序计数器(指令指针)。
170. CPU有两个相互独立的堆栈指针R14和R14',R14代表任务堆栈指针(TSP),R14'代表ISR堆栈指针(ISP)。
171. 状态寄存器(SR)中包含中断屏蔽位以及其他状态标志位,如进位标志、零标志、符号标志、溢出标志、相等标志等。
172. 我们总是先递减栈顶指针,然后再将数据入栈。
173. 任务堆栈的初始化其实是在模拟一个中断,并按照ISR将寄存器入栈的顺序把寄存器推入堆栈
174. 当用户运行中断(或异常处理)返回指令时,PC寄存器会自动载入待运行任务的地址。
175. OSTaskSwHook()函数会将被挂起的任务运行期间的最长关中断时间存储到该任务的任务控制块中。
176. 堆栈指针SP是取自于将要执行的第一个任务的OS_TCB任务控制块的
177. 中断(异常)返回指令是单条指令,该指令恢复程序计数器(PC)和状态寄存器(SR)。
178. 如果该中断打断了某个任务,则需要将被中断的任务的堆栈指针保存到其任务控制块中。
179. 当中断发生时,处理程序会向中断控制器请求需要运行的中断服务程序的地址。
180. 用户需要为时钟节拍中断服务程序设置中断向量,设置的方法取决于CPU的体系结构。
181. 用户需要调用一个函数将中断向量填写到RAM中。
182. μC/OS-Ⅲ的移植工作包括四个内核相关文件(os_cpu.h、os_cpu_a.asm、os_cpu_a.inc和os_cpu_c.c)的代码编写或修改。
183. 每个信号量都有一个等待任务列表,记录等待信号量的任务。
184. 每个互斥型信号量都有一个任务列表,记录了等待信号量的任务。
185. 每个消息队列都有一个等待任务列表,记录了等待队列中消息的任务。
186. 每个事件标志组都有一个等待任务列表,记录了等待事件标志的任务。
187. 把当前任务的堆栈指针保存到当前任务的任务控制块OS_TCB中。
188. 寄存器入栈的顺序必须和CPU在处理中断时自动保存寄存器的入栈顺序相同
189. 从要恢复运行的任务的OS_TCB中恢复该任务的堆栈指针。
190. 从要恢复运行的任务的堆栈中恢复CPU所有的寄存器值。
191. 通常在删除事件标志组前,要先删除等待这个事件标志组的所有任务。
192. 任务等待的条件可以是标志组里任意一个标志置位或清零,也可以是所有事件标志都置位或清零。
193. 如果任务等待的事件标志组不满足设置的条件,那么该任务被置为挂起状态
194. 从新任务的OS_TCB中,将该任务的堆栈指针载入CPU的堆栈指针寄存器。
195. OSMemCreate()创建并初始化一段内存分区。这个内存分区包含了用户指定数量的固定大小的内存块。
196. 内存分区控制块必须由应用程序进行分配。
197. OSMemGet()这个函数为非阻塞函数,可以在中断服务程序中进行调用。
198. 互斥型信号量本身必须由应用程序进行实际分配。
199. OSMuxtexPend()函数将把当前占有信号量的任务的优先级提高到和当前申请任务的优先级一致。
200. 用户不能等待多个事件标志组和互斥型信号量。
201. 消息队列的存储空间必须由应用程序进行实际分配。
202. 被OSTaskSuspend()函数挂起的任务仍然可以接收消息。
203. 用户不能从中断服务程序中调用OSQPend()。
204. OSQPendAbort()使正在等待消息队列的任务结束挂起状态,并进入就绪态。
205. OSQPendAbort()返回终止等待状态、恢复就绪状态的任务的数量。
206. 用户通过调用OSQPost()来向消息队列发送消息。
207. 通过opt选项,可以设置消息队列为先入先出形式或后入先出形式。
208. 当调用完OSSafetyCriticalStart()函数后,不允许再调用创建任务、信号量、互斥型信号量、消息队列、事件标志组或定时器的函数。
209. 任务可以通过OSSched()函数来调用调度器。
210. 如果关闭了内核调度,则调用OSSched()函数将不起任何作用。
211. OSSchedLock()函数锁定系统任务调度器
212. 调用OSSchedLock()函数的任务将可以持续使用CPU,而不管是否有更高优先级的任务进入就绪态。
213.