├── .gitignore
├── Code
├── .vscode
│ └── settings.json
├── DebugConfig
│ └── Target_1_STM32F429ZETx.dbgconf
├── EventRecorderStub.scvd
├── LinOS.uvguix.Administrator
├── LinOS.uvguix.dalin-vm
├── LinOS.uvoptx
├── LinOS.uvprojx
├── LinRTOS Kernel
│ ├── Bitmap.c
│ ├── Event.c
│ ├── EventGroup.c
│ ├── Lists.c
│ ├── Mailbox.c
│ ├── Mempool.c
│ ├── Mutex.c
│ ├── Sem.c
│ ├── Tasks.c
│ ├── Timer.c
│ ├── inc
│ │ ├── Bitmap.h
│ │ ├── Event.h
│ │ ├── EventGroup.h
│ │ ├── LinOS.h
│ │ ├── LinOSConfig.h
│ │ ├── Lists.h
│ │ ├── Mailbox.h
│ │ ├── Mempool.h
│ │ ├── Mutex.h
│ │ ├── Sem.h
│ │ ├── Tasks.h
│ │ └── Timer.h
│ └── portable
│ │ ├── RVDS
│ │ ├── port.c
│ │ └── port.h
│ │ ├── portcpu.c
│ │ └── portcpu.h
├── RTE
│ ├── Device
│ │ ├── ARMCM3
│ │ │ ├── startup_ARMCM3.s
│ │ │ └── system_ARMCM3.c
│ │ ├── ARMCM4
│ │ │ ├── startup_ARMCM4.s
│ │ │ └── system_ARMCM4.c
│ │ └── STM32F429ZETx
│ │ │ ├── startup_stm32f429xx.s
│ │ │ └── system_stm32f4xx.c
│ └── _Target_1
│ │ └── RTE_Components.h
└── User
│ └── main.c
├── Image
├── LinRTOS_Kernel.png
├── 整体框图.png
└── 整体框架.png
├── LICENSE
└── README.MD
/.gitignore:
--------------------------------------------------------------------------------
1 | /Code/Objects
2 |
3 |
--------------------------------------------------------------------------------
/Code/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "*.s": "c",
4 | "tasks.h": "c",
5 | "lists.h": "c",
6 | "linos.h": "c",
7 | "port.h": "c",
8 | "event.h": "c",
9 | "stdint.h": "c",
10 | "bitmap.h": "c",
11 | "sem.h": "c",
12 | "mailbox.h": "c",
13 | "linosconfig.h": "c"
14 | }
15 | }
--------------------------------------------------------------------------------
/Code/DebugConfig/Target_1_STM32F429ZETx.dbgconf:
--------------------------------------------------------------------------------
1 | // File: STM32F405_415_407_417_427_437_429_439.dbgconf
2 | // Version: 1.0.0
3 | // Note: refer to STM32F405/415 STM32F407/417 STM32F427/437 STM32F429/439 reference manual (RM0090)
4 | // refer to STM32F40x STM32F41x datasheets
5 | // refer to STM32F42x STM32F43x datasheets
6 |
7 | // <<< Use Configuration Wizard in Context Menu >>>
8 |
9 | // Debug MCU configuration register (DBGMCU_CR)
10 | // DBG_STANDBY Debug Standby Mode
11 | // DBG_STOP Debug Stop Mode
12 | // DBG_SLEEP Debug Sleep Mode
13 | //
14 | DbgMCU_CR = 0x00000007;
15 |
16 | // Debug MCU APB1 freeze register (DBGMCU_APB1_FZ)
17 | // Reserved bits must be kept at reset value
18 | // DBG_CAN2_STOP CAN2 stopped when core is halted
19 | // DBG_CAN1_STOP CAN2 stopped when core is halted
20 | // DBG_I2C3_SMBUS_TIMEOUT I2C3 SMBUS timeout mode stopped when core is halted
21 | // DBG_I2C2_SMBUS_TIMEOUT I2C2 SMBUS timeout mode stopped when core is halted
22 | // DBG_I2C1_SMBUS_TIMEOUT I2C1 SMBUS timeout mode stopped when core is halted
23 | // DBG_IWDG_STOP Independent watchdog stopped when core is halted
24 | // DBG_WWDG_STOP Window watchdog stopped when core is halted
25 | // DBG_RTC_STOP RTC stopped when core is halted
26 | // DBG_TIM14_STOP TIM14 counter stopped when core is halted
27 | // DBG_TIM13_STOP TIM13 counter stopped when core is halted
28 | // DBG_TIM12_STOP TIM12 counter stopped when core is halted
29 | // DBG_TIM7_STOP TIM7 counter stopped when core is halted
30 | // DBG_TIM6_STOP TIM6 counter stopped when core is halted
31 | // DBG_TIM5_STOP TIM5 counter stopped when core is halted
32 | // DBG_TIM4_STOP TIM4 counter stopped when core is halted
33 | // DBG_TIM3_STOP TIM3 counter stopped when core is halted
34 | // DBG_TIM2_STOP TIM2 counter stopped when core is halted
35 | //
36 | DbgMCU_APB1_Fz = 0x00000000;
37 |
38 | // Debug MCU APB2 freeze register (DBGMCU_APB2_FZ)
39 | // Reserved bits must be kept at reset value
40 | // DBG_TIM11_STOP TIM11 counter stopped when core is halted
41 | // DBG_TIM10_STOP TIM10 counter stopped when core is halted
42 | // DBG_TIM9_STOP TIM9 counter stopped when core is halted
43 | // DBG_TIM8_STOP TIM8 counter stopped when core is halted
44 | // DBG_TIM1_STOP TIM1 counter stopped when core is halted
45 | //
46 | DbgMCU_APB2_Fz = 0x00000000;
47 |
48 | // <<< end of configuration section >>>
--------------------------------------------------------------------------------
/Code/EventRecorderStub.scvd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Code/LinOS.uvoptx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.0
5 |
6 | ### uVision Project, (C) Keil Software
7 |
8 |
9 | *.c
10 | *.s*; *.src; *.a*
11 | *.obj; *.o
12 | *.lib
13 | *.txt; *.h; *.inc; *.md
14 | *.plm
15 | *.cpp; *.cc; *.cxx
16 | 0
17 |
18 |
19 |
20 | 0
21 | 0
22 |
23 |
24 |
25 | Target 1
26 | 0x4
27 | ARM-ADS
28 |
29 | 12000000
30 |
31 | 1
32 | 1
33 | 0
34 | 1
35 | 0
36 |
37 |
38 | 1
39 | 65535
40 | 0
41 | 0
42 | 0
43 |
44 |
45 | 79
46 | 66
47 | 8
48 | .\Listings\
49 |
50 |
51 | 1
52 | 1
53 | 1
54 | 0
55 | 1
56 | 1
57 | 0
58 | 1
59 | 0
60 | 0
61 | 0
62 | 0
63 |
64 |
65 | 1
66 | 1
67 | 1
68 | 1
69 | 1
70 | 1
71 | 1
72 | 0
73 | 0
74 |
75 |
76 | 1
77 | 0
78 | 1
79 |
80 | 7
81 |
82 | 1
83 | 0
84 | 1
85 | 1
86 | 1
87 | 1
88 | 1
89 | 1
90 | 1
91 | 1
92 | 1
93 | 1
94 | 1
95 | 1
96 | 0
97 | 1
98 | 1
99 | 1
100 | 1
101 | 0
102 | 0
103 | 1
104 | 0
105 | 0
106 | 0
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 | BIN\UL2CM3.DLL
118 |
119 |
120 |
121 | 0
122 | UL2CM3
123 | UL2CM3(-S0 -C0 -P0 ) -FC1000 -FD20000000
124 |
125 |
126 | 0
127 | ARMRTXEVENTFLAGS
128 | -L70 -Z18 -C0 -M0 -T1
129 |
130 |
131 | 0
132 | DLGDARM
133 | (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)
134 |
135 |
136 | 0
137 | ARMDBGFLAGS
138 | -T0
139 |
140 |
141 |
142 |
143 |
144 | 0
145 | 1
146 | timer1
147 |
148 |
149 | 1
150 | 1
151 | timer2
152 |
153 |
154 | 2
155 | 1
156 | tTask1
157 |
158 |
159 | 3
160 | 1
161 | tTask2
162 |
163 |
164 | 4
165 | 1
166 | \\vTaskSchedule\Source/main.c\tTask3
167 |
168 |
169 | 5
170 | 1
171 | \\vTaskSchedule\Source/main.c\tTask4
172 |
173 |
174 | 6
175 | 1
176 | timerTask
177 |
178 |
179 | 7
180 | 1
181 | timerHardList
182 |
183 |
184 | 8
185 | 1
186 | timerSoftList
187 |
188 |
189 | 9
190 | 1
191 | timer3
192 |
193 |
194 | 10
195 | 1
196 | taskInfo1
197 |
198 |
199 | 11
200 | 1
201 | taskInfo2
202 |
203 |
204 | 12
205 | 1
206 | taskInfo3
207 |
208 |
209 | 13
210 | 1
211 | systemTicks,0x0A
212 |
213 |
214 | 14
215 | 1
216 | ans
217 |
218 |
219 |
220 |
221 | 0
222 | 2
223 | eventGroup1
224 |
225 |
226 |
227 |
228 | 1
229 | 0
230 | 0x20002A54
231 | 0
232 |
233 |
234 |
235 | 0
236 |
237 |
238 | 0
239 | 1
240 | 1
241 | 0
242 | 0
243 | 0
244 | 0
245 | 1
246 | 0
247 | 0
248 | 0
249 | 0
250 | 0
251 | 0
252 | 0
253 | 0
254 | 1
255 | 0
256 | 0
257 | 0
258 | 1
259 | 0
260 | 0
261 | 0
262 |
263 |
264 |
265 | 0
266 | 0
267 | 0
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 | 0
279 | `task1Flag
280 | 008000000000000000000000000000000000F03F010000000000000000000000000000007461736B31466C6167000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000006B33154828BCCF3F1200000000000000000000000000000000000000CC040008
281 |
282 |
283 | 1
284 | `task3Flag
285 | 00008000000000000000E0C10000C0FFFFFFDF41010000000000000000000000000000007461736B33466C616700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000003000000E36794F81925CE3F12000000000000000000000000000000000000006C030008
286 |
287 |
288 | 2
289 | `task4Flag
290 | 00000000000000000000E0C10000C0FFFFFFDF41010000000000000000000000000000007461736B34466C616700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000004000000E232E093C365D03F120000000000000000000000000000000000000060030008
291 |
292 |
293 | 3
294 | `task2Flag
295 | 000000000000000000000000000000000000F03F000000000000000000000000000000007461736B32466C61670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410000000200000078FFCA4B9BA9D03F120000000000000000000000000000000000000060030008
296 |
297 |
298 |
299 |
300 |
301 |
302 | User
303 | 1
304 | 0
305 | 0
306 | 0
307 |
308 | 1
309 | 1
310 | 1
311 | 0
312 | 0
313 | 0
314 | .\User\main.c
315 | main.c
316 | 0
317 | 0
318 |
319 |
320 |
321 |
322 | LinRTOS
323 | 0
324 | 0
325 | 0
326 | 0
327 |
328 | 2
329 | 2
330 | 1
331 | 0
332 | 0
333 | 0
334 | .\LinRTOS Kernel\Bitmap.c
335 | Bitmap.c
336 | 0
337 | 0
338 |
339 |
340 | 2
341 | 3
342 | 1
343 | 0
344 | 0
345 | 0
346 | .\LinRTOS Kernel\Event.c
347 | Event.c
348 | 0
349 | 0
350 |
351 |
352 | 2
353 | 4
354 | 1
355 | 0
356 | 0
357 | 0
358 | .\LinRTOS Kernel\EventGroup.c
359 | EventGroup.c
360 | 0
361 | 0
362 |
363 |
364 | 2
365 | 5
366 | 1
367 | 0
368 | 0
369 | 0
370 | .\LinRTOS Kernel\Lists.c
371 | Lists.c
372 | 0
373 | 0
374 |
375 |
376 | 2
377 | 6
378 | 1
379 | 0
380 | 0
381 | 0
382 | .\LinRTOS Kernel\Mailbox.c
383 | Mailbox.c
384 | 0
385 | 0
386 |
387 |
388 | 2
389 | 7
390 | 1
391 | 0
392 | 0
393 | 0
394 | .\LinRTOS Kernel\Mempool.c
395 | Mempool.c
396 | 0
397 | 0
398 |
399 |
400 | 2
401 | 8
402 | 1
403 | 0
404 | 0
405 | 0
406 | .\LinRTOS Kernel\Mutex.c
407 | Mutex.c
408 | 0
409 | 0
410 |
411 |
412 | 2
413 | 9
414 | 1
415 | 0
416 | 0
417 | 0
418 | .\LinRTOS Kernel\Sem.c
419 | Sem.c
420 | 0
421 | 0
422 |
423 |
424 | 2
425 | 10
426 | 1
427 | 0
428 | 0
429 | 0
430 | .\LinRTOS Kernel\Tasks.c
431 | Tasks.c
432 | 0
433 | 0
434 |
435 |
436 | 2
437 | 11
438 | 1
439 | 0
440 | 0
441 | 0
442 | .\LinRTOS Kernel\Timer.c
443 | Timer.c
444 | 0
445 | 0
446 |
447 |
448 |
449 |
450 | Portable
451 | 1
452 | 0
453 | 0
454 | 0
455 |
456 | 3
457 | 12
458 | 1
459 | 0
460 | 0
461 | 0
462 | .\LinRTOS Kernel\portable\RVDS\port.c
463 | port.c
464 | 0
465 | 0
466 |
467 |
468 |
469 |
470 | ::CMSIS
471 | 0
472 | 0
473 | 0
474 | 1
475 |
476 |
477 |
478 | ::Device
479 | 1
480 | 0
481 | 0
482 | 1
483 |
484 |
485 |
486 |
--------------------------------------------------------------------------------
/Code/LinOS.uvprojx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2.1
5 |
6 | ### uVision Project, (C) Keil Software
7 |
8 |
9 |
10 | Target 1
11 | 0x4
12 | ARM-ADS
13 | 5060960::V5.06 update 7 (build 960)::.\ARMCC
14 | 0
15 |
16 |
17 | ARMCM4
18 | ARM
19 | ARM.CMSIS.5.7.0
20 | http://www.keil.com/pack/
21 | IRAM(0x20000000,0x00020000) IROM(0x00000000,0x00040000) CPUTYPE("Cortex-M4") CLOCK(12000000) ESEL ELITTLE
22 |
23 |
24 | UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000)
25 | 0
26 | $$Device:ARMCM4$Device\ARM\ARMCM4\Include\ARMCM4.h
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | 0
38 | 0
39 |
40 |
41 |
42 |
43 |
44 |
45 | 0
46 | 0
47 | 0
48 | 0
49 | 1
50 |
51 | .\Objects\
52 | vTaskSchedule
53 | 1
54 | 0
55 | 0
56 | 1
57 | 1
58 | .\Listings\
59 | 1
60 | 0
61 | 0
62 |
63 | 0
64 | 0
65 |
66 |
67 | 0
68 | 0
69 | 0
70 | 0
71 |
72 |
73 | 0
74 | 0
75 |
76 |
77 | 0
78 | 0
79 | 0
80 | 0
81 |
82 |
83 | 0
84 | 0
85 |
86 |
87 | 0
88 | 0
89 | 0
90 | 0
91 |
92 | 0
93 |
94 |
95 |
96 | 0
97 | 0
98 | 0
99 | 0
100 | 0
101 | 1
102 | 0
103 | 0
104 | 0
105 | 0
106 | 3
107 |
108 |
109 | 1
110 |
111 |
112 | SARMCM3.DLL
113 | -MPU
114 | DCM.DLL
115 | -pCM4
116 | SARMCM3.DLL
117 | -MPU
118 | TCM.DLL
119 | -pCM4
120 |
121 |
122 |
123 | 1
124 | 0
125 | 0
126 | 0
127 | 16
128 |
129 |
130 |
131 |
132 | 1
133 | 0
134 | 0
135 | 1
136 | 1
137 | -1
138 |
139 | 1
140 | BIN\UL2CM3.DLL
141 |
142 |
143 |
144 |
145 |
146 | 0
147 |
148 |
149 |
150 | 0
151 | 1
152 | 1
153 | 1
154 | 1
155 | 1
156 | 1
157 | 1
158 | 0
159 | 1
160 | 1
161 | 0
162 | 1
163 | 1
164 | 0
165 | 0
166 | 1
167 | 1
168 | 1
169 | 1
170 | 1
171 | 1
172 | 1
173 | 1
174 | 1
175 | 0
176 | 0
177 | "Cortex-M4"
178 |
179 | 0
180 | 0
181 | 0
182 | 1
183 | 1
184 | 0
185 | 0
186 | 0
187 | 0
188 | 0
189 | 0
190 | 0
191 | 8
192 | 0
193 | 1
194 | 0
195 | 0
196 | 3
197 | 3
198 | 0
199 | 0
200 | 0
201 | 0
202 | 0
203 | 0
204 | 0
205 | 0
206 | 0
207 | 0
208 | 1
209 | 0
210 | 0
211 | 0
212 | 0
213 | 1
214 | 0
215 |
216 |
217 | 0
218 | 0x0
219 | 0x0
220 |
221 |
222 | 0
223 | 0x0
224 | 0x0
225 |
226 |
227 | 0
228 | 0x0
229 | 0x0
230 |
231 |
232 | 0
233 | 0x0
234 | 0x0
235 |
236 |
237 | 0
238 | 0x0
239 | 0x0
240 |
241 |
242 | 0
243 | 0x0
244 | 0x0
245 |
246 |
247 | 0
248 | 0x20000000
249 | 0x20000
250 |
251 |
252 | 1
253 | 0x0
254 | 0x40000
255 |
256 |
257 | 0
258 | 0x0
259 | 0x0
260 |
261 |
262 | 1
263 | 0x0
264 | 0x0
265 |
266 |
267 | 1
268 | 0x0
269 | 0x0
270 |
271 |
272 | 1
273 | 0x0
274 | 0x0
275 |
276 |
277 | 1
278 | 0x0
279 | 0x40000
280 |
281 |
282 | 1
283 | 0x0
284 | 0x0
285 |
286 |
287 | 0
288 | 0x0
289 | 0x0
290 |
291 |
292 | 0
293 | 0x0
294 | 0x0
295 |
296 |
297 | 0
298 | 0x0
299 | 0x0
300 |
301 |
302 | 0
303 | 0x20000000
304 | 0x20000
305 |
306 |
307 | 0
308 | 0x0
309 | 0x0
310 |
311 |
312 |
313 |
314 |
315 | 1
316 | 1
317 | 0
318 | 0
319 | 1
320 | 0
321 | 0
322 | 0
323 | 0
324 | 0
325 | 2
326 | 0
327 | 0
328 | 0
329 | 0
330 | 0
331 | 3
332 | 3
333 | 1
334 | 1
335 | 0
336 | 0
337 | 0
338 |
339 |
340 | __TARGET_CPU_CORTEX_M4
341 |
342 | .\LinRTOS Kernel\inc;.\LinRTOS Kernel\portable\RVDS;.\LinRTOS Kernel\portable;.\User
343 |
344 |
345 |
346 | 1
347 | 0
348 | 0
349 | 0
350 | 0
351 | 0
352 | 0
353 | 0
354 | 0
355 | 1
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 | 1
365 | 0
366 | 0
367 | 0
368 | 1
369 | 0
370 | 0x08000000
371 | 0x20000000
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 | User
385 |
386 |
387 | main.c
388 | 1
389 | .\User\main.c
390 |
391 |
392 |
393 |
394 | LinRTOS
395 |
396 |
397 | Bitmap.c
398 | 1
399 | .\LinRTOS Kernel\Bitmap.c
400 |
401 |
402 | Event.c
403 | 1
404 | .\LinRTOS Kernel\Event.c
405 |
406 |
407 | EventGroup.c
408 | 1
409 | .\LinRTOS Kernel\EventGroup.c
410 |
411 |
412 | Lists.c
413 | 1
414 | .\LinRTOS Kernel\Lists.c
415 |
416 |
417 | Mailbox.c
418 | 1
419 | .\LinRTOS Kernel\Mailbox.c
420 |
421 |
422 | Mempool.c
423 | 1
424 | .\LinRTOS Kernel\Mempool.c
425 |
426 |
427 | Mutex.c
428 | 1
429 | .\LinRTOS Kernel\Mutex.c
430 |
431 |
432 | Sem.c
433 | 1
434 | .\LinRTOS Kernel\Sem.c
435 |
436 |
437 | Tasks.c
438 | 1
439 | .\LinRTOS Kernel\Tasks.c
440 |
441 |
442 | Timer.c
443 | 1
444 | .\LinRTOS Kernel\Timer.c
445 |
446 |
447 |
448 |
449 | Portable
450 |
451 |
452 | port.c
453 | 1
454 | .\LinRTOS Kernel\portable\RVDS\port.c
455 |
456 |
457 |
458 |
459 | ::CMSIS
460 |
461 |
462 | ::Device
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 | RTE\Device\ARMCM3\startup_ARMCM3.s
487 |
488 |
489 |
490 |
491 |
492 | RTE\Device\ARMCM3\system_ARMCM3.c
493 |
494 |
495 |
496 |
497 |
498 | RTE\Device\ARMCM4\startup_ARMCM4.s
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 | RTE\Device\ARMCM4\system_ARMCM4.c
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 | RTE\Device\STM32F429ZETx\startup_stm32f429xx.s
515 |
516 |
517 |
518 |
519 |
520 | RTE\Device\STM32F429ZETx\system_stm32f4xx.c
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 | LinOS
532 | 0
533 | 1
534 |
535 |
536 |
537 |
538 |
539 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Bitmap.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-21
5 | * @LastEditTime: 2021-07-26 22:38:50
6 | * @Description:
7 | */
8 |
9 | #include "Bitmap.h"
10 | #include "Tasks.h"
11 |
12 |
13 |
14 | void vBitmapInit(Bitmap_t * bitmap)
15 | {
16 | bitmap->bitmapValue.Val = 0;
17 | }
18 |
19 |
20 | void vBitmapSet(Bitmap_t * bitmap, uint32_t pos)
21 | {
22 | bitmap->bitmapValue.Val |= 1 << pos;
23 | }
24 |
25 | uint32_t uBitmapGetCount(void)
26 | {
27 | return 32;
28 | }
29 |
30 |
31 | void vBitmapClear(Bitmap_t * bitmap, uint32_t pos)
32 | {
33 | bitmap->bitmapValue.Val &= ~(1 << pos);
34 | }
35 |
36 |
37 | uint32_t bBitmapGet(Bitmap_t * bitmap, uint32_t pos)
38 | {
39 | if (bitmap->bitmapValue.Val & (1 << pos) == 0)
40 | return 1;
41 | else
42 | return 0;
43 | }
44 |
45 | /**
46 | * @Author: YangSL
47 | * @Description:
48 | * @param {Bitmap_t *} bitmap
49 | */
50 | uint32_t uBitmapGetFirstSet(Bitmap_t * bitmap)
51 | {
52 | #if 0
53 | uint32_t index;
54 | for( index = 0; index < 32 && (!(bitmap->bitmapVlaue & (0x01 << index))); index++);
55 | return index;
56 | #else
57 | static const uint8_t quickFindTable[] =
58 | {
59 | /* 00 */ 0xff, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
60 | /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
61 | /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
62 | /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
63 | /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
64 | /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
65 | /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
66 | /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
67 | /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
68 | /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
69 | /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
70 | /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
71 | /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
72 | /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
73 | /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
74 | /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
75 | };
76 |
77 | uint8_t index;
78 | for (index = 0; index < 4 && ( bitmap->bitmapValue.v[index] == 0); index++);
79 |
80 | return quickFindTable[bitmap->bitmapValue.v[index]] + (index << 3);
81 |
82 | // if (bitmap->bitmapValue.Val & 0xff)
83 | // {
84 | // return quickFindTable[bitmap->bitmapValue.Val & 0xff];
85 | // }
86 | // else if (bitmap->bitmapValue.Val & 0xff00)
87 | // {
88 | // return quickFindTable[(bitmap->bitmapValue.Val >> 8) & 0xff] + 8;
89 | // }
90 | // else if (bitmap->bitmapValue.Val & 0xff0000)
91 | // {
92 | // return quickFindTable[(bitmap->bitmapValue.Val >> 16) & 0xff] + 16;
93 | // }
94 | // else if (bitmap->bitmapValue.Val & 0xFF000000)
95 | // {
96 | // return quickFindTable[(bitmap->bitmapValue.Val >> 24) & 0xFF] + 24;
97 | // }
98 | // else
99 | // {
100 | // return uBitmapGetCount();
101 | // }
102 |
103 | #endif
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Event.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-25
5 | * @LastEditTime: 2021-08-02 21:32:19
6 | * @Description:
7 | */
8 |
9 | #include "Event.h"
10 | #include "LinOS.h"
11 |
12 | /**
13 | * @Author: YangSL
14 | * @Description: 初始化事件控制块
15 | * @param {tEvent *} event 事件控制块
16 | * @param {eEventType} type 事件控制块的类型
17 | */
18 | void vEventInit(tEvent * event, eEventType type)
19 | {
20 | event->type = type;
21 | vListInit(&event->waitList);
22 | }
23 |
24 |
25 | /**
26 | * @Author: YangSL
27 | * @Description: 从事件控制块中唤醒首个等待的任务
28 | * @param {tEvent *} event 事件控制块
29 | * @param {tTask *} task 等待事件发生的任务
30 | * @param {void *} msg 事件消息存储的具体位置
31 | * @param {uint32_t} state 消息类型
32 | * @param {uint32_t} timeout 等待多长时间
33 | */
34 | void vEventWait(tEvent * event, tTask * task, void * msg, uint32_t state, uint32_t timeout)
35 | {
36 | /* 进入临界区 */
37 | uint32_t status = uTaskEnterCritical();
38 |
39 | // task->state = state;
40 |
41 | /* 设置任务等待的事件结构 */
42 | task->waitEvent = event;
43 | /* 设置任务等待事件的消息存储位置 */
44 | task->waitEventMsg = msg;
45 | /* 清空事件的等待结果 */
46 | task->waitEventResult = eErrorNoError;
47 |
48 | /* 将任务从就绪队列中移除 */
49 | vTaskRdyListRemove(task);
50 |
51 | /* 将任务插入到等待队列中 */
52 | vListInsertLast(&event->waitList, &task->linkNode);
53 |
54 | if (timeout)
55 | {
56 | tTaskDelayWait(task, timeout);
57 | }
58 |
59 | /* 退出临界区 */
60 | vTaskExitCritical(status);
61 | }
62 |
63 |
64 | /**
65 | * @Author: YangSL
66 | * @Description: 从事件控制块中唤醒最先等待的任务
67 | * @param {tEvent *} event 事件控制块
68 | * @param {void *} msg 事件消息
69 | * @param {uint32_t} result 告知事件的等待结果
70 | * @return value 首个等待的任务,如果没有任务等待,则返回0
71 | */
72 | tTask * tEventWakeUp(tEvent * event, void * msg, uint32_t result)
73 | {
74 | tTask * task = (tTask *)0;
75 | tNode * node;
76 |
77 | uint32_t status = uTaskEnterCritical();
78 |
79 | /* 获取等待队列的第一个节点 */
80 | if((node = tListRemoveFirst(&event->waitList)) != (tNode *)0)
81 | {
82 | /* 获取该节点对应的任务控制块 */
83 | task = (tTask *)nodeParent(node, tTask, linkNode);
84 |
85 | /* 设置收到的消息、结构,清除相应的等待标志位 */
86 | task->waitEvent = (tEvent *)0;
87 | task->waitEventMsg = msg;
88 | task->waitEventResult = result;
89 |
90 | if(task->delayTicks != 0)
91 | {
92 | vTaskDelayWakeUp(task);
93 | }
94 |
95 | /* 将任务加入就绪队列 */
96 | vTaskSchedRdy(task);
97 |
98 | }
99 |
100 | vTaskExitCritical(status);
101 |
102 | return task;
103 | }
104 |
105 |
106 | /**
107 | * @Author: YangSL
108 | * @Description: 从事件控制块中唤醒指定任务
109 | * @param {tEvent *} eventv 事件控制块
110 | * @param {tTask *} task 等待唤醒的任务
111 | * @param {void} *msg 事件消息
112 | * @param {uint32_t} result 告知事件的等待结果
113 | */
114 | void vEventWakeUpTask(tEvent * event, tTask * task, void *msg, uint32_t result)
115 | {
116 | uint32_t status = uTaskEnterCritical();
117 | {
118 | vListRemoveNode(&event->waitList , &task->linkNode);
119 |
120 | /* 设置收到的消息、结构,清除相应的等待标志位 */
121 | task->waitEvent = (tEvent *)0;
122 | task->waitEventMsg = msg;
123 | task->waitEventResult = result;
124 |
125 | if(task->delayTicks != 0)
126 | {
127 | vTaskDelayWakeUp(task);
128 | }
129 |
130 | /* 将任务加入就绪队列 */
131 | vTaskSchedRdy(task);
132 |
133 | }
134 | vTaskExitCritical(status);
135 | }
136 |
137 | /**
138 | * @Author: YangSL
139 | * @Description: 将任务从其等待队列中强制移除
140 | * @param {tTask *} task 待移除的任务
141 | * @param {void *} msg 事件消息
142 | * @param {uint32_t} result 告知事件的等待结果
143 | */
144 | void vEventRemoveTask(tTask * task, void * msg, uint32_t result)
145 | {
146 | /* 进入临界区 */
147 | uint32_t status = uTaskEnterCritical();
148 |
149 | /* 将任务从所在的等待队列中移除 */
150 | vListRemoveNode(&task->waitEvent->waitList, &task->linkNode);
151 |
152 | /* 设置收到的消息、结构,清除相应的等待标志位 */
153 | task->waitEvent = (tEvent *)0;
154 | task->waitEventMsg = msg;
155 | task->waitEventResult = result;
156 |
157 | /* 退出临界区 */
158 | vTaskExitCritical(status);
159 | }
160 |
161 |
162 | /**
163 | * @Author: YangSL
164 | * @Description: 清除所有等待中的任务,将事件发送给所有任务
165 | * @param {tEvent *} event 事件控制块
166 | * @param {void *} msg 事件消息
167 | * @param {uint32_t} result 告知事件的等待结果
168 | * @return value 唤醒的任务数量
169 | */
170 | uint32_t uEventRemoveAll(tEvent * event, void * msg, uint32_t result)
171 | {
172 | uint32_t count;
173 |
174 | tNode * node ;
175 |
176 | /* 进入临界区 */
177 | uint32_t status = uTaskEnterCritical();
178 |
179 | count = uGetListNodeCount(&event->waitList);
180 |
181 | while ((node = tListRemoveFirst(&event->waitList)) != (tNode * )0)
182 | {
183 | tTask * task = (tTask *) nodeParent(node, tTask, linkNode);
184 |
185 | /* 设置收到的消息、结构,清除相应的等待标志位 */
186 | task->waitEvent = (tEvent *)0;
187 | task->waitEventMsg = msg;
188 | task->waitEventResult = result;
189 |
190 | if(task->delayTicks != 0)
191 | {
192 | vTaskDelayWakeUp(task);
193 | }
194 |
195 | /* 将任务加入就绪队列 */
196 | vTaskSchedRdy(task);
197 | }
198 |
199 | /* 退出临界区 */
200 | vTaskExitCritical(status);
201 |
202 | return count;
203 | }
204 |
205 |
206 | /**
207 | * @Author: YangSL
208 | * @Description: 事件控制块中等待的任务数量
209 | * @param {tEvent *} event
210 | */
211 | uint32_t uEventGetWaitCount(tEvent * event)
212 | {
213 | uint32_t count = 0;
214 |
215 | uint32_t status = uTaskEnterCritical();
216 |
217 | count = uGetListNodeCount(&event->waitList);
218 |
219 | vTaskExitCritical(status);
220 |
221 | return count;
222 | }
223 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/EventGroup.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-01 21:40:56
5 | * @LastEditTime: 2022-01-29 11:36:53
6 | * @Description:
7 | */
8 | #include "LinOS.h"
9 | #include "EventGroup.h"
10 |
11 | /**
12 | * @Author: YangSL
13 | * @Description: 初始化事件标志组
14 | */
15 | void vEventGroupInit(tEventGroup * eventGroup, uint32_t flags)
16 | {
17 | vEventInit(&eventGroup->event, eEventTypeEventGroup);
18 |
19 | eventGroup->flags = flags;
20 | }
21 |
22 | static uint32_t uEventGroupCheckAndConsume(tEventGroup * eventGroup, uint32_t type, uint32_t * flags)
23 | {
24 | uint32_t srcFlags = * flags;
25 |
26 | /* 确定是设置操作还是清除操作 */
27 | uint32_t isSet = type & EVENTGROUP_SET;
28 | /* 确定是操作所有位还是部分bits */
29 | uint32_t isAll = type & EVENTGROUP_ALL;
30 | /* 是否消耗掉标志位 */
31 | uint32_t isConsume = type & EVENTGROUP_CONSUME;
32 |
33 |
34 | /* flagGroup->flags & flags:计算出哪些位为1
35 | ~flagGroup->flags & flags:计算出哪位位为0 */
36 | uint32_t calcFlags = isSet ? (eventGroup->flags & srcFlags) : (~eventGroup->flags & srcFlags);
37 |
38 | if(((isAll != 0) && (calcFlags == srcFlags)) || ((isAll == 0) && (calcFlags != 0)))
39 | {
40 | /* 是否消耗掉标志位 */
41 | if(isConsume)
42 | {
43 | if(isSet)
44 | {
45 | /* 清除为1的标志位,变成0 */
46 | eventGroup->flags &= ~srcFlags;
47 | }
48 | else
49 | {
50 | /* 清除为0的标志位,变成1 */
51 | eventGroup->flags |= srcFlags;
52 | }
53 | }
54 |
55 | *flags = calcFlags;
56 | return eErrorNoError;
57 | }
58 | *flags = calcFlags;
59 | return eErrorResourceUnavaliable;
60 | }
61 |
62 | /**
63 | * @Author: YangSL
64 | * @Description: 等待事件标志组中特定的标志
65 | * @param {tEventGroup *} eventGroup 等待的事件标志组
66 | * @param {uint32_t} waitType 等待的事件类型
67 | * @param {uint32_t} requestFlag 请求的事件标志
68 | * @param {uint32_t} *resultFlag 等待标志结果
69 | * @param {uint32_t} waitTicks 当等待的标志没有满足条件时,等待的ticks数,为0时表示永远等待
70 | * @return : eErrorResourceUnavaliable.eErrorNoError,eErrorTimeout
71 | */
72 | uint32_t uEventGroupWaitBits(tEventGroup * eventGroup, uint32_t waitType, uint32_t requestFlag, uint32_t *resultFlag, uint32_t waitTicks)
73 | {
74 | uint32_t result;
75 | uint32_t flags = requestFlag;
76 |
77 | uint32_t status = uTaskEnterCritical();
78 |
79 | result = uEventGroupCheckAndConsume(eventGroup, waitType, &flags);
80 |
81 | if(result != eErrorNoError)
82 | {
83 | /* 如果事件标志不满足条件,则插入到等待队列中 */
84 | currentTask->waitEventGroupType = waitType;
85 | currentTask->waitEventGroupFlag = requestFlag;
86 | vEventWait(&eventGroup->event, currentTask, (void *) 0, eEventTypeEventGroup, waitTicks);
87 |
88 | vTaskExitCritical(status);
89 |
90 | vTaskSched();
91 |
92 | *resultFlag = currentTask->waitEventGroupFlag;
93 | result = currentTask->waitEventResult;
94 | }
95 | else
96 | {
97 | *resultFlag = flags;
98 | vTaskExitCritical(status);
99 | }
100 |
101 | return result;
102 | }
103 |
104 |
105 | /**
106 | * @Author: YangSL
107 | * @Description: 无等待的获取事件标志
108 | * @param {tEventGroup *} eventGroup
109 | * @param {uint32_t} waitType
110 | * @param {uint32_t} requestFlag
111 | * @param {uint32_t *} resultFlag
112 | * @return : eErrorResourceUnavaliable.eErrorNoError
113 | */
114 | uint32_t uEventGroupNoWaitBits(tEventGroup * eventGroup, uint32_t waitType, uint32_t requestFlag, uint32_t * resultFlag)
115 | {
116 | uint32_t flags = requestFlag;
117 |
118 | uint32_t status = uTaskEnterCritical();
119 |
120 | uint32_t result = uEventGroupCheckAndConsume(eventGroup, waitType, &flags);
121 | vTaskExitCritical(status);
122 |
123 | *resultFlag = flags;
124 |
125 | return result;
126 | }
127 |
128 |
129 | /**
130 | * @Author: YangSL
131 | * @Description: 设置相应的标志位置一或清零
132 | * @param {tEventGroup *} eventGroup
133 | * @param {uint8_t} isSet
134 | * @param {uint32_t} flags
135 | */
136 | void vEventGroupNotify(tEventGroup * eventGroup, uint8_t isSet, uint32_t flags)
137 | {
138 |
139 | }
140 |
141 |
142 | /**
143 | * @Author: YangSL
144 | * @Description: 设置清零的位
145 | * @param {tEventGroup *} eventGroup
146 | * @param {uint32_t} clearBits
147 | */
148 | void vEventGroupClearBits(tEventGroup * eventGroup, uint32_t clearBits)
149 | {
150 | uint32_t status = uTaskEnterCritical();
151 | {
152 | eventGroup->flags &= ~clearBits;
153 | }
154 | vTaskExitCritical(status);
155 | }
156 |
157 |
158 | /**
159 | * @Author: YangSL
160 | * @Description: 设置要置一的位
161 | * @param {tEventGroup} *eventGroup
162 | * @param {uint32_t} setBits
163 | */
164 | void vEventGroupSetBits(tEventGroup * eventGroup, uint32_t setBits)
165 | {
166 |
167 | tList * waitList;
168 | tNode * node;
169 | tNode * nextNode;
170 | uint8_t sched = 0;
171 |
172 | /* 临界代码 */
173 | uint32_t status = uTaskEnterCritical();
174 | {
175 | /* Set the bits. */
176 | eventGroup->flags |= setBits;
177 |
178 | waitList = &eventGroup->event.waitList;
179 |
180 | for(node = waitList->headNode.nextNode; node != &(waitList->headNode); node = nextNode)
181 | {
182 | uint32_t result;
183 | tTask * task = nodeParent(eventGroup, tTask, linkNode);
184 | uint32_t flags = task->waitEventGroupFlag;
185 | nextNode = node->nextNode;
186 |
187 | result = uEventGroupCheckAndConsume(eventGroup, task->waitEventGroupType, &flags);
188 | if(result == eErrorNoError)
189 | {
190 | task->waitEventGroupFlag = flags;
191 | vEventWakeUpTask(&eventGroup->event, task, (void * )0, eErrorNoError);
192 | sched = 1;
193 | }
194 | }
195 |
196 | if(sched)
197 | {
198 | vTaskSched();
199 | }
200 | }
201 | vTaskExitCritical(status);
202 | }
203 |
204 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Lists.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-22
5 | * @LastEditTime: 2021-07-26 19:50:15
6 | * @Description:
7 | */
8 |
9 | #include "Lists.h"
10 |
11 |
12 | /**
13 | * @Author: YangSL
14 | * @Description: 初始化节点
15 | * @param {tNode} *node: 要初始化的节点
16 | */
17 | void vNodeInit(tNode *node)
18 | {
19 | node->nextNode = node;
20 | node->preNode = node;
21 |
22 | }
23 |
24 | /**
25 | * @Author: YangSL
26 | * @Description: 初始化链表
27 | * @param {tList *} list :要初始化的链表
28 | */
29 | void vListInit(tList * list)
30 | {
31 | list->headNode.nextNode = &(list->headNode);
32 | list->headNode.preNode = &(list->headNode);
33 | list->nodeCount = 0;
34 | }
35 |
36 |
37 | /**
38 | * @Author: YangSL
39 | * @Description: 返回链表中节点个数
40 | * @param {tList} list : 哪个链表
41 | */
42 | uint32_t uGetListNodeCount(tList *list)
43 | {
44 | return list->nodeCount;
45 | }
46 |
47 |
48 | /**
49 | * @Author: YangSL
50 | * @Description: 返回链表的第一个节点
51 | * @param {tList *} list
52 | */
53 | tNode * tGetFirstNode(tList * list)
54 | {
55 | tNode * node = (tNode *)0;
56 |
57 | if (list->nodeCount != 0)
58 | {
59 | node = list->headNode.nextNode;
60 | }
61 | return node;
62 | }
63 |
64 |
65 | /**
66 | * @Author: YangSL
67 | * @Description: 返回链表的最后一个节点
68 | * @param {tList *} list
69 | */
70 | tNode * tGetLastNode(tList * list)
71 | {
72 | tNode * node = (tNode *)0;
73 |
74 | if(list->nodeCount != 0)
75 | {
76 | node = list->headNode.preNode;
77 | }
78 | return node;
79 | }
80 |
81 |
82 | /**
83 | * @Author: YangSL
84 | * @Description: 返回指定链表的前一个节点
85 | * @param {tList *} list
86 | * @param {tNode *} node
87 | */
88 | tNode * tGetListPre(tList * list, tNode * node)
89 | {
90 | if(node->preNode == node)
91 | {
92 | return (tNode *)0;
93 | }
94 | else
95 | {
96 | return node->preNode;
97 | }
98 | }
99 |
100 |
101 | /**
102 | * @Author: YangSL
103 | * @Description: 返回指定链表的后一个节点
104 | * @param {tList *} list
105 | * @param {tNode *} node
106 | */
107 | tNode * tGetListNext(tList * list, tNode * node)
108 | {
109 | if(node->nextNode == node)
110 | {
111 | return (tNode *)0;
112 | }
113 | else
114 | {
115 | return node->nextNode;
116 | }
117 | }
118 |
119 |
120 | /**
121 | * @Author: YangSL
122 | * @Description: 将新节点插入到链表开头
123 | * @param {tList *} list
124 | * @param {tNode *} node
125 | */
126 | void vListInsertHead(tList * list, tNode * node)
127 | {
128 | node->nextNode = list->headNode.nextNode;
129 | node->preNode = list->headNode.nextNode->preNode;
130 |
131 | list->headNode.nextNode->preNode = node;
132 | list->headNode.nextNode = node;
133 |
134 | list->nodeCount++;
135 | }
136 |
137 |
138 | /**
139 | * @Author: YangSL
140 | * @Description: 将新节点插入到链表结尾
141 | * @param {tList *} list
142 | * @param {tNode *} node
143 | */
144 | void vListInsertLast(tList * list, tNode * node)
145 | {
146 | node->nextNode = &(list->headNode);
147 | node->preNode = list->headNode.preNode;
148 |
149 | list->headNode.preNode->nextNode = node;
150 | list->headNode.preNode = node;
151 |
152 | list->nodeCount++;
153 | }
154 |
155 |
156 | /**
157 | * @Author: YangSL
158 | * @Description: 将新的节点插入到指定节点后面
159 | * @param {tList *} list : 要插入的链表
160 | * @param {tNode *} newNode : 要插入的新节点
161 | * @param {tNode *} toNode : 目标地址
162 | */
163 | void vListInsertNodeAfter(tList * list, tNode * newNode, tNode * toNode)
164 | {
165 | newNode->nextNode = toNode->nextNode;
166 | newNode->preNode = toNode->nextNode->preNode;
167 |
168 | toNode->nextNode->preNode = newNode;
169 | toNode->nextNode = newNode;
170 |
171 | list->nodeCount++;
172 | }
173 |
174 |
175 | /**
176 | * @Author: YangSL
177 | * @Description: 移除链表的第一个节点
178 | * @param {tList *} list
179 | * @Return : 如果链表为空,返回0,否则的话,返回第1个结点
180 | */
181 | tNode * tListRemoveFirst(tList * list)
182 | {
183 | tNode * node = (tNode *)0;
184 | if(list->nodeCount != 0)
185 | {
186 | node = list->headNode.nextNode;
187 |
188 | list->headNode.nextNode->nextNode->preNode = &(list->headNode);
189 | list->headNode.nextNode = list->headNode.nextNode->nextNode;
190 |
191 | list->nodeCount--;
192 | }
193 | return node;
194 | }
195 |
196 |
197 | /**
198 | * @Author: YangSL
199 | * @Description: 移除链表最后一个节点
200 | * @param {tList *} list
201 | * @Return : 如果链表为空,返回0,否则的话,返回最后1个结点
202 | */
203 | tNode *tListRemoveLast(tList * list)
204 | {
205 | tNode * node = (tNode *)0;
206 | if(list->nodeCount != 0)
207 | {
208 | node = list->headNode.preNode;
209 |
210 | list->headNode.preNode = list->headNode.preNode->preNode;
211 | list->headNode.preNode->preNode->nextNode = &(list->headNode);
212 |
213 | list->nodeCount--;
214 | }
215 | return node;
216 | }
217 |
218 |
219 | /**
220 | * @Author: YangSL
221 | * @Description: 移除链表中的指定节点
222 | * @param {tList *} list : 操作的链表
223 | * @param {tNode *} node :要删除得节点
224 | */
225 | void vListRemoveNode(tList * list, tNode * node)
226 | {
227 | node->nextNode->preNode = node->preNode;
228 | node->preNode->nextNode = node->nextNode;
229 |
230 | // node->preNode = node;
231 | // node->nextNode = node;
232 |
233 | list->nodeCount--;
234 | }
235 |
236 |
237 | /**
238 | * @Author: YangSL
239 | * @Description: 移除链表中所有节点
240 | * @param {tList *} list
241 | */
242 | void vListRemoveAll(tList * list)
243 | {
244 | uint32_t count;
245 | tNode * nextNode;
246 |
247 | /* 遍历所有的结点 */
248 | nextNode = list->headNode.nextNode;
249 | for (count = list->nodeCount; count != 0; count-- )
250 | {
251 | /* 先纪录下当前结点,和下一个结点,必须纪录下一结点位置,因为在后面的代码中当前结点的next会被重置 */
252 | tNode * currentNode = nextNode;
253 | nextNode = nextNode->nextNode;
254 |
255 | /* 重置结点自己的信息 */
256 | currentNode->nextNode = currentNode;
257 | currentNode->preNode = currentNode;
258 | }
259 |
260 | list->headNode.nextNode = &(list->headNode);
261 | list->headNode.preNode = &(list->headNode);
262 | list->nodeCount = 0;
263 | }
264 |
265 |
266 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Mailbox.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-28
5 | * @LastEditTime: 2022-01-29 11:38:21
6 | * @Description:
7 | */
8 |
9 | #include "Mailbox.h"
10 | #include "LinOS.h"
11 | /*---------------------------------------------------------------------------------------------------------------------
12 | * MAINBOX METHODS
13 | *--------------------------------------------------------------------------------------------------------------------*/
14 |
15 |
16 | /**
17 | * @Author: YangSL
18 | * @Description: 初始化邮箱
19 | * @param {tMbox} *mbox
20 | * @param {void **} msgBuffer
21 | * @param {uint32_t} maxCount
22 | */
23 | void vMboxInit(tMbox *mbox, void ** msgBuffer, uint32_t maxCount)
24 | {
25 | vEventInit(&mbox->event, eEventTypeMbox);
26 |
27 | mbox->msgBuffer = msgBuffer;
28 | mbox->maxCount = maxCount;
29 | mbox->count = 0;
30 | mbox->read = 0;
31 | mbox->write = 0;
32 | }
33 |
34 |
35 | /**
36 | * @Author: YangSL
37 | * @Description: 向邮箱中发送邮件
38 | * @param {tMbox *} mbox 获取消息的邮箱
39 | * @param {void **} msg 消息存储缓存区
40 | * @param {uint32_t} option 插入的位置:队列前: defineMboxSendFront 队列末尾 : defineMboxSendNormal
41 | */
42 | uint32_t uMboxSend(tMbox * mbox, void * msg, uint32_t option)
43 | {
44 | uint32_t status = uTaskEnterCritical();
45 |
46 | /* 判断是否有等待邮件的任务 */
47 | if( uEventGetWaitCount(&mbox->event) > 0)
48 | {
49 | /* 如果有任务等待,就唤醒等待队列的第一个任务
50 | 唤醒之后需要判断唤醒的任务优先级与当前任务优先级关系,如果当前任务优先级低于唤醒的任务,需要任务切换 */
51 | tTask * task = tEventWakeUp(&mbox->event, (void *)msg, eErrorNoError);
52 |
53 | if( currentTask->prio < task->prio)
54 | vTaskSched();
55 | }
56 | /* 没有等待的任务 */
57 | else
58 | {
59 | /* 如果邮件消息的数量已经达到的最大值,就返回相应错误 */
60 | if (mbox->count >= mbox->maxCount)
61 | {
62 | vTaskExitCritical(status);
63 | return eErrorResourceFull;
64 | }
65 | else
66 | {
67 | /* 将任务插入到队列最前面,这样可以让该任务最先获取到邮件消息*/
68 | if(option & defineMboxSendFront)
69 | {
70 | if(mbox->read <= 0)
71 | {
72 | mbox->read = mbox->maxCount - 1;
73 | }
74 | else
75 | {
76 | --mbox->read;
77 | }
78 | mbox->msgBuffer[mbox->read] = msg;
79 | }
80 | /* 正常的插入到队列末尾 */
81 | else
82 | {
83 | mbox->msgBuffer[mbox->write++] = msg;
84 | if(mbox->write >= mbox->maxCount)
85 | {
86 | mbox->write = 0;
87 | }
88 | }
89 |
90 | }
91 | mbox->count++;
92 | }
93 |
94 | vTaskExitCritical(status);
95 | return eErrorNoError;
96 | }
97 |
98 |
99 | /**
100 | * @Author: YangSL
101 | * @Description: 等待邮箱, 获取一则消息
102 | * @param {tMbox *} mbox 等待的邮箱
103 | * @param {void **} msg 消息存储缓存区
104 | * @param {uint32_t} timeout 超时时间
105 | */
106 | uint32_t uMboxWait(tMbox * mbox, void ** msg, uint32_t timeout)
107 | {
108 | uint32_t status = uTaskEnterCritical();
109 |
110 | /* 判断邮箱是否有消息 */
111 | if (mbox->count > 0)
112 | {
113 | /* 邮箱不为空则:
114 | 1. 将邮箱消息计数值减一
115 | 2. 从read位置获取消息信息
116 | 3. 将read向后移动一位并判断read是否越界 */
117 | mbox->count--;
118 |
119 | *msg = mbox->msgBuffer[mbox->read];
120 |
121 | mbox->read++;
122 |
123 | if(mbox->read >= mbox->maxCount)
124 | {
125 | mbox->read = 0;
126 | }
127 | vTaskExitCritical(status);
128 | return eErrorNoError;
129 | }
130 | else
131 | {
132 | /* 邮箱为空则将当前任务加入等待队列,并设置超时时间 */
133 | vEventWait(&mbox->event, currentTask, (void *)0, 0, timeout);
134 | vTaskExitCritical(status);
135 |
136 | vTaskSched();
137 |
138 | /* 等待调度回来获取信息 */
139 | *msg = currentTask->waitEventMsg;
140 |
141 | return currentTask->waitEventResult;
142 | }
143 | }
144 |
145 |
146 | /**
147 | * @Author: YangSL
148 | * @Description: 清空邮箱中所有消息
149 | * @param {tMbox *} mbox
150 | */
151 | void uMboxFlush(tMbox * mbox)
152 | {
153 | uint32_t status = uTaskEnterCritical();
154 |
155 | if(uEventGetWaitCount(&mbox->event) == 0)
156 | {
157 | mbox->read = 0;
158 | mbox->write = 0;
159 | mbox->count = 0;
160 | }
161 |
162 | vTaskExitCritical(status);
163 | }
164 |
165 |
166 | /**
167 | * @Author: YangSL
168 | * @Description: 删除邮箱
169 | * @param {tMbox} *mbox
170 | */
171 | uint32_t uMboxDelete(tMbox *mbox)
172 | {
173 | uint32_t status = uTaskEnterCritical();
174 |
175 | uint32_t count = uEventRemoveAll(&mbox->event, (void *)0, eErrorDelete);
176 |
177 | vTaskExitCritical(status);
178 |
179 | if (count > 0)
180 | {
181 | vTaskSched();
182 | }
183 |
184 | return count;
185 | }
186 |
187 | /**
188 | * @Author: YangSL
189 | * @Description: 查询邮箱状态信息
190 | * @param {tMbox *} mbox
191 | * @param {tMboxInfo *} info
192 | */
193 | void vMboxGetInfo (tMbox * mbox, tMboxInfo * info)
194 | {
195 | uint32_t status = uTaskEnterCritical();
196 |
197 | /* 拷贝需要的信息 */
198 | info->count = mbox->count;
199 | info->maxCount = mbox->maxCount;
200 | info->taskCount = uEventGetWaitCount(&mbox->event);
201 |
202 | vTaskExitCritical(status);
203 | }
204 |
205 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Mempool.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-31 10:37:13
5 | * @LastEditTime: 2022-01-29 15:53:24
6 | * @Description:
7 | */
8 |
9 | #include "Mempool.h"
10 | #include "LinOS.h"
11 |
12 |
13 | /**
14 | * @Author: YangSL
15 | * @Description: 初始化存储控制块
16 | * @param {tMemPool *} memPool 等待初始化的存储控制块
17 | * @param {void*} startAddress 存储区的起始地址
18 | * @param {uint32_t} blockSize 每个块的大小
19 | * @param {uint32_t} blockTotalCount 总的块数量
20 | */
21 | void vMemPoolInit(tMemPool * memPool, void* startAddress, uint32_t blockSize, uint32_t blockTotalCount)
22 | {
23 | uint8_t * memBlockStart = (uint8_t *) startAddress;
24 | uint8_t * memBlockEnd = (uint8_t *) startAddress + blockSize * blockTotalCount;
25 |
26 | if(blockSize < sizeof(tNode))
27 | {
28 | return;
29 | }
30 |
31 | /* 初始化事件控制块 */
32 | vEventInit(&memPool->event, eEventTypeMemPool);
33 |
34 | /* 初始化Block相关参数 */
35 | memPool->memStartAddress = startAddress;
36 | memPool->blockSize = blockSize;
37 | memPool->blockTotalCount = blockTotalCount;
38 |
39 | /* 初始化存储块链表 */
40 | vListInit(&memPool->blockList);
41 | while(memBlockStart < memBlockEnd)
42 | {
43 | /* 初始化每一个储存块节点 */
44 | vNodeInit((tNode *)memBlockStart);
45 | /* 将存储块节点加入到储存块链表中 */
46 | vListInsertLast(&memPool->blockList, (tNode *)memBlockStart);
47 | memBlockStart += blockSize;
48 | }
49 |
50 | /* 初始化因该存储块挂起的任务链表 */
51 | vListInit(&memPool->suspendList);
52 | }
53 |
54 |
55 | /**
56 | * @Author: YangSL
57 | * @Description: 查询存储控制块的状态信息
58 | * @param {tMemPool *} memPool
59 | * @param {tMemPoolInfo *} info
60 | */
61 | void vMemPoolGetInfo(tMemPool * memPool, tMemPoolInfo * info)
62 | {
63 | uint32_t status = uTaskEnterCritical();
64 |
65 | info->blockCount = memPool->blockList.nodeCount;
66 | info->TalolCount = memPool->blockTotalCount;
67 | info->freeCount = info->TalolCount - info->blockCount;
68 | info->blockSize = memPool->blockSize;
69 | info->suspendCount = memPool->suspendList.nodeCount;
70 |
71 | vTaskExitCritical(status);
72 | }
73 |
74 |
75 | /**
76 | * @Author: YangSL
77 | * @Description: 有等待从内存池中分配存储块
78 | * @param {tMemPool *} memPool 内存池
79 | * @param {uint8_t **} memBlock 分配的内存块d地址
80 | * @param {uint32_t} timeout 超时时间
81 | */
82 | uint32_t uMemPoolWaitAlloc(tMemPool * memPool, uint8_t ** memBlock,uint32_t timeout)
83 | {
84 | uint32_t status =uTaskEnterCritical();
85 |
86 | /* 如果内存是中还有空余的内存块,直接取出一块 */
87 | if(uGetListNodeCount(&memPool->blockList) > 0)
88 | {
89 | *memBlock = (uint8_t *)tListRemoveFirst(&memPool->blockList);
90 | vTaskExitCritical(status);
91 | return eErrorNoError;
92 | }
93 | /* 没有空余的内存块 */
94 | else
95 | {
96 | /* 将任务加入事件的队列中 */
97 | vEventWait(&memPool->event, currentTask, (void *)0, eEventTypeMemPool, timeout);
98 | vTaskExitCritical(status);
99 |
100 | /* 发起任务调度 */
101 | vTaskSched();
102 |
103 | /* 当任务切换回来时获取任务的消息 */
104 | *memBlock = currentTask->waitEventMsg;
105 |
106 | /* 返回事件结果 */
107 | return currentTask->waitEventResult;
108 | }
109 |
110 | vTaskExitCritical(status);
111 | }
112 |
113 | /**
114 | * @Author: YangSL
115 | * @Description: 无等待从内存池中分配存储块
116 | * @param {tMemPool *} memPool
117 | * @param {uint8_t **} memBlock
118 | */
119 | uint32_t uMemPoolNoWaitAlloc(tMemPool * memPool, uint8_t ** memBlock)
120 | {
121 | uint32_t status = uTaskEnterCritical();
122 |
123 | if(uGetListNodeCount(&memPool->blockList) > 0)
124 | {
125 | *memBlock = (uint8_t *)tListRemoveFirst(&memPool->blockList);
126 | vTaskExitCritical(status);
127 | return eErrorNoError;
128 | }
129 | else
130 | {
131 | vTaskExitCritical(status);
132 | return eErrorResourceUnavaliable;
133 | }
134 | }
135 |
136 | /**
137 | * @Author: YangSL
138 | * @Description: 释放内存块
139 | * @param {tMemPool} *memPool 要操作的内存池
140 | * @param {void *} memBlock 释放内存块的地址
141 | */
142 | void vMemPoolFree(tMemPool *memPool, void * memBlock)
143 | {
144 | uint32_t status = uTaskEnterCritical();
145 |
146 | /* 检查是否有等待请求储存块的任务 */
147 | if(uEventGetWaitCount(&memPool->event) > 0)
148 | {
149 | /* 如果有直接唤醒等待队列的第一个任务 */
150 | tTask * task = tEventWakeUp(&memPool->event, (void *)memBlock, eErrorNoError);
151 |
152 | /* 检查是或需要任务切换 */
153 | if(task->prio > currentTask->prio)
154 | {
155 | vTaskSched();
156 | }
157 | }
158 | else
159 | {
160 | /* 等待列表为空,则将存储块加入存储池中 */
161 | vListInsertLast(&memPool->blockList, (tNode *)memBlock);
162 | }
163 |
164 | vTaskExitCritical(status);
165 | }
166 |
167 |
168 | /**
169 | * @Author: YangSL
170 | * @Description: 删除内存池
171 | * @param {tMemPool *} memPool
172 | */
173 | uint32_t uMemPoolDelete(tMemPool * memPool)
174 | {
175 | uint32_t status = uTaskEnterCritical();
176 |
177 | /* 唤醒等待该内存块的所有任务 */
178 | uint32_t count = uEventRemoveAll(&memPool->event, (void *) 0, eErrorDelete);
179 |
180 | vTaskExitCritical(status);
181 |
182 | if (count)
183 | {
184 | vTaskSched();
185 | }
186 | return count;
187 | }
188 |
189 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Mutex.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-03 21:27:12
5 | * @LastEditTime: 2021-08-05 23:15:31
6 | * @Description:
7 | */
8 |
9 | #include "LinOS.h"
10 |
11 |
12 | /**
13 | * @Author: YangSL
14 | * @Description: 初始化互斥信号量
15 | * @param {tMutex *} mutex
16 | */
17 | void vMutexInit(tMutex * mutex)
18 | {
19 | vEventInit(&mutex->event, eEventTypeMutex);
20 |
21 | mutex->lockCount = 0;
22 | mutex->owner =(tTask *)0;
23 | mutex->ownerOriginalPrio = LinOS_PRI_COUNT;
24 |
25 | }
26 |
27 |
28 | /**
29 | * @Author: YangSL
30 | * @Description: 获取互斥量
31 | * @param {tMutex *} mutex
32 | * @param {uint32_t} timeout 等待时间,为零则表示一直等待
33 | */
34 | uint32_t uMutexTake(tMutex * mutex, uint32_t timeout)
35 | {
36 | uint32_t status = uTaskEnterCritical();
37 |
38 | /* 判断互斥量是否又被使用 */
39 | if( mutex->lockCount <= 0)
40 | {
41 | /* 未被使用 */
42 | mutex->owner = currentTask;
43 | mutex->ownerOriginalPrio = currentTask->prio;
44 | mutex->lockCount++;
45 |
46 | vTaskExitCritical(status);
47 | return eErrorNoError;
48 | }
49 | else
50 | {
51 | /*互斥量已经被锁定 */
52 | /* 判断是否是被自己锁定的 */
53 | if(mutex->owner == currentTask)
54 | {
55 | mutex->lockCount++;
56 |
57 | vTaskExitCritical(status);
58 | return eErrorNoError;
59 | }
60 | else
61 | {
62 | /* 互斥量被其他任务占用了 */
63 | if(currentTask->prio < mutex->owner->prio)
64 | {
65 | tTask * owner = mutex->owner;
66 |
67 | /* 如果处以就绪列表中则:
68 | 1. 现将任务从就绪列表中移除
69 | 2. 提高拥有互斥量任务的优先级
70 | 3. 将提高后的拥有互斥量的任务重新加入优先级队列中*/
71 | if(owner->state == eReady)
72 | {
73 | vTaskSchedUnRdy(owner);
74 | owner->prio = currentTask->prio;
75 | vTaskSchedRdy(owner);
76 | }
77 | else
78 | {
79 | /* 其它状态,只需要修改优先级 */
80 | owner->prio = currentTask->prio;
81 | }
82 | }
83 |
84 | /* 将当前任务加入等待队列中 */
85 | vEventWait(&mutex->event, currentTask, (void *)0, eEventTypeMutex, timeout);
86 | vTaskExitCritical(status);
87 |
88 | vTaskSched();
89 | return currentTask->waitEventResult;
90 | }
91 | }
92 | }
93 |
94 |
95 | /**
96 | * @Author: YangSL
97 | * @Description: 无等待获取互斥量,如果没有可用信号量,就立马返回
98 | * @param {tMutex *} mutex
99 | */
100 | //uint32_t uMutexTryTake(tMutex * mutex)
101 | //{
102 |
103 | //}
104 |
105 | /**
106 | * @Author: YangSL
107 | * @Description: 释放互斥量
108 | * @param {tMutex *} mutex
109 | */
110 | uint32_t uMutexRelease(tMutex * mutex)
111 | {
112 | uint32_t status = uTaskEnterCritical();
113 |
114 | if(mutex->lockCount <= 0)
115 | {
116 | vTaskExitCritical(status);
117 | return eErrorNoError;
118 | }
119 |
120 | if(mutex->owner != currentTask)
121 | {
122 | vTaskExitCritical(status);
123 | return eErrorOwner;
124 | }
125 |
126 | if(--mutex->lockCount != 0)
127 | {
128 | vTaskExitCritical(status);
129 | return eErrorNoError;
130 | }
131 |
132 | /* 是否有优先级继承发生 */
133 | if(mutex->ownerOriginalPrio != mutex->owner->prio)
134 | {
135 | /* 如果处以就绪列表中则:
136 | 1. 现将任务从就绪列表中移除
137 | 2. 将任务优先级恢复成之前的优先级
138 | 3. 将提高后的拥有互斥量的任务重新加入优先级队列中*/
139 | if(mutex->owner->state == eReady)
140 | {
141 | vTaskSchedUnRdy(mutex->owner);
142 | currentTask->prio = mutex->ownerOriginalPrio;
143 | vTaskSchedRdy(mutex->owner);
144 | }
145 | else
146 | {
147 | currentTask->prio = mutex->ownerOriginalPrio;
148 | }
149 | }
150 |
151 | /* 检查是否有任务等待 */
152 | if(uEventGetWaitCount(&mutex->event) > 0)
153 | {
154 | /* 优先唤醒位于队列头部的任务 */
155 | tTask * task = tEventWakeUp(&mutex->event, (void *)0, eErrorNoError);
156 |
157 | mutex->owner = task;
158 | mutex->ownerOriginalPrio = task->prio;
159 | mutex->lockCount++;
160 |
161 | /* 唤醒的任务如果比当前任务优先高,进行任务切换 */
162 | if(currentTask->prio < task->prio)
163 | {
164 | vTaskSched();
165 | }
166 | }
167 |
168 | vTaskExitCritical(status);
169 | return eErrorNoError;
170 |
171 |
172 | }
173 |
174 | /**
175 | * @Author: YangSL
176 | * @Description: 删除该互斥量
177 | * @param {tMutex *} mutex
178 | */
179 | uint32_t uMutexDelete(tMutex * mutex)
180 | {
181 | uint32_t deleteCount = 0;
182 | uint32_t status = uTaskEnterCritical();
183 |
184 | /* 互斥量是否被使用了 */
185 | if(mutex->lockCount > 0)
186 | {
187 | if(mutex->owner->prio != mutex->ownerOriginalPrio)
188 | {
189 | /* 如果处以就绪列表中则:
190 | 1. 现将任务从就绪列表中移除
191 | 2. 将任务优先级恢复成之前的优先级
192 | 3. 将提高后的拥有互斥量的任务重新加入优先级队列中*/
193 | if(mutex->owner->state == eReady)
194 | {
195 | vTaskSchedUnRdy(mutex->owner);
196 | currentTask->prio = mutex->ownerOriginalPrio;
197 | vTaskSchedRdy(mutex->owner);
198 | }
199 | else
200 | {
201 | currentTask->prio = mutex->ownerOriginalPrio;
202 | }
203 | }
204 |
205 | deleteCount = uEventRemoveAll(&mutex->event, (void *)0, eErrorDelete);
206 |
207 | if(deleteCount > 0)
208 | {
209 | vTaskSched();
210 | }
211 | }
212 |
213 | vTaskExitCritical(status);
214 | return deleteCount;
215 | }
216 |
217 |
218 | /**
219 | * @Author: YangSL
220 | * @Description: 获取互斥量的相关信息
221 | * @param {tMutex *} mutex
222 | * @param {tMutexInfo *} info
223 | */
224 | void vMutexGetInfo(tMutex * mutex,tMutexInfo * info )
225 | {
226 | uint32_t status = uTaskEnterCritical();
227 |
228 | /* 拷贝需要的信息 */
229 | info->waitTaskCount = uEventGetWaitCount(&mutex->event);
230 | info->ownerPrio = mutex->ownerOriginalPrio;
231 | if (mutex->owner != (tTask *)0)
232 | {
233 | info->inheritedPrio = mutex->owner->prio;
234 | }
235 | else
236 | {
237 | info->inheritedPrio = LinOS_PRI_COUNT;
238 | }
239 | info->owner = mutex->owner;
240 | info->lockCount = mutex->lockCount;
241 |
242 |
243 | vTaskExitCritical(status);
244 | }
245 |
246 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Sem.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-27
5 | * @LastEditTime: 2021-07-27 21:57:07
6 | * @Description:
7 | */
8 |
9 | #include "Sem.h"
10 | #include "LinOs.h"
11 | /**
12 | * @Author: YangSL
13 | * @Description: 初始化信号量
14 | * @param {tSem} *sem
15 | * @param {uint32_t} startCount 初始的计数
16 | * @param {uint32_t} maxCount 最大计数,如果为0,则不限数量
17 | */
18 | void vSemInit(tSem *sem, uint32_t startCount, uint32_t maxCount)
19 | {
20 | vEventInit(&sem->event, eEventTypeSem);
21 |
22 | sem->maxCount = maxCount;
23 | if( maxCount == 0)
24 | {
25 | sem->count = startCount;
26 | }
27 | else
28 | {
29 | sem->count = (startCount > maxCount) ?maxCount :startCount;
30 | }
31 | }
32 |
33 |
34 | /**
35 | * @Author: YangSL
36 | * @Description: 获取信号量
37 | * @param {tSem *} sem 等待的信号量
38 | * @param {uint32_t} time 等待的时间,为零表示永远等待
39 | * RT-Thread描述:
40 | * 线程通过调用该函数获取信号量来获得信号量资源实例,当信号量值大于零时,
41 | * 线程将获得信号量, 并且相应的信号量值会减 1;如果信号量的值等于零,那么说明当前信号量资源实例不可用,
42 | * 申请该信号量的线程将根据 time 参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。
43 | */
44 | uint32_t uSemTake(tSem * sem, uint32_t time)
45 | {
46 | uint32_t status = uTaskEnterCritical();
47 |
48 | /* 当前信号量计数大于1,则直接减一处理 */
49 | if(sem->count > 0)
50 | {
51 | --sem->count;
52 | vTaskExitCritical(status);
53 | return eErrorNoError;
54 | }
55 | else /* 否则将当前任务加入等待队列 */
56 | {
57 | vEventWait(&sem->event, currentTask, (void *)0, eEventTypeSem, time);
58 |
59 | vTaskExitCritical(status);
60 |
61 | vTaskSched();
62 |
63 | return currentTask->waitEventResult;
64 | }
65 | }
66 |
67 |
68 |
69 | /**
70 | * @Author: YangSL
71 | * @Description: 无等待获取信号量
72 | * @param {tSem *} sem 等待的信号量
73 | */
74 | uint32_t uSemTryTake(tSem * sem)
75 | {
76 | uint32_t status = uTaskEnterCritical();
77 |
78 | if(sem->count > 0)
79 | {
80 | --sem->count;
81 | vTaskExitCritical(status);
82 | return eErrorNoError;
83 | }
84 | else
85 | {
86 | vTaskExitCritical(status);
87 | return eErrorResourceUnavaliable;
88 | }
89 | }
90 |
91 |
92 | /**
93 | * @Author: YangSL
94 | * @Description: 释放信号量
95 | * @param {tSem *} sem 操作的信号量
96 | * RT-Thread描述:
97 | * 该函数将释放一个信号量,当信号量的值等于零时,并且有线程等待这个信号量时
98 | * 释放信号量将唤醒等待在该信号量线程队列中的第一个线程,由它获取信号量
99 | * 否则 将把信号量的值加一
100 | */
101 | void vSemRelease(tSem * sem)
102 | {
103 | uint32_t status = uTaskEnterCritical();
104 |
105 | /* 有等待的任务 */
106 | if(uEventGetWaitCount(&sem->event) > 0)
107 | {
108 | tTask * task = tEventWakeUp(&sem->event, (void *)0, eErrorNoError);
109 |
110 | /* 如果等待的任务优先比当前任务高,需要进行任务切换 */
111 | if( task->prio < currentTask->prio)
112 | {
113 | vTaskSched();
114 | }
115 | }
116 | else /* 无等待任务 */
117 | {
118 | /* 计数加一 */
119 | ++sem->count;
120 |
121 | /* 如果计数不是无限的,同时当前计数大于最大设定值,则需要限幅处理 */
122 | if((sem->maxCount != 0) && (sem->count > sem->maxCount))
123 | {
124 | sem->count = sem->maxCount;
125 | }
126 | }
127 | vTaskExitCritical(status);
128 | }
129 |
130 |
131 | /**
132 | * @Author: YangSL
133 | * @Description: 删除信号量
134 | * @param {tSem *} sem
135 | */
136 | uint32_t uSemDelete(tSem * sem)
137 | {
138 | uint32_t status = uTaskEnterCritical();
139 |
140 | uint32_t count = uEventRemoveAll(&sem->event, (void *)0, eErrorDelete);
141 |
142 | sem->count = 0;
143 |
144 | vTaskExitCritical(status);
145 |
146 | if (count > 0)
147 | {
148 | vTaskSched();
149 | }
150 |
151 | return count;
152 | }
153 |
154 |
155 | /**
156 | * @Author: YangSL
157 | * @Description: 查询信号量的状态信息
158 | * @param {tSem *} sem
159 | * @param {tSemInfo *} info
160 | */
161 | void vSemGetInfo(tSem * sem, tSemInfo * info)
162 | {
163 | uint32_t status = uTaskEnterCritical();
164 |
165 | info->count = sem->count;
166 | info->maxCount = sem->maxCount;
167 | info->taskCount = uEventGetWaitCount(&sem->event);
168 |
169 | vTaskExitCritical(status);
170 | }
171 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Tasks.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-08
5 | * @LastEditTime: 2022-01-29 15:53:37
6 | * @Description:
7 | */
8 | #include "Tasks.h"
9 | #include "Bitmap.h"
10 | #include "port.h"
11 | #include "LinOS.h"
12 | #include "LinOSConfig.h"
13 |
14 | /* 当前任务:记录当前是哪个任务正在运行 */
15 | tTask * currentTask;
16 | /* 下一个将即运行的任务 */
17 | tTask * nextTask;
18 | /* 空闲任务 */
19 | tTask * idleTask;
20 |
21 | /* 所有任务的指针数组 */
22 | tList taskPrioTable[LinOS_PRI_COUNT];
23 | /* 调度锁计数器 */
24 | uint8_t schedLockCount;
25 | /* 延时队列 */
26 | tList taskDelayList;
27 | /* 优先级位置 */
28 | Bitmap_t LinOSBitmap;
29 |
30 |
31 | /* 空闲任务空间 */
32 | tTask tTaskIdle;
33 | tTaskStack idleTaskEnv[LinOS_IDLE_STACK_SIZE];
34 |
35 |
36 | /* 空闲任务计数与最大计数 */
37 | uint32_t idleCount;
38 | uint32_t idleMaxCount;
39 |
40 | /* 系统计数 */
41 | long long systemTicks;
42 |
43 | /* CPU使用率统计 */
44 | static float cpuUsage;
45 | /*---------------------------------------------------------------------------------------------------------------------
46 | * 任务调度相关操作
47 | *--------------------------------------------------------------------------------------------------------------------*/
48 |
49 | /**
50 | * @Author: YangSL
51 | * @Description: 任务初始化API
52 | * @param {tTask *} task: 任务名称
53 | * @param {void} * 任务程序入口
54 | * @param {void} *param 传给任务的入口函数
55 | * @param {uint32_t *} stack 任务堆栈
56 | */
57 | void vTaskInit (tTask * task, void (*entry)(void *), void *param, uint32_t prio, uint32_t * stack, uint32_t stackSize)
58 | {
59 | /* 初始化该任务硬件相关的堆栈 */
60 | hwStackInit(task, entry, param, stack, stackSize);
61 |
62 | task->delayTicks = 0; // 任务延时计数器
63 | task->prio = prio; // 设置优先级
64 | task->slice = LinOS_SLICE_MAX; // 初始化时间片计数
65 | task->supendCount = 0; // 初始化挂起次数
66 | task->state = eReady;
67 |
68 | task->clean = (void(*)(void *))0; // 设置清理函数
69 | task->cleanParam = (void *)0; // 设置传递给清理函数的参数
70 | task->requestsDeleteFlag = 0; // 请求删除标记
71 |
72 | task->waitEvent = (tEvent *)0; // 初始化等待事件
73 | task->waitEventMsg = (void *) 0; // 初始化等待消息
74 | task->waitEventResult = eErrorNoError; // 初始化等待事件错误
75 |
76 |
77 | vNodeInit(&(task->delayNode)); // 初始化延时结点
78 |
79 | vNodeInit(&(task->linkNode)); // 初始化链接结点
80 |
81 | vTaskSchedRdy(task); // 将任务插入就绪队列
82 | }
83 |
84 | void idleTaskEntry(void * parm);
85 | /**
86 | * @Author: YangSL
87 | * @Description: 任务调度函数API
88 | */
89 | void vTaskSched(void)
90 | {
91 | tTask * tempTask;
92 | uint32_t status = uTaskEnterCritical();
93 |
94 | /* 创建空闲任务 */
95 | static uint32_t createIdleFlag = 0;
96 | if(createIdleFlag == 0)
97 | {
98 | /* 创建空闲任务 */
99 | vTaskInit(&tTaskIdle, idleTaskEntry, (void *)0, LinOS_PRI_COUNT - 1, idleTaskEnv, LinOS_STACK_SIZE);
100 | createIdleFlag = 1;
101 | }
102 |
103 | /* 判断调度器是否上锁 */
104 | if (schedLockCount > 0)
105 | {
106 | vTaskExitCritical(status);
107 | return;
108 | }
109 |
110 | /* 寻找优先级最高的任务 */
111 | tempTask = tTaskHighestReady();
112 | {
113 | if (tempTask != currentTask)
114 | {
115 | nextTask = tempTask;
116 | taskScheduler();
117 | }
118 | }
119 |
120 | vTaskExitCritical(status);
121 | }
122 |
123 | static void checkCpuUsage(void);
124 | /**
125 | * @Author: YangSL
126 | * @Description: 系统时钟节拍处理
127 | */
128 | void vTaskSystemTickHandler (void)
129 | {
130 | tNode *node;
131 |
132 | /* 进入临界区 */
133 | uint32_t status = uTaskEnterCritical();
134 |
135 |
136 |
137 | /* 系统计数加一 */
138 | systemTicks++;
139 |
140 | /* 检测CPU使用情况 */
141 | #if LinOS_ENABLE_CPU_CHECK
142 | checkCpuUsage();
143 | #endif /* LinOS_ENABLE_CPU_CHECK */
144 |
145 | /* 遍历所有的延时列表 */
146 | for (node = taskDelayList.headNode.nextNode; node != &(taskDelayList.headNode); node = node->nextNode)
147 | {
148 | tTask * task = nodeParent(node , tTask, delayNode);
149 |
150 | if(--task->delayTicks == 0)
151 | {
152 | /* 如果任务还处于等待事件的状态,则将其从事件等待队列中唤醒 */
153 | if (task->waitEvent)
154 | {
155 | /* 此时,消息为空,等待结果为超时 */
156 | vEventRemoveTask(task, (void *)0, eErrorTimeout);
157 | }
158 |
159 |
160 | /* 将任务从延时队列中移除 */
161 | vTaskDelayWakeUp(task);
162 |
163 | /* j将任务添加到就绪列表 */
164 | vTaskSchedRdy(task);
165 | }
166 | }
167 |
168 | if(--currentTask->slice == 0)
169 | {
170 | if(uGetListNodeCount(&taskPrioTable[currentTask->prio]) > 0)
171 | {
172 | /* 刷新要运行的同一个优先级下的任务 */
173 | tListRemoveFirst(&taskPrioTable[currentTask->prio]);
174 | vListInsertLast(&taskPrioTable[currentTask->prio], &(currentTask->linkNode));
175 |
176 | /* 重置计数器 */
177 | currentTask->slice = LinOS_SLICE_MAX;
178 | }
179 | }
180 |
181 | /* 退出临界区 */
182 | vTaskExitCritical(status);
183 |
184 | /* 是否使用定时器 */
185 | #if LinOS_TIMER_SWITCH
186 | vTimerModulCheckTick();
187 | #endif
188 |
189 | vTaskSched();
190 | }
191 |
192 |
193 | /*---------------------------------------------------------------------------------------------------------------------
194 | * 调度器开关
195 | *--------------------------------------------------------------------------------------------------------------------*/
196 | /**
197 | * @Author: YangSL
198 | * @Description: 禁止任务调度
199 | */
200 | void vTaskSchedDisable(void)
201 | {
202 | uint32_t status = uTaskEnterCritical();
203 |
204 | if (schedLockCount <255){
205 | schedLockCount++;
206 | }
207 |
208 | vTaskExitCritical(status);
209 | }
210 |
211 |
212 | /**
213 | * @Author: YangSL
214 | * @Description: 使能任务调度器
215 | */
216 | void vTaskSchedEnable(void)
217 | {
218 | uint32_t status = uTaskEnterCritical();
219 |
220 | if(schedLockCount >0)
221 | {
222 | if(--schedLockCount == 0)
223 | {
224 | vTaskSched();
225 | }
226 | }
227 | }
228 |
229 |
230 | /**
231 | * @Author: YangSL
232 | * @Description: 调度器初始化
233 | */
234 | void vTaskSchedInit(void)
235 | {
236 | int i;
237 | schedLockCount = 0;
238 |
239 | vBitmapInit(&LinOSBitmap);
240 | for(i = 0; i < LinOS_PRI_COUNT; i++)
241 | {
242 | vListInit(&taskPrioTable[i]);
243 | }
244 | }
245 |
246 |
247 | /*---------------------------------------------------------------------------------------------------------------------
248 | * 任务相关队列操作 (就绪态)
249 | *--------------------------------------------------------------------------------------------------------------------*/
250 |
251 | /**
252 | * @Author: YangSL
253 | * @Description: 将任务加入就绪列表
254 | * @param {tTask *} task
255 | */
256 | void vTaskSchedRdy(tTask * task)
257 | {
258 | vListInsertLast(&taskPrioTable[task->prio], &(task->linkNode));
259 |
260 | vBitmapSet(&LinOSBitmap, task->prio);
261 | }
262 |
263 | /**
264 | * @Author: YangSL
265 | * @Description: 将任务从就绪列表中移除
266 | * @param {tTask *} task
267 | */
268 | void vTaskSchedUnRdy(tTask * task)
269 | {
270 | /* */
271 | vListRemoveNode(&taskPrioTable[task->prio], &(task->linkNode));
272 |
273 | if(uGetListNodeCount(&taskPrioTable[task->prio]) == 0)
274 | {
275 | vBitmapClear(&LinOSBitmap, task->prio);
276 | }
277 |
278 | }
279 |
280 | /**
281 | * @Author: YangSL
282 | * @Description: 获取当前最高优先级且可运行的任务
283 | */
284 | tTask *tTaskHighestReady(void)
285 | {
286 | /* 获取最高优先级 */
287 | uint32_t highestPrio = uBitmapGetFirstSet(&LinOSBitmap);
288 | /* 获得最高优先级对应列表的第一个节点 */
289 | tNode * node = tGetFirstNode(&taskPrioTable[highestPrio]);
290 | /* 返回对应任务的tList地址 */
291 | return (tTask *)nodeParent(node, tTask, linkNode);
292 | }
293 |
294 |
295 | /**
296 | * @Author: YangSL
297 | * @Description: 将任务从就绪列表中移除
298 | * @param {tTask *} task
299 | */
300 | void vTaskRdyListRemove(tTask * task)
301 | {
302 | /* */
303 | vListRemoveNode(&taskPrioTable[task->prio], &(task->linkNode));
304 |
305 | if(uGetListNodeCount(&taskPrioTable[task->prio]) == 0)
306 | {
307 | vBitmapClear(&LinOSBitmap, task->prio);
308 | }
309 |
310 | }
311 | /*---------------------------------------------------------------------------------------------------------------------
312 | * 任务相关队列操作 (阻塞态)
313 | *--------------------------------------------------------------------------------------------------------------------*/
314 | /**
315 | * @Author: YangSL
316 | * @Description: 延时队列初始化
317 | */
318 | void vTaskDelayInit(void)
319 | {
320 | vListInit(&taskDelayList);
321 | }
322 |
323 | /**
324 | * @Author: YangSL
325 | * @Description: 将任务加入延时队列
326 | * @param {tTask *} task : 延时列表
327 | * @param {uint32_t} ticks : 延时时间
328 | */
329 | void tTaskDelayWait(tTask * task, uint32_t ticks)
330 | {
331 | task->delayTicks = ticks;
332 | vListInsertLast(&taskDelayList, &(task->delayNode));
333 | task->state = eBlocked;
334 | }
335 |
336 |
337 | /**
338 | * @Author: YangSL
339 | * @Description: 将延时的任务从延时队列中唤醒
340 | * @param {tTask *} task
341 | */
342 | void vTaskDelayWakeUp(tTask * task)
343 | {
344 | vListRemoveNode(&taskDelayList, &(task->delayNode));
345 | task->state = eReady;
346 | }
347 |
348 |
349 | /**
350 | * @Author: YangSL
351 | * @Description: 将延时的任务从延时队列中移除
352 | * @param {tTask *} task
353 | */
354 | void vTaskDelayListRemove(tTask * task)
355 | {
356 | vListRemoveNode(&taskDelayList, &(task->delayNode));
357 | }
358 | /*---------------------------------------------------------------------------------------------------------------------
359 | * 任务相关队列操作 (挂起态)
360 | *--------------------------------------------------------------------------------------------------------------------*/
361 | /**
362 | * @Author: YangSL
363 | * @Description: 挂起指定的任务
364 | * @param {tTask *} task : 指定任务
365 | */
366 | void vTaskSupend(tTask * task)
367 | {
368 | uint32_t status = uTaskEnterCritical();
369 |
370 | if(task->state != eBlocked)
371 | {
372 | /* 如果是该任务是第一次挂起,则需要以下处理
373 | 1. 将任务状态设置为挂起状态
374 | 2. 从就绪列表中移除 */
375 | if( ++task->supendCount <= 1)
376 | {
377 | task->state = eSuspended;
378 |
379 | vTaskSchedUnRdy(task);
380 |
381 | /* 如果挂起的任务是当前正在运行的,则立马就进行调度 */
382 | if(task == currentTask)
383 | {
384 | vTaskSched();
385 | }
386 | }
387 | }
388 | vTaskExitCritical(status);
389 |
390 | }
391 |
392 |
393 | /**
394 | * @Author: YangSL
395 | * @Description: 将任务从挂起态唤醒
396 | * @param {tTask *} task
397 | */
398 | void vTaskResume(tTask * task)
399 | {
400 | uint32_t status = uTaskEnterCritical();
401 |
402 | if(task->state == eSuspended)
403 | {
404 | if(--task->supendCount == 0)
405 | {
406 | /* 将任务设置为就绪态 */
407 | task->state = eReady;
408 |
409 | /* 添加到就绪列表 */
410 | vTaskSchedRdy(task);
411 |
412 | /* 可能唤醒的任务优先级比当前高,就需要执行一次任务调度 */
413 | vTaskSched();
414 | }
415 | }
416 |
417 | vTaskExitCritical(status);
418 | }
419 |
420 |
421 | /*---------------------------------------------------------------------------------------------------------------------
422 | * 任务相关队列操作 (删除)
423 | *--------------------------------------------------------------------------------------------------------------------*/
424 |
425 | /**
426 | * @Author: YangSL
427 | * @Description: 设置任务被删除时调用的清理回调函数
428 | * @param {tTask *} task :待设置的任务
429 | * @param {void} *param :清理函数入口地址
430 | * @param {void *} param :传递给清理函数的参数
431 | */
432 | void vTaskSetCleanCallback(tTask * task, void (*clean )(void *param), void * param)
433 | {
434 | task->clean = clean;
435 | task->cleanParam = param;
436 | }
437 |
438 |
439 | /**
440 | * @Author: YangSL
441 | * @Description: 强制删除任务
442 | * @param {tTask *} task
443 | */
444 | void vTaskForceDelete(tTask * task)
445 | {
446 | /* 进入临界区 */
447 | uint32_t status = uTaskEnterCritical();
448 |
449 | /* 如果任务处于延时状态,则从延时队列中删除 */
450 | if ( task->state == eBlocked)
451 | {
452 | vTaskDelayListRemove(task);
453 | }
454 | /* 如果任务不处于挂起状态,那么就是就绪态,从就绪表中删除 */
455 | else if(!(task->state == eSuspended))
456 | {
457 | vTaskRdyListRemove(task);
458 | }
459 |
460 | /* 删除时,如果有设置清理函数,则调用清理函数 */
461 | if (task->clean)
462 | {
463 | task->clean(task->cleanParam);
464 | }
465 |
466 | /* 如果删除的是自己,那么需要切换至另一个任务,所以执行一次任务调度 */
467 | if (currentTask == task)
468 | {
469 | vTaskSched();
470 | }
471 |
472 | /* 退出临界区 */
473 | vTaskExitCritical(status);
474 | }
475 |
476 |
477 | /**
478 | * @Author: YangSL
479 | * @Description: 请求删除某个任务,最后由任务自己决定是否删除自己
480 | * @param {tTask *} task
481 | */
482 | void vTaskRequestsDelete(tTask * task)
483 | {
484 | /* 进入临界区 */
485 | uint32_t status = uTaskEnterCritical();
486 |
487 | /* 设置清除删除标记 */
488 | task->requestsDeleteFlag = 1;
489 |
490 | /* 退出临界区 */
491 | vTaskExitCritical(status);
492 | }
493 |
494 | /**
495 | * @Author: YangSL
496 | * @Description: 检查是否已经被请求删除自己
497 | * @param {tTask *} task
498 | */
499 | uint8_t uTaskCheckDelete(void)
500 | {
501 | uint8_t deleteFlag;
502 |
503 | /* 进入临界区 */
504 | uint32_t status = uTaskEnterCritical();
505 |
506 | deleteFlag = currentTask->requestsDeleteFlag;
507 |
508 | /* 退出临界区 */
509 | vTaskExitCritical(status);
510 |
511 | return deleteFlag;
512 | }
513 |
514 | /**
515 | * @Author: YangSL
516 | * @Description: 删除自己
517 | */
518 | void vTaskDeleteSelf(void)
519 | {
520 | /* 进入临界区 */
521 | uint32_t status = uTaskEnterCritical();
522 |
523 | /* 将自身从就绪队列中移除 */
524 | vTaskRdyListRemove(currentTask);
525 |
526 | /* 调用清理函数 */
527 | if(currentTask->clean)
528 | {
529 | currentTask->clean(currentTask->cleanParam);
530 | }
531 |
532 | vTaskSched();
533 |
534 | /* 退出临界区 */
535 | vTaskExitCritical(status);
536 | }
537 |
538 | /*---------------------------------------------------------------------------------------------------------------------
539 | * Others
540 | *--------------------------------------------------------------------------------------------------------------------*/
541 | /**
542 | * @Author: YangSL
543 | * @Description: RTOS延时函数
544 | * @param {uint32_t} delay
545 | */
546 | void vTaskDelay(uint32_t delay)
547 | {
548 | uint32_t status = uTaskEnterCritical();
549 |
550 | /* 设置延时值,插入延时队列 */
551 | tTaskDelayWait(currentTask, delay);
552 |
553 | /* 将任务从就绪表中移除 */
554 | vTaskSchedUnRdy(currentTask);
555 |
556 | vTaskSched();
557 |
558 | vTaskExitCritical(status);
559 | }
560 |
561 |
562 | /**
563 | * @Author: YangSL
564 | * @Description: 获取任务相关信息
565 | * @param {tTask *} task :需要查询的任务
566 | * @param {tTaskInfo} info :任务信息存储结构
567 | */
568 | void vTaskGetInfo(tTask * task, tTaskInfo *info)
569 | {
570 | uint32_t * stackEnd;
571 |
572 | /* 进入临界区 */
573 | uint32_t status = uTaskEnterCritical();
574 |
575 | /* 延时信息 */
576 | info->delayTicks = task->delayTicks;
577 |
578 | /* 优先级 */
579 | info->prio = task->prio;
580 |
581 | /* 任务状态 */
582 | info->state = task->state;
583 |
584 | /* 剩余时间片 */
585 | info->slice = task->slice;
586 |
587 | /* 被挂起的次数 */
588 | info->supendCount = task->supendCount;
589 |
590 | info->stackSize = task->stackSize;
591 |
592 | /* 计算堆桟使用情况 */
593 | info->stackFree = 0;
594 | stackEnd = task->stackBase;
595 | /* 注意堆桟是从上往下增长的->stackEnd最小 */
596 | while((*stackEnd++ == 0) && (stackEnd <= task->stackBase + task->stackSize / sizeof(tTaskStack)))
597 | {
598 | info->stackFree++;
599 | }
600 |
601 | /* 转换成字节数 */
602 | info->stackFree *= sizeof(tTaskStack);
603 |
604 | /* 退出临界区 */
605 | vTaskExitCritical(status);
606 | }
607 |
608 |
609 |
610 | /**
611 | * @Author: YangSL
612 | * @Description: 空闲任务
613 | * @param {void *} parm
614 | */
615 | void idleTaskEntry(void * parm)
616 | {
617 | uint32_t status = uTaskEnterCritical();
618 |
619 | #if LinOS_TIMER_SWITCH
620 | /* 初始化定时器相关资源 */
621 | vTimerModulInit();
622 | /* 创建定时器任务 */
623 | vTimerTickInit();
624 | #endif
625 |
626 | vTaskExitCritical(status);
627 |
628 | for(;;)
629 | {
630 | uint32_t status = uTaskEnterCritical();
631 | idleCount++;
632 | vTaskExitCritical(status);
633 | }
634 | }
635 |
636 |
637 | static void checkCpuUsage(void)
638 | {
639 | if(systemTicks % 1000 == 0)
640 | {
641 | idleMaxCount = idleCount;
642 |
643 | cpuUsage = 100 - (idleCount / 1000) * 100;
644 |
645 | idleCount = 0;
646 | }
647 | }
648 |
649 | /**
650 | * @Author: YangSL
651 | * @Description: 获取CPU使用率
652 | */
653 | float fTaskGetCpuUsage(void)
654 | {
655 | float usage = 0;
656 |
657 | uint32_t status = uTaskEnterCritical();
658 | usage = cpuUsage;
659 | vTaskExitCritical(status);
660 |
661 | return usage;
662 | }
663 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/Timer.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-07 11:32:51
5 | * @LastEditTime: 2021-08-09 21:44:29
6 | * @Description:
7 | */
8 | #include "LinOS.h"
9 |
10 | /* "硬"定时器列表 */
11 | static tList timerHardList;
12 | /* "软"定时器列表 */
13 | static tList timerSoftList;
14 |
15 | /* 用于访问软定时器列表的信号量 */
16 | static tSem timerProtectSem;
17 | /* 用于软定时器任务与中断同步的计数信号量 */
18 | static tSem timerTickSem;
19 |
20 |
21 | /* 定义定时器任务和任务的栈空间大小 */
22 | static tTask timerTask;
23 | static tTaskStack timerTaskStack[LinOS_TIMERTASK_STACK_SIZE];
24 |
25 | /*---------------------------------------------------------------------------------------------------------------------
26 | * TIMER FUNC
27 | *--------------------------------------------------------------------------------------------------------------------*/
28 | /**
29 | * @Author: YangSL
30 | * @Description: 初始化定时器
31 | * @param {tTimer *} timer 等待初始化的定时器
32 | * @param {uint32_t} timerTicks 定时器超时Ticks
33 | * @param {uint32_t} flag 设置定时器是一次性还是周期定时器
34 | * @param {void *} timerFunc 定时器回调函数
35 | * @param {void *} arg 传递给定时器回调函数的参数
36 | * @param {uint32_t} config 定时器的初始配置
37 | */
38 | void vTimerInit(tTimer * timer, uint32_t timerTicks, uint32_t flag, void (*timerFunc)(void * arg), void * arg, uint32_t config)
39 | {
40 | /* 初始化定器列表 */
41 | vNodeInit(&timer->linkNode);
42 |
43 | /* 设置定时器类型及定时时间 */
44 | timer->timerTicks = timerTicks;
45 | timer->flag = flag;
46 | /* 当前定时器递减值 */
47 | timer->delayTicks = timerTicks;
48 |
49 | /* 设置定时器的超时回调函数 */
50 | timer->timerFunc = timerFunc;
51 | timer->arg = arg;
52 |
53 | /* 配置模式 */
54 | timer->config = config;
55 |
56 | /* 设定时器标志为:创建完成 */
57 | timer->state = eTimerCreated;
58 |
59 | }
60 |
61 |
62 | /**
63 | * @Author: YangSL
64 | * @Description:
65 | * @param {tList *} timerList
66 | */
67 | static void vTimerCallFuncList(tList * timerList)
68 | {
69 | tNode * node;
70 |
71 | /* 遍历所有的定时任务 */
72 | for(node = timerList->headNode.nextNode; node != &(timerList->headNode); node = node->nextNode)
73 | {
74 | tTimer * timer = nodeParent(node, tTimer, linkNode);
75 |
76 | /* 如果延时已到,则调用定时器处理函数 */
77 | if(timer->delayTicks == 0 || --timer->delayTicks == 0)
78 | {
79 | timer->state = eTimerRunning;
80 |
81 | /* 调用定时器回调函数 */
82 | timer->timerFunc(timer->arg);
83 |
84 | timer->state = eTimerStarted;
85 |
86 | if((timer->flag & TIMER_FLAG_MASK) == TIEMR_FLAG_PERIODIC)
87 | {
88 | /* 周期定时,重新定时计数 */
89 | timer->delayTicks = timer->timerTicks;
90 | }
91 | else
92 | {
93 | /* 是一次性计数器,中止定时器 */
94 | vListRemoveNode(timerList, &timer->linkNode);
95 | timer->state = eTimerStopped;
96 | }
97 | }
98 |
99 | }
100 | }
101 |
102 | /**
103 | * @Author: YangSL
104 | * @Description: 检查定时器模块的时间计数
105 | */
106 | void vTimerModulCheckTick(void)
107 | {
108 | uint32_t status = uTaskEnterCritical();
109 |
110 | /* 处理硬定时器列表 */
111 | vTimerCallFuncList(&timerHardList);
112 |
113 | vTaskExitCritical(status);
114 |
115 | /* 释放信号量通知软件定时器节拍发生变化 */
116 | vSemRelease(&timerTickSem);
117 | }
118 |
119 | /**
120 | * @Author: YangSL
121 | * @Description: 启动定时器任务
122 | * @param {tTimer} *timer
123 | */
124 | void vTimerStart(tTimer *timer)
125 | {
126 | switch (timer->state)
127 | {
128 | case eTimerCreated:
129 | case eTimerStopped:
130 | timer->delayTicks = timer->timerTicks;
131 | timer->state = eTimerStarted;
132 |
133 | if((timer->config & TIMER_MODE_MASK) == TIMER_HARD_MODE)
134 | {
135 | /* 硬件定时器模式 */
136 | uint32_t status = uTaskEnterCritical();
137 |
138 | /* 加入硬定时器列表 */
139 | vListInsertLast(&timerHardList, &timer->linkNode);
140 |
141 | vTaskExitCritical(status);
142 | }
143 | else
144 | {
145 | uSemTake(&timerProtectSem, 0);
146 | vListInsertLast(&timerSoftList, &timer->linkNode);
147 | vSemRelease(&timerProtectSem);
148 | }
149 | break;
150 |
151 | default:
152 | break;
153 | }
154 | }
155 |
156 |
157 | /**
158 | * @Author: YangSL
159 | * @Description: 停止定时器任务
160 | * @param {tTimer *} timer
161 | */
162 | void vTimerStop(tTimer * timer)
163 | {
164 | switch (timer->state)
165 | {
166 | case eTimerStarted:
167 | case eTimerRunning:
168 |
169 | /* 判断定时器模式 */
170 | if((timer->config & TIMER_MODE_MASK) == TIMER_HARD_MODE)
171 | {
172 | /* 硬件定时器模式 */
173 | uint32_t status = uTaskEnterCritical();
174 |
175 | vListRemoveNode(&timerHardList, &timer->linkNode);
176 |
177 | vTaskExitCritical(status);
178 | }
179 | else
180 | {
181 | /* 软件定时器模式 */
182 | uSemTake(&timerProtectSem, 0);
183 | vListRemoveNode(&timerSoftList, &timer->linkNode);
184 | vSemRelease(&timerProtectSem);
185 | }
186 | break;
187 |
188 | default:
189 | break;
190 | }
191 | }
192 |
193 |
194 | /**
195 | * @Author: YangSL
196 | * @Description: 软件定时器任务
197 | * @param {void *} param
198 | */
199 | static void timerSoftTask(void * param)
200 | {
201 | for(;;)
202 | {
203 | /* 无限制等待等待系统节拍发送的中断事件信号 */
204 | uSemTake(&timerTickSem, 0);
205 |
206 | /* 无限制等待软定时器列表的访问权限 */
207 | uSemTake(&timerProtectSem, 0);
208 |
209 | /* 处理软件定时器列表 */
210 | vTimerCallFuncList(&timerSoftList);
211 |
212 | /* 释放定时器访问权限 */
213 | vSemRelease(&timerProtectSem);
214 | }
215 | }
216 |
217 | /**
218 | * @Author: YangSL
219 | * @Description: 创建定时器模块
220 | */
221 | void vTimerModulInit(void)
222 | {
223 | /* 初始化全局定时器 */
224 |
225 |
226 | /* 初始化硬件计数列表 */
227 | vListInit(&timerHardList);
228 | /* 初始化软件定时器列表 */
229 | vListInit(&timerSoftList);
230 | /* */
231 | vSemInit(&timerProtectSem, 1, 1);
232 | /* 初始化软定时器任务与中断同步的计数信号量 */
233 | vSemInit(&timerTickSem, 0, 0);
234 |
235 | }
236 |
237 | /**
238 | * @Author: YangSL
239 | * @Description: 创建定时器任务
240 | */
241 | void vTimerTickInit(void)
242 | {
243 | #if LinOS_TIMER_PRIO >= LinOS_PRI_COUNT -1
244 | #error "The proprity of timer task must be greater then (LinOS_PRI_COUNT - 1)"
245 | #endif
246 | /* 初始化定时器任务 */
247 | vTaskInit(&timerTask, timerSoftTask, (void *)0, LinOS_TIMERTASK_PRIO, timerTaskStack, LinOS_TIMERTASK_STACK_SIZE);
248 | }
249 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Bitmap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-21
5 | * @LastEditTime: 2021-07-28 18:08:33
6 | * @Description:
7 | */
8 |
9 | #ifndef _BIT_MAP_H
10 | #define _BIT_MAP_H
11 |
12 | #include
13 |
14 | typedef union
15 | {
16 | uint32_t Val;
17 | uint16_t w[2];
18 | uint8_t v[4];
19 | struct
20 | {
21 | uint16_t LW;
22 | uint16_t HW;
23 | } word;
24 | struct
25 | {
26 | uint8_t LB;
27 | uint8_t HB;
28 | uint8_t UB;
29 | uint8_t MB;
30 | } byte;
31 | struct
32 | {
33 | uint16_t low;
34 | uint16_t high;
35 | }wordUnion;
36 | struct
37 | {
38 | uint8_t b0:1;
39 | uint8_t b1:1;
40 | uint8_t b2:1;
41 | uint8_t b3:1;
42 | uint8_t b4:1;
43 | uint8_t b5:1;
44 | uint8_t b6:1;
45 | uint8_t b7:1;
46 | uint8_t b8:1;
47 | uint8_t b9:1;
48 | uint8_t b10:1;
49 | uint8_t b11:1;
50 | uint8_t b12:1;
51 | uint8_t b13:1;
52 | uint8_t b14:1;
53 | uint8_t b15:1;
54 | uint8_t b16:1;
55 | uint8_t b17:1;
56 | uint8_t b18:1;
57 | uint8_t b19:1;
58 | uint8_t b20:1;
59 | uint8_t b21:1;
60 | uint8_t b22:1;
61 | uint8_t b23:1;
62 | uint8_t b24:1;
63 | uint8_t b25:1;
64 | uint8_t b26:1;
65 | uint8_t b27:1;
66 | uint8_t b28:1;
67 | uint8_t b29:1;
68 | uint8_t b30:1;
69 | uint8_t b31:1;
70 | } bits;
71 | } UINT32_VAL;
72 |
73 | typedef struct
74 | {
75 | UINT32_VAL bitmapValue;
76 | uint8_t *bits;
77 | }Bitmap_t;
78 |
79 |
80 | void vBitmapInit(Bitmap_t * bitmap);
81 | void vBitmapSet(Bitmap_t * bitmap, uint32_t pos);
82 | void vBitmapClear(Bitmap_t * bitmap, uint32_t pos);
83 | uint32_t uBitmapGetCount(void);
84 | uint32_t bBitmapGet(Bitmap_t * bitmap, uint32_t pos);
85 | uint32_t uBitmapGetFirstSet(Bitmap_t * bitmap);
86 |
87 |
88 | #endif /* _BIT_MAP_H */
89 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Event.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-25
5 | * @LastEditTime: 2021-08-03 22:17:03
6 | * @Description:
7 | */
8 |
9 | #ifndef _EVENT_H
10 | #define _EVENT_H
11 |
12 | #include "Tasks.h"
13 |
14 | /*---------------------------------------------------------------------------------------------------------------------
15 | * EVENTDEFINITIONS
16 | *--------------------------------------------------------------------------------------------------------------------*/
17 | typedef enum _eEventType
18 | {
19 | eEventTypeUnknown = (0 << 16), //未定义类型
20 | eEventTypeSem = (1 << 16), //信号量类型
21 | eEventTypeMbox = (2 << 16), //邮箱类型
22 | eEventTypeMemPool = (3 << 16), //存储块类型
23 | eEventTypeEventGroup = (4 << 16), //事件标志组
24 | eEventTypeMutex = (5 << 16), //互斥信号量类型
25 | }eEventType;
26 |
27 |
28 | typedef struct _tEvent
29 | {
30 | eEventType type;
31 |
32 | tList waitList;
33 |
34 | }tEvent;
35 |
36 |
37 | /*---------------------------------------------------------------------------------------------------------------------
38 | * EVENT API
39 | *--------------------------------------------------------------------------------------------------------------------*/
40 | /**
41 | * @Author: YangSL
42 | * @Description: 初始化事件控制块
43 | * @param {tEvent *} event 事件控制块
44 | * @param {eEventType} type 事件控制块的类型
45 | */
46 | void vEventInit(tEvent * event, eEventType type);
47 |
48 |
49 | /**
50 | * @Author: YangSL
51 | * @Description: 从事件控制块中唤醒首个等待的任务
52 | * @param {tEvent *} event 事件控制块
53 | * @param {tTask *} task 等待事件发生的任务
54 | * @param {void *} msg 事件消息存储的具体位置
55 | * @param {uint32_t} state 消息类型
56 | * @param {uint32_t} timeout 等待多长时间
57 | */
58 | void vEventWait(tEvent * event, tTask * task, void * msg, uint32_t state, uint32_t timeout);
59 |
60 |
61 | /**
62 | * @Author: YangSL
63 | * @Description: 从事件控制块中唤醒最先等待的任务
64 | * @param {tEvent *} event 事件控制块
65 | * @param {void *} msg 事件消息
66 | * @param {uint32_t} result 告知事件的等待结果
67 | * @return value 首个等待的任务,如果没有任务等待,则返回0
68 | */
69 | tTask * tEventWakeUp(tEvent * event, void * msg, uint32_t result);
70 |
71 |
72 | /**
73 | * @Author: YangSL
74 | * @Description: 从事件控制块中唤醒指定任务
75 | * @param {tEvent *} eventv 事件控制块
76 | * @param {tTask *} task 等待唤醒的任务
77 | * @param {void} *msg 事件消息
78 | * @param {uint32_t} result 告知事件的等待结果
79 | */
80 | void vEventWakeUpTask(tEvent * event, tTask * task, void *msg, uint32_t result);
81 |
82 |
83 | /**
84 | * @Author: YangSL
85 | * @Description: 将任务从其等待队列中强制移除
86 | * @param {tTask *} task 待移除的任务
87 | * @param {void *} msg 事件消息
88 | * @param {uint32_t} result 告知事件的等待结果
89 | */
90 | void vEventRemoveTask(tTask * task, void * msg, uint32_t result);
91 |
92 |
93 | /**
94 | * @Author: YangSL
95 | * @Description: 清除所有等待中的任务,将事件发送给所有任务
96 | * @param {tEvent *} event 事件控制块
97 | * @param {void *} msg 事件消息
98 | * @param {uint32_t} result 告知事件的等待结果
99 | * @return value 唤醒的任务数量
100 | */
101 | uint32_t uEventRemoveAll(tEvent * event, void * msg, uint32_t result);
102 |
103 | /**
104 | * @Author: YangSL
105 | * @Description: 事件控制块中等待的任务数量
106 | * @param {tEvent *} event
107 | */
108 | uint32_t uEventGetWaitCount(tEvent * event);
109 |
110 | #endif /* _EVENT_H */
111 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/EventGroup.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-01 21:40:39
5 | * @LastEditTime: 2021-08-02 21:39:31
6 | * @Description:
7 | */
8 |
9 | #ifndef _EVENT_GROUP_H
10 | #define _EVENT_GROUP_H
11 |
12 | #include "Event.h"
13 |
14 | /*---------------------------------------------------------------------------------------------------------------------
15 | * FLAGGROUP DEFINITIONS
16 | *--------------------------------------------------------------------------------------------------------------------*/
17 |
18 | typedef struct _tEventGroup
19 | {
20 | /* 事件控制块 */
21 | tEvent event;
22 |
23 | /* 事件标志 */
24 | uint32_t flags;
25 |
26 | }tEventGroup;
27 |
28 | #define EVENTGROUP_CLEAR (0X0 << 0)
29 | #define EVENTGROUP_SET (0X1 << 0)
30 | #define EVENTGROUP_ANY (0X0 << 1)
31 | #define EVENTGROUP_ALL (0X1 << 1)
32 |
33 | #define EVENTGROUP_SET_ALL (EVENTGROUP_SET | EVENTGROUP_ALL)
34 | #define EVENTGROUP_SET_ANY (EVENTGROUP_SET | EVENTGROUP_ANY)
35 | #define EVENTGROUP_CLEAR_ALL (EVENTGROUP_CLEAR | EVENTGROUP_ALL)
36 | #define EVENTGROUP_CLEAR_ANY (EVENTGROUP_CLEAR | EVENTGROUP_ANY)
37 |
38 | #define EVENTGROUP_CONSUME (0X1 << 7)
39 | /*---------------------------------------------------------------------------------------------------------------------
40 | * FLAGGROUP API
41 | *--------------------------------------------------------------------------------------------------------------------*/
42 | /**
43 | * @Author: YangSL
44 | * @Description: 初始化事件标志组
45 | */
46 | void vEventGroupInit(tEventGroup * eventGroup, uint32_t flags);
47 |
48 |
49 | /**
50 | * @Author: YangSL
51 | * @Description: 等待事件标志组中特定的标志
52 | * @param {tEventGroup *} eventGroup 等待的事件标志组
53 | * @param {uint32_t} waitType 等待的事件类型
54 | * @param {uint32_t} requestFlag 请求的事件标志
55 | * @param {uint32_t} *resultFlag 等待标志结果
56 | * @param {uint32_t} waitTicks 当等待的标志没有满足条件时,等待的ticks数,为0时表示永远等待
57 | * @return : eErrorResourceUnavaliable.eErrorNoError,eErrorTimeout
58 | */
59 | uint32_t uEventGroupWaitBits(tEventGroup * eventGroup, uint32_t waitType, uint32_t requestFlag, uint32_t *resultFlag, uint32_t waitTicks);
60 |
61 |
62 | /**
63 | * @Author: YangSL
64 | * @Description: 无等待的获取事件标志
65 | * @param {tEventGroup *} eventGroup
66 | * @param {uint32_t} waitType
67 | * @param {uint32_t} requestFlag
68 | * @param {uint32_t *} resultFlag
69 | * @return : eErrorResourceUnavaliable.eErrorNoError
70 | */
71 | uint32_t uEventGroupNoWaitBits(tEventGroup * eventGroup, uint32_t waitType, uint32_t requestFlag, uint32_t * resultFlag);
72 |
73 |
74 | /**
75 | * @Author: YangSL
76 | * @Description:
77 | * @param {tEventGroup *} eventGroup
78 | * @param {uint8_t} isSet
79 | * @param {uint32_t} flags
80 | */
81 | void vEventGroupNotify(tEventGroup * eventGroup, uint8_t isSet, uint32_t flags);
82 |
83 |
84 | /**
85 | * @Author: YangSL
86 | * @Description: 设置清零的位
87 | * @param {tEventGroup *} eventGroup
88 | * @param {uint32_t} clearBits
89 | */
90 | void vEventGroupClearBits(tEventGroup * eventGroup, uint32_t clearBits);
91 |
92 |
93 | /**
94 | * @Author: YangSL
95 | * @Description: 设置要置一的位
96 | * @param {tEventGroup} *eventGroup
97 | * @param {uint32_t} setBits
98 | */
99 | void vEventGroupSetBits(tEventGroup * eventGroup, uint32_t setBits);
100 |
101 | #endif /* _FLAG_GROUP_H */
102 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/LinOS.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-06
5 | * @LastEditTime: 2021-08-10 11:31:42
6 | * @Description:
7 | */
8 |
9 | #ifndef LINOS_H
10 | #define LINOS_H
11 |
12 |
13 | // 标准头文件,里面包含了常用的类型定义,如uint32_t
14 | #include
15 | #include
16 | #include "LinOSConfig.h"
17 |
18 | #include "Lists.h"
19 | #include "Tasks.h"
20 | #include "Sem.h"
21 | #include "Mailbox.h"
22 | #include "Mempool.h"
23 | #include "EventGroup.h"
24 | #include "Mutex.h"
25 | #include "Timer.h"
26 |
27 | #include "port.h"
28 |
29 | /* LinOS错误码 */
30 | typedef enum _eError
31 | {
32 | eErrorNoError = 0, // 没有错误
33 | eErrorTimeout, // 超时
34 | eErrorResourceUnavaliable, // 资源不可用
35 | eErrorDelete, // 资源被删除
36 | eErrorResourceFull, // 邮箱满了
37 | eErrorOwner, // 任务不匹配
38 | }eError;
39 |
40 |
41 |
42 |
43 | #endif /* LINOS_H */
44 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/LinOSConfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-09 21:46:45
5 | * @LastEditTime: 2021-08-09 23:01:47
6 | * @Description:
7 | */
8 |
9 | #ifndef _LINOS_CONFIG_H
10 | #define _LINOS_CONFIG_H
11 |
12 | /* LinOS优先级数 */
13 | #define LinOS_PRI_COUNT 32
14 |
15 | /* 每个任务最大运行的时间片计数 */
16 | #define LinOS_SLICE_MAX 10
17 |
18 | /* 堆桟大小 */
19 | #define LinOS_STACK_SIZE 1024
20 | #define LinOS_IDLE_STACK_SIZE 1024
21 |
22 |
23 | /* 时钟节拍的周期,以ms为单位 */
24 | #define LinOS_SYSTICK_MS 1
25 |
26 | #define LinOS_TIMER_PRIO 1
27 |
28 | /* 是否使用定时器 */
29 | #define LinOS_TIMER_SWITCH 0
30 |
31 | /* 是否进行CPU使用率检测 */
32 | #define LinOS_ENABLE_CPU_CHECK 1
33 |
34 | #endif /* _LINOS_CONFIG_H */
35 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Lists.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-22
5 | * @LastEditTime: 2021-07-22 22:53:20
6 | * @Description:
7 | */
8 |
9 | #ifndef _LINOS_LISTS_H
10 | #define _LINOS_LISTS_H
11 | #include
12 |
13 | typedef struct _tNode
14 | {
15 | struct _tNode * preNode;
16 | struct _tNode * nextNode;
17 | }tNode;
18 |
19 | typedef struct _tList
20 | {
21 | tNode headNode;
22 | uint32_t nodeCount;
23 |
24 | }tList;
25 |
26 | typedef enum
27 | {
28 | eListStatusOK = 0,
29 | eListStatusErr,
30 | eListStatusEmpty
31 | }eListStatus;
32 |
33 |
34 | /**
35 | * @Author: YangSL
36 | * @Description: 初始化节点
37 | * @param {tNode} *node
38 | */
39 | void vNodeInit(tNode *node);
40 |
41 |
42 | /**
43 | * @Author: YangSL
44 | * @Description: 初始化链表
45 | * @param {tList *} list
46 | */
47 | void vListInit(tList * list);
48 |
49 |
50 | /**
51 | * @Author: YangSL
52 | * @Description:
53 | * @param {tList} list
54 | */
55 | uint32_t uGetListNodeCount(tList *list);
56 |
57 |
58 | /**
59 | * @Author: YangSL
60 | * @Description: 返回链表的第一个节点
61 | * @param {tList *} list
62 | */
63 | tNode * tGetFirstNode(tList * list);
64 |
65 |
66 | /**
67 | * @Author: YangSL
68 | * @Description: 返回链表的最后一个节点
69 | * @param {tList *} list
70 | */
71 | tNode * tGetLastNode(tList * list);
72 |
73 |
74 | /**
75 | * @Author: YangSL
76 | * @Description: 返回指定链表的前一个节点
77 | * @param {tList *} list
78 | * @param {tNode *} node
79 | */
80 | tNode * tGetListPre(tList * list, tNode * node);
81 |
82 |
83 | /**
84 | * @Author: YangSL
85 | * @Description: 返回指定链表的后一个节点
86 | * @param {tList *} list
87 | * @param {tNode *} node
88 | */
89 | tNode * tGetListNext(tList * list, tNode * node);
90 |
91 |
92 | /**
93 | * @Author: YangSL
94 | * @Description: 将新节点插入到链表开头
95 | * @param {tList *} list
96 | * @param {tNode *} node
97 | */
98 | void vListInsertHead(tList * list, tNode * node);
99 |
100 |
101 | /**
102 | * @Author: YangSL
103 | * @Description: 将新节点插入到链表结尾
104 | * @param {tList *} list
105 | * @param {tNode *} node
106 | */
107 | void vListInsertLast(tList * list, tNode * node);
108 |
109 |
110 | /**
111 | * @Author: YangSL
112 | * @Description: 将新的节点插入到指定节点后面
113 | * @param {tList *} list
114 | * @param {tNode *} node
115 | */
116 | void vListInsertNodeAfter(tList * list, tNode * newNode, tNode * toNode);
117 |
118 |
119 | /**
120 | * @Author: YangSL
121 | * @Description: 移除链表的第一个节点
122 | * @param {tList *} list :
123 | * @Return : 如果链表为空,返回0,否则的话,返回第1个结点
124 | */
125 | tNode *tListRemoveFirst(tList * list);
126 |
127 |
128 | /**
129 | * @Author: YangSL
130 | * @Description: 移除链表最后一个节点
131 | * @param {tList *} list
132 | * @Return : 如果链表为空,返回0,否则的话,返回第1个结点
133 | */
134 | tNode *tListRemoveLast(tList * list);
135 |
136 |
137 | /**
138 | * @Author: YangSL
139 | * @Description: 移除链表中的指定节点
140 | * @param {tList *} list
141 | * @param {tNode *} node
142 | */
143 | void vListRemoveNode(tList * list, tNode * node);
144 |
145 |
146 | /**
147 | * @Author: YangSL
148 | * @Description: 移除链表中所有节点
149 | * @param {tList *} list
150 | */
151 | void vListRemoveAll(tList * list);
152 |
153 | #endif /* _LINOS_LISTS_H */
154 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Mailbox.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-28
5 | * @LastEditTime: 2021-07-28 22:25:12
6 | * @Description:
7 | */
8 |
9 |
10 | #ifndef _MAILBIAX_H
11 | #define _MAILBIAX_H
12 |
13 | #include "Event.h"
14 |
15 | #define defineMboxSendNormal 0x00
16 | #define defineMboxSendFront 0x01
17 |
18 | /*---------------------------------------------------------------------------------------------------------------------
19 | * MAINBOX DEFINITIONS
20 | *--------------------------------------------------------------------------------------------------------------------*/
21 | typedef struct _tMailbox
22 | {
23 | /* 事件控制块,包括:事件的列表和事件类型 */
24 | tEvent event;
25 |
26 | /* 当邮件的数量 */
27 | uint32_t count;
28 |
29 | /* 读取邮件的索引 */
30 | uint32_t read;
31 |
32 | /* 写邮件的索引 */
33 | uint32_t write;
34 |
35 | /* 最大允许的邮件数量 */
36 | uint32_t maxCount;
37 |
38 | /* 消息缓存区的 */
39 | void ** msgBuffer;
40 |
41 | }tMbox;
42 |
43 |
44 | typedef struct _tMboxInfo
45 | {
46 | /* 当前的消息数量 */
47 | uint32_t count;
48 |
49 | /* 最大允许容纳的消息数量 */
50 | uint32_t maxCount;
51 |
52 | /* 当前等待的任务计数 */
53 | uint32_t taskCount;
54 | }tMboxInfo;
55 |
56 | /*---------------------------------------------------------------------------------------------------------------------
57 | * MAINBOX API
58 | *--------------------------------------------------------------------------------------------------------------------*/
59 |
60 | /**
61 | * @Author: YangSL
62 | * @Description: 初始化邮箱
63 | * @param {tMbox} *mbox
64 | * @param {void **} msgBuffer
65 | * @param {uint32_t} maxCount
66 | */
67 | void vMboxInit(tMbox *mbox, void ** msgBuffer, uint32_t maxCount);
68 |
69 |
70 | /**
71 | * @Author: YangSL
72 | * @Description: 向邮箱中发送邮件
73 | * @param {tMbox *} mbox 获取消息的邮箱
74 | * @param {void **} msg 消息存储缓存区
75 | * @param {uint32_t} timeout 发送的选项
76 | */
77 | uint32_t uMboxSend(tMbox * mbox, void * msg, uint32_t option);
78 |
79 |
80 | /**
81 | * @Author: YangSL
82 | * @Description: 等待邮箱, 获取一则消息
83 | * @param {tMbox *} mbox 等待的邮箱
84 | * @param {void **} msg 消息存储缓存区
85 | * @param {uint32_t} timeout 超时时间
86 | */
87 | uint32_t uMboxWait(tMbox * mbox, void ** msg, uint32_t timeout);
88 |
89 |
90 | /**
91 | * @Author: YangSL
92 | * @Description: 清空邮箱中所有消息
93 | * @param {tMbox *} mbox
94 | */
95 | void uMboxFlush(tMbox * mbox);
96 |
97 |
98 | /**
99 | * @Author: YangSL
100 | * @Description: 删除邮箱
101 | * @param {tMbox} *mbox
102 | */
103 | uint32_t uMboxDelete(tMbox *mbox);
104 |
105 |
106 | /**
107 | * @Author: YangSL
108 | * @Description: 查询邮箱状态信息
109 | * @param {tMbox *} mbox
110 | * @param {tMboxInfo *} info
111 | */
112 | void vMboxGetInfo (tMbox * mbox, tMboxInfo * info);
113 | #endif /* _MAILBIAX_H */
114 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Mempool.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-31 10:37:03
5 | * @LastEditTime: 2021-07-31 14:06:17
6 | * @Description:
7 | */
8 |
9 | #ifndef _MEMPOOL_H
10 | #define _MEMPOOL_H
11 | #include "Event.h"
12 |
13 |
14 | /*---------------------------------------------------------------------------------------------------------------------
15 | * MEMPOOL DEFINITIONS
16 | *--------------------------------------------------------------------------------------------------------------------*/
17 | typedef struct _tMemPool
18 | {
19 | /* 事件控制块 */
20 | tEvent event;
21 |
22 | /* 存储块的起始地址 */
23 | void * memStartAddress;
24 |
25 | /* 每个存储块的大小 */
26 | uint32_t blockSize;
27 |
28 | /* 存储块的总数 */
29 | uint32_t blockTotalCount;
30 |
31 | /* 未使用的存数块数量 */
32 | uint32_t blockFreeCount;
33 |
34 | /* 存储块的列表 */
35 | tList blockList;
36 |
37 | /* 挂起的列表 */
38 | tList suspendList;
39 |
40 | }tMemPool;
41 |
42 | typedef struct _MemPoolInfo
43 | {
44 | /* 当前储存块计数 */
45 | uint32_t blockCount;
46 |
47 | /* 存储块总数 */
48 | uint32_t TalolCount;
49 |
50 | /* 未使用的存储块数量 */
51 | uint32_t freeCount;
52 |
53 | /* 每个存储块的大小 */
54 | uint32_t blockSize;
55 |
56 | /* 挂起的任务 */
57 | uint32_t suspendCount;
58 | }tMemPoolInfo;
59 |
60 | /*---------------------------------------------------------------------------------------------------------------------
61 | * MEMPOOL API
62 | *--------------------------------------------------------------------------------------------------------------------*/
63 | /**
64 | * @Author: YangSL
65 | * @Description: 初始化存储控制块
66 | * @param {tMemPool *} memPool 等待初始化的存储控制块
67 | * @param {void*} startAddress 存储区的起始地址
68 | * @param {uint32_t} blockSize 每个块的大小
69 | * @param {uint32_t} blockTotalCount 总的块数量
70 | */
71 | void vMemPoolInit(tMemPool * memPool, void* startAddress, uint32_t blockSize, uint32_t blockTotalCount);
72 |
73 |
74 | /**
75 | * @Author: YangSL
76 | * @Description: 查询存储控制块的状态信息
77 | * @param {tMemPool *} memPool
78 | * @param {tMemPoolInfo *} info
79 | */
80 | void vMemPoolGetInfo(tMemPool * memPool, tMemPoolInfo * info);
81 |
82 |
83 | /**
84 | * @Author: YangSL
85 | * @Description: 有等待从内存池中分配存储块
86 | * @param {tMemPool *} memPool 内存池
87 | * @param {uint8_t **} memBlock 分配的内存块d地址
88 | * @param {uint32_t} timeout 超时时间
89 | */
90 | uint32_t uMemPoolWaitAlloc(tMemPool * memPool, uint8_t ** memBlock,uint32_t timeout);
91 |
92 | /**
93 | * @Author: YangSL
94 | * @Description: 无等待从内存池中分配存储块
95 | * @param {tMemPool *} memPool
96 | * @param {uint8_t **} memBlock
97 | */
98 | uint32_t uMemPoolNoWaitAlloc(tMemPool * memPool, uint8_t ** memBlock);
99 |
100 | /**
101 | * @Author: YangSL
102 | * @Description: 释放内存块
103 | * @param {tMemPool} *memPool 要操作的内存池
104 | * @param {void *} memBlock 释放内存块的地址
105 | */
106 | void vMemPoolFree(tMemPool *memPool, void * memBlock);
107 |
108 |
109 | /**
110 | * @Author: YangSL
111 | * @Description: 删除内存池
112 | * @param {tMemPool *} memPool
113 | */
114 | uint32_t uMemPoolDelete(tMemPool * memPool);
115 |
116 | #endif /* _MEMPOOL_H */
117 |
118 |
119 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Mutex.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-03 21:27:21
5 | * @LastEditTime: 2021-08-05 22:51:31
6 | * @Description:
7 | */
8 | #ifndef _MUTEX_H
9 | #define _MUTEX_H
10 |
11 | #include "Event.h"
12 |
13 | /*---------------------------------------------------------------------------------------------------------------------
14 | * MUTEX DEFINITIONS
15 | *--------------------------------------------------------------------------------------------------------------------*/
16 | typedef struct _tMutex
17 | {
18 | /* 事件控制块 */
19 | tEvent event;
20 |
21 | /* 已被锁定的次数 */
22 | uint32_t lockCount;
23 |
24 | /* 拥有者 */
25 | tTask * owner;
26 |
27 | /* 拥有者原始的优先级 */
28 | uint32_t ownerOriginalPrio;
29 |
30 | }tMutex;
31 |
32 |
33 |
34 | typedef struct _tMutexInfo
35 | {
36 | /* 等待该互斥量的任务数 */
37 | uint32_t waitTaskCount;
38 | /* 拥有该互斥量任务的优先级 */
39 | uint32_t ownerPrio;
40 | /* 拥有该互斥量任务继承的优先级 */
41 | uint32_t inheritedPrio;
42 | /* 互斥量锁定的次数 */
43 | uint32_t lockCount;
44 | /* 当前信号的拥有者 */
45 | tTask * owner;
46 | }tMutexInfo;
47 |
48 | /*---------------------------------------------------------------------------------------------------------------------
49 | * MUTEX API
50 | *--------------------------------------------------------------------------------------------------------------------*/
51 | /**
52 | * @Author: YangSL
53 | * @Description: 初始化互斥信号量
54 | * @param {tMutex *} mutex
55 | */
56 | void vMutexInit(tMutex * mutex);
57 |
58 |
59 | /**
60 | * @Author: YangSL
61 | * @Description: 获取互斥量
62 | * @param {tMutex *} mutex
63 | * @param {uint32_t} timeout
64 | */
65 | uint32_t uMutexTake(tMutex * mutex, uint32_t timeout);
66 |
67 |
68 | /**
69 | * @Author: YangSL
70 | * @Description: 无等待获取互斥量,如果没有可用信号量,就立马返回
71 | * @param {tMutex *} mutex
72 | */
73 | uint32_t uMutexTryTake(tMutex * mutex);
74 |
75 |
76 | /**
77 | * @Author: YangSL
78 | * @Description: 释放互斥量
79 | * @param {tMutex *} mutex
80 | */
81 | uint32_t uMutexRelease(tMutex * mutex);
82 |
83 |
84 | /**
85 | * @Author: YangSL
86 | * @Description: 删除该互斥量
87 | * @param {tMutex *} mutex
88 | */
89 | uint32_t uMutexDelete(tMutex * mutex);
90 |
91 |
92 | /**
93 | * @Author: YangSL
94 | * @Description: 获取互斥量的相关信息
95 | * @param {tMutex *} mutex
96 | * @param {tMutexInfo *} info
97 | */
98 | void vMutexGetInfo(tMutex * mutex,tMutexInfo * info );
99 |
100 |
101 | #endif /* _MUTEX_H */
102 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Sem.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-27
5 | * @LastEditTime: 2021-07-27 21:51:29
6 | * @Description:
7 | */
8 |
9 | #ifndef _SEM_H
10 | #define _SEM_H
11 |
12 | #include "Event.h"
13 |
14 | /*---------------------------------------------------------------------------------------------------------------------
15 | * SEM DEFINITIONS
16 | *--------------------------------------------------------------------------------------------------------------------*/
17 |
18 | typedef struct _tSem
19 | {
20 | /* 事件控制块 */
21 | tEvent event;
22 |
23 | /* 当前的计数 */
24 | uint32_t count;
25 |
26 | /* 最大计数 */
27 | uint32_t maxCount;
28 |
29 | }tSem;
30 |
31 | typedef struct _eSemInfo
32 | {
33 | /* 当前信号量计数 */
34 | uint32_t count;
35 | /* 信号量允许的最大计数 */
36 | uint32_t maxCount;
37 | /* 当前等待任务的计数 */
38 | uint32_t taskCount;
39 | }tSemInfo;
40 |
41 |
42 |
43 | /*---------------------------------------------------------------------------------------------------------------------
44 | * SEM API
45 | *--------------------------------------------------------------------------------------------------------------------*/
46 |
47 | /**
48 | * @Author: YangSL
49 | * @Description: 初始化信号量
50 | * @param {tSem} *sem
51 | * @param {uint32_t} startCount 初始的计数
52 | * @param {uint32_t} maxCount 最大计数,如果为0,则不限数量
53 | */
54 | void vSemInit(tSem *sem, uint32_t startCount, uint32_t maxCount);
55 |
56 |
57 | /**
58 | * @Author: YangSL
59 | * @Description: 获取信号量
60 | * @param {tSem *} sem 等待的信号量
61 | * @param {uint32_t} time 等待的时间,为零表示永远等待
62 | */
63 | uint32_t uSemTake(tSem * sem, uint32_t time);
64 |
65 |
66 | /**
67 | * @Author: YangSL
68 | * @Description: 无等待获取信号量
69 | * @param {tSem *} sem 等待的信号量
70 | */
71 | uint32_t uSemTryTake(tSem * sem);
72 |
73 |
74 | /**
75 | * @Author: YangSL
76 | * @Description: 释放信号量
77 | * @param {tSem *} sem 操作的信号量
78 | */
79 | void vSemRelease(tSem * sem);
80 |
81 |
82 | /**
83 | * @Author: YangSL
84 | * @Description: 删除信号量
85 | * @param {tSem *} sem
86 | */
87 | uint32_t uSemDelete(tSem * sem);
88 |
89 |
90 | /**
91 | * @Author: YangSL
92 | * @Description: 查询信号量的状态信息
93 | * @param {tSem *} sem
94 | * @param {tSemInfo *} info
95 | */
96 | void vSemGetInfo(tSem * sem, tSemInfo * info);
97 |
98 | #endif /* _SEM_H */
99 |
100 |
101 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Tasks.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-06
5 | * @LastEditTime: 2022-01-29 15:53:57
6 | * @Description:
7 | */
8 | #ifndef INC_TASK_H
9 | #define INC_TASK_H
10 |
11 | #include
12 | #include "Bitmap.h"
13 | #include "Lists.h"
14 | #include "LinOSConfig.h"
15 | /*---------------------------------------------------------------------------------------------------------------------
16 | * TASK MACROS
17 | *--------------------------------------------------------------------------------------------------------------------*/
18 |
19 |
20 | /*----------------------------------------------------------------------------------*/
21 |
22 |
23 |
24 | /* 获取结点所在的父struct结构首地址 */
25 | // #define nodeParent(node, parent, name) (parent *)((uint32_t)node - (uint32_t)&((parent *)0)->name)
26 | #define nodeParent(node, parent, name) (parent *)((uint32_t)node - (uint32_t)&((parent *)0)->name)
27 | /*---------------------------------------------------------------------------------------------------------------------
28 | * TASK DEFINITIONS
29 | *--------------------------------------------------------------------------------------------------------------------*/
30 |
31 |
32 |
33 | /* 任务的状态定义 */
34 | typedef enum
35 | {
36 | eRunning = 0, /* 运行状态. */
37 | eReady, /* 就绪状态. */
38 | eBlocked, /* 阻塞状态. */
39 | eSuspended, /* 挂起状态. */
40 | eDeleted, /* 删除状态 */
41 | }eTaskState;
42 |
43 |
44 | /* Cortex-M的堆栈单元类型:堆栈单元的大小为32位,所以使用uint32_t */
45 | typedef uint32_t tTaskStack;
46 |
47 | // 前置声明
48 | struct _tEvent;
49 |
50 | /* 任务结构:包含了一个任务的所有信息 */
51 | typedef struct _tTask {
52 |
53 | /* stack保存了最后保存环境参数的地址位置,用于后续恢复 */
54 | tTaskStack * stack;
55 |
56 | /* 堆桟的起始地址 */
57 | uint32_t *stackBase;
58 | /* 堆桟大小 */
59 | uint32_t stackSize;
60 |
61 | /* 连接节点 */
62 | tNode linkNode;
63 |
64 | /* 任务延时计数器 */
65 | uint32_t delayTicks;
66 |
67 | /* 任务优先级 */
68 | uint32_t prio;
69 |
70 | /* 延时节点 */
71 | tNode delayNode;
72 |
73 | /* 当前任务状态 */
74 | uint32_t state;
75 |
76 | /* 当前剩余的时间片 */
77 | uint32_t slice;
78 |
79 | /* 挂起次数 */
80 | uint32_t supendCount;
81 |
82 |
83 | /* 任务删除时的清理函数 */
84 | void (*clean) (void * param);
85 | /* 传递给清理函数的参数 */
86 | void * cleanParam;
87 | /* 请求删除得标志 */
88 | uint8_t requestsDeleteFlag;
89 |
90 |
91 | /* 任务正在等待的事件类型 */
92 | struct _tEvent * waitEvent;
93 | /* 等待事件的消息存储位置 */
94 | void * waitEventMsg;
95 | /* 等待事件的结果 */
96 | uint32_t waitEventResult;
97 |
98 |
99 | /* 等待是件结果 */
100 | uint32_t waitEventGroupType;
101 | /* 等待事件标志 */
102 | uint32_t waitEventGroupFlag;
103 | }tTask;
104 |
105 |
106 |
107 | typedef struct _tTaskInfo
108 | {
109 | /* 任务延时计时器 */
110 | uint32_t delayTicks;
111 | /* 任务优先级 */
112 | uint32_t prio;
113 | /* 任务当前状态 */
114 | uint32_t state;
115 | /* 任务剩余时间片 */
116 | uint32_t slice;
117 | /* 任务挂起次数 */
118 | uint32_t supendCount;
119 |
120 | /* 堆桟总容量 */
121 | uint32_t stackSize;
122 | /* 堆桟剩余量 */
123 | uint32_t stackFree;
124 | }tTaskInfo;
125 |
126 | /*---------------------------------------------------------------------------------------------------------------------
127 | * TASK EXTERN
128 | *--------------------------------------------------------------------------------------------------------------------*/
129 |
130 | /* 当前任务:记录当前是哪个任务正在运行 */
131 | extern tTask * currentTask;
132 |
133 | /* 下一个将即运行的任务 */
134 | extern tTask * nextTask;
135 |
136 | extern tTask * idleTask;
137 |
138 | /* 所有任务的指针数组 */
139 | extern tList taskPrioTable[LinOS_PRI_COUNT];
140 |
141 | /* 调度锁计数器 */
142 | extern uint8_t schedLockCount;
143 |
144 | /* 延时队列 */
145 | extern tList taskDelayList;
146 |
147 | /* 任务优先级的标记位置结构 */
148 | extern Bitmap_t LinOSBitmap;
149 | /*---------------------------------------------------------------------------------------------------------------------
150 | * TASK CREATION API
151 | *--------------------------------------------------------------------------------------------------------------------*/
152 |
153 | void vTaskInit (tTask * task, void (*entry)(void *), void *param, uint32_t prio, uint32_t * stack, uint32_t stackSize);
154 |
155 | /* 任务调度相关函数 */
156 | void vTaskSched(void);
157 | void vTaskSystemTickHandler (void);
158 |
159 |
160 |
161 | /* 调度器相关函数 */
162 | void vTaskSchedDisable(void);
163 | void vTaskSchedEnable(void);
164 | void vTaskSchedInit(void);
165 |
166 | /*----------------------------------------------------------
167 | * 任务队列相关 (就绪)
168 | *----------------------------------------------------------*/
169 | /* 获取最高优先级任务 */
170 | tTask *tTaskHighestReady(void);
171 | /* 将任务加入就绪列表 */
172 | void vTaskSchedRdy(tTask * task);
173 | /* 将任务从就绪列表中移除 */
174 | void vTaskSchedUnRdy(tTask * task);
175 | /* 将任务从就绪列表中移除 */
176 | void vTaskRdyListRemove(tTask * task);
177 | /*----------------------------------------------------------
178 | * 任务队列相关 (阻塞)
179 | *----------------------------------------------------------*/
180 | void vTaskDelayInit(void);
181 | /* 将任务加入延时队列 */
182 | void tTaskDelayWait(tTask * task, uint32_t ticks);
183 | /* 将延时的任务从延时队列中唤醒 */
184 | void vTaskDelayWakeUp(tTask * task);
185 |
186 | /*----------------------------------------------------------
187 | * 任务队列相关 (挂起)
188 | *----------------------------------------------------------*/
189 | /* 挂起任务 */
190 | void vTaskSupend(tTask * task);
191 | /* 将任务从挂起态唤醒 */
192 | void vTaskResume(tTask * task);
193 |
194 |
195 | /*----------------------------------------------------------
196 | * 任务队列相关 (删除)
197 | *----------------------------------------------------------*/
198 | /**
199 | * @Author: YangSL
200 | * @Description: 设置任务被删除时调用的清理函数
201 | * @param {tTask *} task :待设置的任务
202 | * @param {void} *param :清理函数入口地址
203 | * @param {void *} param :传递给清理函数的参数
204 | */
205 | void vTaskSetCleanCallback(tTask * task, void (*clean )(void *param), void * param);
206 |
207 | /**
208 | * @Author: YangSL
209 | * @Description: 强制删除任务
210 | * @param {tTask *} task
211 | */
212 | void vTaskForceDelete(tTask * task);
213 |
214 | /**
215 | * @Author: YangSL
216 | * @Description: 请求删除某个任务,最后由任务自己决定是否删除自己
217 | * @param {tTask *} task
218 | */
219 | void vTaskRequestsDelete(tTask * task);
220 |
221 | /**
222 | * @Author: YangSL
223 | * @Description: 检查是否已经被请求删除自己
224 | * @param {tTask *} task
225 | */
226 | uint8_t uTaskCheckDelete(void);
227 |
228 | /**
229 | * @Author: YangSL
230 | * @Description: 删除自己
231 | */
232 | void vTaskDeleteSelf(void);
233 |
234 |
235 | /*----------------------------------------------------------
236 | * Others
237 | *----------------------------------------------------------*/
238 | /* 任务级延时函数 */
239 | void vTaskDelay(uint32_t delay);
240 |
241 |
242 | /**
243 | * @Author: YangSL
244 | * @Description: 获取任务相关信息
245 | * @param {tTask *} task :需要查询的任务
246 | * @param {tTaskInfo} info :任务信息存储结构
247 | */
248 | void vTaskGetInfo(tTask * task, tTaskInfo * info);
249 |
250 | /**
251 | * @Author: YangSL
252 | * @Description: 获取CPU使用率
253 | */
254 | float fTaskGetCpuUsage(void);
255 | #endif
256 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/inc/Timer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-07 11:32:44
5 | * @LastEditTime: 2021-08-08 17:08:38
6 | * @Description:
7 | */
8 |
9 | #ifndef _TIMER_H
10 | #define _TIMER_H
11 |
12 | #include "Event.h"
13 |
14 | extern long long timerGlobalTick;
15 |
16 | #define LinOS_TIMERTASK_STACK_SIZE 512
17 | #define LinOS_TIMERTASK_PRIO 1
18 | /*---------------------------------------------------------------------------------------------------------------------
19 | * TIMER DEFINITIONS
20 | *--------------------------------------------------------------------------------------------------------------------*/
21 | typedef enum _eTimerState
22 | {
23 | eTimerCreated, // 定时器已经创建
24 | eTimerStarted, // 定时器已经启动
25 | eTimerRunning, // 定时器正在运行
26 | eTimerStopped, // 定时器已经停止
27 | eTimerDeleted // 定时器已经销毁
28 | }eTimerState;
29 |
30 | typedef struct _tTimer
31 | {
32 | /* 链表节点 */
33 | tNode linkNode;
34 |
35 | /* 定时时间 */
36 | uint32_t timerTicks;
37 | /* 该定时器任务当前时间 */
38 | uint32_t delayTicks;
39 | /* 定时器类型 */
40 | uint32_t flag;
41 |
42 | /* 定时回调函数 */
43 | void (*timerFunc) (void * arg);
44 | /* 传递给回调函数的参数 */
45 | void *arg;
46 |
47 | /* 定时器配置参数 */
48 | uint32_t config;
49 | /* 定时器状态 */
50 | eTimerState state;
51 | }tTimer;
52 |
53 |
54 | #define TIMER_MODE_MASK 0x1
55 | #define TIMER_HARD_MODE (1 << 0) /* 硬件定时器 */
56 | #define TIMER_SOFT_MODE (0 << 0) /* 软件定时器 */
57 |
58 | #define TIMER_FLAG_MASK 0x2
59 | #define TIEMR_FLAG_ONE_SHOT (0 << 1) /* 一次性定时器 */
60 | #define TIEMR_FLAG_PERIODIC (1 << 1) /* 周期性定时器 */
61 |
62 |
63 | /*---------------------------------------------------------------------------------------------------------------------
64 | * TIMER API
65 | *--------------------------------------------------------------------------------------------------------------------*/
66 |
67 | /**
68 | * @Author: YangSL
69 | * @Description: 初始化定时器
70 | * @param {tTimer *} timer 等待初始化的定时器
71 | * @param {uint32_t} timerTicks 定时器超时Ticks
72 | * @param {uint32_t} flag 设置定时器是一次性还是周期定时器
73 | * @param {void *} timerFunc 定时器回调函数
74 | * @param {void *} arg 传递给定时器回调函数的参数
75 | * @param {uint32_t} config 定时器的初始配置
76 | */
77 | void vTimerInit(tTimer * timer, uint32_t timerTicks, uint32_t flag, void (*timerFunc)(void * arg), void * arg, uint32_t config);
78 |
79 |
80 | /**
81 | * @Author: YangSL
82 | * @Description: 检查定时器模块的时间计数
83 | */
84 | void vTimerModulCheckTick(void);
85 |
86 | /**
87 | * @Author: YangSL
88 | * @Description: 启动定时器任务
89 | * @param {tTimer} *timer
90 | */
91 | void vTimerStart(tTimer *timer);
92 |
93 | /**
94 | * @Author: YangSL
95 | * @Description: 停止定时器任务
96 | * @param {tTimer *} timer
97 | */
98 | void vTimerStop(tTimer * timer);
99 |
100 | /**
101 | * @Author: YangSL
102 | * @Description: 创建定时器模块
103 | */
104 | void vTimerModulInit(void);
105 | /**
106 | * @Author: YangSL
107 | * @Description: 创建定时器任务
108 | */
109 | void vTimerTickInit(void);
110 |
111 | #endif /* _TIMER_H */
112 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/portable/RVDS/port.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-23
5 | * @LastEditTime: 2021-08-10 16:15:55
6 | * @Description:
7 | */
8 | #include "port.h"
9 |
10 |
11 | /*---------------------------------------------------------------------------------------------------------------------
12 | * 硬件调度相关操作
13 | *--------------------------------------------------------------------------------------------------------------------*/
14 | /**
15 | * @Author: YangSL
16 | * @Description: 调用PendSV异常发起任务切换请求
17 | */
18 | void taskScheduler(void)
19 | {
20 | MEM32(NVIC_INT_CTRL) = NVIC_PENDSVSET; // 向NVIC_INT_CTRL写NVIC_PENDSVSET,用于PendSV
21 | }
22 |
23 | /**
24 | * @Author: YangSL
25 | * @Description: 系统运行的第一个任务
26 | */
27 | void taskFristRun(void)
28 | {
29 | /* 设置 PSP = MSP, 二者都指向同一个堆栈 */
30 | __set_PSP(__get_MSP());
31 |
32 | MEM8(NVIC_SYSPRI2) = NVIC_PENDSV_PRI; // 向NVIC_SYSPRI2写NVIC_PENDSV_PRI,设置其为最低优先级
33 |
34 | MEM32(NVIC_INT_CTRL) = NVIC_PENDSVSET; // 向NVIC_INT_CTRL写NVIC_PENDSVSET,用于PendSV
35 | }
36 |
37 | /*---------------------------------------------------------------------------------------------------------------------
38 | * 临界区相关操作
39 | *--------------------------------------------------------------------------------------------------------------------*/
40 | /**
41 | * @Author: YangSL
42 | * @Description: 进入临界区
43 | */
44 | uint32_t uTaskEnterCritical(void)
45 | {
46 | uint32_t primask = __get_PRIMASK();
47 | __disable_irq();
48 | return primask;
49 | }
50 |
51 | /**
52 | * @Author: YangSL
53 | * @Description: 退出临界区
54 | * @param {uint32_t} status
55 | */
56 | void vTaskExitCritical(uint32_t status)
57 | {
58 | __set_PRIMASK(status);
59 | }
60 |
61 | /*---------------------------------------------------------------------------------------------------------------------
62 | * 系统硬件设置
63 | *--------------------------------------------------------------------------------------------------------------------*/
64 | /**
65 | * @Author: YangSL
66 | * @Description: 设置触发SysTick异常的的周期
67 | * @param {uint32_t} timetime
68 | */
69 | void vTaskSetTickPeriod(uint32_t time)
70 | {
71 | /* System Core Clock update function */
72 | SystemCoreClockUpdate();
73 |
74 | SysTick->LOAD = time * SystemCoreClock / 1000 - 1;
75 | NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);
76 | SysTick->VAL = 0;
77 | SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
78 | SysTick_CTRL_TICKINT_Msk |
79 | SysTick_CTRL_ENABLE_Msk;
80 | }
81 |
82 |
83 | /* SysTick中断服务函数 */
84 | void SysTick_Handler ()
85 | {
86 | vTaskSystemTickHandler();
87 | }
88 |
89 |
90 | uint32_t loadStackAddress(uint32_t *stackAddress )
91 | {
92 | /* 第一次切换时currentTask == 0,不需要保存 */
93 | if(currentTask != (tTask*)0)
94 | {
95 | currentTask->stack = (uint32_t *)stackAddress;
96 | }
97 | currentTask = nextTask;
98 | /* 返回下一个任务的堆栈地址 */
99 | return (uint32_t) currentTask->stack;
100 | }
101 |
102 | /*---------------------------------------------------------------------------------------------------------------------
103 | * PendSV_Handler : 放到最后不然会使得struct变量无法加载
104 | *--------------------------------------------------------------------------------------------------------------------*/
105 | #if defined(__TARGET_CPU_CORTEX_M0)
106 |
107 | void hwStackInit(tTask * task, void (*entry)(void *), void *param, uint32_t * stack, uint32_t size)
108 | {
109 | /* 定义栈顶 */
110 | uint32_t * stackTop;
111 |
112 | task->stackBase = stack;
113 | task->stackSize = stackSize;
114 | /* 初始化堆桟中的值 */
115 |
116 | memset(stack, 0, stackSize);
117 |
118 | stackTop = task->stackBase + task->stackSize / sizeof(tTaskStack);
119 |
120 | *(--stackTop) = (unsigned long)(1<<24); // XPSR, 设置了Thumb模式
121 | *(--stackTop) = (unsigned long)entry; // 程序的入口地址
122 | *(--stackTop) = (unsigned long)0x14; // R14(LR)
123 | *(--stackTop) = (unsigned long)0x12; // R12, 未用
124 | *(--stackTop) = (unsigned long)0x3; // R3, 未用
125 | *(--stackTop) = (unsigned long)0x2; // R2, 未用
126 | *(--stackTop) = (unsigned long)0x1; // R1, 未用
127 | *(--stackTop) = (unsigned long)param; // R0 = param, 传给任务的入口函数
128 |
129 | *(--stackTop) = (unsigned long)0x7; // R7, 未用
130 | *(--stackTop) = (unsigned long)0x6; // R6, 未用
131 | *(--stackTop) = (unsigned long)0x5; // R5, 未用
132 | *(--stackTop) = (unsigned long)0x4; // R4, 未用
133 |
134 | *(--stackTop) = (unsigned long)0x11; // R11, 未用
135 | *(--stackTop) = (unsigned long)0x10; // R10, 未用
136 | *(--stackTop) = (unsigned long)0x9; // R9, 未用
137 | *(--stackTop) = (unsigned long)0x8; // R8, 未用
138 |
139 |
140 | task->stack = stackTop; // 保存最终的值
141 | }
142 |
143 | #if 1 /* PendSV纯汇编代码 */
144 | __asm void PendSV_Handler ()
145 | {
146 | IMPORT loadStackAddress
147 |
148 | MRS R0, PSP // 获取当前任务的堆栈指针
149 |
150 | MOVS R1, #32
151 | SUBS R0, R1 // 预先计算, R0此时得出的最后的堆栈地址,方便后面用stmia保存
152 | // 保存的地址是当前任务的PSP堆栈中,便于下次恢复
153 | STMIA R1!, {R4-R7} // 将除异常自动保存的寄存器这外的其它寄存器自动保存起来{R4, R11}
154 | MOV R4, R8 // 在cortex-m0不STMDB不支持访问R8~R11寄存器,所以下面通过R4~R7间接写入
155 | MOV R5, R9
156 | MOV R6, R10
157 | MOV R7, R11
158 | STMIA R1!, {R4-R7}
159 |
160 | BL loadStackAddress // 调用函数:参数通过R0传递,返回值也通过R0传递
161 |
162 | LDMIA R0!, {R4-R7} // cortex-m0不支持LDMIA访问R8-R11,所以通过R4-R7间接取出
163 | MOV R8, R4
164 | MOV R9, R5
165 | MOV R10, R6
166 | MOV R11, R7
167 | LDMIA R0!, {R4-R7} // 取出R4-R7
168 |
169 | MSR PSP, R0 // 最后,恢复真正的堆栈指针到PSP
170 |
171 | MOVS R0, #2 // 生成0xFFFFFFFD
172 | MVNS R0, R0
173 | BX R0 // 最后返回,此时任务就会从堆栈中取出LR值,恢复到上次运行的位置
174 |
175 | }
176 | #else /* PendSV汇编 + C代码 */
177 |
178 | __asm void PendSV_Handler(void){
179 | IMPORT switchTaskStack
180 |
181 | MRS R0, PSP
182 | STMDB R0!, {R4-R11} // 将R4~R11保存到当前任务栈,也就是PSP指向的堆栈
183 | BL switchTaskStack // 调用函数:参数通过R0传递,返回值也通过R0传递
184 | LDMIA R0!, {R4-R11}
185 | MSR PSP, R0
186 |
187 | MOV LR, #0XFFFFFFFD
188 | BX LR
189 | }
190 |
191 | uint32_t switchTaskStack(uint32_t stackAddr)
192 | {
193 | if(currentTask != (tTask *)0){
194 | currentTask->stack =(uint32_t *)stackAddr;
195 | }
196 | currentTask = nextTask;
197 | return (uint32_t)currentTask->stack;
198 | }
199 | #endif
200 |
201 | #elif defined(__TARGET_CPU_CORTEX_M3) || defined(__TARGET_CPU_CORTEX_M4)
202 |
203 | void hwStackInit(tTask * task, void (*entry)(void *), void *param, uint32_t * stack, uint32_t stackSize)
204 | {
205 | /* 定义栈顶 */
206 | uint32_t * stackTop;
207 |
208 | task->stackBase = stack;
209 | task->stackSize = stackSize;
210 | /* 初始化堆桟中的值 */
211 |
212 | memset(stack, 0, stackSize);
213 |
214 | stackTop = task->stackBase + task->stackSize / sizeof(tTaskStack);
215 |
216 | *(--stackTop) = (unsigned long)(1<<24); // XPSR, 设置了Thumb模式
217 | *(--stackTop) = (unsigned long)entry; // 程序的入口地址
218 | *(--stackTop) = (unsigned long)0x14; // R14(LR)
219 | *(--stackTop) = (unsigned long)0x12; // R12, 未用
220 | *(--stackTop) = (unsigned long)0x3; // R3, 未用
221 | *(--stackTop) = (unsigned long)0x2; // R2, 未用
222 | *(--stackTop) = (unsigned long)0x1; // R1, 未用
223 | *(--stackTop) = (unsigned long)param; // R0 = param, 传给任务的入口函数
224 |
225 | *(--stackTop) = (unsigned long)0x11; // R11, 未用
226 | *(--stackTop) = (unsigned long)0x10; // R10, 未用
227 | *(--stackTop) = (unsigned long)0x9; // R9, 未用
228 | *(--stackTop) = (unsigned long)0x8; // R8, 未用
229 |
230 | *(--stackTop) = (unsigned long)0x7; // R7, 未用
231 | *(--stackTop) = (unsigned long)0x6; // R6, 未用
232 | *(--stackTop) = (unsigned long)0x5; // R5, 未用
233 | *(--stackTop) = (unsigned long)0x4; // R4, 未用
234 |
235 | task->stack = stackTop; // 保存最终的值
236 | }
237 |
238 | __asm void PendSV_Handler ()
239 | {
240 | IMPORT loadStackAddress
241 |
242 | /* 保存当前上下文 */
243 | MRS R0, PSP // 获取当前任务的堆栈指针
244 |
245 | MOVS R1, #32
246 | SUBS R0, R1 // 预先计算, R0此时得出的最后的堆栈地址,方便后面用stmia保存
247 | // 保存的地址是当前任务的PSP堆栈中,便于下次恢复
248 | STMIA R1!, {R4-R7} // 将除异常自动保存的寄存器这外的其它寄存器自动保存起来{R4, R11}
249 | MOV R4, R8 // 在cortex-m0不STMDB不支持访问R8~R11寄存器,所以下面通过R4~R7间接写入
250 | MOV R5, R9
251 | MOV R6, R10
252 | MOV R7, R11
253 | STMIA R1!, {R4-R7}
254 |
255 | BL loadStackAddress // 调用函数:参数通过R0传递,返回值也通过R0传递
256 |
257 | LDMIA R0!, {R4-R7} // cortex-m0不支持LDMIA访问R8-R11,所以通过R4-R7间接取出
258 | MOV R8, R4
259 | MOV R9, R5
260 | MOV R10, R6
261 | MOV R11, R7
262 | LDMIA R0!, {R4-R7} // 取出R4-R7
263 |
264 | MSR PSP, R0 // 最后,恢复真正的堆栈指针到PSP
265 |
266 | MOVS R0, #2 // 生成0xFFFFFFFD
267 | MVNS R0, R0
268 | BX R0 // 最后返回,此时任务就会从堆栈中取出LR值,恢复到上次运行的位置
269 |
270 | }
271 |
272 | #endif
273 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/portable/RVDS/port.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-23
5 | * @LastEditTime: 2021-08-10 13:35:32
6 | * @Description:
7 | */
8 | #ifndef _PORT_H
9 | #define _PORT_H
10 | #include
11 | #include "portcpu.h"
12 | #include "LinOS.h"
13 |
14 | /* 在任务切换中,主要依赖了PendSV进行切换。PendSV其中的一个很重要的作用便是用于支持RTOS的任务切换。
15 | 1、首先将PendSV的中断优先配置为最低。这样只有在其它所有中断完成后,才会触发该中断;
16 | 实现方法为:向NVIC_SYSPRI2写NVIC_PENDSV_PRI
17 | 2、在需要中断切换时,设置挂起位为1,手动触发。这样,当没有其它中断发生时,将会引发PendSV中断。
18 | 实现方法为:向NVIC_INT_CTRL写NVIC_PENDSVSET
19 | 3、在PendSV中,执行任务切换操作。 */
20 | #define NVIC_INT_CTRL 0xE000ED04 // 中断控制及状态寄存器
21 | #define NVIC_PENDSVSET 0x10000000 // 触发软件中断的值
22 | #define NVIC_SYSPRI2 0xE000ED22 // 系统优先级寄存器
23 | #define NVIC_PENDSV_PRI 0x000000FF // 配置优先级
24 |
25 | #define MEM32(addr) *(volatile unsigned long *)(addr)
26 | #define MEM8(addr) *(volatile unsigned char *)(addr)
27 |
28 |
29 |
30 | /* 临界区相关函数 */
31 | uint32_t uTaskEnterCritical(void);
32 | void vTaskExitCritical(uint32_t status);
33 |
34 | /* 硬件调度 */
35 | void taskScheduler(void);
36 | void taskFristRun(void);
37 |
38 | void vTaskSetTickPeriod(uint32_t time);
39 |
40 | /**
41 | * @Author: YangSL
42 | * @Description:
43 | * @param {tTask *} task
44 | * @param {void} *
45 | * @param {void} *param
46 | * @param {uint32_t *} stack
47 | * @param {uint32_t} size
48 | */
49 | void hwStackInit(tTask * task, void (*entry)(void *), void *param, uint32_t * stack, uint32_t stackSize);
50 |
51 | #endif /* _PORT_H */
52 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/portable/portcpu.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-10 13:28:09
5 | * @LastEditTime: 2021-08-10 13:28:30
6 | * @Description:
7 | */
8 | #include "portcpu.h"
9 |
10 |
--------------------------------------------------------------------------------
/Code/LinRTOS Kernel/portable/portcpu.h:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-08-10 13:24:38
5 | * @LastEditTime: 2021-08-10 16:12:31
6 | * @Description:
7 | */
8 |
9 | #ifndef _PORT_CPU_H
10 | #define _PORT_CPU_H
11 |
12 | #ifdef __TARGET_CPU_CORTEX_M0
13 | #include "ARMCM0.h"
14 | #elif defined(__TARGET_CPU_CORTEX_M3)
15 | #include "ARMCM3.h"
16 | #elif defined(__TARGET_CPU_CORTEX_M4)
17 | #include "ARMCM4.h"
18 | #endif
19 |
20 | #endif /* _PORT_CPU_H */
21 |
22 |
--------------------------------------------------------------------------------
/Code/RTE/Device/ARMCM3/startup_ARMCM3.s:
--------------------------------------------------------------------------------
1 | ;/**************************************************************************//**
2 | ; * @file startup_ARMCM3.s
3 | ; * @brief CMSIS Core Device Startup File for
4 | ; * ARMCM3 Device
5 | ; * @version V1.0.1
6 | ; * @date 23. July 2019
7 | ; ******************************************************************************/
8 | ;/*
9 | ; * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
10 | ; *
11 | ; * SPDX-License-Identifier: Apache-2.0
12 | ; *
13 | ; * Licensed under the Apache License, Version 2.0 (the License); you may
14 | ; * not use this file except in compliance with the License.
15 | ; * You may obtain a copy of the License at
16 | ; *
17 | ; * www.apache.org/licenses/LICENSE-2.0
18 | ; *
19 | ; * Unless required by applicable law or agreed to in writing, software
20 | ; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
21 | ; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 | ; * See the License for the specific language governing permissions and
23 | ; * limitations under the License.
24 | ; */
25 |
26 | ;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
27 |
28 |
29 | ; Stack Configuration
30 | ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
31 | ;
32 |
33 | Stack_Size EQU 0x00000400
34 |
35 | AREA STACK, NOINIT, READWRITE, ALIGN=3
36 | __stack_limit
37 | Stack_Mem SPACE Stack_Size
38 | __initial_sp
39 |
40 |
41 | ; Heap Configuration
42 | ; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
43 | ;
44 |
45 | Heap_Size EQU 0x00000C00
46 |
47 | IF Heap_Size != 0 ; Heap is provided
48 | AREA HEAP, NOINIT, READWRITE, ALIGN=3
49 | __heap_base
50 | Heap_Mem SPACE Heap_Size
51 | __heap_limit
52 | ENDIF
53 |
54 |
55 | PRESERVE8
56 | THUMB
57 |
58 |
59 | ; Vector Table Mapped to Address 0 at Reset
60 |
61 | AREA RESET, DATA, READONLY
62 | EXPORT __Vectors
63 | EXPORT __Vectors_End
64 | EXPORT __Vectors_Size
65 |
66 | __Vectors DCD __initial_sp ; Top of Stack
67 | DCD Reset_Handler ; Reset Handler
68 | DCD NMI_Handler ; -14 NMI Handler
69 | DCD HardFault_Handler ; -13 Hard Fault Handler
70 | DCD MemManage_Handler ; -12 MPU Fault Handler
71 | DCD BusFault_Handler ; -11 Bus Fault Handler
72 | DCD UsageFault_Handler ; -10 Usage Fault Handler
73 | DCD 0 ; Reserved
74 | DCD 0 ; Reserved
75 | DCD 0 ; Reserved
76 | DCD 0 ; Reserved
77 | DCD SVC_Handler ; -5 SVCall Handler
78 | DCD DebugMon_Handler ; -4 Debug Monitor Handler
79 | DCD 0 ; Reserved
80 | DCD PendSV_Handler ; -2 PendSV Handler
81 | DCD SysTick_Handler ; -1 SysTick Handler
82 |
83 | ; Interrupts
84 | DCD Interrupt0_Handler ; 0 Interrupt 0
85 | DCD Interrupt1_Handler ; 1 Interrupt 1
86 | DCD Interrupt2_Handler ; 2 Interrupt 2
87 | DCD Interrupt3_Handler ; 3 Interrupt 3
88 | DCD Interrupt4_Handler ; 4 Interrupt 4
89 | DCD Interrupt5_Handler ; 5 Interrupt 5
90 | DCD Interrupt6_Handler ; 6 Interrupt 6
91 | DCD Interrupt7_Handler ; 7 Interrupt 7
92 | DCD Interrupt8_Handler ; 8 Interrupt 8
93 | DCD Interrupt9_Handler ; 9 Interrupt 9
94 |
95 | SPACE (214 * 4) ; Interrupts 10 .. 224 are left out
96 | __Vectors_End
97 | __Vectors_Size EQU __Vectors_End - __Vectors
98 |
99 |
100 | AREA |.text|, CODE, READONLY
101 |
102 | ; Reset Handler
103 |
104 | Reset_Handler PROC
105 | EXPORT Reset_Handler [WEAK]
106 | IMPORT SystemInit
107 | IMPORT __main
108 |
109 | LDR R0, =SystemInit
110 | BLX R0
111 | LDR R0, =__main
112 | BX R0
113 | ENDP
114 |
115 | ; The default macro is not used for HardFault_Handler
116 | ; because this results in a poor debug illusion.
117 | HardFault_Handler PROC
118 | EXPORT HardFault_Handler [WEAK]
119 | B .
120 | ENDP
121 |
122 | ; Macro to define default exception/interrupt handlers.
123 | ; Default handler are weak symbols with an endless loop.
124 | ; They can be overwritten by real handlers.
125 | MACRO
126 | Set_Default_Handler $Handler_Name
127 | $Handler_Name PROC
128 | EXPORT $Handler_Name [WEAK]
129 | B .
130 | ENDP
131 | MEND
132 |
133 |
134 | ; Default exception/interrupt handler
135 |
136 | Set_Default_Handler NMI_Handler
137 | Set_Default_Handler MemManage_Handler
138 | Set_Default_Handler BusFault_Handler
139 | Set_Default_Handler UsageFault_Handler
140 | Set_Default_Handler SVC_Handler
141 | Set_Default_Handler DebugMon_Handler
142 | Set_Default_Handler PendSV_Handler
143 | Set_Default_Handler SysTick_Handler
144 |
145 | Set_Default_Handler Interrupt0_Handler
146 | Set_Default_Handler Interrupt1_Handler
147 | Set_Default_Handler Interrupt2_Handler
148 | Set_Default_Handler Interrupt3_Handler
149 | Set_Default_Handler Interrupt4_Handler
150 | Set_Default_Handler Interrupt5_Handler
151 | Set_Default_Handler Interrupt6_Handler
152 | Set_Default_Handler Interrupt7_Handler
153 | Set_Default_Handler Interrupt8_Handler
154 | Set_Default_Handler Interrupt9_Handler
155 |
156 | ALIGN
157 |
158 |
159 | ; User setup Stack & Heap
160 |
161 | IF :LNOT::DEF:__MICROLIB
162 | IMPORT __use_two_region_memory
163 | ENDIF
164 |
165 | EXPORT __stack_limit
166 | EXPORT __initial_sp
167 | IF Heap_Size != 0 ; Heap is provided
168 | EXPORT __heap_base
169 | EXPORT __heap_limit
170 | ENDIF
171 |
172 | END
173 |
--------------------------------------------------------------------------------
/Code/RTE/Device/ARMCM3/system_ARMCM3.c:
--------------------------------------------------------------------------------
1 | /**************************************************************************//**
2 | * @file system_ARMCM3.c
3 | * @brief CMSIS Device System Source File for
4 | * ARMCM3 Device
5 | * @version V1.0.1
6 | * @date 15. November 2019
7 | ******************************************************************************/
8 | /*
9 | * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
10 | *
11 | * SPDX-License-Identifier: Apache-2.0
12 | *
13 | * Licensed under the Apache License, Version 2.0 (the License); you may
14 | * not use this file except in compliance with the License.
15 | * You may obtain a copy of the License at
16 | *
17 | * www.apache.org/licenses/LICENSE-2.0
18 | *
19 | * Unless required by applicable law or agreed to in writing, software
20 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT
21 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 | * See the License for the specific language governing permissions and
23 | * limitations under the License.
24 | */
25 |
26 | #include "ARMCM3.h"
27 |
28 | /*----------------------------------------------------------------------------
29 | Define clocks
30 | *----------------------------------------------------------------------------*/
31 | #define XTAL (50000000UL) /* Oscillator frequency */
32 |
33 | #define SYSTEM_CLOCK (XTAL / 2U)
34 |
35 | /*----------------------------------------------------------------------------
36 | Exception / Interrupt Vector table
37 | *----------------------------------------------------------------------------*/
38 | extern const VECTOR_TABLE_Type __VECTOR_TABLE[240];
39 |
40 | /*----------------------------------------------------------------------------
41 | System Core Clock Variable
42 | *----------------------------------------------------------------------------*/
43 | uint32_t SystemCoreClock = SYSTEM_CLOCK; /* System Core Clock Frequency */
44 |
45 |
46 | /*----------------------------------------------------------------------------
47 | System Core Clock update function
48 | *----------------------------------------------------------------------------*/
49 | void SystemCoreClockUpdate (void)
50 | {
51 | SystemCoreClock = SYSTEM_CLOCK;
52 | }
53 |
54 | /*----------------------------------------------------------------------------
55 | System initialization function
56 | *----------------------------------------------------------------------------*/
57 | void SystemInit (void)
58 | {
59 |
60 | #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
61 | SCB->VTOR = (uint32_t) &(__VECTOR_TABLE[0]);
62 | #endif
63 |
64 | SystemCoreClock = SYSTEM_CLOCK;
65 | }
66 |
--------------------------------------------------------------------------------
/Code/RTE/Device/ARMCM4/startup_ARMCM4.s:
--------------------------------------------------------------------------------
1 | ;/**************************************************************************//**
2 | ; * @file startup_ARMCM4.s
3 | ; * @brief CMSIS Core Device Startup File for
4 | ; * ARMCM4 Device
5 | ; * @version V1.0.1
6 | ; * @date 23. July 2019
7 | ; ******************************************************************************/
8 | ;/*
9 | ; * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
10 | ; *
11 | ; * SPDX-License-Identifier: Apache-2.0
12 | ; *
13 | ; * Licensed under the Apache License, Version 2.0 (the License); you may
14 | ; * not use this file except in compliance with the License.
15 | ; * You may obtain a copy of the License at
16 | ; *
17 | ; * www.apache.org/licenses/LICENSE-2.0
18 | ; *
19 | ; * Unless required by applicable law or agreed to in writing, software
20 | ; * distributed under the License is distributed on an AS IS BASIS, WITHOUT
21 | ; * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 | ; * See the License for the specific language governing permissions and
23 | ; * limitations under the License.
24 | ; */
25 |
26 | ;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
27 |
28 |
29 | ; Stack Configuration
30 | ; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
31 | ;
32 |
33 | Stack_Size EQU 0x00000400
34 |
35 | AREA STACK, NOINIT, READWRITE, ALIGN=3
36 | __stack_limit
37 | Stack_Mem SPACE Stack_Size
38 | __initial_sp
39 |
40 |
41 | ; Heap Configuration
42 | ; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
43 | ;
44 |
45 | Heap_Size EQU 0x00000C00
46 |
47 | IF Heap_Size != 0 ; Heap is provided
48 | AREA HEAP, NOINIT, READWRITE, ALIGN=3
49 | __heap_base
50 | Heap_Mem SPACE Heap_Size
51 | __heap_limit
52 | ENDIF
53 |
54 |
55 | PRESERVE8
56 | THUMB
57 |
58 |
59 | ; Vector Table Mapped to Address 0 at Reset
60 |
61 | AREA RESET, DATA, READONLY
62 | EXPORT __Vectors
63 | EXPORT __Vectors_End
64 | EXPORT __Vectors_Size
65 |
66 | __Vectors DCD __initial_sp ; Top of Stack
67 | DCD Reset_Handler ; Reset Handler
68 | DCD NMI_Handler ; -14 NMI Handler
69 | DCD HardFault_Handler ; -13 Hard Fault Handler
70 | DCD MemManage_Handler ; -12 MPU Fault Handler
71 | DCD BusFault_Handler ; -11 Bus Fault Handler
72 | DCD UsageFault_Handler ; -10 Usage Fault Handler
73 | DCD 0 ; Reserved
74 | DCD 0 ; Reserved
75 | DCD 0 ; Reserved
76 | DCD 0 ; Reserved
77 | DCD SVC_Handler ; -5 SVCall Handler
78 | DCD DebugMon_Handler ; -4 Debug Monitor Handler
79 | DCD 0 ; Reserved
80 | DCD PendSV_Handler ; -2 PendSV Handler
81 | DCD SysTick_Handler ; -1 SysTick Handler
82 |
83 | ; Interrupts
84 | DCD Interrupt0_Handler ; 0 Interrupt 0
85 | DCD Interrupt1_Handler ; 1 Interrupt 1
86 | DCD Interrupt2_Handler ; 2 Interrupt 2
87 | DCD Interrupt3_Handler ; 3 Interrupt 3
88 | DCD Interrupt4_Handler ; 4 Interrupt 4
89 | DCD Interrupt5_Handler ; 5 Interrupt 5
90 | DCD Interrupt6_Handler ; 6 Interrupt 6
91 | DCD Interrupt7_Handler ; 7 Interrupt 7
92 | DCD Interrupt8_Handler ; 8 Interrupt 8
93 | DCD Interrupt9_Handler ; 9 Interrupt 9
94 |
95 | SPACE (214 * 4) ; Interrupts 10 .. 224 are left out
96 | __Vectors_End
97 | __Vectors_Size EQU __Vectors_End - __Vectors
98 |
99 |
100 | AREA |.text|, CODE, READONLY
101 |
102 | ; Reset Handler
103 |
104 | Reset_Handler PROC
105 | EXPORT Reset_Handler [WEAK]
106 | IMPORT SystemInit
107 | IMPORT __main
108 |
109 | LDR R0, =SystemInit
110 | BLX R0
111 | LDR R0, =__main
112 | BX R0
113 | ENDP
114 |
115 | ; The default macro is not used for HardFault_Handler
116 | ; because this results in a poor debug illusion.
117 | HardFault_Handler PROC
118 | EXPORT HardFault_Handler [WEAK]
119 | B .
120 | ENDP
121 |
122 | ; Macro to define default exception/interrupt handlers.
123 | ; Default handler are weak symbols with an endless loop.
124 | ; They can be overwritten by real handlers.
125 | MACRO
126 | Set_Default_Handler $Handler_Name
127 | $Handler_Name PROC
128 | EXPORT $Handler_Name [WEAK]
129 | B .
130 | ENDP
131 | MEND
132 |
133 |
134 | ; Default exception/interrupt handler
135 |
136 | Set_Default_Handler NMI_Handler
137 | Set_Default_Handler MemManage_Handler
138 | Set_Default_Handler BusFault_Handler
139 | Set_Default_Handler UsageFault_Handler
140 | Set_Default_Handler SVC_Handler
141 | Set_Default_Handler DebugMon_Handler
142 | Set_Default_Handler PendSV_Handler
143 | Set_Default_Handler SysTick_Handler
144 |
145 | Set_Default_Handler Interrupt0_Handler
146 | Set_Default_Handler Interrupt1_Handler
147 | Set_Default_Handler Interrupt2_Handler
148 | Set_Default_Handler Interrupt3_Handler
149 | Set_Default_Handler Interrupt4_Handler
150 | Set_Default_Handler Interrupt5_Handler
151 | Set_Default_Handler Interrupt6_Handler
152 | Set_Default_Handler Interrupt7_Handler
153 | Set_Default_Handler Interrupt8_Handler
154 | Set_Default_Handler Interrupt9_Handler
155 |
156 | ALIGN
157 |
158 |
159 | ; User setup Stack & Heap
160 |
161 | IF :LNOT::DEF:__MICROLIB
162 | IMPORT __use_two_region_memory
163 | ENDIF
164 |
165 | EXPORT __stack_limit
166 | EXPORT __initial_sp
167 | IF Heap_Size != 0 ; Heap is provided
168 | EXPORT __heap_base
169 | EXPORT __heap_limit
170 | ENDIF
171 |
172 | END
173 |
--------------------------------------------------------------------------------
/Code/RTE/Device/ARMCM4/system_ARMCM4.c:
--------------------------------------------------------------------------------
1 | /**************************************************************************//**
2 | * @file system_ARMCM4.c
3 | * @brief CMSIS Device System Source File for
4 | * ARMCM4 Device
5 | * @version V1.0.1
6 | * @date 15. November 2019
7 | ******************************************************************************/
8 | /*
9 | * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
10 | *
11 | * SPDX-License-Identifier: Apache-2.0
12 | *
13 | * Licensed under the Apache License, Version 2.0 (the License); you may
14 | * not use this file except in compliance with the License.
15 | * You may obtain a copy of the License at
16 | *
17 | * www.apache.org/licenses/LICENSE-2.0
18 | *
19 | * Unless required by applicable law or agreed to in writing, software
20 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT
21 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 | * See the License for the specific language governing permissions and
23 | * limitations under the License.
24 | */
25 |
26 | #if defined (ARMCM4)
27 | #include "ARMCM4.h"
28 | #elif defined (ARMCM4_FP)
29 | #include "ARMCM4_FP.h"
30 | #else
31 | #error device not specified!
32 | #endif
33 |
34 | /*----------------------------------------------------------------------------
35 | Define clocks
36 | *----------------------------------------------------------------------------*/
37 | #define XTAL (50000000UL) /* Oscillator frequency */
38 |
39 | #define SYSTEM_CLOCK (XTAL / 2U)
40 |
41 | /*----------------------------------------------------------------------------
42 | Exception / Interrupt Vector table
43 | *----------------------------------------------------------------------------*/
44 | extern const VECTOR_TABLE_Type __VECTOR_TABLE[240];
45 |
46 |
47 | /*----------------------------------------------------------------------------
48 | System Core Clock Variable
49 | *----------------------------------------------------------------------------*/
50 | uint32_t SystemCoreClock = SYSTEM_CLOCK; /* System Core Clock Frequency */
51 |
52 |
53 | /*----------------------------------------------------------------------------
54 | System Core Clock update function
55 | *----------------------------------------------------------------------------*/
56 | void SystemCoreClockUpdate (void)
57 | {
58 | SystemCoreClock = SYSTEM_CLOCK;
59 | }
60 |
61 | /*----------------------------------------------------------------------------
62 | System initialization function
63 | *----------------------------------------------------------------------------*/
64 | void SystemInit (void)
65 | {
66 |
67 | #if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
68 | SCB->VTOR = (uint32_t) &(__VECTOR_TABLE[0]);
69 | #endif
70 |
71 | #if defined (__FPU_USED) && (__FPU_USED == 1U)
72 | SCB->CPACR |= ((3U << 10U*2U) | /* enable CP10 Full Access */
73 | (3U << 11U*2U) ); /* enable CP11 Full Access */
74 | #endif
75 |
76 | #ifdef UNALIGNED_SUPPORT_DISABLE
77 | SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk;
78 | #endif
79 |
80 | SystemCoreClock = SYSTEM_CLOCK;
81 | }
82 |
--------------------------------------------------------------------------------
/Code/RTE/Device/STM32F429ZETx/system_stm32f4xx.c:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file system_stm32f4xx.c
4 | * @author MCD Application Team
5 | * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
6 | *
7 | * This file provides two functions and one global variable to be called from
8 | * user application:
9 | * - SystemInit(): This function is called at startup just after reset and
10 | * before branch to main program. This call is made inside
11 | * the "startup_stm32f4xx.s" file.
12 | *
13 | * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
14 | * by the user application to setup the SysTick
15 | * timer or configure other parameters.
16 | *
17 | * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
18 | * be called whenever the core clock is changed
19 | * during program execution.
20 | *
21 | *
22 | ******************************************************************************
23 | * @attention
24 | *
25 | * © Copyright (c) 2017 STMicroelectronics.
26 | * All rights reserved.
27 | *
28 | * This software component is licensed by ST under BSD 3-Clause license,
29 | * the "License"; You may not use this file except in compliance with the
30 | * License. You may obtain a copy of the License at:
31 | * opensource.org/licenses/BSD-3-Clause
32 | *
33 | ******************************************************************************
34 | */
35 |
36 | /** @addtogroup CMSIS
37 | * @{
38 | */
39 |
40 | /** @addtogroup stm32f4xx_system
41 | * @{
42 | */
43 |
44 | /** @addtogroup STM32F4xx_System_Private_Includes
45 | * @{
46 | */
47 |
48 |
49 | #include "stm32f4xx.h"
50 |
51 | #if !defined (HSE_VALUE)
52 | #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
53 | #endif /* HSE_VALUE */
54 |
55 | #if !defined (HSI_VALUE)
56 | #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
57 | #endif /* HSI_VALUE */
58 |
59 | /**
60 | * @}
61 | */
62 |
63 | /** @addtogroup STM32F4xx_System_Private_TypesDefinitions
64 | * @{
65 | */
66 |
67 | /**
68 | * @}
69 | */
70 |
71 | /** @addtogroup STM32F4xx_System_Private_Defines
72 | * @{
73 | */
74 |
75 | /************************* Miscellaneous Configuration ************************/
76 | /*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
77 | #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
78 | || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
79 | || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
80 | /* #define DATA_IN_ExtSRAM */
81 | #endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
82 | STM32F412Zx || STM32F412Vx */
83 |
84 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
85 | || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
86 | /* #define DATA_IN_ExtSDRAM */
87 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\
88 | STM32F479xx */
89 |
90 | /*!< Uncomment the following line if you need to relocate your vector Table in
91 | Internal SRAM. */
92 | /* #define VECT_TAB_SRAM */
93 | #define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
94 | This value must be a multiple of 0x200. */
95 | /******************************************************************************/
96 |
97 | /**
98 | * @}
99 | */
100 |
101 | /** @addtogroup STM32F4xx_System_Private_Macros
102 | * @{
103 | */
104 |
105 | /**
106 | * @}
107 | */
108 |
109 | /** @addtogroup STM32F4xx_System_Private_Variables
110 | * @{
111 | */
112 | /* This variable is updated in three ways:
113 | 1) by calling CMSIS function SystemCoreClockUpdate()
114 | 2) by calling HAL API function HAL_RCC_GetHCLKFreq()
115 | 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
116 | Note: If you use this function to configure the system clock; then there
117 | is no need to call the 2 first functions listed above, since SystemCoreClock
118 | variable is updated automatically.
119 | */
120 | uint32_t SystemCoreClock = 12000000;
121 | const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
122 | const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
123 | /**
124 | * @}
125 | */
126 |
127 | /** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
128 | * @{
129 | */
130 |
131 | #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
132 | static void SystemInit_ExtMemCtl(void);
133 | #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
134 |
135 | /**
136 | * @}
137 | */
138 |
139 | /** @addtogroup STM32F4xx_System_Private_Functions
140 | * @{
141 | */
142 |
143 | /**
144 | * @brief Setup the microcontroller system
145 | * Initialize the FPU setting, vector table location and External memory
146 | * configuration.
147 | * @param None
148 | * @retval None
149 | */
150 | void SystemInit(void)
151 | {
152 | /* FPU settings ------------------------------------------------------------*/
153 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
154 | SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
155 | #endif
156 |
157 | #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
158 | SystemInit_ExtMemCtl();
159 | #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
160 |
161 | /* Configure the Vector Table location add offset address ------------------*/
162 | #ifdef VECT_TAB_SRAM
163 | SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
164 | #else
165 | SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
166 | #endif
167 | }
168 |
169 | /**
170 | * @brief Update SystemCoreClock variable according to Clock Register Values.
171 | * The SystemCoreClock variable contains the core clock (HCLK), it can
172 | * be used by the user application to setup the SysTick timer or configure
173 | * other parameters.
174 | *
175 | * @note Each time the core clock (HCLK) changes, this function must be called
176 | * to update SystemCoreClock variable value. Otherwise, any configuration
177 | * based on this variable will be incorrect.
178 | *
179 | * @note - The system frequency computed by this function is not the real
180 | * frequency in the chip. It is calculated based on the predefined
181 | * constant and the selected clock source:
182 | *
183 | * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
184 | *
185 | * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
186 | *
187 | * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
188 | * or HSI_VALUE(*) multiplied/divided by the PLL factors.
189 | *
190 | * (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
191 | * 16 MHz) but the real value may vary depending on the variations
192 | * in voltage and temperature.
193 | *
194 | * (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
195 | * depends on the application requirements), user has to ensure that HSE_VALUE
196 | * is same as the real frequency of the crystal used. Otherwise, this function
197 | * may have wrong result.
198 | *
199 | * - The result of this function could be not correct when using fractional
200 | * value for HSE crystal.
201 | *
202 | * @param None
203 | * @retval None
204 | */
205 | void SystemCoreClockUpdate(void)
206 | {
207 | uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
208 |
209 | /* Get SYSCLK source -------------------------------------------------------*/
210 | tmp = RCC->CFGR & RCC_CFGR_SWS;
211 |
212 | switch (tmp)
213 | {
214 | case 0x00: /* HSI used as system clock source */
215 | SystemCoreClock = HSI_VALUE;
216 | break;
217 | case 0x04: /* HSE used as system clock source */
218 | SystemCoreClock = HSE_VALUE;
219 | break;
220 | case 0x08: /* PLL used as system clock source */
221 |
222 | /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
223 | SYSCLK = PLL_VCO / PLL_P
224 | */
225 | pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
226 | pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
227 |
228 | if (pllsource != 0)
229 | {
230 | /* HSE used as PLL clock source */
231 | pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
232 | }
233 | else
234 | {
235 | /* HSI used as PLL clock source */
236 | pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
237 | }
238 |
239 | pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
240 | SystemCoreClock = pllvco/pllp;
241 | break;
242 | default:
243 | SystemCoreClock = HSI_VALUE;
244 | break;
245 | }
246 | /* Compute HCLK frequency --------------------------------------------------*/
247 | /* Get HCLK prescaler */
248 | tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
249 | /* HCLK frequency */
250 | SystemCoreClock >>= tmp;
251 | }
252 |
253 | #if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
254 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
255 | || defined(STM32F469xx) || defined(STM32F479xx)
256 | /**
257 | * @brief Setup the external memory controller.
258 | * Called in startup_stm32f4xx.s before jump to main.
259 | * This function configures the external memories (SRAM/SDRAM)
260 | * This SRAM/SDRAM will be used as program data memory (including heap and stack).
261 | * @param None
262 | * @retval None
263 | */
264 | void SystemInit_ExtMemCtl(void)
265 | {
266 | __IO uint32_t tmp = 0x00;
267 |
268 | register uint32_t tmpreg = 0, timeout = 0xFFFF;
269 | register __IO uint32_t index;
270 |
271 | /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
272 | RCC->AHB1ENR |= 0x000001F8;
273 |
274 | /* Delay after an RCC peripheral clock enabling */
275 | tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
276 |
277 | /* Connect PDx pins to FMC Alternate function */
278 | GPIOD->AFR[0] = 0x00CCC0CC;
279 | GPIOD->AFR[1] = 0xCCCCCCCC;
280 | /* Configure PDx pins in Alternate function mode */
281 | GPIOD->MODER = 0xAAAA0A8A;
282 | /* Configure PDx pins speed to 100 MHz */
283 | GPIOD->OSPEEDR = 0xFFFF0FCF;
284 | /* Configure PDx pins Output type to push-pull */
285 | GPIOD->OTYPER = 0x00000000;
286 | /* No pull-up, pull-down for PDx pins */
287 | GPIOD->PUPDR = 0x00000000;
288 |
289 | /* Connect PEx pins to FMC Alternate function */
290 | GPIOE->AFR[0] = 0xC00CC0CC;
291 | GPIOE->AFR[1] = 0xCCCCCCCC;
292 | /* Configure PEx pins in Alternate function mode */
293 | GPIOE->MODER = 0xAAAA828A;
294 | /* Configure PEx pins speed to 100 MHz */
295 | GPIOE->OSPEEDR = 0xFFFFC3CF;
296 | /* Configure PEx pins Output type to push-pull */
297 | GPIOE->OTYPER = 0x00000000;
298 | /* No pull-up, pull-down for PEx pins */
299 | GPIOE->PUPDR = 0x00000000;
300 |
301 | /* Connect PFx pins to FMC Alternate function */
302 | GPIOF->AFR[0] = 0xCCCCCCCC;
303 | GPIOF->AFR[1] = 0xCCCCCCCC;
304 | /* Configure PFx pins in Alternate function mode */
305 | GPIOF->MODER = 0xAA800AAA;
306 | /* Configure PFx pins speed to 50 MHz */
307 | GPIOF->OSPEEDR = 0xAA800AAA;
308 | /* Configure PFx pins Output type to push-pull */
309 | GPIOF->OTYPER = 0x00000000;
310 | /* No pull-up, pull-down for PFx pins */
311 | GPIOF->PUPDR = 0x00000000;
312 |
313 | /* Connect PGx pins to FMC Alternate function */
314 | GPIOG->AFR[0] = 0xCCCCCCCC;
315 | GPIOG->AFR[1] = 0xCCCCCCCC;
316 | /* Configure PGx pins in Alternate function mode */
317 | GPIOG->MODER = 0xAAAAAAAA;
318 | /* Configure PGx pins speed to 50 MHz */
319 | GPIOG->OSPEEDR = 0xAAAAAAAA;
320 | /* Configure PGx pins Output type to push-pull */
321 | GPIOG->OTYPER = 0x00000000;
322 | /* No pull-up, pull-down for PGx pins */
323 | GPIOG->PUPDR = 0x00000000;
324 |
325 | /* Connect PHx pins to FMC Alternate function */
326 | GPIOH->AFR[0] = 0x00C0CC00;
327 | GPIOH->AFR[1] = 0xCCCCCCCC;
328 | /* Configure PHx pins in Alternate function mode */
329 | GPIOH->MODER = 0xAAAA08A0;
330 | /* Configure PHx pins speed to 50 MHz */
331 | GPIOH->OSPEEDR = 0xAAAA08A0;
332 | /* Configure PHx pins Output type to push-pull */
333 | GPIOH->OTYPER = 0x00000000;
334 | /* No pull-up, pull-down for PHx pins */
335 | GPIOH->PUPDR = 0x00000000;
336 |
337 | /* Connect PIx pins to FMC Alternate function */
338 | GPIOI->AFR[0] = 0xCCCCCCCC;
339 | GPIOI->AFR[1] = 0x00000CC0;
340 | /* Configure PIx pins in Alternate function mode */
341 | GPIOI->MODER = 0x0028AAAA;
342 | /* Configure PIx pins speed to 50 MHz */
343 | GPIOI->OSPEEDR = 0x0028AAAA;
344 | /* Configure PIx pins Output type to push-pull */
345 | GPIOI->OTYPER = 0x00000000;
346 | /* No pull-up, pull-down for PIx pins */
347 | GPIOI->PUPDR = 0x00000000;
348 |
349 | /*-- FMC Configuration -------------------------------------------------------*/
350 | /* Enable the FMC interface clock */
351 | RCC->AHB3ENR |= 0x00000001;
352 | /* Delay after an RCC peripheral clock enabling */
353 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
354 |
355 | FMC_Bank5_6->SDCR[0] = 0x000019E4;
356 | FMC_Bank5_6->SDTR[0] = 0x01115351;
357 |
358 | /* SDRAM initialization sequence */
359 | /* Clock enable command */
360 | FMC_Bank5_6->SDCMR = 0x00000011;
361 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
362 | while((tmpreg != 0) && (timeout-- > 0))
363 | {
364 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
365 | }
366 |
367 | /* Delay */
368 | for (index = 0; index<1000; index++);
369 |
370 | /* PALL command */
371 | FMC_Bank5_6->SDCMR = 0x00000012;
372 | timeout = 0xFFFF;
373 | while((tmpreg != 0) && (timeout-- > 0))
374 | {
375 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
376 | }
377 |
378 | /* Auto refresh command */
379 | FMC_Bank5_6->SDCMR = 0x00000073;
380 | timeout = 0xFFFF;
381 | while((tmpreg != 0) && (timeout-- > 0))
382 | {
383 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
384 | }
385 |
386 | /* MRD register program */
387 | FMC_Bank5_6->SDCMR = 0x00046014;
388 | timeout = 0xFFFF;
389 | while((tmpreg != 0) && (timeout-- > 0))
390 | {
391 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
392 | }
393 |
394 | /* Set refresh count */
395 | tmpreg = FMC_Bank5_6->SDRTR;
396 | FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
397 |
398 | /* Disable write protection */
399 | tmpreg = FMC_Bank5_6->SDCR[0];
400 | FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
401 |
402 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
403 | /* Configure and enable Bank1_SRAM2 */
404 | FMC_Bank1->BTCR[2] = 0x00001011;
405 | FMC_Bank1->BTCR[3] = 0x00000201;
406 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
407 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
408 | #if defined(STM32F469xx) || defined(STM32F479xx)
409 | /* Configure and enable Bank1_SRAM2 */
410 | FMC_Bank1->BTCR[2] = 0x00001091;
411 | FMC_Bank1->BTCR[3] = 0x00110212;
412 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
413 | #endif /* STM32F469xx || STM32F479xx */
414 |
415 | (void)(tmp);
416 | }
417 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
418 | #elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
419 | /**
420 | * @brief Setup the external memory controller.
421 | * Called in startup_stm32f4xx.s before jump to main.
422 | * This function configures the external memories (SRAM/SDRAM)
423 | * This SRAM/SDRAM will be used as program data memory (including heap and stack).
424 | * @param None
425 | * @retval None
426 | */
427 | void SystemInit_ExtMemCtl(void)
428 | {
429 | __IO uint32_t tmp = 0x00;
430 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
431 | || defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
432 | #if defined (DATA_IN_ExtSDRAM)
433 | register uint32_t tmpreg = 0, timeout = 0xFFFF;
434 | register __IO uint32_t index;
435 |
436 | #if defined(STM32F446xx)
437 | /* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface
438 | clock */
439 | RCC->AHB1ENR |= 0x0000007D;
440 | #else
441 | /* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface
442 | clock */
443 | RCC->AHB1ENR |= 0x000001F8;
444 | #endif /* STM32F446xx */
445 | /* Delay after an RCC peripheral clock enabling */
446 | tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
447 |
448 | #if defined(STM32F446xx)
449 | /* Connect PAx pins to FMC Alternate function */
450 | GPIOA->AFR[0] |= 0xC0000000;
451 | GPIOA->AFR[1] |= 0x00000000;
452 | /* Configure PDx pins in Alternate function mode */
453 | GPIOA->MODER |= 0x00008000;
454 | /* Configure PDx pins speed to 50 MHz */
455 | GPIOA->OSPEEDR |= 0x00008000;
456 | /* Configure PDx pins Output type to push-pull */
457 | GPIOA->OTYPER |= 0x00000000;
458 | /* No pull-up, pull-down for PDx pins */
459 | GPIOA->PUPDR |= 0x00000000;
460 |
461 | /* Connect PCx pins to FMC Alternate function */
462 | GPIOC->AFR[0] |= 0x00CC0000;
463 | GPIOC->AFR[1] |= 0x00000000;
464 | /* Configure PDx pins in Alternate function mode */
465 | GPIOC->MODER |= 0x00000A00;
466 | /* Configure PDx pins speed to 50 MHz */
467 | GPIOC->OSPEEDR |= 0x00000A00;
468 | /* Configure PDx pins Output type to push-pull */
469 | GPIOC->OTYPER |= 0x00000000;
470 | /* No pull-up, pull-down for PDx pins */
471 | GPIOC->PUPDR |= 0x00000000;
472 | #endif /* STM32F446xx */
473 |
474 | /* Connect PDx pins to FMC Alternate function */
475 | GPIOD->AFR[0] = 0x000000CC;
476 | GPIOD->AFR[1] = 0xCC000CCC;
477 | /* Configure PDx pins in Alternate function mode */
478 | GPIOD->MODER = 0xA02A000A;
479 | /* Configure PDx pins speed to 50 MHz */
480 | GPIOD->OSPEEDR = 0xA02A000A;
481 | /* Configure PDx pins Output type to push-pull */
482 | GPIOD->OTYPER = 0x00000000;
483 | /* No pull-up, pull-down for PDx pins */
484 | GPIOD->PUPDR = 0x00000000;
485 |
486 | /* Connect PEx pins to FMC Alternate function */
487 | GPIOE->AFR[0] = 0xC00000CC;
488 | GPIOE->AFR[1] = 0xCCCCCCCC;
489 | /* Configure PEx pins in Alternate function mode */
490 | GPIOE->MODER = 0xAAAA800A;
491 | /* Configure PEx pins speed to 50 MHz */
492 | GPIOE->OSPEEDR = 0xAAAA800A;
493 | /* Configure PEx pins Output type to push-pull */
494 | GPIOE->OTYPER = 0x00000000;
495 | /* No pull-up, pull-down for PEx pins */
496 | GPIOE->PUPDR = 0x00000000;
497 |
498 | /* Connect PFx pins to FMC Alternate function */
499 | GPIOF->AFR[0] = 0xCCCCCCCC;
500 | GPIOF->AFR[1] = 0xCCCCCCCC;
501 | /* Configure PFx pins in Alternate function mode */
502 | GPIOF->MODER = 0xAA800AAA;
503 | /* Configure PFx pins speed to 50 MHz */
504 | GPIOF->OSPEEDR = 0xAA800AAA;
505 | /* Configure PFx pins Output type to push-pull */
506 | GPIOF->OTYPER = 0x00000000;
507 | /* No pull-up, pull-down for PFx pins */
508 | GPIOF->PUPDR = 0x00000000;
509 |
510 | /* Connect PGx pins to FMC Alternate function */
511 | GPIOG->AFR[0] = 0xCCCCCCCC;
512 | GPIOG->AFR[1] = 0xCCCCCCCC;
513 | /* Configure PGx pins in Alternate function mode */
514 | GPIOG->MODER = 0xAAAAAAAA;
515 | /* Configure PGx pins speed to 50 MHz */
516 | GPIOG->OSPEEDR = 0xAAAAAAAA;
517 | /* Configure PGx pins Output type to push-pull */
518 | GPIOG->OTYPER = 0x00000000;
519 | /* No pull-up, pull-down for PGx pins */
520 | GPIOG->PUPDR = 0x00000000;
521 |
522 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
523 | || defined(STM32F469xx) || defined(STM32F479xx)
524 | /* Connect PHx pins to FMC Alternate function */
525 | GPIOH->AFR[0] = 0x00C0CC00;
526 | GPIOH->AFR[1] = 0xCCCCCCCC;
527 | /* Configure PHx pins in Alternate function mode */
528 | GPIOH->MODER = 0xAAAA08A0;
529 | /* Configure PHx pins speed to 50 MHz */
530 | GPIOH->OSPEEDR = 0xAAAA08A0;
531 | /* Configure PHx pins Output type to push-pull */
532 | GPIOH->OTYPER = 0x00000000;
533 | /* No pull-up, pull-down for PHx pins */
534 | GPIOH->PUPDR = 0x00000000;
535 |
536 | /* Connect PIx pins to FMC Alternate function */
537 | GPIOI->AFR[0] = 0xCCCCCCCC;
538 | GPIOI->AFR[1] = 0x00000CC0;
539 | /* Configure PIx pins in Alternate function mode */
540 | GPIOI->MODER = 0x0028AAAA;
541 | /* Configure PIx pins speed to 50 MHz */
542 | GPIOI->OSPEEDR = 0x0028AAAA;
543 | /* Configure PIx pins Output type to push-pull */
544 | GPIOI->OTYPER = 0x00000000;
545 | /* No pull-up, pull-down for PIx pins */
546 | GPIOI->PUPDR = 0x00000000;
547 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
548 |
549 | /*-- FMC Configuration -------------------------------------------------------*/
550 | /* Enable the FMC interface clock */
551 | RCC->AHB3ENR |= 0x00000001;
552 | /* Delay after an RCC peripheral clock enabling */
553 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
554 |
555 | /* Configure and enable SDRAM bank1 */
556 | #if defined(STM32F446xx)
557 | FMC_Bank5_6->SDCR[0] = 0x00001954;
558 | #else
559 | FMC_Bank5_6->SDCR[0] = 0x000019E4;
560 | #endif /* STM32F446xx */
561 | FMC_Bank5_6->SDTR[0] = 0x01115351;
562 |
563 | /* SDRAM initialization sequence */
564 | /* Clock enable command */
565 | FMC_Bank5_6->SDCMR = 0x00000011;
566 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
567 | while((tmpreg != 0) && (timeout-- > 0))
568 | {
569 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
570 | }
571 |
572 | /* Delay */
573 | for (index = 0; index<1000; index++);
574 |
575 | /* PALL command */
576 | FMC_Bank5_6->SDCMR = 0x00000012;
577 | timeout = 0xFFFF;
578 | while((tmpreg != 0) && (timeout-- > 0))
579 | {
580 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
581 | }
582 |
583 | /* Auto refresh command */
584 | #if defined(STM32F446xx)
585 | FMC_Bank5_6->SDCMR = 0x000000F3;
586 | #else
587 | FMC_Bank5_6->SDCMR = 0x00000073;
588 | #endif /* STM32F446xx */
589 | timeout = 0xFFFF;
590 | while((tmpreg != 0) && (timeout-- > 0))
591 | {
592 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
593 | }
594 |
595 | /* MRD register program */
596 | #if defined(STM32F446xx)
597 | FMC_Bank5_6->SDCMR = 0x00044014;
598 | #else
599 | FMC_Bank5_6->SDCMR = 0x00046014;
600 | #endif /* STM32F446xx */
601 | timeout = 0xFFFF;
602 | while((tmpreg != 0) && (timeout-- > 0))
603 | {
604 | tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
605 | }
606 |
607 | /* Set refresh count */
608 | tmpreg = FMC_Bank5_6->SDRTR;
609 | #if defined(STM32F446xx)
610 | FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1));
611 | #else
612 | FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
613 | #endif /* STM32F446xx */
614 |
615 | /* Disable write protection */
616 | tmpreg = FMC_Bank5_6->SDCR[0];
617 | FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
618 | #endif /* DATA_IN_ExtSDRAM */
619 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
620 |
621 | #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
622 | || defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
623 | || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
624 |
625 | #if defined(DATA_IN_ExtSRAM)
626 | /*-- GPIOs Configuration -----------------------------------------------------*/
627 | /* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
628 | RCC->AHB1ENR |= 0x00000078;
629 | /* Delay after an RCC peripheral clock enabling */
630 | tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
631 |
632 | /* Connect PDx pins to FMC Alternate function */
633 | GPIOD->AFR[0] = 0x00CCC0CC;
634 | GPIOD->AFR[1] = 0xCCCCCCCC;
635 | /* Configure PDx pins in Alternate function mode */
636 | GPIOD->MODER = 0xAAAA0A8A;
637 | /* Configure PDx pins speed to 100 MHz */
638 | GPIOD->OSPEEDR = 0xFFFF0FCF;
639 | /* Configure PDx pins Output type to push-pull */
640 | GPIOD->OTYPER = 0x00000000;
641 | /* No pull-up, pull-down for PDx pins */
642 | GPIOD->PUPDR = 0x00000000;
643 |
644 | /* Connect PEx pins to FMC Alternate function */
645 | GPIOE->AFR[0] = 0xC00CC0CC;
646 | GPIOE->AFR[1] = 0xCCCCCCCC;
647 | /* Configure PEx pins in Alternate function mode */
648 | GPIOE->MODER = 0xAAAA828A;
649 | /* Configure PEx pins speed to 100 MHz */
650 | GPIOE->OSPEEDR = 0xFFFFC3CF;
651 | /* Configure PEx pins Output type to push-pull */
652 | GPIOE->OTYPER = 0x00000000;
653 | /* No pull-up, pull-down for PEx pins */
654 | GPIOE->PUPDR = 0x00000000;
655 |
656 | /* Connect PFx pins to FMC Alternate function */
657 | GPIOF->AFR[0] = 0x00CCCCCC;
658 | GPIOF->AFR[1] = 0xCCCC0000;
659 | /* Configure PFx pins in Alternate function mode */
660 | GPIOF->MODER = 0xAA000AAA;
661 | /* Configure PFx pins speed to 100 MHz */
662 | GPIOF->OSPEEDR = 0xFF000FFF;
663 | /* Configure PFx pins Output type to push-pull */
664 | GPIOF->OTYPER = 0x00000000;
665 | /* No pull-up, pull-down for PFx pins */
666 | GPIOF->PUPDR = 0x00000000;
667 |
668 | /* Connect PGx pins to FMC Alternate function */
669 | GPIOG->AFR[0] = 0x00CCCCCC;
670 | GPIOG->AFR[1] = 0x000000C0;
671 | /* Configure PGx pins in Alternate function mode */
672 | GPIOG->MODER = 0x00085AAA;
673 | /* Configure PGx pins speed to 100 MHz */
674 | GPIOG->OSPEEDR = 0x000CAFFF;
675 | /* Configure PGx pins Output type to push-pull */
676 | GPIOG->OTYPER = 0x00000000;
677 | /* No pull-up, pull-down for PGx pins */
678 | GPIOG->PUPDR = 0x00000000;
679 |
680 | /*-- FMC/FSMC Configuration --------------------------------------------------*/
681 | /* Enable the FMC/FSMC interface clock */
682 | RCC->AHB3ENR |= 0x00000001;
683 |
684 | #if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
685 | /* Delay after an RCC peripheral clock enabling */
686 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
687 | /* Configure and enable Bank1_SRAM2 */
688 | FMC_Bank1->BTCR[2] = 0x00001011;
689 | FMC_Bank1->BTCR[3] = 0x00000201;
690 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
691 | #endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
692 | #if defined(STM32F469xx) || defined(STM32F479xx)
693 | /* Delay after an RCC peripheral clock enabling */
694 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
695 | /* Configure and enable Bank1_SRAM2 */
696 | FMC_Bank1->BTCR[2] = 0x00001091;
697 | FMC_Bank1->BTCR[3] = 0x00110212;
698 | FMC_Bank1E->BWTR[2] = 0x0fffffff;
699 | #endif /* STM32F469xx || STM32F479xx */
700 | #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
701 | || defined(STM32F412Zx) || defined(STM32F412Vx)
702 | /* Delay after an RCC peripheral clock enabling */
703 | tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
704 | /* Configure and enable Bank1_SRAM2 */
705 | FSMC_Bank1->BTCR[2] = 0x00001011;
706 | FSMC_Bank1->BTCR[3] = 0x00000201;
707 | FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF;
708 | #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */
709 |
710 | #endif /* DATA_IN_ExtSRAM */
711 | #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\
712 | STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */
713 | (void)(tmp);
714 | }
715 | #endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
716 | /**
717 | * @}
718 | */
719 |
720 | /**
721 | * @}
722 | */
723 |
724 | /**
725 | * @}
726 | */
727 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
728 |
--------------------------------------------------------------------------------
/Code/RTE/_Target_1/RTE_Components.h:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Auto generated Run-Time-Environment Configuration File
4 | * *** Do not modify ! ***
5 | *
6 | * Project: 'LinOS'
7 | * Target: 'Target 1'
8 | */
9 |
10 | #ifndef RTE_COMPONENTS_H
11 | #define RTE_COMPONENTS_H
12 |
13 |
14 | /*
15 | * Define the Device Header File:
16 | */
17 | #define CMSIS_device_header "ARMCM4.h"
18 |
19 |
20 |
21 | #endif /* RTE_COMPONENTS_H */
22 |
--------------------------------------------------------------------------------
/Code/User/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @FileName:
3 | * @Author: YangSL
4 | * @Date: 2021-07-06
5 | * @LastEditTime: 2021-08-09 22:51:27
6 | * @Description:
7 | */
8 | #include "LinOS.h"
9 | #include "port.h"
10 |
11 |
12 | void delay (int count)
13 | {
14 | while (--count > 0);
15 | }
16 |
17 | /* 任务1和任务2的任务结构,以及用于堆栈空间 */
18 | tTask tTask1;
19 | tTask tTask2;
20 | tTask tTask3;
21 | tTask tTask4;
22 | tTaskStack task1Env[LinOS_STACK_SIZE];
23 | tTaskStack task2Env[LinOS_STACK_SIZE];
24 | tTaskStack task3Env[LinOS_STACK_SIZE];
25 | tTaskStack task4Env[LinOS_STACK_SIZE];
26 |
27 | float ans;
28 | int task1Flag;
29 | void task1 (void * param)
30 | {
31 |
32 |
33 | for (;;)
34 | {
35 | ans = fTaskGetCpuUsage();
36 | task1Flag = 1;
37 | vTaskDelay(5);
38 | task1Flag = 0;
39 | vTaskDelay(5);
40 | }
41 |
42 | }
43 |
44 | int task2Flag;
45 | void task2 (void * param)
46 | {
47 | // uMutexTake(&mutex1, 0);
48 | for (;;)
49 | {
50 | task2Flag = 1;
51 | vTaskDelay(1);
52 | task2Flag = 0;
53 | vTaskDelay(1);
54 | }
55 | }
56 |
57 | int task3Flag;
58 | void task3 (void * param)
59 | {
60 | for (;;)
61 | {
62 | task3Flag = 1;
63 | vTaskDelay(1);
64 | task3Flag = 0;
65 | vTaskDelay(1);
66 | }
67 | }
68 |
69 | int task4Flag;
70 | void task4 (void * param)
71 | {
72 | for (;;)
73 | {
74 |
75 | task4Flag = 1;
76 | vTaskDelay(1);
77 | task4Flag = 0;
78 | vTaskDelay(1);
79 |
80 | }
81 | }
82 |
83 |
84 |
85 | int main ()
86 | {
87 | vTaskSchedInit();
88 | vTaskSetTickPeriod(LinOS_SYSTICK_MS);
89 | /* 初始化延时队列 */
90 | vTaskDelayInit();
91 |
92 |
93 | // 初始化任务1和任务2结构,传递运行的起始地址,想要给任意参数,以及运行堆栈空间
94 | vTaskInit(&tTask1, task1, (void *)0x11111111, 0, task1Env, sizeof(task1Env));
95 | vTaskInit(&tTask2, task2, (void *)0x22222222, 1, task2Env, sizeof(task2Env));
96 | vTaskInit(&tTask3, task3, (void *)0x33333333, 1, task3Env, sizeof(task3Env));
97 | vTaskInit(&tTask4, task4, (void *)0x44444444, 1, task4Env, sizeof(task4Env));
98 |
99 |
100 | /* 设置启动任务 */
101 | nextTask = tTaskHighestReady();
102 |
103 | vTaskSetTickPeriod(1);
104 | /* 运行第一个任务 */
105 | taskFristRun();
106 |
107 | return 0;
108 | }
109 |
--------------------------------------------------------------------------------
/Image/LinRTOS_Kernel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DaLinYYY/LinRTOS/89a0694a8bd4f1e60d4d36e521d8293a2901f90d/Image/LinRTOS_Kernel.png
--------------------------------------------------------------------------------
/Image/整体框图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DaLinYYY/LinRTOS/89a0694a8bd4f1e60d4d36e521d8293a2901f90d/Image/整体框图.png
--------------------------------------------------------------------------------
/Image/整体框架.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DaLinYYY/LinRTOS/89a0694a8bd4f1e60d4d36e521d8293a2901f90d/Image/整体框架.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | 木兰宽松许可证, 第2版
2 |
3 | 木兰宽松许可证, 第2版
4 | 2020年1月 http://license.coscl.org.cn/MulanPSL2
5 |
6 |
7 | 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
8 |
9 | 0. 定义
10 |
11 | “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
12 |
13 | “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
14 |
15 | “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
16 |
17 | “法人实体”是指提交贡献的机构及其“关联实体”。
18 |
19 | “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
20 |
21 | 1. 授予版权许可
22 |
23 | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
24 |
25 | 2. 授予专利许可
26 |
27 | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
28 |
29 | 3. 无商标许可
30 |
31 | “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
32 |
33 | 4. 分发限制
34 |
35 | 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
36 |
37 | 5. 免责声明与责任限制
38 |
39 | “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
40 |
41 | 6. 语言
42 | “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
43 |
44 | 条款结束
45 |
46 | 如何将木兰宽松许可证,第2版,应用到您的软件
47 |
48 | 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
49 |
50 | 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
51 |
52 | 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
53 |
54 | 3, 请将如下声明文本放入每个源文件的头部注释中。
55 |
56 | Copyright (c) [Year] [name of copyright holder]
57 | [Software Name] is licensed under Mulan PSL v2.
58 | You can use this software according to the terms and conditions of the Mulan PSL v2.
59 | You may obtain a copy of Mulan PSL v2 at:
60 | http://license.coscl.org.cn/MulanPSL2
61 | THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
62 | See the Mulan PSL v2 for more details.
63 |
64 |
65 | Mulan Permissive Software License,Version 2
66 |
67 | Mulan Permissive Software License,Version 2 (Mulan PSL v2)
68 | January 2020 http://license.coscl.org.cn/MulanPSL2
69 |
70 | Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
71 |
72 | 0. Definition
73 |
74 | Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
75 |
76 | Contribution means the copyrightable work licensed by a particular Contributor under this License.
77 |
78 | Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
79 |
80 | Legal Entity means the entity making a Contribution and all its Affiliates.
81 |
82 | Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
83 |
84 | 1. Grant of Copyright License
85 |
86 | Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
87 |
88 | 2. Grant of Patent License
89 |
90 | Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
91 |
92 | 3. No Trademark License
93 |
94 | No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4.
95 |
96 | 4. Distribution Restriction
97 |
98 | You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
99 |
100 | 5. Disclaimer of Warranty and Limitation of Liability
101 |
102 | THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
103 |
104 | 6. Language
105 |
106 | THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
107 |
108 | END OF THE TERMS AND CONDITIONS
109 |
110 | How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software
111 |
112 | To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
113 |
114 | i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
115 |
116 | ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
117 |
118 | iii Attach the statement to the appropriate annotated syntax at the beginning of each source file.
119 |
120 |
121 | Copyright (c) [Year] [name of copyright holder]
122 | [Software Name] is licensed under Mulan PSL v2.
123 | You can use this software according to the terms and conditions of the Mulan PSL v2.
124 | You may obtain a copy of Mulan PSL v2 at:
125 | http://license.coscl.org.cn/MulanPSL2
126 | THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
127 | See the Mulan PSL v2 for more details.
128 |
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 |
2 | 本项目为2021年自己从零到一写出来的简易RTOS系统,目的是为了能更加深入的学习RTOS系统及底层运行的逻辑,项目命名为"LinRTOS",为什么会取这个名字呢?
3 |
4 | LinRTOS开发基于MDK平台,目前工程工程自动适配Cortex M0/M3/M4,通过软件验证过所有的功能模块均正常工作
5 |
6 | ---
7 | ## 参考说明
8 | 写该系统主要参考的有两个知名的RTOS框架:为[FreeRTOS](https://freertos.org/RTOS.html)和[RT-Thread](https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/README),FreeRTOS从远源码角度进行学习的,RT-Thread从Api的命名及系统框架结构上进行了一定借鉴。
9 |
10 | 这里想对国内的RT-Thread做定义说明,都知道老牌FreeRTOS是免费商业使用,其实RT-Thread也是可免费商业使用,只是RT-Thread有扩展的增值服务才需要进行收费,RT-Thread相对FreeRTOS来说有一个很好的有点,就是有大量的官方中文文档可以进行学习和参考。
11 | - github master代码仓上你能看到的都是开源、免费的,可以免费商用
12 | ---
13 | ## LinRTOS命名
14 | 函数命名规则主要参照FreeRTOS:
15 |
16 | ### **变量名**
17 |
18 | 定义变量的时候往往会把变量的类型当作前缀加在变量上,这样的好处是让用户一看到这个变量就知道该变量的类型:
19 | - c : char 型变量.
20 | - s : short 型变量.
21 | - l : long型变量.
22 | - x : portBASE_TYPE类型变量,数据结构,任务句柄,队列句柄等定义的变量名.
23 | - u : 无符号型的前面.
24 | - p : 指针变量的前面.
25 |
26 | 例:当我们定义一个无符号的 char 型变量的时候会加一个 uc 前缀,当定义一个char 型的指针变量的时候会有一个 pc 前缀。
27 |
28 | ### **函数名**
29 |
30 | 函数名包含了函数返回值的类型、函数所在的文件名和函数的功能,如果是私有的函数则会加一个 prv(private)的前缀。
31 |
32 | 在函数名中加入了函数所在的文件名,这大大的帮助了用户提高寻找函数定义的效率和了解函数作用的目的,具体的举例如下:
33 |
34 | - vTaskPrioritySet()函数的返回值为 void 型,在 task.c这个文件中定义。
35 | - xQueueReceive()函数的返回值为 portBASE_TYPE 型,在 queue.c 这个文件中定义。
36 | - vSemaphoreCreateBinary()函数的返回值为 void 型,在 semphr.h 这个文件中定义。
37 |
38 | ---
39 |
40 | ## LinRTOS系统框架
41 | 这里称系统架构其实也不是很合理的,因为LinRTOS只提供了在ARM的架构之上的内核层面的任务调度和消息处理和对硬件进行一定的抽象,内核层上面的组件框架和在上层的业务逻辑层是没有去实现的。
42 |
43 | 虽然目前只实现了内核层部分,想要这个系统更加的完善,还需要添加部分必要的组件和安全的框架进去,这里先给自己埋一个坑吧,后面有机会在来进行进一步的完善。
44 |
45 | 
46 |
47 | ## LinRTOS Kernel
48 | ### 工程文件结构
49 |
50 | ├─Code
51 | │ ├─LinRTOS Kernel // RTOS内核文件
52 | │ │ ├─inc // 内核头文件
53 | │ │ └─portable // RTOS调用的硬件配置
54 | │ │ └─RVDS
55 | | | src // RTOS源文件
56 | │ ├─RTE
57 | │ │ ├─Device // 硬件支持包
58 | │ └─User // 用户目录
59 |
60 | ### Kernel框架
61 | 
62 |
63 | 对RTOS来说,任务调度是最核心的东西,这里面涉及到优先级调度算法,调度逻辑,及系统运行在硬件平台的一些基础知识点,上面说的所有的东西都是在Task.c和Task.h中来实现的。所以,Task也是RTOS中最重要的文件之一。
64 |
65 |
66 | LinRTOS Config: 整个系统的配置文件,可以配置需要使用那些RTOS资源,优先级的个数等。
67 |
68 | Task: RTOS最核心的模块,负责具体的任务调度的实现。
69 |
70 | Event:事假核心文件,提供给各种类型的消息,信号公用的模块。
71 | - Sem: 信号量: 可用于任务的同步和计数,提供增删改查功能。
72 | - Mutex: 互斥信号量,用于任务的同步,具有互斥属性(用了来防止优先级翻转问题),提供增删改查功能。
73 | - EventGroup: 事件标志组,用了多任务之间的同步,和信号量不同的是,可以实现一对多,多对多的同步。 即一个任务可以等待多个事件的发生:可以是任意一个事件发生时唤醒任务进行事件处理;也可以是几个事件都发生后才唤醒任务进行事件处理。同样,也可以是多个任务同步多个事件。
74 | - Mailbox: 邮箱通讯,同于任务间数据信息传输,提供增删改查功能。
75 |
76 | Scheduler: 操作硬件相关的任务中断,为任务的切换提供入口。
77 |
78 | Mempool:为任务分配空间资源的管理文件。
79 |
80 | Lisa: 提供最基础的双向通用列表,可以进行增删改查。
81 |
82 | Bitmap: 优先级调度算法的数组遍历映射文件。
83 |
84 | Timer: 给真个RTOS计数的模块。
85 |
86 | ---
87 |
88 | **任务调度的一些问题:**
89 |
90 | - 优先级调度算法
91 |
92 | 首先说一说任务优先级调度算法吧,优先级调度算法有很多,在FreeRTOS,UCos2/3实现的都不太一样有些算法为了提高效率会用到一些硬件的资源来实现。
93 |
94 | 在这里实现了简单的比较按位优先级查找算法,通过纯软件实现的,大概的原理是用一个uint32_t的整型变量,其中的每一位表示一个或者多个任务的优先级,用0表示没有任务占用,1表示有任务占用,假定最低位优先级最高,优先级查找算法就是从最低位开始逐个遍历找到第一个不为了零的bit,然后再找到对应bit的任务是什么就实现了当前优先级最高的任务查找,这是不是很简单呢。
95 |
96 | 当然不是,虽然只实现很简单的一个优先级算法,如果采用最原始的遍历方法是很低效的,对于优先级不多的系统来说还好,如果是想把系统的优先级数提高到更多,这种逐个遍历的方法就有些不适用,每一次遍历就浪费了大量时间; 所以这里采用了一种数组查表法的方法,按一定规律事先填好表格里面的数据,通过查表法就可以直接返回对应任务的优先级,(从算法的两个维度分析:时间复杂度和空间复杂度)这两相当于是采用了一点空间来换取时间上的缩减,这对如今比较打的Flash的MCU来说是很值得的。
97 |
98 | - 上下文切换
99 |
100 | 上下为切换这里也叫称任务切换,即从A任务跳转到B任务或者从B任务调回A任务的过程,设立涉及到的就是一个专业的术语“保存现场和恢复现场”
101 | 保存现场:即保存当前程序运行在该处的一些现场资源,局部的变量值,运行的位置等,以便于在程序能跳转回来继续运行之前的状态。
102 |
103 |
104 |
--------------------------------------------------------------------------------