├── .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 | ![整体框架](./Image/整体框图.png) 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 | ![Kelnel框架](./Image/LinRTOS_Kernel.png) 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 | --------------------------------------------------------------------------------