From e160a67ad6ab279711ba99478108858da4f25880 Mon Sep 17 00:00:00 2001 From: Janos Magasrevy Date: Fri, 28 Feb 2020 17:54:21 -0500 Subject: [PATCH] Initial commit --- Cfg/Template/app_cfg.h | 99 + Cfg/Template/app_hooks.c | 253 ++ Cfg/Template/os_cfg.h | 154 ++ Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu.h | 111 + .../68HC12/DG128A/NonPaged/COSMIC/os_cpu_a.s | 325 +++ .../68HC12/DG128A/NonPaged/COSMIC/os_cpu_c.c | 253 ++ Ports/68HC12/DG128A/NonPaged/COSMIC/os_dbg.c | 265 ++ Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU.h | 111 + Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU_C.C | 253 ++ Ports/68HC12/DG128A/NonPaged/IAR/os_cpu_a.s33 | 264 ++ Ports/68HC12/DG128A/NonPaged/IAR/os_dbg.c | 265 ++ Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU.h | 108 + Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_A.S | 345 +++ Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_C.C | 259 ++ Ports/68HC12/DG128A/Paged/COSMIC/os_dbg.c | 172 ++ .../DG128A/Paged/CodeWarrior/Ex1/includes.h | 49 + .../DG128A/Paged/CodeWarrior/Ex1/os_cfg.h | 130 + .../DG128A/Paged/CodeWarrior/Ex1/test.c | 239 ++ .../DG128A/Paged/CodeWarrior/Ex1/vectors.c | 159 ++ .../68HC12/DG128A/Paged/CodeWarrior/os_cpu.h | 108 + .../DG128A/Paged/CodeWarrior/os_cpu_a.s | 347 +++ .../DG128A/Paged/CodeWarrior/os_cpu_c.c | 259 ++ .../68HC12/DG128A/Paged/CodeWarrior/os_dbg.c | 264 ++ Ports/68HC12/DG128A/Paged/IAR/os_cpu.h | 111 + Ports/68HC12/DG128A/Paged/IAR/os_cpu_a.s33 | 286 +++ Ports/68HC12/DG128A/Paged/IAR/os_cpu_c.c | 258 ++ Ports/68HC12/DG128A/Paged/IAR/os_dbg.c | 265 ++ Ports/68HC12/NonPaged/COSMIC/os_cpu.h | 110 + Ports/68HC12/NonPaged/COSMIC/os_cpu_a.s | 220 ++ Ports/68HC12/NonPaged/COSMIC/os_cpu_c.c | 265 ++ Ports/68HC12/NonPaged/COSMIC/os_dbg.c | 266 ++ Ports/68HC12/Paged/COSMIC/os_cpu.h | 111 + Ports/68HC12/Paged/COSMIC/os_cpu_a.S | 345 +++ Ports/68HC12/Paged/COSMIC/os_cpu_c.c | 259 ++ Ports/68HC12/Paged/COSMIC/os_dbg.c | 265 ++ Ports/78K0/IAR/os_cpu.h | 135 ++ Ports/78K0/IAR/os_cpu_a.s26 | 264 ++ Ports/78K0/IAR/os_cpu_c.c | 307 +++ Ports/78K0/IAR/os_dbg.c | 316 +++ Ports/78K0R/IAR/os_cpu.h | 135 ++ Ports/78K0R/IAR/os_cpu_a.asm | 250 ++ Ports/78K0R/IAR/os_cpu_c.c | 302 +++ Ports/78K0R/IAR/os_dbg.c | 316 +++ Ports/80186/DOS/L/BC45/os_cpu.h | 150 ++ Ports/80186/DOS/L/BC45/os_cpu_a.asm | 297 +++ Ports/80186/DOS/L/BC45/os_cpu_c.c | 340 +++ Ports/80186/DOS/L/BC45/os_dbg.c | 265 ++ Ports/80x86/DOS/L-FP-I/BC45/os_cpu.h | 144 ++ Ports/80x86/DOS/L-FP-I/BC45/os_cpu_a.asm | 412 ++++ Ports/80x86/DOS/L-FP-I/BC45/os_cpu_c.c | 368 +++ Ports/80x86/DOS/L-FP-I/BC45/os_dbg.c | 265 ++ Ports/80x86/DOS/L-FP/BC45/os_cpu.h | 123 + Ports/80x86/DOS/L-FP/BC45/os_cpu_a.asm | 391 +++ Ports/80x86/DOS/L-FP/BC45/os_cpu_c.c | 367 +++ Ports/80x86/DOS/L-FP/BC45/os_dbg.c | 265 ++ Ports/80x86/DOS/L-I/BC45/os_cpu.h | 140 ++ Ports/80x86/DOS/L-I/BC45/os_cpu_a.asm | 345 +++ Ports/80x86/DOS/L-I/BC45/os_cpu_c.c | 341 +++ Ports/80x86/DOS/L-I/BC45/os_dbg.c | 267 ++ Ports/80x86/DOS/L/BC45/os_cpu.h | 142 ++ Ports/80x86/DOS/L/BC45/os_cpu_a.asm | 325 +++ Ports/80x86/DOS/L/BC45/os_cpu_c.c | 340 +++ Ports/80x86/DOS/L/BC45/os_dbg.c | 265 ++ Ports/ARC/EM6/MetaWare/os_cpu.h | 149 ++ Ports/ARC/EM6/MetaWare/os_cpu_a.s | 630 +++++ Ports/ARC/EM6/MetaWare/os_cpu_c.c | 415 ++++ Ports/ARC/EM6/MetaWare/os_dbg.c | 316 +++ Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu.h | 306 +++ .../ARMv7-A/ARM/os_cpu_a_vfp-d16.s | 719 ++++++ .../ARMv7-A/ARM/os_cpu_a_vfp-d32.s | 721 ++++++ .../ARMv7-A/ARM/os_cpu_a_vfp-none.s | 684 ++++++ Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu.h | 306 +++ .../ARMv7-A/CCS/os_cpu_a_vfp-d16.asm | 726 ++++++ .../ARMv7-A/CCS/os_cpu_a_vfp-d32.asm | 729 ++++++ .../ARMv7-A/CCS/os_cpu_a_vfp-none.asm | 694 ++++++ Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu.h | 307 +++ .../ARMv7-A/GNU/os_cpu_a_vfp-d16.S | 746 ++++++ .../ARMv7-A/GNU/os_cpu_a_vfp-d32.S | 749 ++++++ .../ARMv7-A/GNU/os_cpu_a_vfp-none.S | 713 ++++++ Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu.h | 307 +++ .../ARMv7-A/IAR/os_cpu_a_vfp-d16.asm | 717 ++++++ .../ARMv7-A/IAR/os_cpu_a_vfp-d32.asm | 719 ++++++ .../ARMv7-A/IAR/os_cpu_a_vfp-none.asm | 684 ++++++ Ports/ARM-Cortex-A/ARMv7-A/os_cpu_c.c | 624 +++++ Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu.h | 223 ++ Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu_a.S | 496 ++++ Ports/ARM-Cortex-A/ARMv8-A/os_cpu_c.c | 510 ++++ Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu.h | 207 ++ Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu_a.asm | 281 +++ Ports/ARM-Cortex-M/ARMv6-M/ARM/os_dbg.c | 325 +++ Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu.h | 207 ++ Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu_a.s | 286 +++ Ports/ARM-Cortex-M/ARMv6-M/GNU/os_dbg.c | 325 +++ Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu.h | 207 ++ Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu_a.asm | 278 +++ Ports/ARM-Cortex-M/ARMv6-M/IAR/os_dbg.c | 325 +++ Ports/ARM-Cortex-M/ARMv6-M/os_cpu_c.c | 543 +++++ Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu.h | 236 ++ Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm | 369 +++ Ports/ARM-Cortex-M/ARMv7-M/ARM/os_dbg.c | 328 +++ Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu.h | 236 ++ Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu_a.asm | 389 +++ Ports/ARM-Cortex-M/ARMv7-M/CCS/os_dbg.c | 328 +++ Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu.h | 236 ++ Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu_a.S | 385 +++ Ports/ARM-Cortex-M/ARMv7-M/GNU/os_dbg.c | 328 +++ Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu.h | 236 ++ Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu_a.asm | 361 +++ Ports/ARM-Cortex-M/ARMv7-M/IAR/os_dbg.c | 328 +++ Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c | 727 ++++++ Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu.h | 300 +++ .../ARMv7-R/ARM/os_cpu_a_vfp-d16.s | 719 ++++++ .../ARMv7-R/ARM/os_cpu_a_vfp-none.s | 684 ++++++ Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu.h | 300 +++ .../ARMv7-R/CCS/os_cpu_a_vfp-d16.asm | 726 ++++++ .../ARMv7-R/CCS/os_cpu_a_vfp-none.asm | 694 ++++++ Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu.h | 302 +++ .../ARMv7-R/GNU/os_cpu_a_vfp-d16.S | 746 ++++++ .../ARMv7-R/GNU/os_cpu_a_vfp-none.S | 712 ++++++ Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu.h | 302 +++ .../ARMv7-R/IAR/os_cpu_a_vfp-d16.asm | 718 ++++++ .../ARMv7-R/IAR/os_cpu_a_vfp-none.asm | 685 ++++++ Ports/ARM-Cortex-R/ARMv7-R/os_cpu_c.c | 624 +++++ Ports/ARM/Generic/GNU/os_cpu.h | 242 ++ Ports/ARM/Generic/GNU/os_cpu_a.s | 846 +++++++ Ports/ARM/Generic/GNU/os_cpu_c.c | 596 +++++ Ports/ARM/Generic/GNU/os_cpu_fpu_a.s | 81 + Ports/ARM/Generic/GNU/os_dbg.c | 321 +++ Ports/ARM/Generic/IAR/os_cpu.h | 250 ++ Ports/ARM/Generic/IAR/os_cpu_a.asm | 838 +++++++ Ports/ARM/Generic/IAR/os_cpu_c.c | 639 +++++ Ports/ARM/Generic/IAR/os_cpu_fpu_a.asm | 81 + Ports/ARM/Generic/IAR/os_dbg.c | 321 +++ Ports/ARM/Generic/IAR/os_dcc.c | 230 ++ Ports/ARM/Generic/RealView/os_cpu.h | 246 ++ Ports/ARM/Generic/RealView/os_cpu_a.asm | 846 +++++++ Ports/ARM/Generic/RealView/os_cpu_c.c | 635 +++++ Ports/ARM/Generic/RealView/os_cpu_fpu_a.asm | 85 + Ports/ARM/Generic/RealView/os_dbg.c | 326 +++ Ports/ARM7/AT91/ARM/IAR/os_cpu.h | 113 + Ports/ARM7/AT91/ARM/IAR/os_cpu_a.s | 262 ++ Ports/ARM7/AT91/ARM/IAR/os_cpu_c.c | 280 +++ Ports/ARM7/AT91/ARM/IAR/os_dbg.c | 268 ++ Ports/ARM7/AT91/Thumb/IAR/os_cpu.h | 105 + Ports/ARM7/AT91/Thumb/IAR/os_cpu_a.s | 338 +++ Ports/ARM7/AT91/Thumb/IAR/os_cpu_c.c | 252 ++ Ports/ARM7/AT91/Thumb/IAR/os_dbg.c | 268 ++ Ports/ARM7/Generic/ARM/IAR/os_cpu.h | 128 + Ports/ARM7/Generic/ARM/IAR/os_cpu_a.s | 269 ++ Ports/ARM7/Generic/ARM/IAR/os_cpu_c.c | 346 +++ Ports/ARM7/Generic/ARM/IAR/os_dbg.c | 268 ++ .../LH79520/ARM/GNU-XTools/Source/os_cpu.h | 115 + .../LH79520/ARM/GNU-XTools/Source/os_cpu_a.s | 254 ++ .../LH79520/ARM/GNU-XTools/Source/os_cpu_c.c | 280 +++ .../LH79520/ARM/GNU-XTools/Source/os_dbg.c | 270 +++ Ports/ARM7/LH79520/ARM/IAR/os_cpu.h | 140 ++ Ports/ARM7/LH79520/ARM/IAR/os_cpu_a.s | 290 +++ Ports/ARM7/LH79520/ARM/IAR/os_cpu_c.c | 334 +++ Ports/ARM7/LH79520/ARM/IAR/os_dbg.c | 268 ++ .../AT91RM9200/ARM/GNU-XTools/Source/os_cpu.h | 115 + .../ARM/GNU-XTools/Source/os_cpu_a.s | 254 ++ .../ARM/GNU-XTools/Source/os_cpu_c.c | 280 +++ .../AT91RM9200/ARM/GNU-XTools/Source/os_dbg.c | 270 +++ Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu.h | 140 ++ Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_a.s | 290 +++ Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_c.c | 334 +++ Ports/ARM9/AT91RM9200/ARM/IAR/os_dbg.c | 268 ++ Ports/AVR/ATmega128/IAR/os_cpu.h | 135 ++ Ports/AVR/ATmega128/IAR/os_cpu_a.s90 | 275 +++ Ports/AVR/ATmega128/IAR/os_cpu_c.c | 358 +++ Ports/AVR/ATmega128/IAR/os_cpu_i.s90 | 155 ++ Ports/AVR/ATmega128/IAR/os_dbg.c | 269 ++ Ports/AVR/ATmega128/ICC/os_cpu.h | 126 + Ports/AVR/ATmega128/ICC/os_cpu_a.s | 236 ++ Ports/AVR/ATmega128/ICC/os_cpu_c.c | 332 +++ Ports/AVR/ATmega128/ICC/os_cpu_i.h | 154 ++ Ports/AVR/ATmega128/ICC/os_dbg.c | 291 +++ Ports/AVR/ATmega256/IAR/os_cpu.h | 135 ++ Ports/AVR/ATmega256/IAR/os_cpu_a.s90 | 284 +++ Ports/AVR/ATmega256/IAR/os_cpu_c.c | 360 +++ Ports/AVR/ATmega256/IAR/os_cpu_i.s90 | 159 ++ Ports/AVR/ATmega256/IAR/os_dbg.c | 291 +++ Ports/AVR/ATmega256/ICC/os_cpu.h | 126 + Ports/AVR/ATmega256/ICC/os_cpu_a.s | 238 ++ Ports/AVR/ATmega256/ICC/os_cpu_c.c | 353 +++ Ports/AVR/ATmega256/ICC/os_cpu_i.h | 159 ++ Ports/AVR/ATmega256/ICC/os_dbg.c | 291 +++ Ports/AVR/ATxmega128/GNU/os_cpu.h | 126 + Ports/AVR/ATxmega128/GNU/os_cpu_a.s | 251 ++ Ports/AVR/ATxmega128/GNU/os_cpu_c.c | 357 +++ Ports/AVR/ATxmega128/GNU/os_cpu_i.h | 212 ++ Ports/AVR/ATxmega128/GNU/os_dbg.c | 293 +++ Ports/AVR/ATxmega128/IAR/os_cpu.h | 93 + Ports/AVR/ATxmega128/IAR/os_cpu_a.s90 | 283 +++ Ports/AVR/ATxmega128/IAR/os_cpu_c.c | 366 +++ Ports/AVR/ATxmega128/IAR/os_cpu_i.s90 | 178 ++ Ports/AVR/ATxmega128/IAR/os_dbg.c | 318 +++ Ports/AVR/Generic/IAR/os_cpu.h | 135 ++ Ports/AVR/Generic/IAR/os_cpu_a.s90 | 423 ++++ Ports/AVR/Generic/IAR/os_cpu_c.c | 332 +++ Ports/AVR/Generic/IAR/os_dbg.c | 269 ++ Ports/AVR32/AP7000/GNU/os_cpu.h | 94 + Ports/AVR32/AP7000/GNU/os_cpu_a.s | 411 ++++ Ports/AVR32/AP7000/GNU/os_cpu_c.c | 392 +++ Ports/AVR32/AP7000/GNU/os_dbg.c | 317 +++ Ports/AVR32/AP7000/IAR/os_cpu.h | 94 + Ports/AVR32/AP7000/IAR/os_cpu_a.asm | 412 ++++ Ports/AVR32/AP7000/IAR/os_cpu_c.c | 392 +++ Ports/AVR32/AP7000/IAR/os_dbg.c | 317 +++ Ports/AVR32/UC3/GNU/os_cpu.h | 86 + Ports/AVR32/UC3/GNU/os_cpu_a.s | 319 +++ Ports/AVR32/UC3/GNU/os_cpu_c.c | 416 ++++ Ports/AVR32/UC3/GNU/os_dbg.c | 317 +++ Ports/AVR32/UC3/IAR/os_cpu.h | 88 + Ports/AVR32/UC3/IAR/os_cpu_a.asm | 319 +++ Ports/AVR32/UC3/IAR/os_cpu_c.c | 412 ++++ Ports/AVR32/UC3/IAR/os_dbg.c | 317 +++ Ports/Blackfin/VDSP++/os_cpu.h | 148 ++ Ports/Blackfin/VDSP++/os_cpu_a.asm | 945 ++++++++ Ports/Blackfin/VDSP++/os_cpu_c.c | 522 ++++ Ports/C28x/Generic/CCS/os_cpu.h | 195 ++ Ports/C28x/Generic/CCS/os_cpu_a.asm | 282 +++ Ports/C28x/Generic/CCS/os_cpu_c.c | 372 +++ Ports/C28x/Generic/CCS/os_cpu_i.asm | 109 + Ports/C28x/Generic/CCS/os_dbg.c | 320 +++ .../Generic/CodeWarrior/os_cpu.h | 112 + .../Generic/CodeWarrior/os_cpu_a.asm | 286 +++ .../Generic/CodeWarrior/os_cpu_c.c | 348 +++ .../Generic/CodeWarrior/os_cpu_i.asm | 63 + .../Generic/CodeWarrior/os_dbg.c | 317 +++ Ports/ColdFire/5272/GNU/os_cpu.h | 140 ++ Ports/ColdFire/5272/GNU/os_cpu_a.s | 393 +++ Ports/ColdFire/5272/GNU/os_cpu_c.c | 333 +++ .../Generic/CW_For_Microcontrollers/os_cpu.h | 125 + .../CW_For_Microcontrollers/os_cpu_a.asm | 308 +++ .../CW_For_Microcontrollers/os_cpu_c.c | 344 +++ .../Generic/CW_For_Microcontrollers/os_dbg.c | 317 +++ Ports/ColdFire/Generic/CodeWarrior/os_cpu.h | 112 + .../ColdFire/Generic/CodeWarrior/os_cpu_a.asm | 264 ++ Ports/ColdFire/Generic/CodeWarrior/os_cpu_c.c | 337 +++ .../ColdFire/Generic/CodeWarrior/os_cpu_i.asm | 40 + Ports/ColdFire/Generic/CodeWarrior/os_dbg.c | 317 +++ Ports/ColdFire/Generic/IAR/os_cpu.h | 112 + Ports/ColdFire/Generic/IAR/os_cpu_a.asm | 263 ++ Ports/ColdFire/Generic/IAR/os_cpu_c.c | 337 +++ Ports/ColdFire/Generic/IAR/os_cpu_i.asm | 40 + Ports/ColdFire/Generic/IAR/os_dbg.c | 317 +++ Ports/DSP56F8xxx/CodeWarrior/OS_CPU.ASM | 371 +++ Ports/DSP56F8xxx/CodeWarrior/OS_CPU.C | 343 +++ Ports/DSP56F8xxx/CodeWarrior/OS_CPU.H | 159 ++ Ports/DSP56F8xxx/CodeWarrior/os_portasm.h | 61 + Ports/FR/Softune/os_cpu.h | 120 + Ports/FR/Softune/os_cpu_a.asm | 203 ++ Ports/FR/Softune/os_cpu_c.c | 291 +++ Ports/FR/Softune/os_cpu_i.asm | 42 + Ports/FR/Softune/os_dbg.c | 269 ++ .../H8-38024/EDK38024/uCOS-II/os_core.c | 969 ++++++++ .../H8-38024/EDK38024/uCOS-II/os_task.c | 110 + .../H8-38024/EDK38024/uCOS-II/os_time.c | 67 + .../H8-38024/EDK38024/uCOS-II/ucos_ii.h | 1297 ++++++++++ Ports/H8-300L/Normal/HEW/os_cpu.h | 135 ++ Ports/H8-300L/Normal/HEW/os_cpu_a.src | 289 +++ Ports/H8-300L/Normal/HEW/os_cpu_c.c | 255 ++ Ports/H8-300L/Normal/HEW/os_dbg.c | 316 +++ Ports/H8-300L/Normal/IAR/os_cpu.h | 137 ++ Ports/H8-300L/Normal/IAR/os_cpu_a.s37 | 288 +++ Ports/H8-300L/Normal/IAR/os_cpu_c.c | 255 ++ Ports/H8-300L/Normal/IAR/os_dbg.c | 316 +++ Ports/H8S/Adv/HEW/os_cpu.h | 121 + Ports/H8S/Adv/HEW/os_cpu_a.src | 281 +++ Ports/H8S/Adv/HEW/os_cpu_c.c | 308 +++ Ports/H8S/Adv/HEW/os_dbg.c | 316 +++ Ports/H8S/Adv/IAR/os_cpu.h | 125 + Ports/H8S/Adv/IAR/os_cpu_a.asm | 301 +++ Ports/H8S/Adv/IAR/os_cpu_a.s37 | 301 +++ Ports/H8S/Adv/IAR/os_cpu_c.c | 258 ++ Ports/H8S/Adv/IAR/os_dbg.c | 271 +++ Ports/H8S/H8S-26xx/Adv/IAR/os_cpu.h | 115 + Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_a.s37 | 337 +++ Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_c.c | 258 ++ Ports/H8S/H8S-26xx/Adv/IAR/os_dbg.c | 271 +++ Ports/H8SX/Adv/HEW/os_cpu.h | 121 + Ports/H8SX/Adv/HEW/os_cpu_a.src | 281 +++ Ports/H8SX/Adv/HEW/os_cpu_c.c | 308 +++ Ports/H8SX/Adv/HEW/os_dbg.c | 316 +++ Ports/H8SX/Adv/IAR/os_cpu.h | 125 + Ports/H8SX/Adv/IAR/os_cpu_a.s37 | 299 +++ Ports/H8SX/Adv/IAR/os_cpu_c.c | 318 +++ Ports/H8SX/Adv/IAR/os_dbg.c | 271 +++ Ports/HCS12/NonPaged/CodeWarrior/OS_CPU.h | 119 + Ports/HCS12/NonPaged/CodeWarrior/OS_CPU_C.C | 293 +++ Ports/HCS12/NonPaged/CodeWarrior/os_cpu_a.asm | 236 ++ .../Paged/CodeWarrior/SerialMonitor/os_cpu.h | 145 ++ .../CodeWarrior/SerialMonitor/os_cpu_a.s | 307 +++ .../CodeWarrior/SerialMonitor/os_cpu_c.c | 365 +++ Ports/HCS12/Paged/CodeWarrior/os_cpu.h | 118 + Ports/HCS12/Paged/CodeWarrior/os_cpu_a.s | 249 ++ Ports/HCS12/Paged/CodeWarrior/os_cpu_c.c | 354 +++ Ports/HCS12X/Paged/Codewarrior/os_cpu.h | 128 + Ports/HCS12X/Paged/Codewarrior/os_cpu_a.s | 321 +++ Ports/HCS12X/Paged/Codewarrior/os_cpu_c.c | 309 +++ Ports/HCS12X/Paged/Cosmic/os_cpu.h | 113 + Ports/HCS12X/Paged/Cosmic/os_cpu_a.S | 407 ++++ Ports/HCS12X/Paged/Cosmic/os_cpu_c.c | 294 +++ Ports/HCS12X/Paged/Cosmic/os_dbg.c | 266 ++ Ports/LatticeMico32/GNU/MicroC_malloc_lock.c | 79 + Ports/LatticeMico32/GNU/MicroC_malloc_lock.h | 18 + Ports/LatticeMico32/GNU/os_cpu.h | 110 + Ports/LatticeMico32/GNU/os_cpu_a.s | 264 ++ Ports/LatticeMico32/GNU/os_cpu_c.c | 303 +++ Ports/LatticeMico32/GNU/os_dbg.c | 305 +++ Ports/M14K/CodeSourcery/os_cpu.h | 113 + Ports/M14K/CodeSourcery/os_cpu_a.S | 841 +++++++ Ports/M14K/CodeSourcery/os_cpu_c.c | 369 +++ Ports/M16C/M16C60/HEW/os_cpu.h | 111 + Ports/M16C/M16C60/HEW/os_cpu_a.a30 | 200 ++ Ports/M16C/M16C60/HEW/os_cpu_c.c | 318 +++ Ports/M16C/M16C60/HEW/os_dbg.c | 273 +++ Ports/M16C/M16C60/IAR/os_cpu.h | 111 + Ports/M16C/M16C60/IAR/os_cpu_a.asm | 198 ++ Ports/M16C/M16C60/IAR/os_cpu_c.c | 319 +++ Ports/M16C/M16C60/IAR/os_dbg.c | 273 +++ Ports/M16C/Tiny/HEW/os_cpu.h | 111 + Ports/M16C/Tiny/HEW/os_cpu_a.a30 | 201 ++ Ports/M16C/Tiny/HEW/os_cpu_c.c | 304 +++ Ports/M16C/Tiny/HEW/os_dbg.c | 273 +++ Ports/M16C/Tiny/IAR/os_cpu.h | 111 + Ports/M16C/Tiny/IAR/os_cpu_a.asm | 199 ++ Ports/M16C/Tiny/IAR/os_cpu_c.c | 303 +++ Ports/M16C/Tiny/IAR/os_dbg.c | 273 +++ Ports/M32C/M16C80/HEW/os_cpu.h | 111 + Ports/M32C/M16C80/HEW/os_cpu_a.a30 | 189 ++ Ports/M32C/M16C80/HEW/os_cpu_c.c | 318 +++ Ports/M32C/M16C80/HEW/os_dbg.c | 271 +++ Ports/M32C/M16C80/IAR/os_cpu.h | 111 + Ports/M32C/M16C80/IAR/os_cpu_a.asm | 199 ++ Ports/M32C/M16C80/IAR/os_cpu_c.c | 318 +++ Ports/M32C/M16C80/IAR/os_dbg.c | 271 +++ Ports/M683xx/68332/COSMIC/os_cpu.h | 147 ++ Ports/M683xx/68332/COSMIC/os_cpu_a.s | 412 ++++ Ports/M683xx/68332/COSMIC/os_cpu_c.c | 271 +++ Ports/M683xx/68332/COSMIC/os_dbg.c | 267 ++ Ports/MC9S08/NonPaged/Codewarrior/OS_CPU.h | 118 + Ports/MC9S08/NonPaged/Codewarrior/os_cpu_a.s | 263 ++ Ports/MC9S08/NonPaged/Codewarrior/os_cpu_c.c | 303 +++ Ports/MC9S08/Paged/Codewarrior/OS_CPU.h | 118 + Ports/MC9S08/Paged/Codewarrior/os_cpu_a.s | 278 +++ Ports/MC9S08/Paged/Codewarrior/os_cpu_c.c | 307 +++ .../MPLAB-PIC32-GCC/os_cpu.h | 106 + .../MPLAB-PIC32-GCC/os_cpu_a.S | 707 ++++++ .../MPLAB-PIC32-GCC/os_cpu_c.c | 321 +++ .../MPLAB-PIC32-GCC/os_dbg.c | 299 +++ Ports/MSP430/IAR/OS_CPU.H | 116 + Ports/MSP430/IAR/Os_cpu_a.s43 | 299 +++ Ports/MSP430/IAR/Os_cpu_c.c | 280 +++ Ports/MSP430/IAR/os_dbg.c | 268 ++ Ports/MSP430X/CCS/MSP430x5xx/os_cpu.h | 128 + Ports/MSP430X/CCS/MSP430x5xx/os_cpu_a.s43 | 318 +++ Ports/MSP430X/CCS/MSP430x5xx/os_cpu_c.c | 280 +++ Ports/MSP430X/CCS/MSP430x5xx/os_dbg.c | 315 +++ Ports/MSP430X/IAR/MSP430x5xx/os_cpu.h | 128 + Ports/MSP430X/IAR/MSP430x5xx/os_cpu_a.s43 | 304 +++ Ports/MSP430X/IAR/MSP430x5xx/os_cpu_c.c | 280 +++ Ports/MSP430X/IAR/MSP430x5xx/os_dbg.c | 317 +++ Ports/MicroBlaze/EDK/Code/includes.h | 32 + Ports/MicroBlaze/EDK/Code/os_cfg.h | 130 + Ports/MicroBlaze/EDK/Code/system.c | 131 + Ports/MicroBlaze/GNU/USE_MSR_INSTR/os_cpu_a.S | 730 ++++++ Ports/MicroBlaze/GNU/os_cpu.h | 108 + Ports/MicroBlaze/GNU/os_cpu_a.S | 744 ++++++ Ports/MicroBlaze/GNU/os_cpu_c.c | 340 +++ Ports/MicroBlaze/GNU/os_dbg.c | 266 ++ Ports/Microchip/PIC24FJ128/C30/os_cpu.h | 94 + Ports/Microchip/PIC24FJ128/C30/os_cpu_a.s | 150 ++ Ports/Microchip/PIC24FJ128/C30/os_cpu_c.c | 349 +++ .../Microchip/PIC24FJ128/C30/os_cpu_util_a.s | 80 + Ports/Microchip/PIC24FJ128/C30/os_dbg.c | 296 +++ Ports/Microchip/PIC24FJ128/DSPICC/os_cpu.h | 96 + Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_a.as | 163 ++ Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_c.c | 350 +++ .../PIC24FJ128/DSPICC/os_cpu_util_a.as | 93 + Ports/Microchip/PIC24FJ128/DSPICC/os_dbg.c | 296 +++ Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu.h | 95 + .../Microchip/PIC24FJ128/ICCDSPIC/os_cpu_a.s | 152 ++ .../Microchip/PIC24FJ128/ICCDSPIC/os_cpu_c.c | 353 +++ .../PIC24FJ128/ICCDSPIC/os_cpu_util_a.s | 81 + Ports/Microchip/PIC24FJ128/ICCDSPIC/os_dbg.c | 296 +++ Ports/Microchip/PIC30F6014/C30/os_cpu.h | 99 + Ports/Microchip/PIC30F6014/C30/os_cpu_a.s | 150 ++ Ports/Microchip/PIC30F6014/C30/os_cpu_c.c | 462 ++++ .../Microchip/PIC30F6014/C30/os_cpu_util_a.s | 102 + Ports/Microchip/PIC33FJ256/C30/os_cpu.h | 95 + Ports/Microchip/PIC33FJ256/C30/os_cpu_a.s | 150 ++ Ports/Microchip/PIC33FJ256/C30/os_cpu_c.c | 445 ++++ .../Microchip/PIC33FJ256/C30/os_cpu_util_a.s | 103 + Ports/Microchip/PIC33FJ256/DSPICC/os_cpu.h | 95 + Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_a.as | 161 ++ Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_c.c | 373 +++ .../PIC33FJ256/DSPICC/os_cpu_util_a.as | 112 + Ports/Microchip/PIC33FJ256/DSPICC/os_dbg.c | 296 +++ Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu.h | 95 + .../PIC33FJ256/ICCDSPIC/os_cpu_a.s59 | 151 ++ .../Microchip/PIC33FJ256/ICCDSPIC/os_cpu_c.c | 373 +++ .../PIC33FJ256/ICCDSPIC/os_cpu_util_a.s59 | 107 + Ports/Microchip/PIC33FJ256/ICCDSPIC/os_dbg.c | 296 +++ Ports/PPC405/GNU/os_cpu.h | 104 + Ports/PPC405/GNU/os_cpu_a.S | 1004 ++++++++ Ports/PPC405/GNU/os_cpu_c.c | 328 +++ Ports/PPC405/GNU/os_dbg.c | 266 ++ Ports/PPC440/GNU/os_cpu.h | 101 + Ports/PPC440/GNU/os_cpu_a.S | 1090 +++++++++ Ports/PPC440/GNU/os_cpu_c.c | 345 +++ Ports/PPC440/GNU/os_dbg.c | 315 +++ .../PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu.h | 129 + .../MPC55xx-VLE/CodeWarrior/os_cpu_a.inc | 335 +++ .../MPC55xx-VLE/CodeWarrior/os_cpu_a.s | 266 ++ .../MPC55xx-VLE/CodeWarrior/os_cpu_c.c | 453 ++++ .../PowerPC/MPC55xx-VLE/CodeWarrior/os_dbg.c | 317 +++ Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu.h | 129 + Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.inc | 335 +++ Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.s | 266 ++ Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_c.c | 454 ++++ Ports/PowerPC/MPC55xx-VLE/GNU/os_dbg.c | 317 +++ Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu.h | 129 + .../PowerPC/MPC55xx/CodeWarrior/os_cpu_a.inc | 334 +++ Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.s | 264 ++ Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_c.c | 453 ++++ Ports/PowerPC/MPC55xx/CodeWarrior/os_dbg.c | 317 +++ Ports/PowerPC/MPC55xx/GNU/os_cpu.h | 129 + Ports/PowerPC/MPC55xx/GNU/os_cpu_a.inc | 334 +++ Ports/PowerPC/MPC55xx/GNU/os_cpu_a.s | 264 ++ Ports/PowerPC/MPC55xx/GNU/os_cpu_c.c | 454 ++++ Ports/PowerPC/MPC55xx/GNU/os_dbg.c | 317 +++ .../PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu.h | 146 ++ .../MPC56xx-VLE/CodeWarrior/os_cpu_a.inc | 331 +++ .../MPC56xx-VLE/CodeWarrior/os_cpu_a.s | 306 +++ .../MPC56xx-VLE/CodeWarrior/os_cpu_c.c | 464 ++++ .../PowerPC/MPC56xx-VLE/CodeWarrior/os_dbg.c | 317 +++ Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu.h | 146 ++ .../PowerPC/MPC56xx/CodeWarrior/os_cpu_a.inc | 331 +++ Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.s | 304 +++ Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_c.c | 464 ++++ Ports/PowerPC/MPC56xx/CodeWarrior/os_dbg.c | 317 +++ Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu.h | 166 ++ Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.S | 464 ++++ Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.inc | 215 ++ Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_c.c | 494 ++++ Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu.h | 213 ++ .../PowerPC/MPC8349E/CodeWarrior/os_cpu_a.inc | 210 ++ Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.s | 272 +++ Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_c.c | 402 +++ Ports/PowerPC/MPC8349E/CodeWarrior/os_dbg.c | 316 +++ Ports/R32C/R32C100/HEW/os_cpu.h | 111 + Ports/R32C/R32C100/HEW/os_cpu_a.a30 | 194 ++ Ports/R32C/R32C100/HEW/os_cpu_c.c | 335 +++ Ports/R32C/R32C100/HEW/os_dbg.c | 273 +++ Ports/R32C/R32C100/IAR/os_cpu.h | 117 + Ports/R32C/R32C100/IAR/os_cpu_a.s53 | 237 ++ Ports/R32C/R32C100/IAR/os_cpu_c.c | 335 +++ Ports/R32C/R32C100/IAR/os_dbg.c | 317 +++ Ports/RISC-V/RV32/GCC/os_cpu.h | 161 ++ Ports/RISC-V/RV32/GCC/os_cpu_a.S | 318 +++ Ports/RISC-V/RV32/GCC/os_cpu_c.c | 441 ++++ Ports/RL78/GNURL78/os_cpu.h | 139 ++ Ports/RL78/GNURL78/os_cpu_a.asm | 246 ++ Ports/RL78/GNURL78/os_cpu_a.inc | 155 ++ Ports/RL78/GNURL78/os_cpu_c.c | 315 +++ Ports/RL78/GNURL78/os_dbg.c | 315 +++ Ports/RL78/IAR/os_cpu.h | 141 ++ Ports/RL78/IAR/os_cpu_a.asm | 189 ++ Ports/RL78/IAR/os_cpu_a.inc | 153 ++ Ports/RL78/IAR/os_cpu_c.c | 307 +++ Ports/RL78/IAR/os_dbg.c | 317 +++ Ports/RX/GNURX/os_cpu.h | 124 + Ports/RX/GNURX/os_cpu_a.S | 282 +++ Ports/RX/GNURX/os_cpu_c.c | 437 ++++ Ports/RX/GNURX/os_dbg.c | 325 +++ Ports/RX/IAR/os_cpu.h | 121 + Ports/RX/IAR/os_cpu_a.s | 276 +++ Ports/RX/IAR/os_cpu_c.c | 418 ++++ Ports/RX/IAR/os_dbg.c | 325 +++ Ports/RX/RXC/os_cpu.h | 124 + Ports/RX/RXC/os_cpu_a.src | 281 +++ Ports/RX/RXC/os_cpu_c.c | 437 ++++ Ports/RX/RXC/os_dbg.c | 325 +++ Ports/SH-2/Renesas/os_cpu.h | 144 ++ Ports/SH-2/Renesas/os_cpu_a.src | 279 +++ Ports/SH-2/Renesas/os_cpu_c.c | 316 +++ Ports/SH-2/Renesas/os_dbg.c | 316 +++ Ports/SH2A-FPU/HEW/os_cpu.h | 157 ++ Ports/SH2A-FPU/HEW/os_cpu_a.inc | 150 ++ Ports/SH2A-FPU/HEW/os_cpu_a.src | 138 ++ Ports/SH2A-FPU/HEW/os_cpu_c.c | 355 +++ Ports/SH2A-FPU/HEW/os_dbg.c | 317 +++ Ports/SH2A-FPU/Renesas/os_cpu.h | 154 ++ Ports/SH2A-FPU/Renesas/os_cpu_a.src | 314 +++ Ports/SH2A-FPU/Renesas/os_cpu_c.c | 337 +++ Ports/SH2A-FPU/Renesas/os_dbg.c | 316 +++ Ports/SH2A/Renesas/os_cpu.h | 154 ++ Ports/SH2A/Renesas/os_cpu_a.src | 212 ++ Ports/SH2A/Renesas/os_cpu_c.c | 320 +++ Ports/SH2A/Renesas/os_dbg.c | 316 +++ Ports/V850E2M/CubeSuite+/os_cpu.h | 124 + Ports/V850E2M/CubeSuite+/os_cpu_a.asm | 237 ++ Ports/V850E2M/CubeSuite+/os_cpu_a.inc | 284 +++ Ports/V850E2M/CubeSuite+/os_cpu_c.c | 351 +++ Ports/V850E2M/CubeSuite+/os_dbg.c | 318 +++ Ports/V850E2M/IAR/os_cpu.h | 119 + Ports/V850E2M/IAR/os_cpu_a.inc | 255 ++ Ports/V850E2M/IAR/os_cpu_a.s85 | 240 ++ Ports/V850E2M/IAR/os_cpu_c.c | 344 +++ Ports/V850E2M/IAR/os_dbg.c | 318 +++ Ports/V850E2S/IAR/os_cpu.h | 119 + Ports/V850E2S/IAR/os_cpu_a.inc | 256 ++ Ports/V850E2S/IAR/os_cpu_a.s85 | 241 ++ Ports/V850E2S/IAR/os_cpu_c.c | 344 +++ Ports/V850E2S/IAR/os_dbg.c | 318 +++ Ports/V850ES/CubeSuite/os_cpu.h | 123 + Ports/V850ES/CubeSuite/os_cpu_a.inc | 280 +++ Ports/V850ES/CubeSuite/os_cpu_a.s | 245 ++ Ports/V850ES/CubeSuite/os_cpu_c.c | 351 +++ Ports/V850ES/CubeSuite/os_dbg.c | 318 +++ Ports/V850ES/IAR/os_cpu.h | 120 + Ports/V850ES/IAR/os_cpu_a.inc | 256 ++ Ports/V850ES/IAR/os_cpu_a.s85 | 250 ++ Ports/V850ES/IAR/os_cpu_c.c | 344 +++ Ports/V850ES/IAR/os_dbg.c | 318 +++ Ports/V850ES/PM+/os_cpu.h | 122 + Ports/V850ES/PM+/os_cpu_a.s | 394 +++ Ports/V850ES/PM+/os_cpu_c.c | 352 +++ Ports/V850ES/PM+/os_dbg.c | 318 +++ Ports/Win32/Visual Studio/os_cpu.h | 105 + Ports/Win32/Visual Studio/os_cpu_c.c | 1394 +++++++++++ Ports/XA/Tasking/os_cpu.h | 233 ++ Ports/XA/Tasking/os_cpu_c.c | 697 ++++++ Ports/XA/Tasking/os_dbg.c | 267 ++ Source/os.h | 36 + Source/os_core.c | 2153 +++++++++++++++++ Source/os_dbg_r.c | 342 +++ Source/os_flag.c | 1286 ++++++++++ Source/os_mbox.c | 708 ++++++ Source/os_mem.c | 489 ++++ Source/os_mutex.c | 818 +++++++ Source/os_q.c | 964 ++++++++ Source/os_sem.c | 679 ++++++ Source/os_task.c | 1386 +++++++++++ Source/os_time.c | 280 +++ Source/os_tmr.c | 1140 +++++++++ Source/os_trace.h | 474 ++++ Source/ucos_ii.c | 39 + Source/ucos_ii.h | 1987 +++++++++++++++ TLS/CCES/os_tls.c | 425 ++++ TLS/IAR/os_tls.c | 822 +++++++ TLS/IAR/os_tls_v8.c | 847 +++++++ Trace/readme.txt | 9 + license.txt | 29 + readme.md | 6 + 557 files changed, 170883 insertions(+) create mode 100644 Cfg/Template/app_cfg.h create mode 100644 Cfg/Template/app_hooks.c create mode 100644 Cfg/Template/os_cfg.h create mode 100644 Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu.h create mode 100644 Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_a.s create mode 100644 Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_c.c create mode 100644 Ports/68HC12/DG128A/NonPaged/COSMIC/os_dbg.c create mode 100644 Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU.h create mode 100644 Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU_C.C create mode 100644 Ports/68HC12/DG128A/NonPaged/IAR/os_cpu_a.s33 create mode 100644 Ports/68HC12/DG128A/NonPaged/IAR/os_dbg.c create mode 100644 Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU.h create mode 100644 Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_A.S create mode 100644 Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_C.C create mode 100644 Ports/68HC12/DG128A/Paged/COSMIC/os_dbg.c create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/includes.h create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/os_cfg.h create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/test.c create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/vectors.c create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu.h create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_a.s create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_c.c create mode 100644 Ports/68HC12/DG128A/Paged/CodeWarrior/os_dbg.c create mode 100644 Ports/68HC12/DG128A/Paged/IAR/os_cpu.h create mode 100644 Ports/68HC12/DG128A/Paged/IAR/os_cpu_a.s33 create mode 100644 Ports/68HC12/DG128A/Paged/IAR/os_cpu_c.c create mode 100644 Ports/68HC12/DG128A/Paged/IAR/os_dbg.c create mode 100644 Ports/68HC12/NonPaged/COSMIC/os_cpu.h create mode 100644 Ports/68HC12/NonPaged/COSMIC/os_cpu_a.s create mode 100644 Ports/68HC12/NonPaged/COSMIC/os_cpu_c.c create mode 100644 Ports/68HC12/NonPaged/COSMIC/os_dbg.c create mode 100644 Ports/68HC12/Paged/COSMIC/os_cpu.h create mode 100644 Ports/68HC12/Paged/COSMIC/os_cpu_a.S create mode 100644 Ports/68HC12/Paged/COSMIC/os_cpu_c.c create mode 100644 Ports/68HC12/Paged/COSMIC/os_dbg.c create mode 100644 Ports/78K0/IAR/os_cpu.h create mode 100644 Ports/78K0/IAR/os_cpu_a.s26 create mode 100644 Ports/78K0/IAR/os_cpu_c.c create mode 100644 Ports/78K0/IAR/os_dbg.c create mode 100644 Ports/78K0R/IAR/os_cpu.h create mode 100644 Ports/78K0R/IAR/os_cpu_a.asm create mode 100644 Ports/78K0R/IAR/os_cpu_c.c create mode 100644 Ports/78K0R/IAR/os_dbg.c create mode 100644 Ports/80186/DOS/L/BC45/os_cpu.h create mode 100644 Ports/80186/DOS/L/BC45/os_cpu_a.asm create mode 100644 Ports/80186/DOS/L/BC45/os_cpu_c.c create mode 100644 Ports/80186/DOS/L/BC45/os_dbg.c create mode 100644 Ports/80x86/DOS/L-FP-I/BC45/os_cpu.h create mode 100644 Ports/80x86/DOS/L-FP-I/BC45/os_cpu_a.asm create mode 100644 Ports/80x86/DOS/L-FP-I/BC45/os_cpu_c.c create mode 100644 Ports/80x86/DOS/L-FP-I/BC45/os_dbg.c create mode 100644 Ports/80x86/DOS/L-FP/BC45/os_cpu.h create mode 100644 Ports/80x86/DOS/L-FP/BC45/os_cpu_a.asm create mode 100644 Ports/80x86/DOS/L-FP/BC45/os_cpu_c.c create mode 100644 Ports/80x86/DOS/L-FP/BC45/os_dbg.c create mode 100644 Ports/80x86/DOS/L-I/BC45/os_cpu.h create mode 100644 Ports/80x86/DOS/L-I/BC45/os_cpu_a.asm create mode 100644 Ports/80x86/DOS/L-I/BC45/os_cpu_c.c create mode 100644 Ports/80x86/DOS/L-I/BC45/os_dbg.c create mode 100644 Ports/80x86/DOS/L/BC45/os_cpu.h create mode 100644 Ports/80x86/DOS/L/BC45/os_cpu_a.asm create mode 100644 Ports/80x86/DOS/L/BC45/os_cpu_c.c create mode 100644 Ports/80x86/DOS/L/BC45/os_dbg.c create mode 100644 Ports/ARC/EM6/MetaWare/os_cpu.h create mode 100644 Ports/ARC/EM6/MetaWare/os_cpu_a.s create mode 100644 Ports/ARC/EM6/MetaWare/os_cpu_c.c create mode 100644 Ports/ARC/EM6/MetaWare/os_dbg.c create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu.h create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d16.s create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d32.s create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-none.s create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu.h create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d16.asm create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d32.asm create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-none.asm create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu.h create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d16.S create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d32.S create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-none.S create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu.h create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d16.asm create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d32.asm create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-none.asm create mode 100644 Ports/ARM-Cortex-A/ARMv7-A/os_cpu_c.c create mode 100644 Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu.h create mode 100644 Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu_a.S create mode 100644 Ports/ARM-Cortex-A/ARMv8-A/os_cpu_c.c create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu.h create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu_a.asm create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/ARM/os_dbg.c create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu.h create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu_a.s create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/GNU/os_dbg.c create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu.h create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu_a.asm create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/IAR/os_dbg.c create mode 100644 Ports/ARM-Cortex-M/ARMv6-M/os_cpu_c.c create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu.h create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/ARM/os_dbg.c create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu.h create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu_a.asm create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/CCS/os_dbg.c create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu.h create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu_a.S create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/GNU/os_dbg.c create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu.h create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu_a.asm create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/IAR/os_dbg.c create mode 100644 Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu.h create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-d16.s create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-none.s create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu.h create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-d16.asm create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-none.asm create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu.h create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-d16.S create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-none.S create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu.h create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-d16.asm create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-none.asm create mode 100644 Ports/ARM-Cortex-R/ARMv7-R/os_cpu_c.c create mode 100644 Ports/ARM/Generic/GNU/os_cpu.h create mode 100644 Ports/ARM/Generic/GNU/os_cpu_a.s create mode 100644 Ports/ARM/Generic/GNU/os_cpu_c.c create mode 100644 Ports/ARM/Generic/GNU/os_cpu_fpu_a.s create mode 100644 Ports/ARM/Generic/GNU/os_dbg.c create mode 100644 Ports/ARM/Generic/IAR/os_cpu.h create mode 100644 Ports/ARM/Generic/IAR/os_cpu_a.asm create mode 100644 Ports/ARM/Generic/IAR/os_cpu_c.c create mode 100644 Ports/ARM/Generic/IAR/os_cpu_fpu_a.asm create mode 100644 Ports/ARM/Generic/IAR/os_dbg.c create mode 100644 Ports/ARM/Generic/IAR/os_dcc.c create mode 100644 Ports/ARM/Generic/RealView/os_cpu.h create mode 100644 Ports/ARM/Generic/RealView/os_cpu_a.asm create mode 100644 Ports/ARM/Generic/RealView/os_cpu_c.c create mode 100644 Ports/ARM/Generic/RealView/os_cpu_fpu_a.asm create mode 100644 Ports/ARM/Generic/RealView/os_dbg.c create mode 100644 Ports/ARM7/AT91/ARM/IAR/os_cpu.h create mode 100644 Ports/ARM7/AT91/ARM/IAR/os_cpu_a.s create mode 100644 Ports/ARM7/AT91/ARM/IAR/os_cpu_c.c create mode 100644 Ports/ARM7/AT91/ARM/IAR/os_dbg.c create mode 100644 Ports/ARM7/AT91/Thumb/IAR/os_cpu.h create mode 100644 Ports/ARM7/AT91/Thumb/IAR/os_cpu_a.s create mode 100644 Ports/ARM7/AT91/Thumb/IAR/os_cpu_c.c create mode 100644 Ports/ARM7/AT91/Thumb/IAR/os_dbg.c create mode 100644 Ports/ARM7/Generic/ARM/IAR/os_cpu.h create mode 100644 Ports/ARM7/Generic/ARM/IAR/os_cpu_a.s create mode 100644 Ports/ARM7/Generic/ARM/IAR/os_cpu_c.c create mode 100644 Ports/ARM7/Generic/ARM/IAR/os_dbg.c create mode 100644 Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu.h create mode 100644 Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_a.s create mode 100644 Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_c.c create mode 100644 Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_dbg.c create mode 100644 Ports/ARM7/LH79520/ARM/IAR/os_cpu.h create mode 100644 Ports/ARM7/LH79520/ARM/IAR/os_cpu_a.s create mode 100644 Ports/ARM7/LH79520/ARM/IAR/os_cpu_c.c create mode 100644 Ports/ARM7/LH79520/ARM/IAR/os_dbg.c create mode 100644 Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu.h create mode 100644 Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_a.s create mode 100644 Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_c.c create mode 100644 Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_dbg.c create mode 100644 Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu.h create mode 100644 Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_a.s create mode 100644 Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_c.c create mode 100644 Ports/ARM9/AT91RM9200/ARM/IAR/os_dbg.c create mode 100644 Ports/AVR/ATmega128/IAR/os_cpu.h create mode 100644 Ports/AVR/ATmega128/IAR/os_cpu_a.s90 create mode 100644 Ports/AVR/ATmega128/IAR/os_cpu_c.c create mode 100644 Ports/AVR/ATmega128/IAR/os_cpu_i.s90 create mode 100644 Ports/AVR/ATmega128/IAR/os_dbg.c create mode 100644 Ports/AVR/ATmega128/ICC/os_cpu.h create mode 100644 Ports/AVR/ATmega128/ICC/os_cpu_a.s create mode 100644 Ports/AVR/ATmega128/ICC/os_cpu_c.c create mode 100644 Ports/AVR/ATmega128/ICC/os_cpu_i.h create mode 100644 Ports/AVR/ATmega128/ICC/os_dbg.c create mode 100644 Ports/AVR/ATmega256/IAR/os_cpu.h create mode 100644 Ports/AVR/ATmega256/IAR/os_cpu_a.s90 create mode 100644 Ports/AVR/ATmega256/IAR/os_cpu_c.c create mode 100644 Ports/AVR/ATmega256/IAR/os_cpu_i.s90 create mode 100644 Ports/AVR/ATmega256/IAR/os_dbg.c create mode 100644 Ports/AVR/ATmega256/ICC/os_cpu.h create mode 100644 Ports/AVR/ATmega256/ICC/os_cpu_a.s create mode 100644 Ports/AVR/ATmega256/ICC/os_cpu_c.c create mode 100644 Ports/AVR/ATmega256/ICC/os_cpu_i.h create mode 100644 Ports/AVR/ATmega256/ICC/os_dbg.c create mode 100644 Ports/AVR/ATxmega128/GNU/os_cpu.h create mode 100644 Ports/AVR/ATxmega128/GNU/os_cpu_a.s create mode 100644 Ports/AVR/ATxmega128/GNU/os_cpu_c.c create mode 100644 Ports/AVR/ATxmega128/GNU/os_cpu_i.h create mode 100644 Ports/AVR/ATxmega128/GNU/os_dbg.c create mode 100644 Ports/AVR/ATxmega128/IAR/os_cpu.h create mode 100644 Ports/AVR/ATxmega128/IAR/os_cpu_a.s90 create mode 100644 Ports/AVR/ATxmega128/IAR/os_cpu_c.c create mode 100644 Ports/AVR/ATxmega128/IAR/os_cpu_i.s90 create mode 100644 Ports/AVR/ATxmega128/IAR/os_dbg.c create mode 100644 Ports/AVR/Generic/IAR/os_cpu.h create mode 100644 Ports/AVR/Generic/IAR/os_cpu_a.s90 create mode 100644 Ports/AVR/Generic/IAR/os_cpu_c.c create mode 100644 Ports/AVR/Generic/IAR/os_dbg.c create mode 100644 Ports/AVR32/AP7000/GNU/os_cpu.h create mode 100644 Ports/AVR32/AP7000/GNU/os_cpu_a.s create mode 100644 Ports/AVR32/AP7000/GNU/os_cpu_c.c create mode 100644 Ports/AVR32/AP7000/GNU/os_dbg.c create mode 100644 Ports/AVR32/AP7000/IAR/os_cpu.h create mode 100644 Ports/AVR32/AP7000/IAR/os_cpu_a.asm create mode 100644 Ports/AVR32/AP7000/IAR/os_cpu_c.c create mode 100644 Ports/AVR32/AP7000/IAR/os_dbg.c create mode 100644 Ports/AVR32/UC3/GNU/os_cpu.h create mode 100644 Ports/AVR32/UC3/GNU/os_cpu_a.s create mode 100644 Ports/AVR32/UC3/GNU/os_cpu_c.c create mode 100644 Ports/AVR32/UC3/GNU/os_dbg.c create mode 100644 Ports/AVR32/UC3/IAR/os_cpu.h create mode 100644 Ports/AVR32/UC3/IAR/os_cpu_a.asm create mode 100644 Ports/AVR32/UC3/IAR/os_cpu_c.c create mode 100644 Ports/AVR32/UC3/IAR/os_dbg.c create mode 100644 Ports/Blackfin/VDSP++/os_cpu.h create mode 100644 Ports/Blackfin/VDSP++/os_cpu_a.asm create mode 100644 Ports/Blackfin/VDSP++/os_cpu_c.c create mode 100644 Ports/C28x/Generic/CCS/os_cpu.h create mode 100644 Ports/C28x/Generic/CCS/os_cpu_a.asm create mode 100644 Ports/C28x/Generic/CCS/os_cpu_c.c create mode 100644 Ports/C28x/Generic/CCS/os_cpu_i.asm create mode 100644 Ports/C28x/Generic/CCS/os_dbg.c create mode 100644 Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu.h create mode 100644 Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_a.asm create mode 100644 Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_c.c create mode 100644 Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_i.asm create mode 100644 Ports/ColdFire-EMAC/Generic/CodeWarrior/os_dbg.c create mode 100644 Ports/ColdFire/5272/GNU/os_cpu.h create mode 100644 Ports/ColdFire/5272/GNU/os_cpu_a.s create mode 100644 Ports/ColdFire/5272/GNU/os_cpu_c.c create mode 100644 Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu.h create mode 100644 Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu_a.asm create mode 100644 Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu_c.c create mode 100644 Ports/ColdFire/Generic/CW_For_Microcontrollers/os_dbg.c create mode 100644 Ports/ColdFire/Generic/CodeWarrior/os_cpu.h create mode 100644 Ports/ColdFire/Generic/CodeWarrior/os_cpu_a.asm create mode 100644 Ports/ColdFire/Generic/CodeWarrior/os_cpu_c.c create mode 100644 Ports/ColdFire/Generic/CodeWarrior/os_cpu_i.asm create mode 100644 Ports/ColdFire/Generic/CodeWarrior/os_dbg.c create mode 100644 Ports/ColdFire/Generic/IAR/os_cpu.h create mode 100644 Ports/ColdFire/Generic/IAR/os_cpu_a.asm create mode 100644 Ports/ColdFire/Generic/IAR/os_cpu_c.c create mode 100644 Ports/ColdFire/Generic/IAR/os_cpu_i.asm create mode 100644 Ports/ColdFire/Generic/IAR/os_dbg.c create mode 100644 Ports/DSP56F8xxx/CodeWarrior/OS_CPU.ASM create mode 100644 Ports/DSP56F8xxx/CodeWarrior/OS_CPU.C create mode 100644 Ports/DSP56F8xxx/CodeWarrior/OS_CPU.H create mode 100644 Ports/DSP56F8xxx/CodeWarrior/os_portasm.h create mode 100644 Ports/FR/Softune/os_cpu.h create mode 100644 Ports/FR/Softune/os_cpu_a.asm create mode 100644 Ports/FR/Softune/os_cpu_c.c create mode 100644 Ports/FR/Softune/os_cpu_i.asm create mode 100644 Ports/FR/Softune/os_dbg.c create mode 100644 Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_core.c create mode 100644 Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_task.c create mode 100644 Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_time.c create mode 100644 Ports/H8-300L/H8-38024/EDK38024/uCOS-II/ucos_ii.h create mode 100644 Ports/H8-300L/Normal/HEW/os_cpu.h create mode 100644 Ports/H8-300L/Normal/HEW/os_cpu_a.src create mode 100644 Ports/H8-300L/Normal/HEW/os_cpu_c.c create mode 100644 Ports/H8-300L/Normal/HEW/os_dbg.c create mode 100644 Ports/H8-300L/Normal/IAR/os_cpu.h create mode 100644 Ports/H8-300L/Normal/IAR/os_cpu_a.s37 create mode 100644 Ports/H8-300L/Normal/IAR/os_cpu_c.c create mode 100644 Ports/H8-300L/Normal/IAR/os_dbg.c create mode 100644 Ports/H8S/Adv/HEW/os_cpu.h create mode 100644 Ports/H8S/Adv/HEW/os_cpu_a.src create mode 100644 Ports/H8S/Adv/HEW/os_cpu_c.c create mode 100644 Ports/H8S/Adv/HEW/os_dbg.c create mode 100644 Ports/H8S/Adv/IAR/os_cpu.h create mode 100644 Ports/H8S/Adv/IAR/os_cpu_a.asm create mode 100644 Ports/H8S/Adv/IAR/os_cpu_a.s37 create mode 100644 Ports/H8S/Adv/IAR/os_cpu_c.c create mode 100644 Ports/H8S/Adv/IAR/os_dbg.c create mode 100644 Ports/H8S/H8S-26xx/Adv/IAR/os_cpu.h create mode 100644 Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_a.s37 create mode 100644 Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_c.c create mode 100644 Ports/H8S/H8S-26xx/Adv/IAR/os_dbg.c create mode 100644 Ports/H8SX/Adv/HEW/os_cpu.h create mode 100644 Ports/H8SX/Adv/HEW/os_cpu_a.src create mode 100644 Ports/H8SX/Adv/HEW/os_cpu_c.c create mode 100644 Ports/H8SX/Adv/HEW/os_dbg.c create mode 100644 Ports/H8SX/Adv/IAR/os_cpu.h create mode 100644 Ports/H8SX/Adv/IAR/os_cpu_a.s37 create mode 100644 Ports/H8SX/Adv/IAR/os_cpu_c.c create mode 100644 Ports/H8SX/Adv/IAR/os_dbg.c create mode 100644 Ports/HCS12/NonPaged/CodeWarrior/OS_CPU.h create mode 100644 Ports/HCS12/NonPaged/CodeWarrior/OS_CPU_C.C create mode 100644 Ports/HCS12/NonPaged/CodeWarrior/os_cpu_a.asm create mode 100644 Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu.h create mode 100644 Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_a.s create mode 100644 Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_c.c create mode 100644 Ports/HCS12/Paged/CodeWarrior/os_cpu.h create mode 100644 Ports/HCS12/Paged/CodeWarrior/os_cpu_a.s create mode 100644 Ports/HCS12/Paged/CodeWarrior/os_cpu_c.c create mode 100644 Ports/HCS12X/Paged/Codewarrior/os_cpu.h create mode 100644 Ports/HCS12X/Paged/Codewarrior/os_cpu_a.s create mode 100644 Ports/HCS12X/Paged/Codewarrior/os_cpu_c.c create mode 100644 Ports/HCS12X/Paged/Cosmic/os_cpu.h create mode 100644 Ports/HCS12X/Paged/Cosmic/os_cpu_a.S create mode 100644 Ports/HCS12X/Paged/Cosmic/os_cpu_c.c create mode 100644 Ports/HCS12X/Paged/Cosmic/os_dbg.c create mode 100644 Ports/LatticeMico32/GNU/MicroC_malloc_lock.c create mode 100644 Ports/LatticeMico32/GNU/MicroC_malloc_lock.h create mode 100644 Ports/LatticeMico32/GNU/os_cpu.h create mode 100644 Ports/LatticeMico32/GNU/os_cpu_a.s create mode 100644 Ports/LatticeMico32/GNU/os_cpu_c.c create mode 100644 Ports/LatticeMico32/GNU/os_dbg.c create mode 100644 Ports/M14K/CodeSourcery/os_cpu.h create mode 100644 Ports/M14K/CodeSourcery/os_cpu_a.S create mode 100644 Ports/M14K/CodeSourcery/os_cpu_c.c create mode 100644 Ports/M16C/M16C60/HEW/os_cpu.h create mode 100644 Ports/M16C/M16C60/HEW/os_cpu_a.a30 create mode 100644 Ports/M16C/M16C60/HEW/os_cpu_c.c create mode 100644 Ports/M16C/M16C60/HEW/os_dbg.c create mode 100644 Ports/M16C/M16C60/IAR/os_cpu.h create mode 100644 Ports/M16C/M16C60/IAR/os_cpu_a.asm create mode 100644 Ports/M16C/M16C60/IAR/os_cpu_c.c create mode 100644 Ports/M16C/M16C60/IAR/os_dbg.c create mode 100644 Ports/M16C/Tiny/HEW/os_cpu.h create mode 100644 Ports/M16C/Tiny/HEW/os_cpu_a.a30 create mode 100644 Ports/M16C/Tiny/HEW/os_cpu_c.c create mode 100644 Ports/M16C/Tiny/HEW/os_dbg.c create mode 100644 Ports/M16C/Tiny/IAR/os_cpu.h create mode 100644 Ports/M16C/Tiny/IAR/os_cpu_a.asm create mode 100644 Ports/M16C/Tiny/IAR/os_cpu_c.c create mode 100644 Ports/M16C/Tiny/IAR/os_dbg.c create mode 100644 Ports/M32C/M16C80/HEW/os_cpu.h create mode 100644 Ports/M32C/M16C80/HEW/os_cpu_a.a30 create mode 100644 Ports/M32C/M16C80/HEW/os_cpu_c.c create mode 100644 Ports/M32C/M16C80/HEW/os_dbg.c create mode 100644 Ports/M32C/M16C80/IAR/os_cpu.h create mode 100644 Ports/M32C/M16C80/IAR/os_cpu_a.asm create mode 100644 Ports/M32C/M16C80/IAR/os_cpu_c.c create mode 100644 Ports/M32C/M16C80/IAR/os_dbg.c create mode 100644 Ports/M683xx/68332/COSMIC/os_cpu.h create mode 100644 Ports/M683xx/68332/COSMIC/os_cpu_a.s create mode 100644 Ports/M683xx/68332/COSMIC/os_cpu_c.c create mode 100644 Ports/M683xx/68332/COSMIC/os_dbg.c create mode 100644 Ports/MC9S08/NonPaged/Codewarrior/OS_CPU.h create mode 100644 Ports/MC9S08/NonPaged/Codewarrior/os_cpu_a.s create mode 100644 Ports/MC9S08/NonPaged/Codewarrior/os_cpu_c.c create mode 100644 Ports/MC9S08/Paged/Codewarrior/OS_CPU.h create mode 100644 Ports/MC9S08/Paged/Codewarrior/os_cpu_a.s create mode 100644 Ports/MC9S08/Paged/Codewarrior/os_cpu_c.c create mode 100644 Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu.h create mode 100644 Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_a.S create mode 100644 Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_c.c create mode 100644 Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_dbg.c create mode 100644 Ports/MSP430/IAR/OS_CPU.H create mode 100644 Ports/MSP430/IAR/Os_cpu_a.s43 create mode 100644 Ports/MSP430/IAR/Os_cpu_c.c create mode 100644 Ports/MSP430/IAR/os_dbg.c create mode 100644 Ports/MSP430X/CCS/MSP430x5xx/os_cpu.h create mode 100644 Ports/MSP430X/CCS/MSP430x5xx/os_cpu_a.s43 create mode 100644 Ports/MSP430X/CCS/MSP430x5xx/os_cpu_c.c create mode 100644 Ports/MSP430X/CCS/MSP430x5xx/os_dbg.c create mode 100644 Ports/MSP430X/IAR/MSP430x5xx/os_cpu.h create mode 100644 Ports/MSP430X/IAR/MSP430x5xx/os_cpu_a.s43 create mode 100644 Ports/MSP430X/IAR/MSP430x5xx/os_cpu_c.c create mode 100644 Ports/MSP430X/IAR/MSP430x5xx/os_dbg.c create mode 100644 Ports/MicroBlaze/EDK/Code/includes.h create mode 100644 Ports/MicroBlaze/EDK/Code/os_cfg.h create mode 100644 Ports/MicroBlaze/EDK/Code/system.c create mode 100644 Ports/MicroBlaze/GNU/USE_MSR_INSTR/os_cpu_a.S create mode 100644 Ports/MicroBlaze/GNU/os_cpu.h create mode 100644 Ports/MicroBlaze/GNU/os_cpu_a.S create mode 100644 Ports/MicroBlaze/GNU/os_cpu_c.c create mode 100644 Ports/MicroBlaze/GNU/os_dbg.c create mode 100644 Ports/Microchip/PIC24FJ128/C30/os_cpu.h create mode 100644 Ports/Microchip/PIC24FJ128/C30/os_cpu_a.s create mode 100644 Ports/Microchip/PIC24FJ128/C30/os_cpu_c.c create mode 100644 Ports/Microchip/PIC24FJ128/C30/os_cpu_util_a.s create mode 100644 Ports/Microchip/PIC24FJ128/C30/os_dbg.c create mode 100644 Ports/Microchip/PIC24FJ128/DSPICC/os_cpu.h create mode 100644 Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_a.as create mode 100644 Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_c.c create mode 100644 Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_util_a.as create mode 100644 Ports/Microchip/PIC24FJ128/DSPICC/os_dbg.c create mode 100644 Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu.h create mode 100644 Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_a.s create mode 100644 Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_c.c create mode 100644 Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_util_a.s create mode 100644 Ports/Microchip/PIC24FJ128/ICCDSPIC/os_dbg.c create mode 100644 Ports/Microchip/PIC30F6014/C30/os_cpu.h create mode 100644 Ports/Microchip/PIC30F6014/C30/os_cpu_a.s create mode 100644 Ports/Microchip/PIC30F6014/C30/os_cpu_c.c create mode 100644 Ports/Microchip/PIC30F6014/C30/os_cpu_util_a.s create mode 100644 Ports/Microchip/PIC33FJ256/C30/os_cpu.h create mode 100644 Ports/Microchip/PIC33FJ256/C30/os_cpu_a.s create mode 100644 Ports/Microchip/PIC33FJ256/C30/os_cpu_c.c create mode 100644 Ports/Microchip/PIC33FJ256/C30/os_cpu_util_a.s create mode 100644 Ports/Microchip/PIC33FJ256/DSPICC/os_cpu.h create mode 100644 Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_a.as create mode 100644 Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_c.c create mode 100644 Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_util_a.as create mode 100644 Ports/Microchip/PIC33FJ256/DSPICC/os_dbg.c create mode 100644 Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu.h create mode 100644 Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_a.s59 create mode 100644 Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_c.c create mode 100644 Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_util_a.s59 create mode 100644 Ports/Microchip/PIC33FJ256/ICCDSPIC/os_dbg.c create mode 100644 Ports/PPC405/GNU/os_cpu.h create mode 100644 Ports/PPC405/GNU/os_cpu_a.S create mode 100644 Ports/PPC405/GNU/os_cpu_c.c create mode 100644 Ports/PPC405/GNU/os_dbg.c create mode 100644 Ports/PPC440/GNU/os_cpu.h create mode 100644 Ports/PPC440/GNU/os_cpu_a.S create mode 100644 Ports/PPC440/GNU/os_cpu_c.c create mode 100644 Ports/PPC440/GNU/os_dbg.c create mode 100644 Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu.h create mode 100644 Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.s create mode 100644 Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_dbg.c create mode 100644 Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu.h create mode 100644 Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.s create mode 100644 Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC55xx-VLE/GNU/os_dbg.c create mode 100644 Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu.h create mode 100644 Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.s create mode 100644 Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC55xx/CodeWarrior/os_dbg.c create mode 100644 Ports/PowerPC/MPC55xx/GNU/os_cpu.h create mode 100644 Ports/PowerPC/MPC55xx/GNU/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC55xx/GNU/os_cpu_a.s create mode 100644 Ports/PowerPC/MPC55xx/GNU/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC55xx/GNU/os_dbg.c create mode 100644 Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu.h create mode 100644 Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.s create mode 100644 Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_dbg.c create mode 100644 Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu.h create mode 100644 Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.s create mode 100644 Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC56xx/CodeWarrior/os_dbg.c create mode 100644 Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu.h create mode 100644 Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.S create mode 100644 Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu.h create mode 100644 Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.inc create mode 100644 Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.s create mode 100644 Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_c.c create mode 100644 Ports/PowerPC/MPC8349E/CodeWarrior/os_dbg.c create mode 100644 Ports/R32C/R32C100/HEW/os_cpu.h create mode 100644 Ports/R32C/R32C100/HEW/os_cpu_a.a30 create mode 100644 Ports/R32C/R32C100/HEW/os_cpu_c.c create mode 100644 Ports/R32C/R32C100/HEW/os_dbg.c create mode 100644 Ports/R32C/R32C100/IAR/os_cpu.h create mode 100644 Ports/R32C/R32C100/IAR/os_cpu_a.s53 create mode 100644 Ports/R32C/R32C100/IAR/os_cpu_c.c create mode 100644 Ports/R32C/R32C100/IAR/os_dbg.c create mode 100644 Ports/RISC-V/RV32/GCC/os_cpu.h create mode 100644 Ports/RISC-V/RV32/GCC/os_cpu_a.S create mode 100644 Ports/RISC-V/RV32/GCC/os_cpu_c.c create mode 100644 Ports/RL78/GNURL78/os_cpu.h create mode 100644 Ports/RL78/GNURL78/os_cpu_a.asm create mode 100644 Ports/RL78/GNURL78/os_cpu_a.inc create mode 100644 Ports/RL78/GNURL78/os_cpu_c.c create mode 100644 Ports/RL78/GNURL78/os_dbg.c create mode 100644 Ports/RL78/IAR/os_cpu.h create mode 100644 Ports/RL78/IAR/os_cpu_a.asm create mode 100644 Ports/RL78/IAR/os_cpu_a.inc create mode 100644 Ports/RL78/IAR/os_cpu_c.c create mode 100644 Ports/RL78/IAR/os_dbg.c create mode 100644 Ports/RX/GNURX/os_cpu.h create mode 100644 Ports/RX/GNURX/os_cpu_a.S create mode 100644 Ports/RX/GNURX/os_cpu_c.c create mode 100644 Ports/RX/GNURX/os_dbg.c create mode 100644 Ports/RX/IAR/os_cpu.h create mode 100644 Ports/RX/IAR/os_cpu_a.s create mode 100644 Ports/RX/IAR/os_cpu_c.c create mode 100644 Ports/RX/IAR/os_dbg.c create mode 100644 Ports/RX/RXC/os_cpu.h create mode 100644 Ports/RX/RXC/os_cpu_a.src create mode 100644 Ports/RX/RXC/os_cpu_c.c create mode 100644 Ports/RX/RXC/os_dbg.c create mode 100644 Ports/SH-2/Renesas/os_cpu.h create mode 100644 Ports/SH-2/Renesas/os_cpu_a.src create mode 100644 Ports/SH-2/Renesas/os_cpu_c.c create mode 100644 Ports/SH-2/Renesas/os_dbg.c create mode 100644 Ports/SH2A-FPU/HEW/os_cpu.h create mode 100644 Ports/SH2A-FPU/HEW/os_cpu_a.inc create mode 100644 Ports/SH2A-FPU/HEW/os_cpu_a.src create mode 100644 Ports/SH2A-FPU/HEW/os_cpu_c.c create mode 100644 Ports/SH2A-FPU/HEW/os_dbg.c create mode 100644 Ports/SH2A-FPU/Renesas/os_cpu.h create mode 100644 Ports/SH2A-FPU/Renesas/os_cpu_a.src create mode 100644 Ports/SH2A-FPU/Renesas/os_cpu_c.c create mode 100644 Ports/SH2A-FPU/Renesas/os_dbg.c create mode 100644 Ports/SH2A/Renesas/os_cpu.h create mode 100644 Ports/SH2A/Renesas/os_cpu_a.src create mode 100644 Ports/SH2A/Renesas/os_cpu_c.c create mode 100644 Ports/SH2A/Renesas/os_dbg.c create mode 100644 Ports/V850E2M/CubeSuite+/os_cpu.h create mode 100644 Ports/V850E2M/CubeSuite+/os_cpu_a.asm create mode 100644 Ports/V850E2M/CubeSuite+/os_cpu_a.inc create mode 100644 Ports/V850E2M/CubeSuite+/os_cpu_c.c create mode 100644 Ports/V850E2M/CubeSuite+/os_dbg.c create mode 100644 Ports/V850E2M/IAR/os_cpu.h create mode 100644 Ports/V850E2M/IAR/os_cpu_a.inc create mode 100644 Ports/V850E2M/IAR/os_cpu_a.s85 create mode 100644 Ports/V850E2M/IAR/os_cpu_c.c create mode 100644 Ports/V850E2M/IAR/os_dbg.c create mode 100644 Ports/V850E2S/IAR/os_cpu.h create mode 100644 Ports/V850E2S/IAR/os_cpu_a.inc create mode 100644 Ports/V850E2S/IAR/os_cpu_a.s85 create mode 100644 Ports/V850E2S/IAR/os_cpu_c.c create mode 100644 Ports/V850E2S/IAR/os_dbg.c create mode 100644 Ports/V850ES/CubeSuite/os_cpu.h create mode 100644 Ports/V850ES/CubeSuite/os_cpu_a.inc create mode 100644 Ports/V850ES/CubeSuite/os_cpu_a.s create mode 100644 Ports/V850ES/CubeSuite/os_cpu_c.c create mode 100644 Ports/V850ES/CubeSuite/os_dbg.c create mode 100644 Ports/V850ES/IAR/os_cpu.h create mode 100644 Ports/V850ES/IAR/os_cpu_a.inc create mode 100644 Ports/V850ES/IAR/os_cpu_a.s85 create mode 100644 Ports/V850ES/IAR/os_cpu_c.c create mode 100644 Ports/V850ES/IAR/os_dbg.c create mode 100644 Ports/V850ES/PM+/os_cpu.h create mode 100644 Ports/V850ES/PM+/os_cpu_a.s create mode 100644 Ports/V850ES/PM+/os_cpu_c.c create mode 100644 Ports/V850ES/PM+/os_dbg.c create mode 100644 Ports/Win32/Visual Studio/os_cpu.h create mode 100644 Ports/Win32/Visual Studio/os_cpu_c.c create mode 100644 Ports/XA/Tasking/os_cpu.h create mode 100644 Ports/XA/Tasking/os_cpu_c.c create mode 100644 Ports/XA/Tasking/os_dbg.c create mode 100644 Source/os.h create mode 100644 Source/os_core.c create mode 100644 Source/os_dbg_r.c create mode 100644 Source/os_flag.c create mode 100644 Source/os_mbox.c create mode 100644 Source/os_mem.c create mode 100644 Source/os_mutex.c create mode 100644 Source/os_q.c create mode 100644 Source/os_sem.c create mode 100644 Source/os_task.c create mode 100644 Source/os_time.c create mode 100644 Source/os_tmr.c create mode 100644 Source/os_trace.h create mode 100644 Source/ucos_ii.c create mode 100644 Source/ucos_ii.h create mode 100644 TLS/CCES/os_tls.c create mode 100644 TLS/IAR/os_tls.c create mode 100644 TLS/IAR/os_tls_v8.c create mode 100644 Trace/readme.txt create mode 100644 license.txt create mode 100644 readme.md diff --git a/Cfg/Template/app_cfg.h b/Cfg/Template/app_cfg.h new file mode 100644 index 0000000..0d380bf --- /dev/null +++ b/Cfg/Template/app_cfg.h @@ -0,0 +1,99 @@ +/* +********************************************************************************************************* +* EXAMPLE CODE +* +* This file is provided as an example on how to use Micrium products. +* +* Please feel free to use any application code labeled as 'EXAMPLE CODE' in +* your application products. Example code may be used as is, in whole or in +* part, or may be used as a reference only. This file can be modified as +* required to meet the end-product requirements. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* APPLICATION CONFIGURATION +* +* EXAMPLE CODE +* +* Filename : app_cfg.h +********************************************************************************************************* +*/ + +#ifndef _APP_CFG_H_ +#define _APP_CFG_H_ + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include +#include + + +/* +********************************************************************************************************* +* MODULE ENABLE / DISABLE +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* TASK PRIORITIES +********************************************************************************************************* +*/ + +#define APP_CFG_STARTUP_TASK_PRIO 3u + +#define OS_TASK_TMR_PRIO (OS_LOWEST_PRIO - 2u) + + +/* +********************************************************************************************************* +* TASK STACK SIZES +* Size of the task stacks (# of OS_STK entries) +********************************************************************************************************* +*/ + +#define APP_CFG_STARTUP_TASK_STK_SIZE 128u + + +/* +********************************************************************************************************* +* TRACE / DEBUG CONFIGURATION +********************************************************************************************************* +*/ + +#ifndef TRACE_LEVEL_OFF +#define TRACE_LEVEL_OFF 0u +#endif + +#ifndef TRACE_LEVEL_INFO +#define TRACE_LEVEL_INFO 1u +#endif + +#ifndef TRACE_LEVEL_DBG +#define TRACE_LEVEL_DBG 2u +#endif + +#define APP_TRACE_LEVEL TRACE_LEVEL_OFF +#define APP_TRACE printf + +#define APP_TRACE_INFO(x) ((APP_TRACE_LEVEL >= TRACE_LEVEL_INFO) ? (void)(APP_TRACE x) : (void)0) +#define APP_TRACE_DBG(x) ((APP_TRACE_LEVEL >= TRACE_LEVEL_DBG) ? (void)(APP_TRACE x) : (void)0) + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif /* End of module include. */ diff --git a/Cfg/Template/app_hooks.c b/Cfg/Template/app_hooks.c new file mode 100644 index 0000000..83f8fab --- /dev/null +++ b/Cfg/Template/app_hooks.c @@ -0,0 +1,253 @@ +/* +********************************************************************************************************* +* EXAMPLE CODE +* +* This file is provided as an example on how to use Micrium products. +* +* Please feel free to use any application code labeled as 'EXAMPLE CODE' in +* your application products. Example code may be used as is, in whole or in +* part, or may be used as a reference only. This file can be modified as +* required to meet the end-product requirements. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* uC/OS-II +* Application Hooks +* +* Filename : app_hooks.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* EXTERN GLOBAL VARIABLES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* LOCAL DATA TYPES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* LOCAL TABLES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* LOCAL FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + + + +/* +********************************************************************************************************* +********************************************************************************************************* +** GLOBAL FUNCTIONS +********************************************************************************************************* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +********************************************************************************************************* +** uC/OS-II APP HOOKS +********************************************************************************************************* +********************************************************************************************************* +*/ + +#if (OS_APP_HOOKS_EN > 0) + +/* +********************************************************************************************************* +* TASK CREATION HOOK (APPLICATION) +* +* Description : This function is called when a task is created. +* +* Argument(s) : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : (1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +void App_TaskCreateHook (OS_TCB *ptcb) +{ + (void)ptcb; +} + + +/* +********************************************************************************************************* +* TASK DELETION HOOK (APPLICATION) +* +* Description : This function is called when a task is deleted. +* +* Argument(s) : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : (1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +void App_TaskDelHook (OS_TCB *ptcb) +{ + (void)ptcb; +} + + +/* +********************************************************************************************************* +* IDLE TASK HOOK (APPLICATION) +* +* Description : This function is called by OSTaskIdleHook(), which is called by the idle task. This hook +* has been added to allow you to do such things as STOP the CPU to conserve power. +* +* Argument(s) : none. +* +* Note(s) : (1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 251 +void App_TaskIdleHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK (APPLICATION) +* +* Description : This function is called by OSTaskStatHook(), which is called every second by uC/OS-II's +* statistics task. This allows your application to add functionality to the statistics task. +* +* Argument(s) : none. +********************************************************************************************************* +*/ + +void App_TaskStatHook (void) +{ +} + + +/* +********************************************************************************************************* +* TASK RETURN HOOK (APPLICATION) +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + + +#if OS_VERSION >= 289 +void App_TaskReturnHook (OS_TCB *ptcb) +{ + (void)ptcb; +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK (APPLICATION) +* +* Description : This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Argument(s) : none. +* +* Note(s) : (1) Interrupts are disabled during this call. +* +* (2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if OS_TASK_SW_HOOK_EN > 0 +void App_TaskSwHook (void) +{ + +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK (APPLICATION) +* +* Description : This function is called by OSTCBInitHook(), which is called by OS_TCBInit() after setting +* up most of the TCB. +* +* Argument(s) : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : (1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 204 +void App_TCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK (APPLICATION) +* +* Description : This function is called every tick. +* +* Argument(s) : none. +* +* Note(s) : (1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_TIME_TICK_HOOK_EN > 0 +void App_TimeTickHook (void) +{ + +} +#endif +#endif diff --git a/Cfg/Template/os_cfg.h b/Cfg/Template/os_cfg.h new file mode 100644 index 0000000..eb45ab8 --- /dev/null +++ b/Cfg/Template/os_cfg.h @@ -0,0 +1,154 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* uC/OS-II Configuration File for V2.9x +* +* Filename : os_cfg.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CFG_H +#define OS_CFG_H + + + /* ---------------------- MISCELLANEOUS ----------------------- */ +#define OS_APP_HOOKS_EN 1u /* Application-defined hooks are called from the uC/OS-II hooks */ +#define OS_ARG_CHK_EN 1u /* Enable (1) or Disable (0) argument checking */ +#define OS_CPU_HOOKS_EN 1u /* uC/OS-II hooks are found in the processor port files */ + +#define OS_DEBUG_EN 1u /* Enable(1) debug variables */ + +#define OS_EVENT_MULTI_EN 1u /* Include code for OSEventPendMulti() */ +#define OS_EVENT_NAME_EN 1u /* Enable names for Sem, Mutex, Mbox and Q */ + +#define OS_LOWEST_PRIO 63u /* Defines the lowest priority that can be assigned ... */ + /* ... MUST NEVER be higher than 254! */ + +#define OS_MAX_EVENTS 10u /* Max. number of event control blocks in your application */ +#define OS_MAX_FLAGS 5u /* Max. number of Event Flag Groups in your application */ +#define OS_MAX_MEM_PART 5u /* Max. number of memory partitions */ +#define OS_MAX_QS 4u /* Max. number of queue control blocks in your application */ +#define OS_MAX_TASKS 20u /* Max. number of tasks in your application, MUST be >= 2 */ + +#define OS_SCHED_LOCK_EN 1u /* Include code for OSSchedLock() and OSSchedUnlock() */ + +#define OS_TICK_STEP_EN 1u /* Enable tick stepping feature for uC/OS-View */ +#define OS_TICKS_PER_SEC 100u /* Set the number of ticks in one second */ + +#define OS_TLS_TBL_SIZE 0u /* Size of Thread-Local Storage Table */ + + + /* --------------------- TASK STACK SIZE ---------------------- */ +#define OS_TASK_TMR_STK_SIZE 128u /* Timer task stack size (# of OS_STK wide entries) */ +#define OS_TASK_STAT_STK_SIZE 128u /* Statistics task stack size (# of OS_STK wide entries) */ +#define OS_TASK_IDLE_STK_SIZE 128u /* Idle task stack size (# of OS_STK wide entries) */ + + + /* --------------------- TASK MANAGEMENT ---------------------- */ +#define OS_TASK_CHANGE_PRIO_EN 1u /* Include code for OSTaskChangePrio() */ +#define OS_TASK_CREATE_EN 1u /* Include code for OSTaskCreate() */ +#define OS_TASK_CREATE_EXT_EN 1u /* Include code for OSTaskCreateExt() */ +#define OS_TASK_DEL_EN 1u /* Include code for OSTaskDel() */ +#define OS_TASK_NAME_EN 1u /* Enable task names */ +#define OS_TASK_PROFILE_EN 1u /* Include variables in OS_TCB for profiling */ +#define OS_TASK_QUERY_EN 1u /* Include code for OSTaskQuery() */ +#define OS_TASK_REG_TBL_SIZE 1u /* Size of task variables array (#of INT32U entries) */ +#define OS_TASK_STAT_EN 1u /* Enable (1) or Disable(0) the statistics task */ +#define OS_TASK_STAT_STK_CHK_EN 1u /* Check task stacks from statistic task */ +#define OS_TASK_SUSPEND_EN 1u /* Include code for OSTaskSuspend() and OSTaskResume() */ +#define OS_TASK_SW_HOOK_EN 1u /* Include code for OSTaskSwHook() */ + + + /* ----------------------- EVENT FLAGS ------------------------ */ +#define OS_FLAG_EN 1u /* Enable (1) or Disable (0) code generation for EVENT FLAGS */ +#define OS_FLAG_ACCEPT_EN 1u /* Include code for OSFlagAccept() */ +#define OS_FLAG_DEL_EN 1u /* Include code for OSFlagDel() */ +#define OS_FLAG_NAME_EN 1u /* Enable names for event flag group */ +#define OS_FLAG_QUERY_EN 1u /* Include code for OSFlagQuery() */ +#define OS_FLAG_WAIT_CLR_EN 1u /* Include code for Wait on Clear EVENT FLAGS */ +#define OS_FLAGS_NBITS 16u /* Size in #bits of OS_FLAGS data type (8, 16 or 32) */ + + + /* -------------------- MESSAGE MAILBOXES --------------------- */ +#define OS_MBOX_EN 1u /* Enable (1) or Disable (0) code generation for MAILBOXES */ +#define OS_MBOX_ACCEPT_EN 1u /* Include code for OSMboxAccept() */ +#define OS_MBOX_DEL_EN 1u /* Include code for OSMboxDel() */ +#define OS_MBOX_PEND_ABORT_EN 1u /* Include code for OSMboxPendAbort() */ +#define OS_MBOX_POST_EN 1u /* Include code for OSMboxPost() */ +#define OS_MBOX_POST_OPT_EN 1u /* Include code for OSMboxPostOpt() */ +#define OS_MBOX_QUERY_EN 1u /* Include code for OSMboxQuery() */ + + + /* --------------------- MEMORY MANAGEMENT -------------------- */ +#define OS_MEM_EN 1u /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */ +#define OS_MEM_NAME_EN 1u /* Enable memory partition names */ +#define OS_MEM_QUERY_EN 1u /* Include code for OSMemQuery() */ + + + /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */ +#define OS_MUTEX_EN 1u /* Enable (1) or Disable (0) code generation for MUTEX */ +#define OS_MUTEX_ACCEPT_EN 1u /* Include code for OSMutexAccept() */ +#define OS_MUTEX_DEL_EN 1u /* Include code for OSMutexDel() */ +#define OS_MUTEX_QUERY_EN 1u /* Include code for OSMutexQuery() */ + + + /* ---------------------- MESSAGE QUEUES ---------------------- */ +#define OS_Q_EN 1u /* Enable (1) or Disable (0) code generation for QUEUES */ +#define OS_Q_ACCEPT_EN 1u /* Include code for OSQAccept() */ +#define OS_Q_DEL_EN 1u /* Include code for OSQDel() */ +#define OS_Q_FLUSH_EN 1u /* Include code for OSQFlush() */ +#define OS_Q_PEND_ABORT_EN 1u /* Include code for OSQPendAbort() */ +#define OS_Q_POST_EN 1u /* Include code for OSQPost() */ +#define OS_Q_POST_FRONT_EN 1u /* Include code for OSQPostFront() */ +#define OS_Q_POST_OPT_EN 1u /* Include code for OSQPostOpt() */ +#define OS_Q_QUERY_EN 1u /* Include code for OSQQuery() */ + + + /* ------------------------ SEMAPHORES ------------------------ */ +#define OS_SEM_EN 1u /* Enable (1) or Disable (0) code generation for SEMAPHORES */ +#define OS_SEM_ACCEPT_EN 1u /* Include code for OSSemAccept() */ +#define OS_SEM_DEL_EN 1u /* Include code for OSSemDel() */ +#define OS_SEM_PEND_ABORT_EN 1u /* Include code for OSSemPendAbort() */ +#define OS_SEM_QUERY_EN 1u /* Include code for OSSemQuery() */ +#define OS_SEM_SET_EN 1u /* Include code for OSSemSet() */ + + + /* --------------------- TIME MANAGEMENT ---------------------- */ +#define OS_TIME_DLY_HMSM_EN 1u /* Include code for OSTimeDlyHMSM() */ +#define OS_TIME_DLY_RESUME_EN 1u /* Include code for OSTimeDlyResume() */ +#define OS_TIME_GET_SET_EN 1u /* Include code for OSTimeGet() and OSTimeSet() */ +#define OS_TIME_TICK_HOOK_EN 1u /* Include code for OSTimeTickHook() */ + + + /* --------------------- TIMER MANAGEMENT --------------------- */ +#define OS_TMR_EN 1u /* Enable (1) or Disable (0) code generation for TIMERS */ +#define OS_TMR_CFG_MAX 16u /* Maximum number of timers */ +#define OS_TMR_CFG_NAME_EN 1u /* Determine timer names */ +#define OS_TMR_CFG_WHEEL_SIZE 7u /* Size of timer wheel (#Spokes) */ +#define OS_TMR_CFG_TICKS_PER_SEC 10u /* Rate at which timer management task runs (Hz) */ + + + /* ---------------------- TRACE RECORDER ---------------------- */ +#define OS_TRACE_EN 0u /* Enable (1) or Disable (0) uC/OS-II Trace instrumentation */ +#define OS_TRACE_API_ENTER_EN 0u /* Enable (1) or Disable (0) uC/OS-II Trace API enter instrum. */ +#define OS_TRACE_API_EXIT_EN 0u /* Enable (1) or Disable (0) uC/OS-II Trace API exit instrum. */ + +#endif diff --git a/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu.h b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu.h new file mode 100644 index 0000000..ae89032 --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* (COSMIC C V4.2F) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_a.s b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_a.s new file mode 100644 index 0000000..12dc547 --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_a.s @@ -0,0 +1,325 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 68HC12 Specific code +; (COSMIC C V4.2F) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + +OS_TICK_OC: equ 7 ; We will use Output Compare #7 to generate tick interrupts +OS_TICK_OC_CNTS: equ 5000 ; 100 Hz tick rate (assumes Free Running Timer runs at 500 KHz) + ; OS_TICK_OC_CNTS = CPU_FRT_FREQ / OS_TICKS_PER_SEC + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +TFLG1: equ $008E ; I/O port addresses. Assumes all 68HC12 I/Os start at 0x0000 +TC0: equ $0090 +TC1: equ $0092 +TC2: equ $0094 +TC3: equ $0096 +TC4: equ $0098 +TC5: equ $009A +TC6: equ $009C +TC7: equ $009E + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef _OSStartHighRdy + xdef _OSCtxSw + xdef _OSIntCtxSw + xdef _OSCPUSaveSR + xdef _OSCPURestoreSR + xdef _OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref _OSIntExit + xref _OSIntNesting + xref _OSPrioCur + xref _OSPrioHighRdy + xref _OSRunning + xref _OSTaskSwHook + xref _OSTCBCur + xref _OSTCBHighRdy + xref _OSTimeTick + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +_OSStartHighRdy: + jsr _OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab _OSRunning ; 4~ + + ldx _OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 --> PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +;******************************************************************************************************** + +_OSCtxSw: + pshy ; 2~, Save context of 'old' task + pshx ; 2~ + psha ; 2~ + pshb ; 2~ + pshc ; 2~ + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +_OSIntCtxSw: + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + + +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the B register as expected by the +; compiler. +;******************************************************************************************************** + +_OSCPUSaveSR: + tfr ccr,b ; Save CCR in B + sei ; Disable interrupts + rts + +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the CCR to restore. It is assumed that this 'argument' is +; passed in the B register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** + +_OSCPURestoreSR: + tfr b,ccr + rts + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the 68HC12's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see OS_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see OS_CFG.H and this file) which corresponds to the number of FRT (Free Running +; Timer) counts to the next interrupt. +; +; 2) You must specify which output compare will be used by the tick ISR as follows: +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 0 to use OUTPUT COMPARE #0 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 1 to use OUTPUT COMPARE #1 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 2 to use OUTPUT COMPARE #2 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 3 to use OUTPUT COMPARE #3 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 4 to use OUTPUT COMPARE #4 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 5 to use OUTPUT COMPARE #5 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 6 to use OUTPUT COMPARE #6 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 7 to use OUTPUT COMPARE #7 +; +; 3) TFLG1, TC0 ... TC7 are defined in this file. +;******************************************************************************************************** + +_OSTickISR: + inc _OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab _OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne _OSTickISR1 ; 3~ + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +_OSTickISR1: +if OS_TICK_OC == 0 + ldab #$01 ; 2~, Clear C0F interrupt flag (bit 0) + stab TFLG1 ; 4~ + ldd TC0 ; 5~, Set TC0 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC0 ; 5~ +endif + +if OS_TICK_OC == 1 + ldab #$02 ; 2~, Clear C1F interrupt flag (bit 1) + stab TFLG1 ; 4~ + ldd TC1 ; 5~, Set TC1 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC1 ; 5~ +endif + +if OS_TICK_OC == 2 + ldab #$04 ; 2~, Clear C2F interrupt flag (bit 2) + stab TFLG1 ; 4~ + ldd TC2 ; 5~, Set TC2 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC2 ; 5~ +endif + +if OS_TICK_OC == 3 + ldab #$08 ; 2~, Clear C3F interrupt flag (bit 3) + stab TFLG1 ; 4~ + ldd TC3 ; 5~, Set TC3 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC3 ; 5~ +endif + +if OS_TICK_OC == 4 + ldab #$10 ; 2~, Clear C4F interrupt flag (bit 4) + stab TFLG1 ; 4~ + ldd TC4 ; 5~, Set TC4 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC4 ; 5~ +endif + +if OS_TICK_OC == 5 + ldab #$20 ; 2~, Clear C5F interrupt flag (bit 5) + stab TFLG1 ; 4~ + ldd TC5 ; 5~, Set TC5 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC5 ; 5~ +endif + +if OS_TICK_OC == 6 + ldab #$40 ; 2~, Clear C6F interrupt flag (bit 6) + stab TFLG1 ; 4~ + ldd TC6 ; 5~, Set TC6 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC6 ; 5~ +endif + +if OS_TICK_OC == 7 + ldab #$80 ; 2~, Clear C7F interrupt flag (bit 7) + stab TFLG1 ; 4~ + ldd TC7 ; 5~, Set TC7 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC7 ; 5~ +endif + + cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr _OSTimeTick ; 6~+, Call uC/OS-II's tick updating function + + jsr _OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_c.c b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_c.c new file mode 100644 index 0000000..37ecd4e --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_cpu_c.c @@ -0,0 +1,253 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* (COSMIC C V4.2F) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +******************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)p_arg; /* Simulate call to function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = 0x80; /* CCR Register (Disable STOP instruction) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/68HC12/DG128A/NonPaged/COSMIC/os_dbg.c b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_dbg.c new file mode 100644 index 0000000..396160f --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/COSMIC/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU.h b/Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU.h new file mode 100644 index 0000000..61b7f04 --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* IAR +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU_C.C b/Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU_C.C new file mode 100644 index 0000000..5fd129c --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/IAR/OS_CPU_C.C @@ -0,0 +1,253 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* IAR +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)pdata; /* Simulate call to function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = 0x80; /* CCR Register (Disable STOP instruction) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/68HC12/DG128A/NonPaged/IAR/os_cpu_a.s33 b/Ports/68HC12/DG128A/NonPaged/IAR/os_cpu_a.s33 new file mode 100644 index 0000000..3af1bb6 --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/IAR/os_cpu_a.s33 @@ -0,0 +1,264 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 68HC12 Specific code +; (COSMIC C V4.2F) +; +; Filename : os_cpu_a.s33 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + +OS_TICK_OC: equ 7 ; We will use Output Compare #7 to generate tick interrupts +OS_TICK_OC_CNTS: equ 5000 ; 100 Hz tick rate (assumes Free Running Timer runs at 500 KHz) + ; OS_TICK_OC_CNTS = CPU_FRT_FREQ / OS_TICKS_PER_SEC + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +TFLG1: equ $008E ; I/O port addresses. Assumes all 68HC12 I/Os start at 0x0000 +TC0: equ $0090 +TC1: equ $0092 +TC2: equ $0094 +TC3: equ $0096 +TC4: equ $0098 +TC5: equ $009A +TC6: equ $009C +TC7: equ $009E + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSCPUSaveSR + PUBLIC OSCPURestoreSR + PUBLIC OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSTimeTick + + RSEG CODE(0) + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + jsr OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab OSRunning ; 4~ + + ldx OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 --> PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +;******************************************************************************************************** + + +OSCtxSw: + pshy ; 2~, Save context of 'old' task + pshx ; 2~ + psha ; 2~ + pshb ; 2~ + pshc ; 2~ + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +OSIntCtxSw: + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + + +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the B register as expected by the +; compiler. +;******************************************************************************************************** + +OSCPUSaveSR: + tfr ccr,b ; Save CCR in B + sei ; Disable interrupts + rts + +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the CCR to restore. It is assumed that this 'argument' is +; passed in the B register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** + +OSCPURestoreSR: + tfr b,ccr + rts + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the 68HC12's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see OS_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see OS_CFG.H and this file) which corresponds to the number of FRT (Free Running +; Timer) counts to the next interrupt. +; +; 2) This code assues the use of Output Compare #7 to generate the tick rate. +; +; 3) TFLG1, TC0 ... TC7 are defined in this file. +;******************************************************************************************************** + +OSTickISR: + inc OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne OSTickISR1 ; 3~ + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +OSTickISR1: + ldab #$80 ; 2~, Clear C7F interrupt flag (bit 7) + stab TFLG1 ; 4~ + ldd TC7 ; 5~, Set TC7 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC7 ; 5~ + + cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr OSTimeTick ; 6~+, Call uC/OS-II's tick updating function + + jsr OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + rti ; 12~, Return from interrupt, no higher priority tasks ready. + + END \ No newline at end of file diff --git a/Ports/68HC12/DG128A/NonPaged/IAR/os_dbg.c b/Ports/68HC12/DG128A/NonPaged/IAR/os_dbg.c new file mode 100644 index 0000000..396160f --- /dev/null +++ b/Ports/68HC12/DG128A/NonPaged/IAR/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU.h b/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU.h new file mode 100644 index 0000000..b0c27c3 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU.h @@ -0,0 +1,108 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Paged 68HC12 Specific code +* (COSMIC C V4.2F) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_A.S b/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_A.S new file mode 100644 index 0000000..d839609 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_A.S @@ -0,0 +1,345 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PAGED 68HC12 Specific code +; (COSMIC C V4.2F) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + +OS_TICK_OC: equ 7 ; We will use Output Compare #7 to generate tick interrupts +OS_TICK_OC_CNTS: equ 5000 ; 100 Hz tick rate (assumes Free Running Timer runs at 500 KHz) + ; OS_TICK_OC_CNTS = CPU_FRT_FREQ / OS_TICKS_PER_SEC + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +TFLG1: equ $008E ; I/O port addresses. Assumes all 68HC12 I/Os start at 0x0000 +TC0: equ $0090 +TC1: equ $0092 +TC2: equ $0094 +TC3: equ $0096 +TC4: equ $0098 +TC5: equ $009A +TC6: equ $009C +TC7: equ $009E + +PPAGE: equ $0035 ; Addres of PPAGE register + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef _OSCPUSaveSR + xdef _OSCPURestoreSR + xdef _OSStartHighRdy + xdef _OSCtxSw + xdef _OSIntCtxSw + xdef _OSTickISR + + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref _OSIntExit + xref _OSIntNesting + xref _OSPrioCur + xref _OSPrioHighRdy + xref _OSRunning + xref _OSTaskSwHook + xref _OSTCBCur + xref _OSTCBHighRdy + xref _OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the B register to pass a single 8-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +_OSCPUSaveSR: + tfr ccr,b ; It's assumed that 8-bit return value is in register B + sei ; Disable interrupts + rts ; Return to caller with B containing the previous CCR + + +_OSCPURestoreSR: + tfr b,ccr ; B contains the CCR value to restore, move to CCR + rts + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> pPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +_OSStartHighRdy: + jsr _OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab _OSRunning ; 4~ + + ldx _OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> pPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +;******************************************************************************************************** + +_OSCtxSw: + pshy ; 2~, Save context of 'old' task + pshx ; 2~ + psha ; 2~ + pshb ; 2~ + pshc ; 2~ + + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +_OSIntCtxSw: + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the 68HC12's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see OS_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see OS_CFG.H and this file) which corresponds to the number of FRT (Free Running +; Timer) counts to the next interrupt. +; +; 2) You must specify which output compare will be used by the tick ISR as follows: +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 0 to use OUTPUT COMPARE #0 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 1 to use OUTPUT COMPARE #1 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 2 to use OUTPUT COMPARE #2 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 3 to use OUTPUT COMPARE #3 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 4 to use OUTPUT COMPARE #4 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 5 to use OUTPUT COMPARE #5 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 6 to use OUTPUT COMPARE #6 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 7 to use OUTPUT COMPARE #7 +; +; 3) TFLG1, TC0 ... TC7 are defined in this file. +;******************************************************************************************************** + +_OSTickISR: + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + inc _OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab _OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne _OSTickISR1 ; 3~ + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +_OSTickISR1: +if OS_TICK_OC == 0 + ldab #$01 ; 2~, Clear C0F interrupt flag (bit 0) + stab TFLG1 ; 4~ + ldd TC0 ; 5~, Set TC0 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC0 ; 5~ +endif + +if OS_TICK_OC == 1 + ldab #$02 ; 2~, Clear C1F interrupt flag (bit 1) + stab TFLG1 ; 4~ + ldd TC1 ; 5~, Set TC1 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC1 ; 5~ +endif + +if OS_TICK_OC == 2 + ldab #$04 ; 2~, Clear C2F interrupt flag (bit 2) + stab TFLG1 ; 4~ + ldd TC2 ; 5~, Set TC2 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC2 ; 5~ +endif + +if OS_TICK_OC == 3 + ldab #$08 ; 2~, Clear C3F interrupt flag (bit 3) + stab TFLG1 ; 4~ + ldd TC3 ; 5~, Set TC3 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC3 ; 5~ +endif + +if OS_TICK_OC == 4 + ldab #$10 ; 2~, Clear C4F interrupt flag (bit 4) + stab TFLG1 ; 4~ + ldd TC4 ; 5~, Set TC4 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC4 ; 5~ +endif + +if OS_TICK_OC == 5 + ldab #$20 ; 2~, Clear C5F interrupt flag (bit 5) + stab TFLG1 ; 4~ + ldd TC5 ; 5~, Set TC5 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC5 ; 5~ +endif + +if OS_TICK_OC == 6 + ldab #$40 ; 2~, Clear C6F interrupt flag (bit 6) + stab TFLG1 ; 4~ + ldd TC6 ; 5~, Set TC6 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC6 ; 5~ +endif + +if OS_TICK_OC == 7 + ldab #$80 ; 2~, Clear C7F interrupt flag (bit 7) + stab TFLG1 ; 4~ + ldd TC7 ; 5~, Set TC7 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC7 ; 5~ +endif + + cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr _OSTimeTick ; 6~+, Call uC/OS-II's tick updating function + + jsr _OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_C.C b/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_C.C new file mode 100644 index 0000000..c5233b1 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/COSMIC/OS_CPU_C.C @@ -0,0 +1,259 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* PAGED 68HC12 Specific code +* (COSMIC C V4.2F) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) All your tasks are assumed to be in NON-PAGED memory. However, the tasks can call +* functions in PAGED memory and if a context switch occurs, the proper page will be +* saved/restored by uC/OS-II. Page #0 is stored onto the task's stack as a 'dummy' +* value. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + INT8U ppage; + + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)pdata; /* Simulate call to NON-BANKED function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = 0x80; /* CCR Register (Disable STOP instruction) */ + *--bstk = 0x00; /* Save the PPAGE register (Always page 0, see note 6) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/68HC12/DG128A/Paged/COSMIC/os_dbg.c b/Ports/68HC12/DG128A/Paged/COSMIC/os_dbg.c new file mode 100644 index 0000000..06bb615 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/COSMIC/os_dbg.c @@ -0,0 +1,172 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/includes.h b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/includes.h new file mode 100644 index 0000000..8e1e7d8 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/includes.h @@ -0,0 +1,49 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Master Include File +* +* Filename : includes.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define CPU_FRT_FREQ 500000L /* Free Running Timer rate (Hz) */ + +#define OS_TICK_OC 7 /* Output compare # used to generate a tick int. */ + + /* Number of FRT counts to produce an interrupt @tick rate */ +#define OS_TICK_OC_CNTS (CPU_FRT_FREQ / OS_TICKS_PER_SEC) + +/* +********************************************************************************************************* +* FILES TO INCLUDE +********************************************************************************************************* +*/ + +#include +#include + +#include diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/os_cfg.h b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/os_cfg.h new file mode 100644 index 0000000..e70f1c7 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/os_cfg.h @@ -0,0 +1,130 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Configuration for Motorola Paged 68HC12 +* +* Filename : os_cfg.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + + +#ifndef OS_CFG_H +#define OS_CFG_H + + /* ---------------------- MISCELLANEOUS ----------------------- */ +#define OS_ARG_CHK_EN 1 /* Enable (1) or Disable (0) argument checking */ +#define OS_CPU_HOOKS_EN 1 /* uC/OS-II hooks are found in the processor port files */ + +#define OS_DEBUG_EN 1 /* Enable(1) debug variables */ + +#define OS_EVENT_NAME_SIZE 32 /* Determine the size of the name of a Sem, Mutex, Mbox or Q */ + +#define OS_LOWEST_PRIO 63 /* Defines the lowest priority that can be assigned ... */ + /* ... MUST NEVER be higher than 63! */ + +#define OS_MAX_EVENTS 10 /* Max. number of event control blocks in your application */ +#define OS_MAX_FLAGS 5 /* Max. number of Event Flag Groups in your application */ +#define OS_MAX_MEM_PART 5 /* Max. number of memory partitions */ +#define OS_MAX_QS 4 /* Max. number of queue control blocks in your application */ +#define OS_MAX_TASKS 63 /* Max. number of tasks in your application, MUST be >= 2 */ + +#define OS_SCHED_LOCK_EN 1 /* Include code for OSSchedLock() and OSSchedUnlock() */ + +#define OS_TASK_IDLE_STK_SIZE 128 /* Idle task stack size (# of OS_STK wide entries) */ + +#define OS_TASK_STAT_EN 1 /* Enable (1) or Disable(0) the statistics task */ +#define OS_TASK_STAT_STK_SIZE 128 /* Statistics task stack size (# of OS_STK wide entries) */ +#define OS_TASK_STAT_STK_CHK_EN 1 /* Check task stacks from statistic task */ + +#define OS_TICK_STEP_EN 1 /* Enable tick stepping feature for uC/OS-View */ +#define OS_TICKS_PER_SEC 20 /* Set the number of ticks in one second */ + + + /* ----------------------- EVENT FLAGS ------------------------ */ +#define OS_FLAG_EN 1 /* Enable (1) or Disable (0) code generation for EVENT FLAGS */ +#define OS_FLAG_WAIT_CLR_EN 1 /* Include code for Wait on Clear EVENT FLAGS */ +#define OS_FLAG_ACCEPT_EN 1 /* Include code for OSFlagAccept() */ +#define OS_FLAG_DEL_EN 1 /* Include code for OSFlagDel() */ +#define OS_FLAG_NAME_SIZE 32 /* Determine the size of the name of an event flag group */ +#define OS_FLAG_QUERY_EN 1 /* Include code for OSFlagQuery() */ + + + /* -------------------- MESSAGE MAILBOXES --------------------- */ +#define OS_MBOX_EN 1 /* Enable (1) or Disable (0) code generation for MAILBOXES */ +#define OS_MBOX_ACCEPT_EN 1 /* Include code for OSMboxAccept() */ +#define OS_MBOX_DEL_EN 1 /* Include code for OSMboxDel() */ +#define OS_MBOX_POST_EN 1 /* Include code for OSMboxPost() */ +#define OS_MBOX_POST_OPT_EN 1 /* Include code for OSMboxPostOpt() */ +#define OS_MBOX_QUERY_EN 1 /* Include code for OSMboxQuery() */ + + + /* --------------------- MEMORY MANAGEMENT -------------------- */ +#define OS_MEM_EN 1 /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */ +#define OS_MEM_QUERY_EN 1 /* Include code for OSMemQuery() */ +#define OS_MEM_NAME_SIZE 32 /* Determine the size of a memory partition name */ + + + /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */ +#define OS_MUTEX_EN 1 /* Enable (1) or Disable (0) code generation for MUTEX */ +#define OS_MUTEX_ACCEPT_EN 1 /* Include code for OSMutexAccept() */ +#define OS_MUTEX_DEL_EN 1 /* Include code for OSMutexDel() */ +#define OS_MUTEX_QUERY_EN 1 /* Include code for OSMutexQuery() */ + + + /* ---------------------- MESSAGE QUEUES ---------------------- */ +#define OS_Q_EN 1 /* Enable (1) or Disable (0) code generation for QUEUES */ +#define OS_Q_ACCEPT_EN 1 /* Include code for OSQAccept() */ +#define OS_Q_DEL_EN 1 /* Include code for OSQDel() */ +#define OS_Q_FLUSH_EN 1 /* Include code for OSQFlush() */ +#define OS_Q_POST_EN 1 /* Include code for OSQPost() */ +#define OS_Q_POST_FRONT_EN 1 /* Include code for OSQPostFront() */ +#define OS_Q_POST_OPT_EN 1 /* Include code for OSQPostOpt() */ +#define OS_Q_QUERY_EN 1 /* Include code for OSQQuery() */ + + + /* ------------------------ SEMAPHORES ------------------------ */ +#define OS_SEM_EN 1 /* Enable (1) or Disable (0) code generation for SEMAPHORES */ +#define OS_SEM_ACCEPT_EN 1 /* Include code for OSSemAccept() */ +#define OS_SEM_DEL_EN 1 /* Include code for OSSemDel() */ +#define OS_SEM_QUERY_EN 1 /* Include code for OSSemQuery() */ + + + /* --------------------- TASK MANAGEMENT ---------------------- */ +#define OS_TASK_CHANGE_PRIO_EN 1 /* Include code for OSTaskChangePrio() */ +#define OS_TASK_CREATE_EN 1 /* Include code for OSTaskCreate() */ +#define OS_TASK_CREATE_EXT_EN 1 /* Include code for OSTaskCreateExt() */ +#define OS_TASK_DEL_EN 1 /* Include code for OSTaskDel() */ +#define OS_TASK_NAME_SIZE 32 /* Determine the size of a task name */ +#define OS_TASK_PROFILE_EN 1 /* Include variables in OS_TCB for profiling */ +#define OS_TASK_QUERY_EN 1 /* Include code for OSTaskQuery() */ +#define OS_TASK_SUSPEND_EN 1 /* Include code for OSTaskSuspend() and OSTaskResume() */ +#define OS_TASK_SW_HOOK_EN 1 /* Include code for OSTaskSwHook() */ + + + /* --------------------- TIME MANAGEMENT ---------------------- */ +#define OS_TIME_DLY_HMSM_EN 1 /* Include code for OSTimeDlyHMSM() */ +#define OS_TIME_DLY_RESUME_EN 1 /* Include code for OSTimeDlyResume() */ +#define OS_TIME_GET_SET_EN 1 /* Include code for OSTimeGet() and OSTimeSet() */ +#define OS_TIME_TICK_HOOK_EN 1 /* Include code for OSTimeTickHook() */ + + +typedef INT16U OS_FLAGS; /* Date type for event flag bits (8, 16 or 32 bits) */ + +#endif diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/test.c b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/test.c new file mode 100644 index 0000000..207710c --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/test.c @@ -0,0 +1,239 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Paged M68HC12 Sample code +* IAR +* +* Filename : test.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* VARIABLES +********************************************************************************************************* +*/ + +#define APP_TASK_STK_SIZE 256 + +/* +********************************************************************************************************* +* VARIABLES +********************************************************************************************************* +*/ + +OS_STK AppStartTaskStk[APP_TASK_STK_SIZE]; +OS_STK AppTask1Stk[APP_TASK_STK_SIZE]; +OS_STK AppTask2Stk[APP_TASK_STK_SIZE]; + +INT16U AppTask1Ctr; +INT16U AppTask2Ctr; + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +static void AppStartTask(void *pdata); +static void AppTask1(void *pdata); +static void AppTask2(void *pdata); +static void AppTickInit(void); + +/* +********************************************************************************************************* +* main() +* +* Description : This is the standard entry point for C code. It is assumed that your code will call +* main() once you have performed all necessary 68HC12 and C initialization. +* Arguments : none +********************************************************************************************************* +*/ + +void main (void) +{ + /*---- Any initialization code prior to calling OSInit() goes HERE --------------------------------*/ + + OSInit(); /* Initialize "uC/OS-II, The Real-Time Kernel" */ + + /*---- Any initialization code before starting multitasking ---------------------------------------*/ + + OSTaskCreate(AppStartTask, (void *)0, (void *)&AppStartTaskStk[APP_TASK_STK_SIZE - 1], 0); + + /*---- Create any other task you want before we start multitasking --------------------------------*/ + + OSStart(); /* Start multitasking (i.e. give control to uC/OS-II) */ +} + +/* +********************************************************************************************************* +* STARTUP TASK +* +* Description : This is an example of a startup task. As mentioned in the book's text, you MUST +* initialize the ticker only once multitasking has started. +* Arguments : pdata is the argument passed to 'AppStartTask()' by 'OSTaskCreate()'. +* Notes : 1) The first line of code is used to prevent a compiler warning because 'pdata' is not +* used. The compiler should not generate any code for this statement. +* 2) Interrupts are enabled once the task start because the I-bit of the CCR register was +* set to 0 by 'OSTaskCreate()'. +********************************************************************************************************* +*/ + +static void AppStartTask (void *pdata) +{ + pdata = pdata; + AppTickInit(); /* Initialize the ticker */ + /*---- Task initialization code goes HERE! --------------------------------------------------------*/ + OSTaskCreate(AppTask1, (void *)0, (void *)&AppTask1Stk[APP_TASK_STK_SIZE - 1], 10); + OSTaskCreate(AppTask2, (void *)0, (void *)&AppTask2Stk[APP_TASK_STK_SIZE - 1], 20); + + while (TRUE) { /* Task body, always written as an infinite loop. */ + /*---- Task code goes HERE! -------------------------------------------------------------------*/ + OSTimeDly(1); /* Delay task execution for one clock tick */ + } +} + +/* +********************************************************************************************************* +* TASK #1 +* +* Description : This is an example of a task. +* Arguments : pdata is the argument passed to 'AppTask1()' by 'OSTaskCreate()'. +* Notes : 1) The first line of code is used to prevent a compiler warning because 'pdata' is not +* used. The compiler should not generate any code for this statement. +* 2) Interrupts are enabled once the task start because the I-bit of the CCR register was +* set to 0 by 'OSTaskCreate()'. +********************************************************************************************************* +*/ + +static void AppTask1 (void *pdata) +{ + pdata = pdata; + /*---- Task initialization code goes HERE! --------------------------------------------------------*/ + + while (TRUE) { /* Task body, always written as an infinite loop. */ + /*---- Task code goes HERE! -------------------------------------------------------------------*/ + AppTask1Ctr++; + OSTimeDly(1); /* Delay task execution for one clock tick */ + } +} + +/* +********************************************************************************************************* +* TASK #2 +* +* Description : This is an example of a task. +* Arguments : pdata is the argument passed to 'AppTask2()' by 'OSTaskCreate()'. +* Notes : 1) The first line of code is used to prevent a compiler warning because 'pdata' is not +* used. The compiler should not generate any code for this statement. +* 2) Interrupts are enabled once the task start because the I-bit of the CCR register was +* set to 0 by 'OSTaskCreate()'. +********************************************************************************************************* +*/ + +static void AppTask2 (void *pdata) +{ + pdata = pdata; + /*---- Task initialization code goes HERE! --------------------------------------------------------*/ + + while (TRUE) { /* Task body, always written as an infinite loop. */ + /*---- Task code goes HERE! -------------------------------------------------------------------*/ + AppTask2Ctr++; + OSTimeDly(1); /* Delay task execution for one clock tick */ + } +} + +/* +********************************************************************************************************* +* TICKER INITIALIZATION +* +* Description : This function is used to initialize one of the eight output compares to generate an +* interrupt at the desired tick rate. You must decide which output compare you will be +* using by setting the configuration variable OS_TICK_OC (see OS_CFG.H and also OS_CPU_A.S) +* to 0..7 depending on which output compare to use. +* OS_TICK_OC set to 0 chooses output compare #0 as the ticker source +* OS_TICK_OC set to 1 chooses output compare #1 as the ticker source +* OS_TICK_OC set to 2 chooses output compare #2 as the ticker source +* OS_TICK_OC set to 3 chooses output compare #3 as the ticker source +* OS_TICK_OC set to 4 chooses output compare #4 as the ticker source +* OS_TICK_OC set to 5 chooses output compare #5 as the ticker source +* OS_TICK_OC set to 6 chooses output compare #6 as the ticker source +* OS_TICK_OC set to 7 chooses output compare #7 as the ticker source +* Arguments : none +* Notes : 1) It is assumed that you have set the prescaler rate of the free running timer within +* the first 64 E clock cycles of the 68HC12. +* 2) CPU registers are define in IO.H (see COSMIC compiler) and in OS_CPU_A.S. +********************************************************************************************************* +*/ + +static void AppTickInit (void) +{ + TSCR = 0x80; /* Enable timer */ + +#if OS_TICK_OC == 0 + TIOS |= 0x01; /* Make channel an output compare */ + TC0 = TCNT + OS_TICK_OC_CNTS; /* Set TC0 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x01; /* Enable OC0 interrupt. */ +#endif + +#if OS_TICK_OC == 1 + TIOS |= 0x02; /* Make channel an output compare */ + TC1 = TCNT + OS_TICK_OC_CNTS; /* Set TC1 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x02; /* Enable OC1 interrupt. */ +#endif + +#if OS_TICK_OC == 2 + TIOS |= 0x04; /* Make channel an output compare */ + TC2 = TCNT + OS_TICK_OC_CNTS; /* Set TC2 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x04; /* Enable OC2 interrupt. */ +#endif + +#if OS_TICK_OC == 3 + TIOS |= 0x08; /* Make channel an output compare */ + TC3 = TCNT + OS_TICK_OC_CNTS; /* Set TC3 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x08; /* Enable OC3 interrupt. */ +#endif + +#if OS_TICK_OC == 4 + TIOS |= 0x10; /* Make channel an output compare */ + TC4 = TCNT + OS_TICK_OC_CNTS; /* Set TC4 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x10; /* Enable OC4 interrupt. */ +#endif + +#if OS_TICK_OC == 5 + TIOS |= 0x20; /* Make channel an output compare */ + TC5 = TCNT + OS_TICK_OC_CNTS; /* Set TC5 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x20; /* Enable OC5 interrupt. */ +#endif + +#if OS_TICK_OC == 6 + TIOS |= 0x40; /* Make channel an output compare */ + TC6 = TCNT + OS_TICK_OC_CNTS; /* Set TC6 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x40; /* Enable OC6 interrupt. */ +#endif + +#if OS_TICK_OC == 7 + TIOS |= 0x80; /* Make channel an output compare */ + TC7 = TCNT + OS_TICK_OC_CNTS; /* Set TC7 to present time + OS_TICK_OC_CNTS */ + TMSK1 |= 0x80; /* Enable OC7 interrupt. */ +#endif +} diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/vectors.c b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/vectors.c new file mode 100644 index 0000000..4407d7d --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/Ex1/vectors.c @@ -0,0 +1,159 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* PAGED 68HC812 INTERRUPT VECTOR TABLE +* IAR +* +* Filename : vectors.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* MC68HC812 +* INTERRUPT VECTOR TABLE +* +* Description: This is the interrupt vector table used by the MC68HC812 CPU. Note that unused +* interrupts are vectored to NULL. +* Notes : 1) You MUST define the vector that defines the address of your startup code. +********************************************************************************************************* +*/ + +void (* const OSVectorTbl[])(void) = { /* This table begins at 0xFF80 */ + (void (*)())NULL, /* 0xFF80 Reserved */ + (void (*)())NULL, /* 0xFF82 Reserved */ + (void (*)())NULL, /* 0xFF84 Reserved */ + (void (*)())NULL, /* 0xFF86 Reserved */ + (void (*)())NULL, /* 0xFF88 Reserved */ + (void (*)())NULL, /* 0xFF8A Reserved */ + (void (*)())NULL, /* 0xFF8C Reserved */ + (void (*)())NULL, /* 0xFF8E Reserved */ + + (void (*)())NULL, /* 0xFF90 Reserved */ + (void (*)())NULL, /* 0xFF92 Reserved */ + (void (*)())NULL, /* 0xFF94 Reserved */ + (void (*)())NULL, /* 0xFF96 Reserved */ + (void (*)())NULL, /* 0xFF98 Reserved */ + (void (*)())NULL, /* 0xFF9A Reserved */ + (void (*)())NULL, /* 0xFF9C Reserved */ + (void (*)())NULL, /* 0xFF9E Reserved */ + + (void (*)())NULL, /* 0xFFA0 Reserved */ + (void (*)())NULL, /* 0xFFA2 Reserved */ + (void (*)())NULL, /* 0xFFA4 Reserved */ + (void (*)())NULL, /* 0xFFA6 Reserved */ + (void (*)())NULL, /* 0xFFA8 Reserved */ + (void (*)())NULL, /* 0xFFAA Reserved */ + (void (*)())NULL, /* 0xFFAC Reserved */ + (void (*)())NULL, /* 0xFFAE Reserved */ + + (void (*)())NULL, /* 0xFFB0 Reserved */ + (void (*)())NULL, /* 0xFFB2 Reserved */ + (void (*)())NULL, /* 0xFFB4 Reserved */ + (void (*)())NULL, /* 0xFFB6 Reserved */ + (void (*)())NULL, /* 0xFFB8 Reserved */ + (void (*)())NULL, /* 0xFFBA Reserved */ + (void (*)())NULL, /* 0xFFBC Reserved */ + (void (*)())NULL, /* 0xFFBE Reserved */ + + (void (*)())NULL, /* 0xFFC0 Reserved */ + (void (*)())NULL, /* 0xFFC2 Reserved */ + (void (*)())NULL, /* 0xFFC4 Reserved */ + (void (*)())NULL, /* 0xFFC6 Reserved */ + (void (*)())NULL, /* 0xFFC8 Reserved */ + (void (*)())NULL, /* 0xFFCA Reserved */ + (void (*)())NULL, /* 0xFFCC Reserved */ + (void (*)())NULL, /* 0xFFCE Key Wakeup H */ + + (void (*)())NULL, /* 0xFFD0 Key Wakeup J */ + (void (*)())NULL, /* 0xFFD2 ATD */ + (void (*)())NULL, /* 0xFFD4 SCI 1 */ + (void (*)())NULL, /* 0xFFD6 SCI 0 */ + (void (*)())NULL, /* 0xFFD8 SPI Serial Transfer Complete */ + (void (*)())NULL, /* 0xFFDA Pulse Accumulator Input Edge */ + (void (*)())NULL, /* 0xFFDC Pulse Accumulator Overflow */ + (void (*)())NULL, /* 0xFFDE Timer Overflow */ + +#if OS_TICK_OC == 7 + (void (*)())OSTickISR, /* 0xFFE0 Timer Channel 7 */ +#else + (void (*)())NULL, /* 0xFFE0 Timer Channel 7 */ +#endif + +#if OS_TICK_OC == 6 + (void (*)())OSTickISR, /* 0xFFE2 Timer Channel 6 */ +#else + (void (*)())NULL, /* 0xFFE2 Timer Channel 6 */ +#endif + +#if OS_TICK_OC == 5 + (void (*)())OSTickISR, /* 0xFFE4 Timer Channel 5 */ +#else + (void (*)())NULL, /* 0xFFE4 Timer Channel 5 */ +#endif + +#if OS_TICK_OC == 4 + (void (*)())OSTickISR, /* 0xFFE6 Timer Channel 4 */ +#else + (void (*)())NULL, /* 0xFFE6 Timer Channel 4 */ +#endif + +#if OS_TICK_OC == 3 + (void (*)())OSTickISR, /* 0xFFE8 Timer Channel 3 */ +#else + (void (*)())NULL, /* 0xFFE8 Timer Channel 3 */ +#endif + +#if OS_TICK_OC == 2 + (void (*)())OSTickISR, /* 0xFFEA Timer Channel 2 */ +#else + (void (*)())NULL, /* 0xFFEA Timer Channel 2 */ +#endif + +#if OS_TICK_OC == 1 + (void (*)())OSTickISR, /* 0xFFEA Timer Channel 1 */ +#else + (void (*)())NULL, /* 0xFFEA Timer Channel 1 */ +#endif + +#if OS_TICK_OC == 0 + (void (*)())OSTickISR, /* 0xFFEA Timer Channel 0 */ +#else + (void (*)())NULL, /* 0xFFEA Timer Channel 0 */ +#endif + + (void (*)())NULL, /* 0xFFF0 Real Time Interrupt (RTI) */ + + (void (*)())NULL, /* 0xFFF2 IRQ (External Pin) or Key Wakeup D */ + + (void (*)())NULL, /* 0xFFF4 XIRQ Pin (Pseudo Nonmaskable Interrupt) */ + + (void (*)())NULL, /* 0xFFF6 SWI */ + + (void (*)())NULL, /* 0xFFF8 Illegal Opcode Trap */ + + (void (*)())NULL, /* 0xFFFA COP Failure (Reset) */ + + (void (*)())NULL, /* 0xFFFC COP Clock Monitor Fail (Reset) */ + + (void (*)())NULL /* 0xFFFE RESET */ +}; diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu.h b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..96167c3 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu.h @@ -0,0 +1,108 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* PAGED 68HC12 Specific code +* (MetroWerks) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_a.s b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_a.s new file mode 100644 index 0000000..043ed5c --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_a.s @@ -0,0 +1,347 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + + +;******************************************************************************************************** +; +; PAGED 68HC12 Specific code +; (MetroWerks) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + +OS_TICK_OC: equ 7 ; We will use Output Compare #7 to generate tick interrupts +OS_TICK_OC_CNTS: equ 5000 ; 100 Hz tick rate (assumes Free Running Timer runs at 500 KHz) + ; OS_TICK_OC_CNTS = CPU_FRT_FREQ / OS_TICKS_PER_SEC + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +TFLG1: equ $008E ; I/O port addresses. Assumes all 68HC12 I/Os start at 0x0000 +TC0: equ $0090 +TC1: equ $0092 +TC2: equ $0094 +TC3: equ $0096 +TC4: equ $0098 +TC5: equ $009A +TC6: equ $009C +TC7: equ $009E + +PPAGE: equ $0035 ; Addres of PPAGE register + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef OSCPUSaveSR + xdef OSCPURestoreSR + xdef OSStartHighRdy + xdef OSCtxSw + xdef OSIntCtxSw + xdef OSTickISR + + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref OSIntExit + xref OSIntNesting + xref OSPrioCur + xref OSPrioHighRdy + xref OSRunning + xref OSTaskSwHook + xref OSTCBCur + xref OSTCBHighRdy + xref OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the B register to pass a single 8-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +_OSCPUSaveSR: + tfr ccr,b ; It's assumed that 8-bit return value is in register B + sei ; Disable interrupts + rts ; Return to caller with B containing the previous CCR + + +_OSCPURestoreSR: + tfr b,ccr ; B contains the CCR value to restore, move to CCR + rts + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> pPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + jsr OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab OSRunning ; 4~ + + ldx OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> pPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +;******************************************************************************************************** + +OSCtxSw: + pshy ; 2~, Save context of 'old' task + pshx ; 2~ + psha ; 2~ + pshb ; 2~ + pshc ; 2~ + + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +OSIntCtxSw: + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the 68HC12's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see OS_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see OS_CFG.H and this file) which corresponds to the number of FRT (Free Running +; Timer) counts to the next interrupt. +; +; 2) You must specify which output compare will be used by the tick ISR as follows: +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 0 to use OUTPUT COMPARE #0 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 1 to use OUTPUT COMPARE #1 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 2 to use OUTPUT COMPARE #2 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 3 to use OUTPUT COMPARE #3 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 4 to use OUTPUT COMPARE #4 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 5 to use OUTPUT COMPARE #5 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 6 to use OUTPUT COMPARE #6 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 7 to use OUTPUT COMPARE #7 +; +; 3) TFLG1, TC0 ... TC7 are defined in this file. +;******************************************************************************************************** + +OSTickISR: + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + inc OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne OSTickISR1 ; 3~ + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +OSTickISR1: +if OS_TICK_OC == 0 + ldab #$01 ; 2~, Clear C0F interrupt flag (bit 0) + stab TFLG1 ; 4~ + ldd TC0 ; 5~, Set TC0 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC0 ; 5~ +endif + +if OS_TICK_OC == 1 + ldab #$02 ; 2~, Clear C1F interrupt flag (bit 1) + stab TFLG1 ; 4~ + ldd TC1 ; 5~, Set TC1 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC1 ; 5~ +endif + +if OS_TICK_OC == 2 + ldab #$04 ; 2~, Clear C2F interrupt flag (bit 2) + stab TFLG1 ; 4~ + ldd TC2 ; 5~, Set TC2 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC2 ; 5~ +endif + +if OS_TICK_OC == 3 + ldab #$08 ; 2~, Clear C3F interrupt flag (bit 3) + stab TFLG1 ; 4~ + ldd TC3 ; 5~, Set TC3 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC3 ; 5~ +endif + +if OS_TICK_OC == 4 + ldab #$10 ; 2~, Clear C4F interrupt flag (bit 4) + stab TFLG1 ; 4~ + ldd TC4 ; 5~, Set TC4 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC4 ; 5~ +endif + +if OS_TICK_OC == 5 + ldab #$20 ; 2~, Clear C5F interrupt flag (bit 5) + stab TFLG1 ; 4~ + ldd TC5 ; 5~, Set TC5 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC5 ; 5~ +endif + +if OS_TICK_OC == 6 + ldab #$40 ; 2~, Clear C6F interrupt flag (bit 6) + stab TFLG1 ; 4~ + ldd TC6 ; 5~, Set TC6 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC6 ; 5~ +endif + +if OS_TICK_OC == 7 + ldab #$80 ; 2~, Clear C7F interrupt flag (bit 7) + stab TFLG1 ; 4~ + ldd TC7 ; 5~, Set TC7 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC7 ; 5~ +endif + + cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr OSTimeTick ; 6~+, Call uC/OS-II's tick updating function + + jsr OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_c.c b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_c.c new file mode 100644 index 0000000..97de121 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_cpu_c.c @@ -0,0 +1,259 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* PAGED 68HC12 Specific code +* (MetroWerks) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) All your tasks are assumed to be in NON-PAGED memory. However, the tasks can call +* functions in PAGED memory and if a context switch occurs, the proper page will be +* saved/restored by uC/OS-II. Page #0 is stored onto the task's stack as a 'dummy' +* value. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + INT8U ppage; + + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)pdata; /* Simulate call to NON-BANKED function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = 0x80; /* CCR Register (Disable STOP instruction) */ + *--bstk = 0x00; /* Save the PPAGE register (Always page 0, see note 6) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/68HC12/DG128A/Paged/CodeWarrior/os_dbg.c b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..29f4a53 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/CodeWarrior/os_dbg.c @@ -0,0 +1,264 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/68HC12/DG128A/Paged/IAR/os_cpu.h b/Ports/68HC12/DG128A/Paged/IAR/os_cpu.h new file mode 100644 index 0000000..61b7f04 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/IAR/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* IAR +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/68HC12/DG128A/Paged/IAR/os_cpu_a.s33 b/Ports/68HC12/DG128A/Paged/IAR/os_cpu_a.s33 new file mode 100644 index 0000000..2a1f3bf --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/IAR/os_cpu_a.s33 @@ -0,0 +1,286 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 68HC12 Specific code +; (COSMIC C V4.2F) +; +; Filename : os_cpu_a.s33 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + +OS_TICK_OC: equ 7 ; We will use Output Compare #7 to generate tick interrupts +OS_TICK_OC_CNTS: equ 5000 ; 100 Hz tick rate (assumes Free Running Timer runs at 500 KHz) + ; OS_TICK_OC_CNTS = CPU_FRT_FREQ / OS_TICKS_PER_SEC + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +TFLG1: equ $008E ; I/O port addresses. Assumes all 68HC12 I/Os start at 0x0000 +TC0: equ $0090 +TC1: equ $0092 +TC2: equ $0094 +TC3: equ $0096 +TC4: equ $0098 +TC5: equ $009A +TC6: equ $009C +TC7: equ $009E + +PPAGE: equ $0035 ; Address of PPAGE register + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSCPUSaveSR + PUBLIC OSCPURestoreSR + PUBLIC OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSTimeTick + + RSEG CODE(0) + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> PPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + jsr OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab OSRunning ; 4~ + + ldx OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get the value of the PPAGE register from task's stack + staa PPAGE ; 3~, Store into the CPU's PPAGE register + + rti ; 8~, Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 --> PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> PPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +;******************************************************************************************************** + + +OSCtxSw: + pshy ; 2~, Save context of 'old' task + pshx ; 2~ + psha ; 2~ + pshb ; 2~ + pshc ; 2~ + + ldaa PPAGE ; 3~, Store PPAGE onto task's stack + psha ; 2~ + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get the value of the PPAGE register from task's stack + staa PPAGE ; 3~, Store into the CPU's PPAGE register + + rti ; 8~, Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +OSIntCtxSw: + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get the value of the PPAGE register from task's stack + staa PPAGE ; 3~, Store into the CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the B register as expected by the +; compiler. +;******************************************************************************************************** + +OSCPUSaveSR: + tfr ccr,b ; Save CCR in B + sei ; Disable interrupts + rts + +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the CCR to restore. It is assumed that this 'argument' is +; passed in the B register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** + +OSCPURestoreSR: + tfr b,ccr + rts + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the 68HC12's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see OS_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see OS_CFG.H and this file) which corresponds to the number of FRT (Free Running +; Timer) counts to the next interrupt. +; +; 2) This code assues the use of Output Compare #7 to generate the tick rate. +; +; 3) TFLG1, TC0 ... TC7 are defined in this file. +;******************************************************************************************************** + +OSTickISR: + ldaa PPAGE ; 3~, Store PPAGE onto task's stack + psha ; 2~ + + inc OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne OSTickISR1 ; 3~ + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +OSTickISR1: + ldab #$80 ; 2~, Clear C7F interrupt flag (bit 7) + stab TFLG1 ; 4~ + ldd TC7 ; 5~, Set TC7 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC7 ; 5~ + + cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr OSTimeTick ; 6~+, Call uC/OS-II's tick updating function + + jsr OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + pula ; 3~, Get the value of the PPAGE register from task's stack + staa PPAGE ; 3~, Store into the CPU's PPAGE register + + rti ; 12~, Return from interrupt, no higher priority tasks ready. + + END \ No newline at end of file diff --git a/Ports/68HC12/DG128A/Paged/IAR/os_cpu_c.c b/Ports/68HC12/DG128A/Paged/IAR/os_cpu_c.c new file mode 100644 index 0000000..4b180c5 --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/IAR/os_cpu_c.c @@ -0,0 +1,258 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* IAR +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) All your tasks are assumed to be in NON-PAGED memory. However, the tasks can call +* functions in PAGED memory and if a context switch occurs, the proper page will be +* saved/restored by uC/OS-II. Page #0 is stored onto the task's stack as a 'dummy' +* value. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)pdata; /* Simulate call to NON-BANKED function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = 0x80; /* CCR Register (Disable STOP instruction) */ + *--bstk = 0x00; /* Save the PPAGE register (Always page 0, see note 6) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/68HC12/DG128A/Paged/IAR/os_dbg.c b/Ports/68HC12/DG128A/Paged/IAR/os_dbg.c new file mode 100644 index 0000000..396160f --- /dev/null +++ b/Ports/68HC12/DG128A/Paged/IAR/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/68HC12/NonPaged/COSMIC/os_cpu.h b/Ports/68HC12/NonPaged/COSMIC/os_cpu.h new file mode 100644 index 0000000..fbc4472 --- /dev/null +++ b/Ports/68HC12/NonPaged/COSMIC/os_cpu.h @@ -0,0 +1,110 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); /* Return the value of the CCR register and then .. */ + /* ... disable interrupts via SEI instruction. */ +void OS_CPU_SR_Restore(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/68HC12/NonPaged/COSMIC/os_cpu_a.s b/Ports/68HC12/NonPaged/COSMIC/os_cpu_a.s new file mode 100644 index 0000000..a3fc894 --- /dev/null +++ b/Ports/68HC12/NonPaged/COSMIC/os_cpu_a.s @@ -0,0 +1,220 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 68HC12 Specific code +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef _OSStartHighRdy + xdef _OSCtxSw + xdef _OSIntCtxSw + xdef _OS_CPU_SR_Save + xdef _OS_CPU_SR_Restore + xdef _OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref _OSIntExit + xref _OSIntNesting + xref _OSPrioCur + xref _OSPrioHighRdy + xref _OSRunning + xref _OSTaskSwHook + xref _OSTCBCur + xref _OSTCBHighRdy + xref _OSTickISR_Handler + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +_OSStartHighRdy: + jsr _OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab _OSRunning ; 4~ + + ldx _OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 --> PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +;******************************************************************************************************** + +_OSCtxSw: + pshy ; 2~, Save context of 'old' task + pshx ; 2~ + psha ; 2~ + pshb ; 2~ + pshc ; 2~ + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +_OSIntCtxSw: + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + + +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the B register as expected by the +; compiler. +;******************************************************************************************************** + +_OS_CPU_SR_Save: + tfr ccr,b ; Save CCR in B + sei ; Disable interrupts + rts + +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the CCR to restore. It is assumed that this 'argument' is +; passed in the B register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** + +_OS_CPU_SR_Restore: + tfr b,ccr + rts + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the 68HC12's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +;******************************************************************************************************** + +_OSTickISR: + inc _OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab _OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne _OSTickISR1 ; 3~ + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +_OSTickISR1: + jsr _OSTickISR_Handler ; 4~, OSTickISR_Handler(); + + jsr _OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/68HC12/NonPaged/COSMIC/os_cpu_c.c b/Ports/68HC12/NonPaged/COSMIC/os_cpu_c.c new file mode 100644 index 0000000..d07aefd --- /dev/null +++ b/Ports/68HC12/NonPaged/COSMIC/os_cpu_c.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#ifdef OS_VIEW_MODULE + OSView_TaskCreateHook(ptcb); +#else + ptcb = ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +******************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)p_arg; /* Simulate call to function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = 0x80; /* CCR Register (Disable STOP instruction) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#ifdef OS_VIEW_MODULE + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#ifdef OS_VIEW_MODULE + OSView_TickHook(); +#endif +} +#endif diff --git a/Ports/68HC12/NonPaged/COSMIC/os_dbg.c b/Ports/68HC12/NonPaged/COSMIC/os_dbg.c new file mode 100644 index 0000000..e7a28ee --- /dev/null +++ b/Ports/68HC12/NonPaged/COSMIC/os_dbg.c @@ -0,0 +1,266 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* 68HC12 Specific code +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/68HC12/Paged/COSMIC/os_cpu.h b/Ports/68HC12/Paged/COSMIC/os_cpu.h new file mode 100644 index 0000000..a7c47e9 --- /dev/null +++ b/Ports/68HC12/Paged/COSMIC/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Paged 68HC12 Specific code +* (COSMIC C V4.2F) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/68HC12/Paged/COSMIC/os_cpu_a.S b/Ports/68HC12/Paged/COSMIC/os_cpu_a.S new file mode 100644 index 0000000..b8c1335 --- /dev/null +++ b/Ports/68HC12/Paged/COSMIC/os_cpu_a.S @@ -0,0 +1,345 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PAGED 68HC12 Specific code +; (COSMIC C V4.2F) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + +OS_TICK_OC: equ 7 ; We will use Output Compare #7 to generate tick interrupts +OS_TICK_OC_CNTS: equ 5000 ; 100 Hz tick rate (assumes Free Running Timer runs at 500 KHz) + ; OS_TICK_OC_CNTS = CPU_FRT_FREQ / OS_TICKS_PER_SEC + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +TFLG1: equ $008E ; I/O port addresses. Assumes all 68HC12 I/Os start at 0x0000 +TC0: equ $0090 +TC1: equ $0092 +TC2: equ $0094 +TC3: equ $0096 +TC4: equ $0098 +TC5: equ $009A +TC6: equ $009C +TC7: equ $009E + +PPAGE: equ $0030 ; Addres of PPAGE register (assuming 68HC12DP256 part) + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef _OSCPUSaveSR + xdef _OSCPURestoreSR + xdef _OSStartHighRdy + xdef _OSCtxSw + xdef _OSIntCtxSw + xdef _OSTickISR + + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref _OSIntExit + xref _OSIntNesting + xref _OSPrioCur + xref _OSPrioHighRdy + xref _OSRunning + xref _OSTaskSwHook + xref _OSTCBCur + xref _OSTCBHighRdy + xref _OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the B register to pass a single 8-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +_OSCPUSaveSR: + tfr ccr,b ; It's assumed that 8-bit return value is in register B + sei ; Disable interrupts + rts ; Return to caller with B containing the previous CCR + + +_OSCPURestoreSR: + tfr b,ccr ; B contains the CCR value to restore, move to CCR + rts + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> pPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +_OSStartHighRdy: + jsr _OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab _OSRunning ; 4~ + + ldx _OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> pPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +;******************************************************************************************************** + +_OSCtxSw: + pshy ; 2~, Save context of 'old' task + pshx ; 2~ + psha ; 2~ + pshb ; 2~ + pshc ; 2~ + + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +_OSIntCtxSw: + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the 68HC12's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see OS_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see OS_CFG.H and this file) which corresponds to the number of FRT (Free Running +; Timer) counts to the next interrupt. +; +; 2) You must specify which output compare will be used by the tick ISR as follows: +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 0 to use OUTPUT COMPARE #0 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 1 to use OUTPUT COMPARE #1 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 2 to use OUTPUT COMPARE #2 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 3 to use OUTPUT COMPARE #3 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 4 to use OUTPUT COMPARE #4 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 5 to use OUTPUT COMPARE #5 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 6 to use OUTPUT COMPARE #6 +; Set OS_TICK_OC in OS_CFG.H (AND in this file) to 7 to use OUTPUT COMPARE #7 +; +; 3) TFLG1, TC0 ... TC7 are defined in this file. +;******************************************************************************************************** + +_OSTickISR: + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + inc _OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab _OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne _OSTickISR1 ; 3~ + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +_OSTickISR1: +if OS_TICK_OC == 0 + ldab #$01 ; 2~, Clear C0F interrupt flag (bit 0) + stab TFLG1 ; 4~ + ldd TC0 ; 5~, Set TC0 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC0 ; 5~ +endif + +if OS_TICK_OC == 1 + ldab #$02 ; 2~, Clear C1F interrupt flag (bit 1) + stab TFLG1 ; 4~ + ldd TC1 ; 5~, Set TC1 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC1 ; 5~ +endif + +if OS_TICK_OC == 2 + ldab #$04 ; 2~, Clear C2F interrupt flag (bit 2) + stab TFLG1 ; 4~ + ldd TC2 ; 5~, Set TC2 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC2 ; 5~ +endif + +if OS_TICK_OC == 3 + ldab #$08 ; 2~, Clear C3F interrupt flag (bit 3) + stab TFLG1 ; 4~ + ldd TC3 ; 5~, Set TC3 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC3 ; 5~ +endif + +if OS_TICK_OC == 4 + ldab #$10 ; 2~, Clear C4F interrupt flag (bit 4) + stab TFLG1 ; 4~ + ldd TC4 ; 5~, Set TC4 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC4 ; 5~ +endif + +if OS_TICK_OC == 5 + ldab #$20 ; 2~, Clear C5F interrupt flag (bit 5) + stab TFLG1 ; 4~ + ldd TC5 ; 5~, Set TC5 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC5 ; 5~ +endif + +if OS_TICK_OC == 6 + ldab #$40 ; 2~, Clear C6F interrupt flag (bit 6) + stab TFLG1 ; 4~ + ldd TC6 ; 5~, Set TC6 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC6 ; 5~ +endif + +if OS_TICK_OC == 7 + ldab #$80 ; 2~, Clear C7F interrupt flag (bit 7) + stab TFLG1 ; 4~ + ldd TC7 ; 5~, Set TC7 to present time + desired counts to next ISR + addd #OS_TICK_OC_CNTS ; 4~ + std TC7 ; 5~ +endif + + cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr _OSTimeTick ; 6~+, Call uC/OS-II's tick updating function + + jsr _OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/68HC12/Paged/COSMIC/os_cpu_c.c b/Ports/68HC12/Paged/COSMIC/os_cpu_c.c new file mode 100644 index 0000000..c5233b1 --- /dev/null +++ b/Ports/68HC12/Paged/COSMIC/os_cpu_c.c @@ -0,0 +1,259 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* PAGED 68HC12 Specific code +* (COSMIC C V4.2F) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) All your tasks are assumed to be in NON-PAGED memory. However, the tasks can call +* functions in PAGED memory and if a context switch occurs, the proper page will be +* saved/restored by uC/OS-II. Page #0 is stored onto the task's stack as a 'dummy' +* value. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + INT8U ppage; + + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)pdata; /* Simulate call to NON-BANKED function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = 0x80; /* CCR Register (Disable STOP instruction) */ + *--bstk = 0x00; /* Save the PPAGE register (Always page 0, see note 6) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/68HC12/Paged/COSMIC/os_dbg.c b/Ports/68HC12/Paged/COSMIC/os_dbg.c new file mode 100644 index 0000000..82725c6 --- /dev/null +++ b/Ports/68HC12/Paged/COSMIC/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/78K0/IAR/os_cpu.h b/Ports/78K0/IAR/os_cpu.h new file mode 100644 index 0000000..71882dd --- /dev/null +++ b/Ports/78K0/IAR/os_cpu.h @@ -0,0 +1,135 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* NEC 78K0 Specific code +* IAR C/C++ Compiler for NEC 78K0 4.60A +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short int INT16U; /* Unsigned 16 bit quantity */ +typedef signed short int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* The status register (SR) is 8-bits wide */ + +/* +********************************************************************************************************* +* NEC 78K0 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() __disable_interrupt() + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __enable_interrupt() + +#endif + +#if OS_CRITICAL_METHOD == 2 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() __asm("PUSH PSW"); \ + __asm("DI"); + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __asm("POP PSW"); \ + __asm("EI"); + +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = __get_interrupt_state(); \ + __disable_interrupt() + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __set_interrupt_state(cpu_sr) + +#endif + +/* +********************************************************************************************************* +* NEC 78K0 MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on the NEC 78K0 */ + +#define OS_TASK_SW() __break() /* Issues a break instruction */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSStartHighRdy ( void ); +void OSIntCtxSw ( void ); +void OSCtxSw ( void ); + +#endif diff --git a/Ports/78K0/IAR/os_cpu_a.s26 b/Ports/78K0/IAR/os_cpu_a.s26 new file mode 100644 index 0000000..0f29d68 --- /dev/null +++ b/Ports/78K0/IAR/os_cpu_a.s26 @@ -0,0 +1,264 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; NEC 78K0 Specific code +; IAR C/C++ Compiler for NEC 78K0 4.60A +; +; Filename : os_cpu_a.s26 +; Version : V2.93.00 +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + EXTERN OSTaskSwHook + EXTERN OSTCBHighRdy + EXTERN OSRunning + EXTERN OSTCBCur + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntEnter + EXTERN OSTimeTick + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN Tmr_TickISR_Handler ; implement function to clear the OS tick source + +;******************************************************************************************************** +; MACRO DEFINITIONS +;******************************************************************************************************** + +PUSHALL MACRO + PUSH RP0 + PUSH RP1 + PUSH RP2 + PUSH RP3 + ENDM + +POPALL MACRO + POP RP3 + POP RP2 + POP RP1 + POP RP0 + ENDM + + ASEGN RCODE:CODE, 0x0020 + DW OSTickISR ; Time tick vector + + ASEGN RCODE:CODE, 0x003E + DW OSCtxSw ; Context Switch vector + + RSEG CODE ; Program code + +;******************************************************************************************************** +; START HIGHEST PRIORITY READY TASK +; +; Description: This function is called by OSStart() to start the highest priority task that is ready to run. +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: + + CALL OSTaskSwHook ; call OSTaskSwHook() + + MOVW RP0, OSTCBHighRdy ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW RP3, RP0 + MOV R1, [RP3] + MOV R0, R1 + MOV R1, [RP3+0x01] + + MOVW SP, RP0 ; stack pointer = RP0 + + MOV A, #0x01 ; OSRunning = true + MOV OSRunning, A + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description: This function is called by OS_Sched() to perform a task level context switch. +; +; Note : OSCtxSw() MUST: +; a) Save the current task's registers onto the current task stack +; b) Save the SP into the current task's OS_TCB +; c) Call OSTaskSwHook() +; d) Copy OSPrioHighRdy to OSPrioCur +; e) Copy OSTCBHighRdy to OSTCBCur +; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; g) Restore all the registers from the high priority task stack +; h) Perform a return from interrupt +;******************************************************************************************************** + +OSCtxSw: + + PUSHALL ; save processor registers on the stack + + ; save current task's stack pointer into current task's OS_TCB + MOVW RP0, OSTCBCur ; OSTCBCur in RP3 + MOVW RP3, RP0 + MOVW RP0, SP + MOV [RP3+0x01], R1 ; OSTCBCur->OSTCBStkPtr = SP + MOV R1, R0 + MOV [RP3], R1 + + CALL OSTaskSwHook ; call OSTaskSwHook() + + MOVW RP0, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW OSTCBCur, RP0 ; OSTCBCur = OSTCBHighRdy + + MOV R1, OSPrioHighRdy + MOV OSPrioCur, R1 ; OSPrioCur = OSPrioHighRdy + + MOVW RP0, OSTCBHighRdy ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW RP3, RP0 + MOV R1, [RP3] + MOV R0, R1 + MOV R1, [RP3+0x01] + + MOVW SP, RP0 ; stack pointer = RP0 + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; ISR LEVEL CONTEXT SWITCH +; +; Description: This function is called by OSIntExit() to perform an ISR level context switch. +; +; Note : OSIntCtxSw() MUST: +; a) Call OSTaskSwHook() +; b) Copy OSPrioHighRdy to OSPrioCur +; c) Copy OSTCBHighRdy to OSTCBCur +; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; e) Restore all the registers from the high priority task stack +; f) Perform a return from interrupt +;******************************************************************************************************** + +OSIntCtxSw: + + CALL OSTaskSwHook ; call OSTaskSwHook() + + MOVW RP0, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW OSTCBCur, RP0 ; OSTCBCur = OSTCBHighRdy + + MOV R1, OSPrioHighRdy + MOV OSPrioCur, R1 ; OSPrioCur = OSPrioHighRdy + + MOVW RP0, OSTCBHighRdy ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW RP3, RP0 + MOV R1, [RP3] + MOV R0, R1 + MOV R1, [RP3+0x01] + + MOVW SP, RP0 ; stack pointer = RP0 + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; TICK ISR +; +; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source. +; +; Notes : 1) The following C pseudo-code describes the operations being performed in the code below. +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; SP = OSISRStkPtr; /* Use the ISR stack from now on */ +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; DISABLE general interrupts; /* Must DI before calling OSIntExit() */ +; OSIntExit(); +; if (OSIntNesting == 0) { +; SP = OSTCBHighRdy->OSTCBStkPtr; /* Restore the current task's stack */ +; } +; Restore the CPU registers +; Return from interrupt. +; +; 2) ALL ISRs should be written like this! +; +; 3) You MUST disable general interrupts BEFORE you call OSIntExit() because an interrupt +; COULD occur just as OSIntExit() returns and thus, the new ISR would save the SP of +; the ISR stack and NOT the SP of the task stack. This of course will most likely cause +; the code to crash. By disabling interrupts BEFORE OSIntExit(), interrupts would be +; disabled when OSIntExit() would return. This assumes that you are using OS_CRITICAL_METHOD +; #3 (which is the prefered method). +; +; 4) If you DON'T use a separate ISR stack then you don't need to disable general interrupts +; just before calling OSIntExit(). The pseudo-code for an ISR would thus look like this: +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; OSIntExit(); +; Restore the CPU registers +; Return from interrupt. +;******************************************************************************************************** + +OSTickISR: + + PUSHALL ; Save processor registers on the stack + + MOV R1, OSIntNesting + INC R1 ; increment OSIntNesting + CMP R1, #1 ; if OSIntNesting != 1 + BNZ OSTickISR1 ; jump to OSTickISR1 + + ; else + + MOVW RP0, OSTCBCur ; OSTCBCur in RP3 + MOVW RP3, RP0 + MOVW RP0, SP + MOV [RP3+0x01], R1 ; OSTCBCur->OSTCBStkPtr = SP + MOV R1, R0 + MOV [RP3], R1 + +OSTickISR1: + + CALL Tmr_TickISR_Handler ; clear timer interrupt source + + CALL OSTimeTick ; call OSTimeTick() + + CALL OSIntExit ; call OSIntExit() + + POPALL ; restore all processor registers from stack + + RETI ; return from interrupt + + END diff --git a/Ports/78K0/IAR/os_cpu_c.c b/Ports/78K0/IAR/os_cpu_c.c new file mode 100644 index 0000000..a0b5f09 --- /dev/null +++ b/Ports/78K0/IAR/os_cpu_c.c @@ -0,0 +1,307 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* NEC 78K0 Specific code +* IAR C/C++ Compiler for NEC 78K0 4.60A +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT8U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT8U *)ptos; /* Load stack pointer */ + *stk-- = (INT8U)((INT16U)pdata >> 8); + *stk-- = (INT8U)pdata; + *stk-- = (INT8U)0x82; /* PSW */ + *stk-- = (INT8U)((INT16U)task >> 8); /* PC bits 8-15 */ + *stk-- = (INT8U)task; /* PC bits 0-7 */ + *stk-- = 0x11; /* R1 */ + *stk-- = 0x00; /* R0 */ + *stk-- = 0x33; /* R3 */ + *stk-- = 0x22; /* R2 */ + *stk-- = 0x55; /* R5 */ + *stk-- = 0x44; /* R4 */ + *stk-- = 0x77; /* R7 */ + *stk = 0x66; /* R6 */ + + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/78K0/IAR/os_dbg.c b/Ports/78K0/IAR/os_dbg.c new file mode 100644 index 0000000..6ac5e86 --- /dev/null +++ b/Ports/78K0/IAR/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/78K0R/IAR/os_cpu.h b/Ports/78K0R/IAR/os_cpu.h new file mode 100644 index 0000000..6cdf7fd --- /dev/null +++ b/Ports/78K0R/IAR/os_cpu.h @@ -0,0 +1,135 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* NEC 78K0R Specific code +* IAR C/C++ Compiler for NEC 78K0R 4.60A +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short int INT16U; /* Unsigned 16 bit quantity */ +typedef signed short int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* The status register (SR) is 8-bits wide */ + +/* +********************************************************************************************************* +* NEC 78K0R +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() __disable_interrupt() + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __enable_interrupt() + +#endif + +#if OS_CRITICAL_METHOD == 2 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() __asm("PUSH PSW"); \ + __asm("DI"); + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __asm("POP PSW"); \ + __asm("EI"); + +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = __get_interrupt_state(); \ + __disable_interrupt() + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __set_interrupt_state(cpu_sr) + +#endif + +/* +********************************************************************************************************* +* NEC 78K0R MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on the NEC 78K0R */ + +#define OS_TASK_SW() __break() /* Issues a break instruction */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSStartHighRdy ( void ); +void OSIntCtxSw ( void ); +void OSCtxSw ( void ); + +#endif diff --git a/Ports/78K0R/IAR/os_cpu_a.asm b/Ports/78K0R/IAR/os_cpu_a.asm new file mode 100644 index 0000000..a5fc5b1 --- /dev/null +++ b/Ports/78K0R/IAR/os_cpu_a.asm @@ -0,0 +1,250 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; NEC 78K0R Specific code +; IAR C/C++ Compiler for NEC 78K0R 4.60A +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + EXTERN OSTaskSwHook + EXTERN OSTCBHighRdy + EXTERN OSRunning + EXTERN OSTCBCur + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntEnter + EXTERN OSTimeTick + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN Tmr_TickISR_Handler ; implement function to clear the OS tick source + +;******************************************************************************************************** +; MACRO DEFINITIONS +;******************************************************************************************************** + +PUSHALL MACRO + PUSH RP0 + PUSH RP1 + PUSH RP2 + PUSH RP3 + MOV A, CS ; Save CS register. + XCH A, X + MOV A, ES ; Save ES register. + PUSH AX + ENDM + +POPALL MACRO + POP AX ; Restore the ES register. + MOV ES, A + XCH A, X ; Restore the CS register. + MOV CS, A + POP RP3 + POP RP2 + POP RP1 + POP RP0 + ENDM + + ASEGN RCODE:CODE, 0x002C + DW OSTickISR ; Time tick vector + + ASEGN RCODE:CODE, 0x007E + DW OSCtxSw ; Context Switch vector + + RSEG CODE ; Program code + +;******************************************************************************************************** +; START HIGHEST PRIORITY READY TASK +; +; Description: This function is called by OSStart() to start the highest priority task that is ready to run. +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: + + CALL OSTaskSwHook ; call OSTaskSwHook() + MOVW RP1, OSTCBHighRdy ; address of OSTCBHighRdy in RP1 + MOVW RP0, 0x0000[RP1] ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW SP, RP0 ; stack pointer = RP0 + + MOV OSRunning, #0x01 ; OSRunning = True + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description: This function is called by OS_Sched() to perform a task level context switch. +; +; Note : OSCtxSw() MUST: +; a) Save the current task's registers onto the current task stack +; b) Save the SP into the current task's OS_TCB +; c) Call OSTaskSwHook() +; d) Copy OSPrioHighRdy to OSPrioCur +; e) Copy OSTCBHighRdy to OSTCBCur +; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; g) Restore all the registers from the high priority task stack +; h) Perform a return from interrupt +;******************************************************************************************************** + +OSCtxSw: + + PUSHALL ; save processor registers on the stack + + ; save current task's stack pointer into current task's OS_TCB + MOVW RP2, OSTCBCur ; OSTCBCur in RP2 + MOVW RP0, SP + MOVW [RP2], RP0 ; OSTCBCur->OSTCBStkPtr = SP + + CALL OSTaskSwHook ; call OSTaskSwHook + + MOVW RP0, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW OSTCBCur, RP0 ; OSTCBCur = OSTCBHighRdy + + MOV R1, OSPrioHighRdy + MOV OSPrioCur, R1 ; OSPrioCur = OSPrioHighRdy + + MOVW RP1, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW RP0, 0x0000[RP1] ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW SP, RP0 ; stack pointer = RP0 + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; ISR LEVEL CONTEXT SWITCH +; +; Description: This function is called by OSIntExit() to perform an ISR level context switch. +; +; Note : OSIntCtxSw() MUST: +; a) Call OSTaskSwHook() +; b) Copy OSPrioHighRdy to OSPrioCur +; c) Copy OSTCBHighRdy to OSTCBCur +; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; e) Restore all the registers from the high priority task stack +; f) Perform a return from interrupt +;******************************************************************************************************** + +OSIntCtxSw: + CALL OSTaskSwHook ; call OSTaskSwHook + + MOVW RP0, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW OSTCBCur, RP0 ; OSTCBCur = OSTCBHighRdy + + MOV R1, OSPrioHighRdy + MOV OSPrioCur, R1 ; OSPrioCur = OSPrioHighRdy + + MOVW RP1, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW RP0, 0x0000[RP1] ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW SP, RP0 ; stack pointer = RP0 + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; TICK ISR +; +; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source. +; +; Notes : 1) The following C pseudo-code describes the operations being performed in the code below. +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; SP = OSISRStkPtr; /* Use the ISR stack from now on */ +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; DISABLE general interrupts; /* Must DI before calling OSIntExit() */ +; OSIntExit(); +; if (OSIntNesting == 0) { +; SP = OSTCBHighRdy->OSTCBStkPtr; /* Restore the current task's stack */ +; } +; Restore the CPU registers +; Return from interrupt. +; +; 2) ALL ISRs should be written like this! +; +; 3) You MUST disable general interrupts BEFORE you call OSIntExit() because an interrupt +; COULD occur just as OSIntExit() returns and thus, the new ISR would save the SP of +; the ISR stack and NOT the SP of the task stack. This of course will most likely cause +; the code to crash. By disabling interrupts BEFORE OSIntExit(), interrupts would be +; disabled when OSIntExit() would return. This assumes that you are using OS_CRITICAL_METHOD +; #3 (which is the prefered method). +; +; 4) If you DON'T use a separate ISR stack then you don't need to disable general interrupts +; just before calling OSIntExit(). The pseudo-code for an ISR would thus look like this: +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; OSIntExit(); +; Restore the CPU registers +; Return from interrupt. +;******************************************************************************************************** + +OSTickISR: + + PUSHALL ; Save processor registers on the stack + + INC OSIntNesting ; increment OSIntNesting + CMP OSIntNesting, #1 ; if OSIntNesting != 1 + BNZ OSTickISR1 ; jump to OSTickISR1 + + ; else + + MOVW RP2, OSTCBCur ; OSTCBCur in RP2 + MOVW RP0, SP + MOVW [RP2], RP0 ; OSTCBCur->OSTCBStkPtr = SP + +OSTickISR1: + + CALL Tmr_TickISR_Handler ; clear timer interrupt source + + CALL OSTimeTick ; call OSTimeTick() + + CALL OSIntExit ; call OSIntExit() + + POPALL ; restore all processor registers from stack + + RETI ; return from interrupt + + END + diff --git a/Ports/78K0R/IAR/os_cpu_c.c b/Ports/78K0R/IAR/os_cpu_c.c new file mode 100644 index 0000000..12846ff --- /dev/null +++ b/Ports/78K0R/IAR/os_cpu_c.c @@ -0,0 +1,302 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* NEC 78K0R Specific code +* IAR C/C++ Compiler for NEC 78K0R 4.60A +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT16U *)ptos; /* Load stack pointer */ + *stk-- = (INT16U)((INT32U)pdata >> 16); + *stk-- = (INT16U)pdata; + *stk-- = (INT16U)(((INT32U)task >> 16) & 0x000F) | 0x8600; /* PC bits 16-19 in lower 8 bits, psw in upper 16 bits */ + *stk-- = (INT16U)task; /* PC bits 0-15 */ + *stk-- = 0x1100; /* RP0 */ + *stk-- = 0x3322; /* RP1 */ + *stk-- = 0x5544; /* RP2 */ + *stk = 0x7766; /* RP3 */ + + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/78K0R/IAR/os_dbg.c b/Ports/78K0R/IAR/os_dbg.c new file mode 100644 index 0000000..6ac5e86 --- /dev/null +++ b/Ports/78K0R/IAR/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/80186/DOS/L/BC45/os_cpu.h b/Ports/80186/DOS/L/BC45/os_cpu.h new file mode 100644 index 0000000..2b12d08 --- /dev/null +++ b/Ports/80186/DOS/L/BC45/os_cpu.h @@ -0,0 +1,150 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include +#include +#include +#include +#include +#include +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx. Not actually needed for ... */ +#define WORD INT16S /* ... uC/OS-II. */ +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 2 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm CLI /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm STI /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm {PUSHF; CLI} /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm POPF /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on 80x86 */ + +#define uCOS 0x80 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() asm INT uCOS + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT8U OSTickDOSCtr; /* Counter used to invoke DOS's tick handler every 'n' ticks */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +extern INT8U const OSTickDOSCtrReload; /* Reload value for OSTickDOSCtr when it reaches 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSTaskStkInit_FPE_x86(OS_STK **pptos, OS_STK **ppbos, INT32U *psize); + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); +void OSCPURestoreSR(OS_CPU_SR cpu_sr); +#endif + +#endif diff --git a/Ports/80186/DOS/L/BC45/os_cpu_a.asm b/Ports/80186/DOS/L/BC45/os_cpu_a.asm new file mode 100644 index 0000000..2dd7de7 --- /dev/null +++ b/Ports/80186/DOS/L/BC45/os_cpu_a.asm @@ -0,0 +1,297 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 80186 Specific code +; LARGE MEMORY MODEL +; +; Borland C/C++ V4.51 +; (IBM/PC Compatible Target) +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC and EXTERNAL REFERENCES +;******************************************************************************************************** + + PUBLIC _OSTickISR + PUBLIC _OSStartHighRdy + PUBLIC _OSCtxSw + PUBLIC _OSIntCtxSw + + EXTRN _OSIntExit:FAR + EXTRN _OSTimeTick:FAR + EXTRN _OSTaskSwHook:FAR + + EXTRN _OSIntNesting:BYTE + EXTRN _OSPrioHighRdy:BYTE + EXTRN _OSPrioCur:BYTE + EXTRN _OSRunning:BYTE + EXTRN _OSTCBCur:DWORD + EXTRN _OSTCBHighRdy:DWORD + +.MODEL LARGE +.CODE +.186 + PAGE +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW +; OFFSET of task code address +; SEGMENT of task code address +; OFFSET of 'p_arg' +; SEGMENT of 'p_arg' (High memory) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy PROC FAR + + MOV AX, SEG _OSTCBHighRdy ; Reload DS + MOV DS, AX ; +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AL, 1 ; OSRunning = TRUE; + MOV BYTE PTR DS:_OSRunning, AL ; (Indicates that multitasking has started) +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX+0] ; +; + POP DS ; Load task's context + POP ES ; + POPA ; +; + IRET ; Run task + +_OSStartHighRdy ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; void OSCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP -> OFFSET of task to suspend (Low memory) +; SEGMENT of task to suspend +; PSW of task to suspend (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSCtxSw PROC FAR +; + PUSHA ; Save current task's context + PUSH ES ; + PUSH DS ; +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL ; +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSCtxSw ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; void OSIntCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; OSTCBCur->OSTCBStkPtr ------> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +; +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSIntCtxSw PROC FAR +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSIntCtxSw ENDP + + PAGE +;********************************************************************************************************* +; HANDLE TICK ISR +; +; Description: This function is called 18.20648 times per second +; +; Arguments : none +; +; Returns : none +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SS:SP +; } + INT 81H; Chain into DOS every 54.925 mS +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* +; +_OSTickISR PROC FAR +; + PUSHA ; Save interrupted task's context + PUSH ES + PUSH DS +; + MOV AX, SEG(_OSIntNesting) ; Reload DS + MOV DS, AX + INC BYTE PTR DS:_OSIntNesting ; Notify uC/OS-II of ISR +; + CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1) + JNE SHORT _OSTickISR1 + MOV AX, SEG(_OSTCBCur) ; Reload DS + MOV DS, AX + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; +_OSTickISR1: + INT 081H ; Chain into DOS's tick ISR (Interrupt will be cleared by DOS) +; + CALL FAR PTR _OSTimeTick ; Process system tick +; + CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR +; + POP DS ; Restore interrupted task's context + POP ES + POPA +; + IRET ; Return to interrupted task +; +_OSTickISR ENDP +; + END diff --git a/Ports/80186/DOS/L/BC45/os_cpu_c.c b/Ports/80186/DOS/L/BC45/os_cpu_c.c new file mode 100644 index 0000000..33ebf51 --- /dev/null +++ b/Ports/80186/DOS/L/BC45/os_cpu_c.c @@ -0,0 +1,340 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +INT8U const OSTickDOSCtrReload = (INT8U)((FP32)OS_TICKS_PER_SEC / (FP32)18.20648 + (FP32)0.5); + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* PSW to 0x0002 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable +* interrupts. Failure to do this will make your system crash! +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT16U *)ptos; /* Load stack pointer */ + *stk-- = (INT16U)FP_SEG(p_arg); /* Simulate call to function with argument */ + *stk-- = (INT16U)FP_OFF(p_arg); + *stk-- = (INT16U)FP_SEG(task); + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0x0202; /* SW = Interrupts enabled */ + *stk-- = (INT16U)FP_SEG(task); /* Put pointer to task on top of stack */ + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0xAAAA; /* AX = 0xAAAA */ + *stk-- = (INT16U)0xCCCC; /* CX = 0xCCCC */ + *stk-- = (INT16U)0xDDDD; /* DX = 0xDDDD */ + *stk-- = (INT16U)0xBBBB; /* BX = 0xBBBB */ + *stk-- = (INT16U)0x0000; /* SP = 0x0000 */ + *stk-- = (INT16U)0x1111; /* BP = 0x1111 */ + *stk-- = (INT16U)0x2222; /* SI = 0x2222 */ + *stk-- = (INT16U)0x3333; /* DI = 0x3333 */ + *stk-- = (INT16U)0x4444; /* ES = 0x4444 */ + *stk = _DS; /* DS = Current value of DS */ + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK FOR FLOATING POINT EMULATION +* +* Description: This function MUST be called BEFORE calling either OSTaskCreate() or OSTaskCreateExt() in +* order to initialize the task's stack to allow the task to use the Borland floating-point +* emulation. The returned pointer MUST be used in the task creation call. +* +* Ex.: OS_STK TaskStk[1000]; +* +* +* void main (void) +* { +* OS_STK *ptos; +* OS_STK *pbos; +* INT32U size; +* +* +* OSInit(); +* . +* . +* ptos = &TaskStk[999]; +* pbos = &TaskStk[0]; +* psize = 1000; +* OSTaskStkInit_FPE_x86(&ptos, &pbos, &size); +* OSTaskCreate(Task, (void *)0, ptos, 10); +* . +* . +* OSStart(); +* } +* +* Arguments : pptos is the pointer to the task's top-of-stack pointer which would be passed to +* OSTaskCreate() or OSTaskCreateExt(). +* +* ppbos is the pointer to the new bottom of stack pointer which would be passed to +* OSTaskCreateExt(). +* +* psize is a pointer to the size of the stack (in number of stack elements). You +* MUST allocate sufficient stack space to leave at least 384 bytes for the +* floating-point emulation. +* +* Returns : The new size of the stack once memory is allocated to the floating-point emulation. +* +* Note(s) : 1) _SS is a Borland 'pseudo-register' and returns the contents of the Stack Segment (SS) +* 2) The pointer to the top-of-stack (pptos) will be modified so that it points to the new +* top-of-stack. +* 3) The pointer to the bottom-of-stack (ppbos) will be modified so that it points to the new +* bottom-of-stack. +* 4) The new size of the stack is adjusted to reflect the fact that memory was reserved on +* the stack for the floating-point emulation. +********************************************************************************************************* +*/ + +void OSTaskStkInit_FPE_x86 (OS_STK **pptos, OS_STK **ppbos, INT32U *psize) +{ + INT32U lin_tos; /* 'Linear' version of top-of-stack address */ + INT32U lin_bos; /* 'Linear' version of bottom-of-stack address */ + INT16U seg; + INT16U off; + INT32U bytes; + + + seg = FP_SEG(*pptos); /* Decompose top-of-stack pointer into seg:off */ + off = FP_OFF(*pptos); + lin_tos = ((INT32U)seg << 4) + (INT32U)off; /* Convert seg:off to linear address */ + bytes = *psize * sizeof(OS_STK); /* Determine how many bytes for the stack */ + lin_bos = (lin_tos - bytes + 15) & 0xFFFFFFF0L; /* Ensure paragraph alignment for BOS */ + + seg = (INT16U)(lin_bos >> 4); /* Get new 'normalized' segment */ + *ppbos = (OS_STK *)MK_FP(seg, 0x0000); /* Create 'normalized' BOS pointer */ + /* Copy FP emulation memory to task's stack */ + OS_MemCopy((INT8U *)*ppbos, (INT8U *)MK_FP(_SS, 0), 384u); + bytes = bytes - 16; /* Loose 16 bytes because of alignment */ + *pptos = (OS_STK *)MK_FP(seg, (INT16U)bytes); /* Determine new top-of-stack */ + *ppbos = (OS_STK *)MK_FP(seg, 384u); /* Determine new bottom-of-stack */ + bytes = bytes - 384u; + *psize = bytes / sizeof(OS_STK); /* Determine new stack size */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/80186/DOS/L/BC45/os_dbg.c b/Ports/80186/DOS/L/BC45/os_dbg.c new file mode 100644 index 0000000..396160f --- /dev/null +++ b/Ports/80186/DOS/L/BC45/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/80x86/DOS/L-FP-I/BC45/os_cpu.h b/Ports/80x86/DOS/L-FP-I/BC45/os_cpu.h new file mode 100644 index 0000000..4803896 --- /dev/null +++ b/Ports/80x86/DOS/L-FP-I/BC45/os_cpu.h @@ -0,0 +1,144 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL WITH FLOATING-POINT AND SEPARATE INTERRUPT STACK +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned int OS_CPU_SR; /* The CPU Status Word is 16-bit wide */ + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 2 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm CLI /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm STI /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm {PUSHF; CLI} /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm POPF /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on 80x86 */ + +#define OS_ISR_STK_SIZE 512 /* Size of ISR stack */ + +#define uCOS 0x80 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() asm INT uCOS + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT8U OSTickDOSCtr; /* Counter used to invoke DOS's tick handler every 'n' ticks */ + +OS_CPU_EXT OS_STK OSISRStk[OS_ISR_STK_SIZE]; /* ISR stack */ +OS_CPU_EXT OS_STK *OSISRStkPtr; /* Pointer to top-of ISR stack */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +extern INT8U const OSTickDOSCtrReload; /* Reload value for OSTickDOSCtr when it reaches 0 */ + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +void OSFPInit(void); +void OSFPRestore(void *pblk); +void OSFPSave(void *pblk); + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OSCPUSaveSR(void); +void OSCPURestoreSR(OS_CPU_SR cpu_sr); +#endif + +#endif diff --git a/Ports/80x86/DOS/L-FP-I/BC45/os_cpu_a.asm b/Ports/80x86/DOS/L-FP-I/BC45/os_cpu_a.asm new file mode 100644 index 0000000..386238d --- /dev/null +++ b/Ports/80x86/DOS/L-FP-I/BC45/os_cpu_a.asm @@ -0,0 +1,412 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 80x86/80x88 Specific code +; LARGE MEMORY MODEL WITH FLOATING-POINT AND SEPARATE INTERRUPT STACK +; Borland C/C++ V4.51 +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** + + PUBLIC _OSStartHighRdy + PUBLIC _OSCtxSw + PUBLIC _OSIntCtxSw + PUBLIC _OSFPRestore + PUBLIC _OSFPSave + PUBLIC _OSTickISR + + EXTRN _OSIntExit:FAR + EXTRN _OSTimeTick:FAR + EXTRN _OSTaskSwHook:FAR + + EXTRN _OSIntNesting:BYTE + EXTRN _OSTickDOSCtr:BYTE + EXTRN _OSTickDOSCtrReload:BYTE + EXTRN _OSISRStkPtr:WORD + EXTRN _OSPrioHighRdy:BYTE + EXTRN _OSPrioCur:BYTE + EXTRN _OSRunning:BYTE + EXTRN _OSTCBCur:DWORD + EXTRN _OSTCBHighRdy:DWORD + +.MODEL LARGE +.CODE +.186 + PAGE +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW +; OFFSET of task code address +; SEGMENT of task code address +; OFFSET of 'p_arg' +; SEGMENT of 'p_arg' (High memory) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy PROC FAR + + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBHighRdy ; Reload DS + MOV DS, AX ; + MOV AL, 1 ; OSRunning = TRUE; + MOV BYTE PTR DS:_OSRunning, AL ; (Indicates that multitasking has started) +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX+0] ; +; + POP DS ; Load task's context + POP ES ; + POPA ; +; + IRET ; Run task + +_OSStartHighRdy ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; void OSCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP -> OFFSET of task to suspend (Low memory) +; SEGMENT of task to suspend +; PSW of task to suspend (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSCtxSw PROC FAR +; + PUSHA ; Save current task's context + PUSH ES ; + PUSH DS ; +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL ; +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSCtxSw ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; void OSIntCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; OSTCBCur->OSTCBStkPtr ------> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSIntCtxSw PROC FAR +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSIntCtxSw ENDP + + PAGE +;********************************************************************************************************* +; RESTORE FPU REGISTERS +; void OSFPRestore(void *pblk) +; +; Description : This function is called to restore the contents of the FPU registers during a context +; switch. It is assumed that a pointer to a storage area for the FPU registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). +; Arguments : pblk is passed to this function when called. +; Note(s) : 1) The stack frame upon entry looks as follows: +; +; SP + 0 -> OFFSET of caller (Low memory) +; + 2 SEGMENT of caller +; + 4 OFFSET of pblk +; + 6 SEGMENT of pblk (High memory) +;********************************************************************************************************* + +_OSFPRestore PROC FAR +; + PUSH BP ; Save work registers + MOV BP,SP + PUSH ES + PUSH BX +; + LES BX, DWORD PTR [BP+6] ; Point to 'pblk' +; + FRSTOR ES:[BX] ; Restore FPU context +; + POP BX ; Restore work registers + POP ES + POP BP +; + RET ; Return to caller +; +_OSFPRestore ENDP + + PAGE +;********************************************************************************************************* +; SAVE FPU REGISTERS +; void OSFPSave(void *pblk) +; +; Description : This function is called to save the contents of the FPU registers during a context +; switch. It is assumed that a pointer to a storage area for the FPU registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). +; Arguments : pblk is passed to this function when called. +; Note(s) : 1) The stack frame upon entry looks as follows: +; +; SP + 0 -> OFFSET of caller (Low memory) +; + 2 SEGMENT of caller +; + 4 OFFSET of pblk +; + 6 SEGMENT of pblk (High memory) +;********************************************************************************************************* + +_OSFPSave PROC FAR +; + PUSH BP ; Save work registers + MOV BP,SP + PUSH ES + PUSH BX +; + LES BX, DWORD PTR [BP+6] ; Point to 'pblk' +; + FSAVE ES:[BX] ; Save FPU context +; + POP BX ; Restore work registers + POP ES + POP BP +; + RET ; Return to caller +; +_OSFPSave ENDP + + PAGE +;********************************************************************************************************* +; HANDLE TICK ISR +; +; Description: This function is called 199.99 times per second or, 11 times faster than the normal DOS +; tick rate of 18.20648 Hz. Thus every 11th time, the normal DOS tick handler is called. +; This is called chaining. 10 times out of 11, however, the interrupt controller on the PC +; must be cleared to allow for the next interrupt. +; +; Arguments : none +; +; Returns : none +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SS:SP +; SS:SP = OSISRStkPtr; +; } +; OSTickDOSCtr--; +; if (OSTickDOSCtr == 0) { +; OSTickDOSCtr = OSTickDOSCtrReload; +; INT 81H; Chain into DOS every 54.925 mS +; (Interrupt will be cleared by DOS) +; } else { +; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259 +; PIC (Priority Interrupt Controller) +; } +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; if (OSIntNesting == 0) { if we don't have a NEW HPT +; SS:SP = OSTCBHighRdy->OSTCBStkPtr; Restore the current task's SP +; } +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* +; +_OSTickISR PROC FAR +; + PUSHA ; Save interrupted task's context + PUSH ES + PUSH DS +; + MOV AX, SEG(_OSIntNesting) ; Reload DS + MOV DS, AX + INC BYTE PTR DS:_OSIntNesting ; Notify uC/OS-II of ISR +; + CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1) + JNE SHORT _OSTickISR1 + MOV AX, SEG(_OSTCBCur) ; Reload DS + MOV DS, AX + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; + MOV AX, SEG(_OSISRStkPtr) ; SS:SP = OSISRStkPtr + MOV DS, AX + MOV BX, DS:_OSISRStkPtr+2 + MOV CX, DS:_OSISRStkPtr + MOV SS, BX + MOV SP, CX +; +_OSTickISR1: + MOV AX, SEG(_OSTickDOSCtr) ; if (OSTickDOSCtr == 0) + MOV DS, AX + DEC BYTE PTR DS:_OSTickDOSCtr + CMP BYTE PTR DS:_OSTickDOSCtr, 0 + JNE SHORT _OSTickISR2 +; + MOV AL, BYTE PTR DS:_OSTickDOSCtrReload + MOV BYTE PTR DS:_OSTickDOSCtr, AL + INT 081H ; Chain into DOS's tick ISR (Every 11 ticks (~199.99 Hz)) + JMP SHORT _OSTickISR3 + +_OSTickISR2: ; else + MOV AL, 20H ; Send EOI to PIC + MOV DX, 20H + OUT DX, AL +; +_OSTickISR3: + CALL FAR PTR _OSTimeTick ; Process system tick +; + CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR +; + CMP BYTE PTR DS:_OSIntNesting, 0 ; if (OSIntNesting == 0) + JNE SHORT _OSTickISR4 + MOV AX, SEG(_OSTCBCur) ; Reload DS + MOV DS, AX + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] + MOV SP, ES:[BX] + +_OSTickISR4: + POP DS ; Restore interrupted task's context + POP ES + POPA +; + IRET ; Return to interrupted task +; +_OSTickISR ENDP +; + END diff --git a/Ports/80x86/DOS/L-FP-I/BC45/os_cpu_c.c b/Ports/80x86/DOS/L-FP-I/BC45/os_cpu_c.c new file mode 100644 index 0000000..1b1d18a --- /dev/null +++ b/Ports/80x86/DOS/L-FP-I/BC45/os_cpu_c.c @@ -0,0 +1,368 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86 Specific code +* LARGE MEMORY MODEL WITH FLOATING-POINT AND SEPARATE INTERRUPT STACK +* Borland C/C++ V4.51 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +INT8U const OSTickDOSCtrReload = (INT8U)((FP32)OS_TICKS_PER_SEC / (FP32)18.20648 + (FP32)0.5); + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +* +* Note(s) : 1) OS_NTASKS_FP establishes the number of tasks capable of supporting floating-point. One +* task is removed for the idle task because it doesn't do floating-point at all. +* 2) OS_FP_STORAGE_SIZE currently allocates 128 bytes of storage even though the 80x86 FPU +* only require 108 bytes to save the FPU context. I decided to allocate 128 bytes for +* future expansion. +********************************************************************************************************* +*/ + +#define OS_NTASKS_FP (OS_MAX_TASKS + OS_N_SYS_TASKS - 1) +#define OS_FP_STORAGE_SIZE 128 + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +static OS_MEM *OSFPPartPtr; /* Pointer to memory partition holding FPU storage areas */ + + /* I used INT32U to ensure that storage is aligned on a ... */ + /* ... 32-bit boundary. */ +static INT32U OSFPPart[OS_NTASKS_FP][OS_FP_STORAGE_SIZE / sizeof(INT32U)]; + + +/* +********************************************************************************************************* +* INITIALIZE FP SUPPORT +* +* Description: This function is called to initialize the memory partition needed to support context +* switching the Floating-Point registers. This function MUST be called AFTER calling +* OSInit(). +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) Tasks that are to use FP support MUST be created with OSTaskCreateExt(). +* 2) For the 80x86 FPU, 108 bytes are required to save the FPU context. I decided to +* allocate 128 bytes for future expansion. Also, I used INT32U to ensure that storage +* is aligned on a 32-bit boundary. +* 3) I decided to 'change' the 'Options' attribute for the statistic task in case you +* use OSTaskStatHook() and need to perform floating-point operations in this function. +* This only applies if OS_TaskStat() was created with OSTaskCreateExt(). +********************************************************************************************************* +*/ + +void OSFPInit (void) +{ + INT8U err; +#if OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN + OS_TCB *ptcb; + void *pblk; +#endif + + + OSFPPartPtr = OSMemCreate(&OSFPPart[0][0], OS_NTASKS_FP, OS_FP_STORAGE_SIZE, &err); + +#if OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN /* CHANGE 'OPTIONS' for OS_TaskStat() */ + ptcb = OSTCBPrioTbl[OS_STAT_PRIO]; + ptcb->OSTCBOpt |= OS_TASK_OPT_SAVE_FP; /* Allow floating-point support for Statistic task */ + pblk = OSMemGet(OSFPPartPtr, &err); /* Get storage for FPU registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OSFPSave(pblk); /* Save the FPU registers in block */ + } +#endif +} + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSISRStkPtr = (OS_STK *)&OSISRStk[OS_ISR_STK_SIZE - 1]; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ + OSFPInit(); +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) I decided to change the options on the statistic task to allow for floating-point in +* case you decide to do math. in OSTaskStatHook(). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + INT8U err; + void *pblk; + + + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task needs FP support */ + pblk = OSMemGet(OSFPPartPtr, &err); /* Yes, Get storage for FPU registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OSFPSave(pblk); /* Save the FPU registers in block */ + } + } +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task had FP support */ + if (ptcb->OSTCBExtPtr != (void *)0) { /* Yes, OSTCBExtPtr must not be NULL */ + OSMemPut(OSFPPartPtr, ptcb->OSTCBExtPtr); /* Return memory block to free pool */ + } + } +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* PSW to 0x0002 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable +* interrupts. Failure to do this will make your system crash! +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT16U *)ptos; /* Load stack pointer */ + *stk-- = (INT16U)FP_SEG(p_arg); /* Simulate call to function with argument */ + *stk-- = (INT16U)FP_OFF(p_arg); + *stk-- = (INT16U)FP_SEG(task); + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0x0202; /* SW = Interrupts enabled */ + *stk-- = (INT16U)FP_SEG(task); /* Put pointer to task on top of stack */ + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0xAAAA; /* AX = 0xAAAA */ + *stk-- = (INT16U)0xCCCC; /* CX = 0xCCCC */ + *stk-- = (INT16U)0xDDDD; /* DX = 0xDDDD */ + *stk-- = (INT16U)0xBBBB; /* BX = 0xBBBB */ + *stk-- = (INT16U)0x0000; /* SP = 0x0000 */ + *stk-- = (INT16U)0x1111; /* BP = 0x1111 */ + *stk-- = (INT16U)0x2222; /* SI = 0x2222 */ + *stk-- = (INT16U)0x3333; /* DI = 0x3333 */ + *stk-- = (INT16U)0x4444; /* ES = 0x4444 */ + *stk = _DS; /* DS = Current value of DS */ + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ + INT8U err; + void *pblk; + /* Save FPU context of preempted task */ + if (OSRunning == TRUE) { /* Don't save on OSStart()! */ + if (OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task used FP */ + pblk = OSTCBCur->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OSFPSave(pblk); /* Save the FPU registers in block */ + } + } + } + /* Restore FPU context of new task */ + if (OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if new task uses FP */ + pblk = OSTCBHighRdy->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OSFPRestore(pblk); /* Get contents of FPU registers */ + } + } +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/80x86/DOS/L-FP-I/BC45/os_dbg.c b/Ports/80x86/DOS/L-FP-I/BC45/os_dbg.c new file mode 100644 index 0000000..82725c6 --- /dev/null +++ b/Ports/80x86/DOS/L-FP-I/BC45/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/80x86/DOS/L-FP/BC45/os_cpu.h b/Ports/80x86/DOS/L-FP/BC45/os_cpu.h new file mode 100644 index 0000000..d621a82 --- /dev/null +++ b/Ports/80x86/DOS/L-FP/BC45/os_cpu.h @@ -0,0 +1,123 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL +* With Floating-Point Register Support +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned int OS_CPU_SR; /* The CPU Status Word is 16-bit wide */ + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 2 + + +#define OS_ENTER_CRITICAL() asm {PUSHF; CLI} /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm POPF /* Enable interrupts */ + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on 80x86 */ + +#define uCOS 0x80 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() asm INT uCOS + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT8U OSTickDOSCtr; /* Counter used to invoke DOS's tick handler every 'n' ticks */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +extern INT8U const OSTickDOSCtrReload; /* Reload value for OSTickDOSCtr when it reaches 0 */ + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +void OSFPInit(void); +void OSFPRestore(void *pblk); +void OSFPSave(void *pblk); + +#endif diff --git a/Ports/80x86/DOS/L-FP/BC45/os_cpu_a.asm b/Ports/80x86/DOS/L-FP/BC45/os_cpu_a.asm new file mode 100644 index 0000000..71bdef6 --- /dev/null +++ b/Ports/80x86/DOS/L-FP/BC45/os_cpu_a.asm @@ -0,0 +1,391 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 80x86/80x88 Specific code +; LARGE MEMORY MODEL WITH FLOATING-POINT +; Borland C/C++ V4.51 +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** + + PUBLIC _OSStartHighRdy + PUBLIC _OSCtxSw + PUBLIC _OSIntCtxSw + PUBLIC _OSFPRestore + PUBLIC _OSFPSave + PUBLIC _OSTickISR + + EXTRN _OSIntExit:FAR + EXTRN _OSTimeTick:FAR + EXTRN _OSTaskSwHook:FAR + + EXTRN _OSIntNesting:BYTE + EXTRN _OSTickDOSCtr:BYTE + EXTRN _OSTickDOSCtrReload:BYTE + EXTRN _OSPrioHighRdy:BYTE + EXTRN _OSPrioCur:BYTE + EXTRN _OSRunning:BYTE + EXTRN _OSTCBCur:DWORD + EXTRN _OSTCBHighRdy:DWORD + +.MODEL LARGE +.CODE +.186 + PAGE +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW +; OFFSET of task code address +; SEGMENT of task code address +; OFFSET of 'p_arg' +; SEGMENT of 'p_arg' (High memory) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy PROC FAR + + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBHighRdy ; Reload DS + MOV DS, AX ; + MOV AL, 1 ; OSRunning = TRUE; + MOV BYTE PTR DS:_OSRunning, AL ; (Indicates that multitasking has started) +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX+0] ; +; + POP DS ; Load task's context + POP ES ; + POPA ; +; + IRET ; Run task + +_OSStartHighRdy ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; void OSCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP -> OFFSET of task to suspend (Low memory) +; SEGMENT of task to suspend +; PSW of task to suspend (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSCtxSw PROC FAR +; + PUSHA ; Save current task's context + PUSH ES ; + PUSH DS ; +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL ; +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSCtxSw ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; void OSIntCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; OSTCBCur->OSTCBStkPtr ------> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSIntCtxSw PROC FAR +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSIntCtxSw ENDP + + PAGE +;********************************************************************************************************* +; RESTORE FPU REGISTERS +; void OSFPRestore(void *pblk) +; +; Description : This function is called to restore the contents of the FPU registers during a context +; switch. It is assumed that a pointer to a storage area for the FPU registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). +; Arguments : pblk is passed to this function when called. +; Note(s) : 1) The stack frame upon entry looks as follows: +; +; SP + 0 -> OFFSET of caller (Low memory) +; + 2 SEGMENT of caller +; + 4 OFFSET of pblk +; + 6 SEGMENT of pblk (High memory) +;********************************************************************************************************* + +_OSFPRestore PROC FAR +; + PUSH BP ; Save work registers + MOV BP,SP + PUSH ES + PUSH BX +; + LES BX, DWORD PTR [BP+6] ; Point to 'pblk' +; + FRSTOR ES:[BX] ; Restore FPU context +; + POP BX ; Restore work registers + POP ES + POP BP +; + RET ; Return to caller +; +_OSFPRestore ENDP + + PAGE +;********************************************************************************************************* +; SAVE FPU REGISTERS +; void OSFPSave(void *pblk) +; +; Description : This function is called to save the contents of the FPU registers during a context +; switch. It is assumed that a pointer to a storage area for the FPU registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). +; Arguments : pblk is passed to this function when called. +; Note(s) : 1) The stack frame upon entry looks as follows: +; +; SP + 0 -> OFFSET of caller (Low memory) +; + 2 SEGMENT of caller +; + 4 OFFSET of pblk +; + 6 SEGMENT of pblk (High memory) +;********************************************************************************************************* + +_OSFPSave PROC FAR +; + PUSH BP ; Save work registers + MOV BP,SP + PUSH ES + PUSH BX +; + LES BX, DWORD PTR [BP+6] ; Point to 'pblk' +; + FSAVE ES:[BX] ; Save FPU context +; + POP BX ; Restore work registers + POP ES + POP BP +; + RET ; Return to caller +; +_OSFPSave ENDP + + PAGE +;********************************************************************************************************* +; HANDLE TICK ISR +; +; Description: This function is called 199.99 times per second or, 11 times faster than the normal DOS +; tick rate of 18.20648 Hz. Thus every 11th time, the normal DOS tick handler is called. +; This is called chaining. 10 times out of 11, however, the interrupt controller on the PC +; must be cleared to allow for the next interrupt. +; +; Arguments : none +; +; Returns : none +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SS:SP +; } +; OSTickDOSCtr--; +; if (OSTickDOSCtr == 0) { +; OSTickDOSCtr = OSTickDOSCtrReload; +; INT 81H; Chain into DOS every 54.925 mS +; (Interrupt will be cleared by DOS) +; } else { +; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259 +; PIC (Priority Interrupt Controller) +; } +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* +; +_OSTickISR PROC FAR +; + PUSHA ; Save interrupted task's context + PUSH ES + PUSH DS +; + MOV AX, SEG(_OSIntNesting) ; Reload DS + MOV DS, AX + INC BYTE PTR DS:_OSIntNesting ; Notify uC/OS-II of ISR +; + CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1) + JNE SHORT _OSTickISR1 + MOV AX, SEG(_OSTCBCur) ; Reload DS + MOV DS, AX + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; +_OSTickISR1: + MOV AX, SEG(_OSTickDOSCtr) ; Reload DS + MOV DS, AX + DEC BYTE PTR DS:_OSTickDOSCtr + CMP BYTE PTR DS:_OSTickDOSCtr, 0 + JNE SHORT _OSTickISR2 ; Every 11 ticks (~199.99 Hz), chain into DOS +; + MOV AL, BYTE PTR DS:_OSTickDOSCtrReload + MOV BYTE PTR DS:_OSTickDOSCtr, AL + INT 081H ; Chain into DOS's tick ISR + JMP SHORT _OSTickISR3 + +_OSTickISR2: + MOV AL, 20H ; Move EOI code into AL. + MOV DX, 20H ; Address of 8259 PIC in DX. + OUT DX, AL ; Send EOI to PIC if not processing DOS timer. +; +_OSTickISR3: + CALL FAR PTR _OSTimeTick ; Process system tick +; + CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR +; + POP DS ; Restore interrupted task's context + POP ES + POPA +; + IRET ; Return to interrupted task +; +_OSTickISR ENDP +; + END diff --git a/Ports/80x86/DOS/L-FP/BC45/os_cpu_c.c b/Ports/80x86/DOS/L-FP/BC45/os_cpu_c.c new file mode 100644 index 0000000..da701f3 --- /dev/null +++ b/Ports/80x86/DOS/L-FP/BC45/os_cpu_c.c @@ -0,0 +1,367 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86 Specific code +* LARGE MEMORY MODEL WITH FLOATING-POINT +* Borland C/C++ V4.51 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +INT8U const OSTickDOSCtrReload = (INT8U)((FP32)OS_TICKS_PER_SEC / (FP32)18.20648 + (FP32)0.5); + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +* +* Note(s) : 1) OS_NTASKS_FP establishes the number of tasks capable of supporting floating-point. One +* task is removed for the idle task because it doesn't do floating-point at all. +* 2) OS_FP_STORAGE_SIZE currently allocates 128 bytes of storage even though the 80x86 FPU +* only require 108 bytes to save the FPU context. I decided to allocate 128 bytes for +* future expansion. +********************************************************************************************************* +*/ + +#define OS_NTASKS_FP (OS_MAX_TASKS + OS_N_SYS_TASKS - 1) +#define OS_FP_STORAGE_SIZE 128 + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +static OS_MEM *OSFPPartPtr; /* Pointer to memory partition holding FPU storage areas */ + + /* I used INT32U to ensure that storage is aligned on a ... */ + /* ... 32-bit boundary. */ +static INT32U OSFPPart[OS_NTASKS_FP][OS_FP_STORAGE_SIZE / sizeof(INT32U)]; + + +/* +********************************************************************************************************* +* INITIALIZE FP SUPPORT +* +* Description: This function is called to initialize the memory partition needed to support context +* switching the Floating-Point registers. This function MUST be called AFTER calling +* OSInit(). +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) Tasks that are to use FP support MUST be created with OSTaskCreateExt(). +* 2) For the 80x86 FPU, 108 bytes are required to save the FPU context. I decided to +* allocate 128 bytes for future expansion. Also, I used INT32U to ensure that storage +* is aligned on a 32-bit boundary. +* 3) I decided to 'change' the 'Options' attribute for the statistic task in case you +* use OSTaskStatHook() and need to perform floating-point operations in this function. +* This only applies if OS_TaskStat() was created with OSTaskCreateExt(). +********************************************************************************************************* +*/ + +void OSFPInit (void) +{ + INT8U err; +#if OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN + OS_TCB *ptcb; + void *pblk; +#endif + + + OSFPPartPtr = OSMemCreate(&OSFPPart[0][0], OS_NTASKS_FP, OS_FP_STORAGE_SIZE, &err); + +#if OS_TASK_STAT_EN && OS_TASK_CREATE_EXT_EN /* CHANGE 'OPTIONS' for OS_TaskStat() */ + ptcb = OSTCBPrioTbl[OS_STAT_PRIO]; + ptcb->OSTCBOpt |= OS_TASK_OPT_SAVE_FP; /* Allow floating-point support for Statistic task */ + pblk = OSMemGet(OSFPPartPtr, &err); /* Get storage for FPU registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OSFPSave(pblk); /* Save the FPU registers in block */ + } +#endif +} + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ + OSFPInit(); +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) I decided to change the options on the statistic task to allow for floating-point in +* case you decide to do math. in OSTaskStatHook(). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + INT8U err; + void *pblk; + + + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task needs FP support */ + pblk = OSMemGet(OSFPPartPtr, &err); /* Yes, Get storage for FPU registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OSFPSave(pblk); /* Save the FPU registers in block */ + } + } +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task had FP support */ + if (ptcb->OSTCBExtPtr != (void *)0) { /* Yes, OSTCBExtPtr must not be NULL */ + OSMemPut(OSFPPartPtr, ptcb->OSTCBExtPtr); /* Return memory block to free pool */ + } + } +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* PSW to 0x0002 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable +* interrupts. Failure to do this will make your system crash! +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT16U *)ptos; /* Load stack pointer */ + *stk-- = (INT16U)FP_SEG(p_arg); /* Simulate call to function with argument */ + *stk-- = (INT16U)FP_OFF(p_arg); + *stk-- = (INT16U)FP_SEG(task); + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0x0202; /* SW = Interrupts enabled */ + *stk-- = (INT16U)FP_SEG(task); /* Put pointer to task on top of stack */ + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0xAAAA; /* AX = 0xAAAA */ + *stk-- = (INT16U)0xCCCC; /* CX = 0xCCCC */ + *stk-- = (INT16U)0xDDDD; /* DX = 0xDDDD */ + *stk-- = (INT16U)0xBBBB; /* BX = 0xBBBB */ + *stk-- = (INT16U)0x0000; /* SP = 0x0000 */ + *stk-- = (INT16U)0x1111; /* BP = 0x1111 */ + *stk-- = (INT16U)0x2222; /* SI = 0x2222 */ + *stk-- = (INT16U)0x3333; /* DI = 0x3333 */ + *stk-- = (INT16U)0x4444; /* ES = 0x4444 */ + *stk = _DS; /* DS = Current value of DS */ + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ + INT8U err; + void *pblk; + /* Save FPU context of preempted task */ + if (OSRunning == TRUE) { /* Don't save on OSStart()! */ + if (OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task used FP */ + pblk = OSTCBCur->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OSFPSave(pblk); /* Save the FPU registers in block */ + } + } + } + /* Restore FPU context of new task */ + if (OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if new task uses FP */ + pblk = OSTCBHighRdy->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OSFPRestore(pblk); /* Get contents of FPU registers */ + } + } +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/80x86/DOS/L-FP/BC45/os_dbg.c b/Ports/80x86/DOS/L-FP/BC45/os_dbg.c new file mode 100644 index 0000000..82725c6 --- /dev/null +++ b/Ports/80x86/DOS/L-FP/BC45/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/80x86/DOS/L-I/BC45/os_cpu.h b/Ports/80x86/DOS/L-I/BC45/os_cpu.h new file mode 100644 index 0000000..7848519 --- /dev/null +++ b/Ports/80x86/DOS/L-I/BC45/os_cpu.h @@ -0,0 +1,140 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 2 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm CLI /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm STI /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm {PUSHF; CLI} /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm POPF /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on 80x86 */ + +#define uCOS 0x80 /* Interrupt vector # used for context switch */ + +#define OS_ISR_STK_SIZE 512 /* Size of ISR stack */ + +#define OS_TASK_SW() asm INT uCOS + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT8U OSTickDOSCtr; /* Ctr to call DOS tick handler every 'n' ticks */ + +OS_CPU_EXT OS_STK OSISRStk[OS_ISR_STK_SIZE]; /* ISR stack */ +OS_CPU_EXT OS_STK *OSISRStkPtr; /* Pointer to top-of ISR stack */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +extern INT8U const OSTickDOSCtrReload; /* Reload value for OSTickDOSCtr when it's 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSTaskStkInit_FPE_x86(OS_STK **pptos, OS_STK **ppbos, INT32U *psize); + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OSCPUSaveSR(void); +void OSCPURestoreSR(OS_CPU_SR cpu_sr); +#endif + +#endif diff --git a/Ports/80x86/DOS/L-I/BC45/os_cpu_a.asm b/Ports/80x86/DOS/L-I/BC45/os_cpu_a.asm new file mode 100644 index 0000000..fdbaf2f --- /dev/null +++ b/Ports/80x86/DOS/L-I/BC45/os_cpu_a.asm @@ -0,0 +1,345 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 80x86/80x88 Specific code +; LARGE MEMORY MODEL with SEPARATE ISR STACK +; +; Borland C/C++ V4.51 +; (IBM/PC Compatible Target) +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC and EXTERNAL REFERENCES +;******************************************************************************************************** + + PUBLIC _OSTickISR + PUBLIC _OSStartHighRdy + PUBLIC _OSCtxSw + PUBLIC _OSIntCtxSw + + EXTRN _OSIntExit:FAR + EXTRN _OSTimeTick:FAR + EXTRN _OSTaskSwHook:FAR + + EXTRN _OSIntNesting:BYTE + EXTRN _OSTickDOSCtr:BYTE + EXTRN _OSTickDOSCtrReload:BYTE + EXTRN _OSISRStkPtr:WORD + EXTRN _OSPrioHighRdy:BYTE + EXTRN _OSPrioCur:BYTE + EXTRN _OSRunning:BYTE + EXTRN _OSTCBCur:DWORD + EXTRN _OSTCBHighRdy:DWORD + +.MODEL LARGE +.CODE +.186 + PAGE +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW +; OFFSET of task code address +; SEGMENT of task code address +; OFFSET of 'p_arg' +; SEGMENT of 'p_arg' (High memory) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy PROC FAR + + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBHighRdy ; Reload DS + MOV DS, AX ; +; + MOV AL, 1 ; OSRunning = TRUE; + MOV BYTE PTR DS:_OSRunning, AL ; (Indicates that multitasking has started) +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX+0] ; +; + POP DS ; Load task's context + POP ES ; + POPA ; +; + IRET ; Run task + +_OSStartHighRdy ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; void OSCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP -> OFFSET of task to suspend (Low memory) +; SEGMENT of task to suspend +; PSW of task to suspend (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSCtxSw PROC FAR +; + PUSHA ; Save current task's context + PUSH ES ; + PUSH DS ; +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL ; +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSCtxSw ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; void OSIntCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP --> DS +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSIntCtxSw PROC FAR +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSIntCtxSw ENDP + + PAGE +;********************************************************************************************************* +; HANDLE TICK ISR +; +; Description: This function is called 199.99 times per second or, 11 times faster than the normal DOS +; tick rate of 18.20648 Hz. Thus every 11th time, the normal DOS tick handler is called. +; This is called chaining. 10 times out of 11, however, the interrupt controller on the PC +; must be cleared to allow for the next interrupt. +; +; Arguments : none +; +; Returns : none +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SS:SP +; SS:SP = OSISRStkPtr; +; } +; OSTickDOSCtr--; +; if (OSTickDOSCtr == 0) { +; OSTickDOSCtr = OSTickDOSCtrReload; +; INT 81H; Chain into DOS every 54.925 mS +; (Interrupt will be cleared by DOS) +; } else { +; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259 +; PIC (Priority Interrupt Controller) +; } +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; if (OSIntNesting == 0) { if we don't have a NEW HPT +; SS:SP = OSTCBHighRdy->OSTCBStkPtr; Restore the current task's SP +; } +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* +; +_OSTickISR PROC FAR +; + PUSHA ; Save interrupted task's context + PUSH ES + PUSH DS +; + MOV AX, SEG(_OSIntNesting) ; Reload DS + MOV DS, AX + INC BYTE PTR DS:_OSIntNesting ; Notify uC/OS-II of ISR +; + CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1) + JNE SHORT _OSTickISR1 + MOV AX, SEG(_OSTCBCur) ; Reload DS + MOV DS, AX + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS + MOV ES:[BX+0], SP +; + MOV AX, SEG(_OSISRStkPtr) ; SS:SP = OSISRStkPtr + MOV DS, AX + MOV BX, DS:_OSISRStkPtr+2 + MOV CX, DS:_OSISRStkPtr + MOV SS, BX + MOV SP, CX +; +_OSTickISR1: + MOV AX, SEG(_OSTickDOSCtr) ; if (OSTickDOSCtr == 0) + MOV DS, AX + DEC BYTE PTR DS:_OSTickDOSCtr + CMP BYTE PTR DS:_OSTickDOSCtr, 0 + JNE SHORT _OSTickISR2 +; + MOV AL, BYTE PTR DS:_OSTickDOSCtrReload + MOV BYTE PTR DS:_OSTickDOSCtr, AL + INT 081H ; Chain into DOS's tick ISR (Every 11 ticks (~199.99 Hz)) + JMP SHORT _OSTickISR3 + +_OSTickISR2: ; else + MOV AL, 20H ; Send EOI to PIC + MOV DX, 20H + OUT DX, AL +; +_OSTickISR3: + CALL FAR PTR _OSTimeTick ; Process system tick +; + CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR +; + CMP BYTE PTR DS:_OSIntNesting, 0 ; if (OSIntNesting == 0) + JNE SHORT _OSTickISR4 + MOV AX, SEG(_OSTCBCur) ; Reload DS + MOV DS, AX + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] + MOV SP, ES:[BX] + +_OSTickISR4: + POP DS ; Restore interrupted task's context + POP ES + POPA +; + IRET ; Return to interrupted task +; +_OSTickISR ENDP +; + END diff --git a/Ports/80x86/DOS/L-I/BC45/os_cpu_c.c b/Ports/80x86/DOS/L-I/BC45/os_cpu_c.c new file mode 100644 index 0000000..ea3a7b6 --- /dev/null +++ b/Ports/80x86/DOS/L-I/BC45/os_cpu_c.c @@ -0,0 +1,341 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +INT8U const OSTickDOSCtrReload = (INT8U)((FP32)OS_TICKS_PER_SEC / (FP32)18.20648 + (FP32)0.5); + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSISRStkPtr = (OS_STK *)&OSISRStk[OS_ISR_STK_SIZE - 1]; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* PSW to 0x0002 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable +* interrupts. Failure to do this will make your system crash! +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT16U *)ptos; /* Load stack pointer */ + *stk-- = (INT16U)FP_SEG(p_arg); /* Simulate call to function with argument */ + *stk-- = (INT16U)FP_OFF(p_arg); + *stk-- = (INT16U)FP_SEG(task); + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0x0202; /* SW = Interrupts enabled */ + *stk-- = (INT16U)FP_SEG(task); /* Put pointer to task on top of stack */ + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0xAAAA; /* AX = 0xAAAA */ + *stk-- = (INT16U)0xCCCC; /* CX = 0xCCCC */ + *stk-- = (INT16U)0xDDDD; /* DX = 0xDDDD */ + *stk-- = (INT16U)0xBBBB; /* BX = 0xBBBB */ + *stk-- = (INT16U)0x0000; /* SP = 0x0000 */ + *stk-- = (INT16U)0x1111; /* BP = 0x1111 */ + *stk-- = (INT16U)0x2222; /* SI = 0x2222 */ + *stk-- = (INT16U)0x3333; /* DI = 0x3333 */ + *stk-- = (INT16U)0x4444; /* ES = 0x4444 */ + *stk = _DS; /* DS = Current value of DS */ + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK FOR FLOATING POINT EMULATION +* +* Description: This function MUST be called BEFORE calling either OSTaskCreate() or OSTaskCreateExt() in +* order to initialize the task's stack to allow the task to use the Borland floating-point +* emulation. The returned pointer MUST be used in the task creation call. +* +* Ex.: OS_STK TaskStk[1000]; +* +* +* void main (void) +* { +* OS_STK *ptos; +* OS_STK *pbos; +* INT32U size; +* +* +* OSInit(); +* . +* . +* ptos = &TaskStk[999]; +* pbos = &TaskStk[0]; +* psize = 1000; +* OSTaskStkInit_FPE_x86(&ptos, &pbos, &size); +* OSTaskCreate(Task, (void *)0, ptos, 10); +* . +* . +* OSStart(); +* } +* +* Arguments : pptos is the pointer to the task's top-of-stack pointer which would be passed to +* OSTaskCreate() or OSTaskCreateExt(). +* +* ppbos is the pointer to the new bottom of stack pointer which would be passed to +* OSTaskCreateExt(). +* +* psize is a pointer to the size of the stack (in number of stack elements). You +* MUST allocate sufficient stack space to leave at least 384 bytes for the +* floating-point emulation. +* +* Returns : The new size of the stack once memory is allocated to the floating-point emulation. +* +* Note(s) : 1) _SS is a Borland 'pseudo-register' and returns the contents of the Stack Segment (SS) +* 2) The pointer to the top-of-stack (pptos) will be modified so that it points to the new +* top-of-stack. +* 3) The pointer to the bottom-of-stack (ppbos) will be modified so that it points to the new +* bottom-of-stack. +* 4) The new size of the stack is adjusted to reflect the fact that memory was reserved on +* the stack for the floating-point emulation. +********************************************************************************************************* +*/ + +void OSTaskStkInit_FPE_x86 (OS_STK **pptos, OS_STK **ppbos, INT32U *psize) +{ + INT32U lin_tos; /* 'Linear' version of top-of-stack address */ + INT32U lin_bos; /* 'Linear' version of bottom-of-stack address */ + INT16U seg; + INT16U off; + INT32U bytes; + + + seg = FP_SEG(*pptos); /* Decompose top-of-stack pointer into seg:off */ + off = FP_OFF(*pptos); + lin_tos = ((INT32U)seg << 4) + (INT32U)off; /* Convert seg:off to linear address */ + bytes = *psize * sizeof(OS_STK); /* Determine how many bytes for the stack */ + lin_bos = (lin_tos - bytes + 15) & 0xFFFFFFF0L; /* Ensure paragraph alignment for BOS */ + + seg = (INT16U)(lin_bos >> 4); /* Get new 'normalized' segment */ + *ppbos = (OS_STK *)MK_FP(seg, 0x0000); /* Create 'normalized' BOS pointer */ + /* Copy FP emulation memory to task's stack */ + OS_MemCopy((INT8U *)*ppbos, (INT8U *)MK_FP(_SS, 0), 384u); + bytes = bytes - 16; /* Loose 16 bytes because of alignment */ + *pptos = (OS_STK *)MK_FP(seg, (INT16U)bytes); /* Determine new top-of-stack */ + *ppbos = (OS_STK *)MK_FP(seg, 384u); /* Determine new bottom-of-stack */ + bytes = bytes - 384u; + *psize = bytes / sizeof(OS_STK); /* Determine new stack size */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/80x86/DOS/L-I/BC45/os_dbg.c b/Ports/80x86/DOS/L-I/BC45/os_dbg.c new file mode 100644 index 0000000..d631d94 --- /dev/null +++ b/Ports/80x86/DOS/L-I/BC45/os_dbg.c @@ -0,0 +1,267 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #ff 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/80x86/DOS/L/BC45/os_cpu.h b/Ports/80x86/DOS/L/BC45/os_cpu.h new file mode 100644 index 0000000..199c5d0 --- /dev/null +++ b/Ports/80x86/DOS/L/BC45/os_cpu.h @@ -0,0 +1,142 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx. Not actually needed for ... */ +#define WORD INT16S /* ... uC/OS-II. */ +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 2 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm CLI /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm STI /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm {PUSHF; CLI} /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm POPF /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* Intel 80x86 (Real-Mode, Large Model) Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on 80x86 */ + +#define uCOS 0x80 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() asm INT uCOS + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT8U OSTickDOSCtr; /* Counter used to invoke DOS's tick handler every 'n' ticks */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +extern INT8U const OSTickDOSCtrReload; /* Reload value for OSTickDOSCtr when it reaches 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSTaskStkInit_FPE_x86(OS_STK **pptos, OS_STK **ppbos, INT32U *psize); + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); +void OSCPURestoreSR(OS_CPU_SR cpu_sr); +#endif + +#endif diff --git a/Ports/80x86/DOS/L/BC45/os_cpu_a.asm b/Ports/80x86/DOS/L/BC45/os_cpu_a.asm new file mode 100644 index 0000000..43178dc --- /dev/null +++ b/Ports/80x86/DOS/L/BC45/os_cpu_a.asm @@ -0,0 +1,325 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 80x86/80x88 Specific code +; LARGE MEMORY MODEL +; +; Borland C/C++ V4.51 +; (IBM/PC Compatible Target) +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC and EXTERNAL REFERENCES +;******************************************************************************************************** + + PUBLIC _OSTickISR + PUBLIC _OSStartHighRdy + PUBLIC _OSCtxSw + PUBLIC _OSIntCtxSw + + EXTRN _OSIntExit:FAR + EXTRN _OSTimeTick:FAR + EXTRN _OSTaskSwHook:FAR + + EXTRN _OSIntNesting:BYTE + EXTRN _OSTickDOSCtr:BYTE + EXTRN _OSTickDOSCtrReload:BYTE + EXTRN _OSPrioHighRdy:BYTE + EXTRN _OSPrioCur:BYTE + EXTRN _OSRunning:BYTE + EXTRN _OSTCBCur:DWORD + EXTRN _OSTCBHighRdy:DWORD + +.MODEL LARGE +.CODE +.186 + PAGE +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW +; OFFSET of task code address +; SEGMENT of task code address +; OFFSET of 'p_arg' +; SEGMENT of 'p_arg' (High memory) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy PROC FAR + + MOV AX, SEG _OSTCBHighRdy ; Reload DS + MOV DS, AX ; +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AL, 1 ; OSRunning = TRUE; + MOV BYTE PTR DS:_OSRunning, AL ; (Indicates that multitasking has started) +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX+0] ; +; + POP DS ; Load task's context + POP ES ; + POPA ; +; + IRET ; Run task + +_OSStartHighRdy ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; void OSCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP -> OFFSET of task to suspend (Low memory) +; SEGMENT of task to suspend +; PSW of task to suspend (High memory) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSCtxSw PROC FAR +; + PUSHA ; Save current task's context + PUSH ES ; + PUSH DS ; +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL ; +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSCtxSw ENDP + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; void OSIntCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; OSTCBCur->OSTCBStkPtr ------> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +; +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> DS (Low memory) +; ES +; DI +; SI +; BP +; SP +; BX +; DX +; CX +; AX +; OFFSET of task code address +; SEGMENT of task code address +; Flags to load in PSW (High memory) +;********************************************************************************************************* + +_OSIntCtxSw PROC FAR +; + CALL FAR PTR _OSTaskSwHook ; Call user defined task switch hook +; + MOV AX, SEG _OSTCBCur ; Reload DS in case it was altered + MOV DS, AX ; +; + MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy + MOV DX, WORD PTR DS:_OSTCBHighRdy ; + MOV WORD PTR DS:_OSTCBCur+2, AX ; + MOV WORD PTR DS:_OSTCBCur, DX ; +; + MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + MOV BYTE PTR DS:_OSPrioCur, AL +; + LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr + MOV SS, ES:[BX+2] ; + MOV SP, ES:[BX] ; +; + POP DS ; Load new task's context + POP ES ; + POPA ; +; + IRET ; Return to new task +; +_OSIntCtxSw ENDP + + PAGE +;********************************************************************************************************* +; HANDLE TICK ISR +; +; Description: This function is called 199.99 times per second or, 11 times faster than the normal DOS +; tick rate of 18.20648 Hz. Thus every 11th time, the normal DOS tick handler is called. +; This is called chaining. 10 times out of 11, however, the interrupt controller on the PC +; must be cleared to allow for the next interrupt. +; +; Arguments : none +; +; Returns : none +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SS:SP +; } +; OSTickDOSCtr--; +; if (OSTickDOSCtr == 0) { +; OSTickDOSCtr = OSTickDOSCtrReload; +; INT 81H; Chain into DOS every 54.925 mS +; (Interrupt will be cleared by DOS) +; } else { +; Send EOI to PIC; Clear tick interrupt by sending an End-Of-Interrupt to the 8259 +; PIC (Priority Interrupt Controller) +; } +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* +; +_OSTickISR PROC FAR +; + PUSHA ; Save interrupted task's context + PUSH ES + PUSH DS +; + MOV AX, SEG(_OSIntNesting) ; Reload DS + MOV DS, AX + INC BYTE PTR DS:_OSIntNesting ; Notify uC/OS-II of ISR +; + CMP BYTE PTR DS:_OSIntNesting, 1 ; if (OSIntNesting == 1) + JNE SHORT _OSTickISR1 + MOV AX, SEG(_OSTCBCur) ; Reload DS + MOV DS, AX + LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr = SS:SP + MOV ES:[BX+2], SS ; + MOV ES:[BX+0], SP ; +; +_OSTickISR1: + MOV AX, SEG(_OSTickDOSCtr) ; Reload DS + MOV DS, AX + DEC BYTE PTR DS:_OSTickDOSCtr + CMP BYTE PTR DS:_OSTickDOSCtr, 0 + JNE SHORT _OSTickISR2 ; Every 11 ticks (~199.99 Hz), chain into DOS +; + MOV AL, BYTE PTR DS:_OSTickDOSCtrReload + MOV BYTE PTR DS:_OSTickDOSCtr, AL + INT 081H ; Chain into DOS's tick ISR + JMP SHORT _OSTickISR3 + +_OSTickISR2: + MOV AL, 20H ; Move EOI code into AL. + MOV DX, 20H ; Address of 8259 PIC in DX. + OUT DX, AL ; Send EOI to PIC if not processing DOS timer. +; +_OSTickISR3: + CALL FAR PTR _OSTimeTick ; Process system tick +; + CALL FAR PTR _OSIntExit ; Notify uC/OS-II of end of ISR +; + POP DS ; Restore interrupted task's context + POP ES + POPA +; + IRET ; Return to interrupted task +; +_OSTickISR ENDP +; + END diff --git a/Ports/80x86/DOS/L/BC45/os_cpu_c.c b/Ports/80x86/DOS/L/BC45/os_cpu_c.c new file mode 100644 index 0000000..33ebf51 --- /dev/null +++ b/Ports/80x86/DOS/L/BC45/os_cpu_c.c @@ -0,0 +1,340 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* 80x86/80x88 Specific code +* LARGE MEMORY MODEL +* +* Borland C/C++ V4.51 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +INT8U const OSTickDOSCtrReload = (INT8U)((FP32)OS_TICKS_PER_SEC / (FP32)18.20648 + (FP32)0.5); + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* PSW to 0x0002 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable +* interrupts. Failure to do this will make your system crash! +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT16U *)ptos; /* Load stack pointer */ + *stk-- = (INT16U)FP_SEG(p_arg); /* Simulate call to function with argument */ + *stk-- = (INT16U)FP_OFF(p_arg); + *stk-- = (INT16U)FP_SEG(task); + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0x0202; /* SW = Interrupts enabled */ + *stk-- = (INT16U)FP_SEG(task); /* Put pointer to task on top of stack */ + *stk-- = (INT16U)FP_OFF(task); + *stk-- = (INT16U)0xAAAA; /* AX = 0xAAAA */ + *stk-- = (INT16U)0xCCCC; /* CX = 0xCCCC */ + *stk-- = (INT16U)0xDDDD; /* DX = 0xDDDD */ + *stk-- = (INT16U)0xBBBB; /* BX = 0xBBBB */ + *stk-- = (INT16U)0x0000; /* SP = 0x0000 */ + *stk-- = (INT16U)0x1111; /* BP = 0x1111 */ + *stk-- = (INT16U)0x2222; /* SI = 0x2222 */ + *stk-- = (INT16U)0x3333; /* DI = 0x3333 */ + *stk-- = (INT16U)0x4444; /* ES = 0x4444 */ + *stk = _DS; /* DS = Current value of DS */ + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK FOR FLOATING POINT EMULATION +* +* Description: This function MUST be called BEFORE calling either OSTaskCreate() or OSTaskCreateExt() in +* order to initialize the task's stack to allow the task to use the Borland floating-point +* emulation. The returned pointer MUST be used in the task creation call. +* +* Ex.: OS_STK TaskStk[1000]; +* +* +* void main (void) +* { +* OS_STK *ptos; +* OS_STK *pbos; +* INT32U size; +* +* +* OSInit(); +* . +* . +* ptos = &TaskStk[999]; +* pbos = &TaskStk[0]; +* psize = 1000; +* OSTaskStkInit_FPE_x86(&ptos, &pbos, &size); +* OSTaskCreate(Task, (void *)0, ptos, 10); +* . +* . +* OSStart(); +* } +* +* Arguments : pptos is the pointer to the task's top-of-stack pointer which would be passed to +* OSTaskCreate() or OSTaskCreateExt(). +* +* ppbos is the pointer to the new bottom of stack pointer which would be passed to +* OSTaskCreateExt(). +* +* psize is a pointer to the size of the stack (in number of stack elements). You +* MUST allocate sufficient stack space to leave at least 384 bytes for the +* floating-point emulation. +* +* Returns : The new size of the stack once memory is allocated to the floating-point emulation. +* +* Note(s) : 1) _SS is a Borland 'pseudo-register' and returns the contents of the Stack Segment (SS) +* 2) The pointer to the top-of-stack (pptos) will be modified so that it points to the new +* top-of-stack. +* 3) The pointer to the bottom-of-stack (ppbos) will be modified so that it points to the new +* bottom-of-stack. +* 4) The new size of the stack is adjusted to reflect the fact that memory was reserved on +* the stack for the floating-point emulation. +********************************************************************************************************* +*/ + +void OSTaskStkInit_FPE_x86 (OS_STK **pptos, OS_STK **ppbos, INT32U *psize) +{ + INT32U lin_tos; /* 'Linear' version of top-of-stack address */ + INT32U lin_bos; /* 'Linear' version of bottom-of-stack address */ + INT16U seg; + INT16U off; + INT32U bytes; + + + seg = FP_SEG(*pptos); /* Decompose top-of-stack pointer into seg:off */ + off = FP_OFF(*pptos); + lin_tos = ((INT32U)seg << 4) + (INT32U)off; /* Convert seg:off to linear address */ + bytes = *psize * sizeof(OS_STK); /* Determine how many bytes for the stack */ + lin_bos = (lin_tos - bytes + 15) & 0xFFFFFFF0L; /* Ensure paragraph alignment for BOS */ + + seg = (INT16U)(lin_bos >> 4); /* Get new 'normalized' segment */ + *ppbos = (OS_STK *)MK_FP(seg, 0x0000); /* Create 'normalized' BOS pointer */ + /* Copy FP emulation memory to task's stack */ + OS_MemCopy((INT8U *)*ppbos, (INT8U *)MK_FP(_SS, 0), 384u); + bytes = bytes - 16; /* Loose 16 bytes because of alignment */ + *pptos = (OS_STK *)MK_FP(seg, (INT16U)bytes); /* Determine new top-of-stack */ + *ppbos = (OS_STK *)MK_FP(seg, 384u); /* Determine new bottom-of-stack */ + bytes = bytes - 384u; + *psize = bytes / sizeof(OS_STK); /* Determine new stack size */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/80x86/DOS/L/BC45/os_dbg.c b/Ports/80x86/DOS/L/BC45/os_dbg.c new file mode 100644 index 0000000..82725c6 --- /dev/null +++ b/Ports/80x86/DOS/L/BC45/os_dbg.c @@ -0,0 +1,265 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARC/EM6/MetaWare/os_cpu.h b/Ports/ARC/EM6/MetaWare/os_cpu.h new file mode 100644 index 0000000..4fdd22d --- /dev/null +++ b/Ports/ARC/EM6/MetaWare/os_cpu.h @@ -0,0 +1,149 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Synopsys ARC EM6 Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Synopsys ARC EM6 +* Mode : Little-Endian, 32 registers, FPU, Code Density, Loop Counter, Stack Check +* Toolchain : MetaWare C/C++ Clang-based Compiler +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* CONFIGURATION PRAGMAS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (STATUS = 32 bits) */ + + +/* +********************************************************************************************************* +* Synopsys ARC EM6 +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + + +/* +********************************************************************************************************* +* Synopsys ARC EM6 Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); + +void OSStartHighRdy (void); + +void OS_CPU_EM6_ExceptionHandler(void); +void OS_CPU_EM6_InterruptHandler(void); +void OS_CPU_EM6_TrapHandler (void); + + /* Must be implemented in the BSP for the OS. */ +void OS_CPU_ExceptionHandler (INT8U except_id); +void OS_CPU_InterruptHandler (INT8U int_id); + + +#endif diff --git a/Ports/ARC/EM6/MetaWare/os_cpu_a.s b/Ports/ARC/EM6/MetaWare/os_cpu_a.s new file mode 100644 index 0000000..2776d1c --- /dev/null +++ b/Ports/ARC/EM6/MetaWare/os_cpu_a.s @@ -0,0 +1,630 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Synopsys ARC EM6 Port +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; For : Synopsys ARC EM6 +; Mode : Little-Endian, 32 registers, FPU, Code Density, Loop Counter, Stack Check +; Toolchain : MetaWare C/C++ Clang-based Compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSCtxSw + .global OSIntCtxSw + + .global OSStartHighRdy + + .global OS_CPU_EM6_ExceptionHandler + .global OS_CPU_EM6_InterruptHandler + .global OS_CPU_EM6_TrapHandler + + +;******************************************************************************************************** +; EXTERNAL GLOBAL VARIABLES +;******************************************************************************************************** + + .extern OSPrioCur ; Declared as INT08U , 8-bit wide. + .extern OSPrioHighRdy ; Declared as INT08U , 8-bit wide. + .extern OSRunning ; Declared as INT08U , 8-bit wide. + .extern OSTCBCur ; Declared as OS_TCB * , 32-bit wide. + .extern OSTCBHighRdy ; Declared as OS_TCB * , 32-bit wide. + .extern OSTaskSwHook ; Declared as ptr to function, 32-bit wide. + .extern OS_CPU_ExceptionHandler ; Declared as ptr to function, 32-bit wide. + .extern OS_CPU_InterruptHandler ; Declared as ptr to function, 32-bit wide. + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + + ; Auxiliary Registers + .equ OS_CPU_AR_LP_START, 0x02 + .equ OS_CPU_AR_LP_END, 0x03 + .equ OS_CPU_AR_STATUS32, 0x0A + .equ OS_CPU_AR_JLI_BASE, 0x290 + .equ OS_CPU_AR_LDI_BASE, 0x291 + .equ OS_CPU_AR_EI_BASE, 0x292 + .equ OS_CPU_AR_ERET, 0x400 + .equ OS_CPU_AR_ERSTATUS, 0x402 + .equ OS_CPU_AR_ECR, 0x403 + .equ OS_CPU_AR_ICAUSE, 0x40A + + .equ OS_CPU_STATUS32_MASK, 0xFFF8603F + + ; Context offsets, in bytes, in saved stack. + .equ OS_CPU_STK_OFFSET_END, 164 + .equ OS_CPU_STK_OFFSET_STATUS32, 160 + .equ OS_CPU_STK_OFFSET_PC, 156 + .equ OS_CPU_STK_OFFSET_JLI_BASE, 152 + .equ OS_CPU_STK_OFFSET_LDI_BASE, 148 + .equ OS_CPU_STK_OFFSET_EI_BASE, 144 + .equ OS_CPU_STK_OFFSET_LP_COUNT, 140 + .equ OS_CPU_STK_OFFSET_LP_START, 136 + .equ OS_CPU_STK_OFFSET_LP_END, 132 + .equ OS_CPU_STK_OFFSET_R27, 128 + .equ OS_CPU_STK_OFFSET_R26, 124 + .equ OS_CPU_STK_OFFSET_R25, 120 + .equ OS_CPU_STK_OFFSET_R24, 116 + .equ OS_CPU_STK_OFFSET_R23, 112 + .equ OS_CPU_STK_OFFSET_R22, 108 + .equ OS_CPU_STK_OFFSET_R21, 104 + .equ OS_CPU_STK_OFFSET_R20, 100 + .equ OS_CPU_STK_OFFSET_R19, 96 + .equ OS_CPU_STK_OFFSET_R18, 92 + .equ OS_CPU_STK_OFFSET_R17, 88 + .equ OS_CPU_STK_OFFSET_R16, 84 + .equ OS_CPU_STK_OFFSET_R15, 80 + .equ OS_CPU_STK_OFFSET_R14, 76 + .equ OS_CPU_STK_OFFSET_R13, 72 + .equ OS_CPU_STK_OFFSET_R12, 68 + .equ OS_CPU_STK_OFFSET_R11, 64 + .equ OS_CPU_STK_OFFSET_R10, 60 + .equ OS_CPU_STK_OFFSET_R9, 56 + .equ OS_CPU_STK_OFFSET_R8, 52 + .equ OS_CPU_STK_OFFSET_R7, 48 + .equ OS_CPU_STK_OFFSET_R6, 44 + .equ OS_CPU_STK_OFFSET_R5, 40 + .equ OS_CPU_STK_OFFSET_R4, 36 + .equ OS_CPU_STK_OFFSET_R3, 32 + .equ OS_CPU_STK_OFFSET_R2, 28 + .equ OS_CPU_STK_OFFSET_R1, 24 + .equ OS_CPU_STK_OFFSET_R0, 20 + .equ OS_CPU_STK_OFFSET_BLINK, 16 + .equ OS_CPU_STK_OFFSET_R30, 12 + .equ OS_CPU_STK_OFFSET_R29, 8 + .equ OS_CPU_STK_OFFSET_ACCH, 4 + .equ OS_CPU_STK_OFFSET_ACCL, 0 + + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + +;******************************************************************************************************** +; FUNCTION +; +; Description : This macro declares a symbol of type function and aligns it to 4-bytes. +; +; Arguments : fname function to declare. +; +; Note(s) : none. +;******************************************************************************************************** + +.macro FUNCTION, fname + .type \&fname, @function + .align 4 + \&fname: +.endm + + +;******************************************************************************************************** +; SAVE_CONTEXT_FROM_EXCEPTION +; +; Description : Macro used to save the context of a task at the task level as if it were saved +; by an interrupt. +; +; Arguments : none. +; +; Note(s) : none. +;******************************************************************************************************** + +.macro SAVE_CONTEXT_FROM_EXCEPTION + ; Push context as if saved from interrupt. + ST %r0, [%sp, -(OS_CPU_STK_OFFSET_END-OS_CPU_STK_OFFSET_R0)] ; Save r0 first, used as a buffer. + + LR %r0, [OS_CPU_AR_ERSTATUS] ; STATUS32 + PUSH %r0 + LR %r0, [OS_CPU_AR_ERET] ; PC + PUSH %r0 + + LR %r0, [OS_CPU_AR_JLI_BASE] ; JLI_BASE + PUSH %r0 + LR %r0, [OS_CPU_AR_LDI_BASE] ; LDI_BASE + PUSH %r0 + LR %r0, [OS_CPU_AR_EI_BASE] ; EI_BASE + PUSH %r0 + + PUSH %lp_count ; LP_COUNT + LR %r0, [OS_CPU_AR_LP_START] ; LP_START + PUSH %r0 + LR %r0, [OS_CPU_AR_LP_END] ; LP_END + PUSH %r0 + + PUSH %r27 ; r27..r1 + PUSH %r26 + PUSH %r25 + PUSH %r24 + PUSH %r23 + PUSH %r22 + PUSH %r21 + PUSH %r20 + PUSH %r19 + PUSH %r18 + PUSH %r17 + PUSH %r16 + PUSH %r15 + PUSH %r14 + PUSH %r13 + PUSH %r12 + PUSH %r11 + PUSH %r10 + PUSH %r9 + PUSH %r8 + PUSH %r7 + PUSH %r6 + PUSH %r5 + PUSH %r4 + PUSH %r3 + PUSH %r2 + PUSH %r1 + + SUB %sp, %sp, 4 ; skip r0 + + PUSH %r31 ; r31..r29 + PUSH %r30 + PUSH %r29 + + PUSH %acch ; ACCH + PUSH %accl ; ACCL +.endm + + +;******************************************************************************************************** +; RESTORE_CONTEXT_FROM_EXCEPTION +; +; Description : Macro used to restore the context of a task at the task level as if it were restored +; by an interrupt. +; +; Arguments : none. +; +; Note(s) : none. +;******************************************************************************************************** + +.macro RESTORE_CONTEXT_FROM_EXCEPTION + ; Load ERET + LD %r0, [%sp, OS_CPU_STK_OFFSET_PC] + SR %r0, [OS_CPU_AR_ERET] + + ; Restore context manually because this is + ; a return from exception. + LD %r0, [%sp, OS_CPU_STK_OFFSET_JLI_BASE] ; JLI_BASE + SR %r0, [OS_CPU_AR_JLI_BASE] + + LD %r0, [%sp, OS_CPU_STK_OFFSET_LDI_BASE] ; LDI_BASE + SR %r0, [OS_CPU_AR_LDI_BASE] + + LD %r0, [%sp, OS_CPU_STK_OFFSET_EI_BASE] ; EI_BASE + SR %r0, [OS_CPU_AR_EI_BASE] + + LD %r0, [%sp, OS_CPU_STK_OFFSET_LP_COUNT] ; LP_COUNT + MOV %lp_count, %r0 + + LD %r0, [%sp, OS_CPU_STK_OFFSET_LP_START] ; LP_START + SR %r0, [OS_CPU_AR_LP_START] + + LD %r0, [%sp, OS_CPU_STK_OFFSET_LP_END] ; LP_END + SR %r0, [OS_CPU_AR_LP_END] + + LD %r31, [%sp, OS_CPU_STK_OFFSET_BLINK] ; r31..r29 + LD %r30, [%sp, OS_CPU_STK_OFFSET_R30] + LD %r29, [%sp, OS_CPU_STK_OFFSET_R29] + + LD %acch, [%sp, OS_CPU_STK_OFFSET_ACCH] ; ACCH and ACCL + LD %accl, [%sp, OS_CPU_STK_OFFSET_ACCL] + + LD %r27, [%sp, OS_CPU_STK_OFFSET_R27] ; r27..r0 + LD %r26, [%sp, OS_CPU_STK_OFFSET_R26] + LD %r25, [%sp, OS_CPU_STK_OFFSET_R25] + LD %r24, [%sp, OS_CPU_STK_OFFSET_R24] + LD %r23, [%sp, OS_CPU_STK_OFFSET_R23] + LD %r22, [%sp, OS_CPU_STK_OFFSET_R22] + LD %r21, [%sp, OS_CPU_STK_OFFSET_R21] + LD %r20, [%sp, OS_CPU_STK_OFFSET_R20] + LD %r19, [%sp, OS_CPU_STK_OFFSET_R19] + LD %r18, [%sp, OS_CPU_STK_OFFSET_R18] + LD %r17, [%sp, OS_CPU_STK_OFFSET_R17] + LD %r16, [%sp, OS_CPU_STK_OFFSET_R16] + LD %r15, [%sp, OS_CPU_STK_OFFSET_R15] + LD %r14, [%sp, OS_CPU_STK_OFFSET_R14] + LD %r13, [%sp, OS_CPU_STK_OFFSET_R13] + LD %r12, [%sp, OS_CPU_STK_OFFSET_R12] + LD %r11, [%sp, OS_CPU_STK_OFFSET_R11] + LD %r10, [%sp, OS_CPU_STK_OFFSET_R10] + LD %r9, [%sp, OS_CPU_STK_OFFSET_R9] + LD %r8, [%sp, OS_CPU_STK_OFFSET_R8] + LD %r7, [%sp, OS_CPU_STK_OFFSET_R7] + LD %r6, [%sp, OS_CPU_STK_OFFSET_R6] + LD %r5, [%sp, OS_CPU_STK_OFFSET_R5] + LD %r4, [%sp, OS_CPU_STK_OFFSET_R4] + LD %r3, [%sp, OS_CPU_STK_OFFSET_R3] + LD %r2, [%sp, OS_CPU_STK_OFFSET_R2] + LD %r1, [%sp, OS_CPU_STK_OFFSET_R1] + LD %r0, [%sp, OS_CPU_STK_OFFSET_R0] + + ; Adjust stack pointer. + ADD %sp, %sp, OS_CPU_STK_OFFSET_END +.endm + + +;******************************************************************************************************** +; SAVE_CONTEXT_FROM_INTERRUPT +; +; Description : Macro used to save the remaining context of a task when saved by an interrupt. +; +; Arguments : none. +; +; Note(s) : none. +;******************************************************************************************************** + +.macro SAVE_CONTEXT_FROM_INTERRUPT + ; Save manual part of context + PUSH %blink + PUSH %r30 + PUSH %r29 + PUSH %acch + PUSH %accl +.endm + + +;******************************************************************************************************** +; RESTORE_CONTEXT_FROM_INTERRUPT +; +; Description : Macro used to restore the remaining context of a task when restored by an interrupt. +; +; Arguments : none. +; +; Note(s) : none. +;******************************************************************************************************** + +.macro RESTORE_CONTEXT_FROM_INTERRUPT + ; Restore manual part of context. + POP %accl + POP %acch + POP %r29 + POP %r30 + POP %blink +.endm + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .text + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +FUNCTION OS_CPU_SR_Save + CLRI %r0 + J_S [%blink] + +FUNCTION OS_CPU_SR_Restore + SETI %r0 + J_S [%blink] + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook(). +; b) Set OSRunning to OS_TRUE. +; b) Restore context for OSTCBCur. +; c) RTIE into highest ready task. +;******************************************************************************************************** + +FUNCTION OSStartHighRdy + ; Call OSTaskSwHook + MOV %r0, OSTaskSwHook + JL_S [%r0] + + ; Set OSRunning to OS_TRUE + MOV %r0, OSRunning + STB 1, [%r0] + + ; Get stack pointer from OSTCBCur + MOV %r0, OSTCBCur + LD %r0, [%r0] + LD %sp, [%r0] + + ; Load ERSTATUS + LR %r0, [OS_CPU_AR_STATUS32] ; Merge Global and Local state. + AND %r0, %r0, OS_CPU_STATUS32_MASK + LD %r1, [%sp, OS_CPU_STK_OFFSET_STATUS32] + OR %r1, %r0, %r1 + SR %r1, [OS_CPU_AR_ERSTATUS] + + ; Restore context. + RESTORE_CONTEXT_FROM_EXCEPTION + RTIE + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +; triggers the TRAP exception which is where the real work is done. +;******************************************************************************************************** + +FUNCTION OSCtxSw + TRAP_S 0 + J_S [%blink] + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +; the result of an interrupt. +;******************************************************************************************************** + +FUNCTION OSIntCtxSw + ; Call OSTaskSwHook + MOV %r0, OSTaskSwHook + JL_S [%r0] + ; OSPrioCur = OSPrioHighRdy; + MOV %r0, OSPrioCur + MOV %r1, OSPrioHighRdy + LDB %r1, [%r1] + STB %r1, [%r0] + + ; OSTCBCur = OSTCBHighRdy; + MOV %r0, OSTCBCur + MOV %r1, OSTCBHighRdy + LD %r1, [%r1] + ST %r1, [%r0] + + ; Get SP from OSTCBHighRdy->OSTCBStkPtr. + LD %sp, [%r1] + + ; Merge Global and Local state. + LR %r0, [OS_CPU_AR_STATUS32] + AND %r0, %r0, OS_CPU_STATUS32_MASK + LD %r1, [%sp, OS_CPU_STK_OFFSET_STATUS32] + OR %r1, %r0, %r1 + ST %r1, [%sp, OS_CPU_STK_OFFSET_STATUS32] + + ; Restore manual part of context. + RESTORE_CONTEXT_FROM_INTERRUPT + ; Restore atomatic part of context. + RTIE + + +;******************************************************************************************************** +; GENERIC EXCEPTION HANDLER +; void OS_CPU_EM6_ExceptionHandler(void) +; +; Note(s) : 1) This is the global exception handler. It handles all exceptions an EM6 core may have. +; +; 2) The global exception handler calls the BSP defined 'OS_CPU_ExceptionHandler()' function to +; actually handle the exception. +; +; 3) This handler should fill all Vector Table entries for exceptions except for entry 0 (reset) +; and 9 (Trap). +;******************************************************************************************************** + +FUNCTION OS_CPU_EM6_ExceptionHandler + LR %r0, [OS_CPU_AR_ECR] + MOV %r1, OS_CPU_ExceptionHandler + JL [%r1] + RTIE + + +;******************************************************************************************************** +; GENERIC INTERRUPT HANDLER +; void OS_CPU_EM6_InterruptHandler(void) +; +; Note(s) : 1) This is the global interrupt handler. It handles all kernel-aware interrupts an EM6 core +; can observe. +; +; 2) The global interrupt handler calls the BSP defined 'OS_CPU_InterruptHandler()' function to +; actually handle the interrupt. +; +; 3) This handler should fill all Vector Table entries for interrupts. +;******************************************************************************************************** + +FUNCTION OS_CPU_EM6_InterruptHandler + ; Save manual part of context + SAVE_CONTEXT_FROM_INTERRUPT + + ; OSRunning? + MOV %r0, OSRunning + LDB %r0, [%r0] + BRNE_S %r0, 0, OS_CPU_EM6_InterruptHandler_Running + +;******************************************************************************************************** +; GENERIC INTERRUPT HANDLER: OS NOT RUNNING +; +; Note(s) : 1) If the OS is not running, the pseudo-code is: +; a) Calls OS_CPU_InterruptHandler(); +; b) Restore context and return to interrupted code. +;******************************************************************************************************** + +OS_CPU_EM6_InterruptHandler_NotRunning: + ; Call OS_CPU_InterruptHandler(); + LR %r0, [OS_CPU_AR_ICAUSE] + MOV %r1, OS_CPU_InterruptHandler + JL [%r1] + + ; Restore manual part of context. + RESTORE_CONTEXT_FROM_INTERRUPT + ; Restore atomatic part of context. + RTIE + +;******************************************************************************************************** +; GENERIC INTERRUPT HANDLER: OS RUNNING +; +; Note(s) : 1) If the OS is running, the pseudo-code is: +; a) OSTCBCur->OSTCBStkPtr = SP; +; b) Call OSIntEnter(); +; c) Call OS_CPU_InterruptHandler(); +; d) Call OSIntExit(); +; e) (if OSIntExit() returns): Restore context and return to interrupted task. +;******************************************************************************************************** + +OS_CPU_EM6_InterruptHandler_Running: + ; Save SP in OSTCBCur->OSTCBStkPtr. + MOV %r0, OSTCBCur + LD %r0, [%r0] + ST %sp, [%r0] + + ; Call OSIntEnter(); + MOV %r1, OSIntEnter + JL [%r1] + ; Call OS_CPU_InterruptHandler(); + LR %r0, [OS_CPU_AR_ICAUSE] + MOV %r1, OS_CPU_InterruptHandler + JL [%r1] + ; Call OSIntExit(); + MOV %r1, OSIntExit + JL [%r1] + ; Restore manual part of context. + RESTORE_CONTEXT_FROM_INTERRUPT + ; Restore atomatic part of context. + RTIE + +;******************************************************************************************************** +; HANDLE Trap EXCEPTION +; void OS_CPU_EM6_TrapHandler(void) +; +; Note(s) : 1) Trap is used to cause a context switch. +; +; 2) Pseudo-code is: +; a) Save registers as if saved by interrupt; +; c) Save the SP (r28): OSTCBCur->OSTCBStkPtr = SP; +; d) Call OSTaskSwHook(); +; e) Set current high priority , OSPrioCur = OSPrioHighRdy; +; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; g) Get new SP (r28): SP = OSTCBHighRdy->OSTCBStkPtr; +; h) Restore context. +; +; 3) On entry into Trap handler: +; a) The processor is in Kernel+Exception state. +; b) OSTCBCurPtr points to the OS_TCB of the task to suspend +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume +; +; 4) This function MUST be placed in entry 9 (Trap) of the Interruot Vector Table. +;******************************************************************************************************** + +FUNCTION OS_CPU_EM6_TrapHandler + ; Save current task's context. + SAVE_CONTEXT_FROM_EXCEPTION + + ; Save SP in OSTCBCur->OSTCBStkPtr. + MOV %r0, OSTCBCur + LD %r0, [%r0] + ST %sp, [%r0] + + ; Call OSTaskSwHook + MOV %r0, OSTaskSwHook + JL_S [%r0] + ; OSPrioCur = OSPrioHighRdy; + MOV %r0, OSPrioCur + MOV %r1, OSPrioHighRdy + LDB %r1, [%r1] + STB %r1, [%r0] + + ; OSTCBCur = OSTCBHighRdy; + MOV %r0, OSTCBCur + MOV %r1, OSTCBHighRdy + LD %r1, [%r1] + ST %r1, [%r0] + + ; Get SP from OSTCBHighRdy->OSTCBStkPtr. + LD %sp, [%r1] + + ; Load ERSTATUS + LR %r0, [OS_CPU_AR_ERSTATUS] ; Merge Global and Local state. + AND %r0, %r0, OS_CPU_STATUS32_MASK + LD %r1, [%sp, OS_CPU_STK_OFFSET_STATUS32] + OR %r1, %r0, %r1 + SR %r1, [OS_CPU_AR_ERSTATUS] + ; Restore context. + RESTORE_CONTEXT_FROM_EXCEPTION + RTIE + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + +.end diff --git a/Ports/ARC/EM6/MetaWare/os_cpu_c.c b/Ports/ARC/EM6/MetaWare/os_cpu_c.c new file mode 100644 index 0000000..6a9b801 --- /dev/null +++ b/Ports/ARC/EM6/MetaWare/os_cpu_c.c @@ -0,0 +1,415 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Synopsys ARC EM6 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Synopsys ARC EM6 +* Mode : Little-Endian, 32 registers, FPU, Code Density, Loop Counter, Stack Check +* Toolchain : MetaWare C/C++ Clang-based Compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + +#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES +const CPU_CHAR *os_cpu_c__c = "$Id: $"; +#endif + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* AUXILIARY REGISTERS +********************************************************************************************************* +*/ + /* Interrupt Controller Registers. */ +#define OS_CPU_AR_AUX_IRQ_CTRL (0x00Eu) + + /* Interrupt Controller Bits. */ +#define OS_CPU_AR_AUX_IRQ_CTRL_L (0x0400u) +#define OS_CPU_AR_AUX_IRQ_CTRL_LP (0x2000u) +#define OS_CPU_AR_AUX_IRQ_CTRL_NR (14u) + + +/* +********************************************************************************************************* +* AUXILIARY REGISTER RD/WR +********************************************************************************************************* +*/ + +#define OS_CPU_AR_RD(addr) _lr((addr)) +#define OS_CPU_AR_WR(addr, val) _sr((val), (addr)) + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +* +* 2) This hook sets up automatic context save on interrupts. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + /* Set automatic context save on interrupt for: */ + OS_CPU_AR_WR(OS_CPU_AR_AUX_IRQ_CTRL, OS_CPU_AR_AUX_IRQ_CTRL_L | /* loop registers. */ + OS_CPU_AR_AUX_IRQ_CTRL_LP | /* code-density registers. */ + OS_CPU_AR_AUX_IRQ_CTRL_NR); /* r27..r0 registers. */ +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ + +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when task starts executing. +* +* 2) Registers are stacked in the following order, from high to low: +* +* STATUS32 (0x0A) +* PC (r63) +* JLI_BASE (0x290) +* LDI_BASE (0x291) +* EI_BASE (0x292) +* LP_COUNT (r60) +* LP_START (0x02) +* LP_END (0x03) +* r27 +* r26 +* r25 +* . +* . +* . +* r0 +* r31 +* r30 +* r29 +* ACCH (r59) +* ACCL (r58) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *p_stk; + INT32U i; + + + (void)opt; /* 'opt' is not used, prevent warning */ + + p_stk = ptos + 1u; /* Load stack pointer */ + /* Align the stack to 4 bytes. */ + p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFFCu); + + /* Registers stacked as in saved by regular interrupt. */ + *(--p_stk) = (OS_STK)0x80000000; /* STATUS32 (0x0A) */ + *(--p_stk) = (OS_STK)task; /* PC (r63) */ + *(--p_stk) = (OS_STK)0x0; /* JLI_BASE (0x290) */ + *(--p_stk) = (OS_STK)0x0; /* LDI_BASE (0x291) */ + *(--p_stk) = (OS_STK)0x0; /* EI_BASE (0x292) */ + *(--p_stk) = (OS_STK)0x0; /* LP_COUNT (r60) */ + *(--p_stk) = (OS_STK)0x0; /* LP_START (0x02) */ + *(--p_stk) = (OS_STK)0x0; /* LP_END (0x03) */ + + *(--p_stk) = (OS_STK)0x0; /* FP (r27) */ + *(--p_stk) = (OS_STK)_core_read(26); /* GP (r26) */ + + + for (i = 25; i >= 1; --i) { /* r25..r1 */ + *(--p_stk) = (OS_STK)(0x01010101*i); + } + + *(--p_stk) = (OS_STK)p_arg; /* r0 */ + + *(--p_stk) = (OS_STK)OS_TaskReturn; /* BLINK (r31) */ + *(--p_stk) = (OS_STK)0x1E1E1E1E; /* r30 */ + *(--p_stk) = (OS_STK)0x1D1D1D1D; /* r29 */ + *(--p_stk) = (OS_STK)0x59595959; /* ACCH (r59) */ + *(--p_stk) = (OS_STK)0x58585858; /* ACCL (r58) */ + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/ARC/EM6/MetaWare/os_dbg.c b/Ports/ARC/EM6/MetaWare/os_dbg.c new file mode 100644 index 0000000..ad1e711 --- /dev/null +++ b/Ports/ARC/EM6/MetaWare/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu.h b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu.h new file mode 100644 index 0000000..3d41740 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu.h @@ -0,0 +1,306 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-A Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-A Cortex-A +* Mode : ARM or Thumb +* Toolchain : ARM C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-A line from the A5 to the A15 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.s are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.s +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d32.s +* Suitable for cpus implementing the NEON Media Processing Engine with +* 32 double word registers. +* +* os_cpu_a_vfp-d16.s +* Suitable for cpus with VFP-only support and 16 double word registers. +* Must also be used when the CPACR.D32DIS bit is set and access to registers +* D16-D31 would cause an exception. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if (defined(__BIG_ENDIAN)) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d16.s b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d16.s new file mode 100644 index 0000000..af1e046 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d16.s @@ -0,0 +1,719 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-d16.s +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : ARM C Compiler +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + + EXPORT OSStartHighRdy + EXPORT OSCtxSw + EXPORT OSIntCtxSw + + ; Functions related to exception handling. + EXPORT OS_CPU_ARM_ExceptUndefInstrHndlr + EXPORT OS_CPU_ARM_ExceptSwiHndlr + EXPORT OS_CPU_ARM_ExceptPrefetchAbortHndlr + EXPORT OS_CPU_ARM_ExceptDataAbortHndlr + EXPORT OS_CPU_ARM_ExceptIrqHndlr + EXPORT OS_CPU_ARM_ExceptFiqHndlr + + EXPORT OS_CPU_SR_INT_Dis + EXPORT OS_CPU_SR_INT_En + EXPORT OS_CPU_SR_FIQ_Dis + EXPORT OS_CPU_SR_FIQ_En + EXPORT OS_CPU_SR_IRQ_Dis + EXPORT OS_CPU_SR_IRQ_En + + EXPORT OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + REQUIRE8 + PRESERVE8 + + AREA CODE, CODE, READONLY + CODE32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + + MACRO + OS_CPU_ARM_FP_REG_POP $rx + POP {$rx} + VMSR FPEXC, $rx ; ... Pop new task's FPEXC + FLDMIAD SP!, {D0-D15} ; ... Pop new task's General-Purpose floating point registers. + POP {$rx} + VMSR FPSCR, $rx ; ... Pop new task's FPSCR. + MEND + + MACRO + OS_CPU_ARM_FP_REG_PUSH $rx + VMRS $rx, FPSCR ; ... Save current FPSCR + PUSH {$rx} ; ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + VMRS $rx, FPEXC ; ... Save Floating point exception register. + PUSH {$rx} + MEND + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #16 + BX LR + + END diff --git a/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d32.s b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d32.s new file mode 100644 index 0000000..c308070 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-d32.s @@ -0,0 +1,721 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-d32.s +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : ARM C Compiler +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + + EXPORT OSStartHighRdy + EXPORT OSCtxSw + EXPORT OSIntCtxSw + + ; Functions related to exception handling. + EXPORT OS_CPU_ARM_ExceptUndefInstrHndlr + EXPORT OS_CPU_ARM_ExceptSwiHndlr + EXPORT OS_CPU_ARM_ExceptPrefetchAbortHndlr + EXPORT OS_CPU_ARM_ExceptDataAbortHndlr + EXPORT OS_CPU_ARM_ExceptIrqHndlr + EXPORT OS_CPU_ARM_ExceptFiqHndlr + + EXPORT OS_CPU_SR_INT_Dis + EXPORT OS_CPU_SR_INT_En + EXPORT OS_CPU_SR_FIQ_Dis + EXPORT OS_CPU_SR_FIQ_En + EXPORT OS_CPU_SR_IRQ_Dis + EXPORT OS_CPU_SR_IRQ_En + + EXPORT OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + REQUIRE8 + PRESERVE8 + + AREA CODE, CODE, READONLY + CODE32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + + MACRO + OS_CPU_ARM_FP_REG_POP $rx + POP {$rx} + VMSR FPEXC, $rx ; ... Pop new task's FPEXC + FLDMIAD SP!, {D16-D31} + FLDMIAD SP!, {D0-D15} ; ... Pop new task's General-Purpose floating point registers. + POP {$rx} + VMSR FPSCR, $rx ; ... Pop new task's FPSCR. + MEND + + MACRO + OS_CPU_ARM_FP_REG_PUSH $rx + VMRS $rx, FPSCR ; ... Save current FPSCR + PUSH {$rx} ; ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + FSTMDBD SP!, {D16-D31} + VMRS $rx, FPEXC ; ... Save Floating point exception register. + PUSH {$rx} + MEND + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #32 + BX LR + + END diff --git a/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-none.s b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-none.s new file mode 100644 index 0000000..0f1e1c3 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/ARM/os_cpu_a_vfp-none.s @@ -0,0 +1,684 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-none.s +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : ARM C Compiler +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + + EXPORT OSStartHighRdy + EXPORT OSCtxSw + EXPORT OSIntCtxSw + + ; Functions related to exception handling. + EXPORT OS_CPU_ARM_ExceptUndefInstrHndlr + EXPORT OS_CPU_ARM_ExceptSwiHndlr + EXPORT OS_CPU_ARM_ExceptPrefetchAbortHndlr + EXPORT OS_CPU_ARM_ExceptDataAbortHndlr + EXPORT OS_CPU_ARM_ExceptIrqHndlr + EXPORT OS_CPU_ARM_ExceptFiqHndlr + + EXPORT OS_CPU_SR_INT_Dis + EXPORT OS_CPU_SR_INT_En + EXPORT OS_CPU_SR_FIQ_Dis + EXPORT OS_CPU_SR_FIQ_En + EXPORT OS_CPU_SR_IRQ_Dis + EXPORT OS_CPU_SR_IRQ_En + + EXPORT OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + REQUIRE8 + PRESERVE8 + + AREA CODE, CODE, READONLY + CODE32 + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #0 + BX LR + + END diff --git a/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu.h b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu.h new file mode 100644 index 0000000..d32e8f7 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu.h @@ -0,0 +1,306 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-A Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-A Cortex-A +* Mode : ARM or Thumb +* Toolchain : TI TMS470 COMPILER +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-A line from the A5 to the A15 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.asm are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.asm +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d32.asm +* Suitable for cpus implementing the NEON Media Processing Engine with +* 32 double word registers. +* +* os_cpu_a_vfp-d16.asm +* Suitable for cpus with VFP-only support and 16 double word registers. +* Must also be used when the CPACR.D32DIS bit is set and access to registers +* D16-D31 would cause an exception. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if defined(__big_endian__) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d16.asm b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d16.asm new file mode 100644 index 0000000..348eeb5 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d16.asm @@ -0,0 +1,726 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-d16.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : TI TMS470 COMPILER +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + .global OSRunning + .global OSPrioCur + .global OSPrioHighRdy + .global OSTCBCur + .global OSTCBHighRdy + .global OSIntNesting + .global OSIntExit + .global OSTaskSwHook + .global OS_CPU_ExceptStkBase + .global OS_CPU_ExceptStkPtr + .global OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +OSRunningAddr .word OSRunning +OSPrioCurAddr .word OSPrioCur +OSPrioHighRdyAddr .word OSPrioHighRdy +OSTCBCurAddr .word OSTCBCur +OSTCBHighRdyAddr .word OSTCBHighRdy +OSIntNestingAddr .word OSIntNesting +OSIntExitAddr .word OSIntExit +OSTaskSwHookAddr .word OSTaskSwHook +OS_CPU_ExceptStkBaseAddr .word OS_CPU_ExceptStkBase +OS_CPU_ExceptStkPtrAddr .word OS_CPU_ExceptStkPtr +OS_CPU_ExceptHndlrAddr .word OS_CPU_ExceptHndlr + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + ; Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS .equ 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS .equ 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS .equ 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB .equ 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM .equ 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK .equ 0x1F +OS_CPU_ARM_MODE_USR .equ 0x10 +OS_CPU_ARM_MODE_FIQ .equ 0x11 +OS_CPU_ARM_MODE_IRQ .equ 0x12 +OS_CPU_ARM_MODE_SVC .equ 0x13 +OS_CPU_ARM_MODE_ABT .equ 0x17 +OS_CPU_ARM_MODE_UND .equ 0x1B +OS_CPU_ARM_MODE_SYS .equ 0x1F + +OS_CPU_ARM_EXCEPT_RESET .equ 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR .equ 0x01 +OS_CPU_ARM_EXCEPT_SWI .equ 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT .equ 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT .equ 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT .equ 0x05 +OS_CPU_ARM_EXCEPT_IRQ .equ 0x06 +OS_CPU_ARM_EXCEPT_FIQ .equ 0x07 + +OS_CPU_ARM_FPEXC_EN .equ 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + .text + .state32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + +OS_CPU_ARM_FP_REG_POP .macro rx + POP {rx} + VMSR FPEXC, rx ; ... Pop new task's FPEXC + FLDMIAD SP!, {D0-D15} ; ... Pop new task's General-Purpose floating point registers. + POP {rx} + VMSR FPSCR, rx ; ... Pop new task's FPSCR. + .endm + +OS_CPU_ARM_FP_REG_PUSH .macro rx + VMRS rx, FPSCR ; ... Save current FPSCR + PUSH {rx} ; ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + VMRS rx, FPEXC ; ... Save Floating point exception register. + PUSH {rx} + .endm + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSRunningAddr ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, OSTCBHighRdyAddr ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + LDR R0, OSTCBCurAddr ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCur = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCurPtr = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + LDR R3, OSRunningAddr + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + LDR R3, OSTCBCurAddr ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, OS_CPU_ExceptStkBaseAddr ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + LDR R3, OSTCBCurAddr ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #16 + BX LR + diff --git a/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d32.asm b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d32.asm new file mode 100644 index 0000000..cb7f901 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-d32.asm @@ -0,0 +1,729 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-d32.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : TI TMS470 COMPILER +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + .global OSRunning + .global OSPrioCur + .global OSPrioHighRdy + .global OSTCBCur + .global OSTCBHighRdy + .global OSIntNesting + .global OSIntExit + .global OSTaskSwHook + .global OS_CPU_ExceptStkBase + .global OS_CPU_ExceptStkPtr + .global OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +OSRunningAddr .word OSRunning +OSPrioCurAddr .word OSPrioCur +OSPrioHighRdyAddr .word OSPrioHighRdy +OSTCBCurAddr .word OSTCBCur +OSTCBHighRdyAddr .word OSTCBHighRdy +OSIntNestingAddr .word OSIntNesting +OSIntExitAddr .word OSIntExit +OSTaskSwHookAddr .word OSTaskSwHook +OS_CPU_ExceptStkBaseAddr .word OS_CPU_ExceptStkBase +OS_CPU_ExceptStkPtrAddr .word OS_CPU_ExceptStkPtr +OS_CPU_ExceptHndlrAddr .word OS_CPU_ExceptHndlr + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + ; Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS .equ 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS .equ 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS .equ 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB .equ 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM .equ 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK .equ 0x1F +OS_CPU_ARM_MODE_USR .equ 0x10 +OS_CPU_ARM_MODE_FIQ .equ 0x11 +OS_CPU_ARM_MODE_IRQ .equ 0x12 +OS_CPU_ARM_MODE_SVC .equ 0x13 +OS_CPU_ARM_MODE_ABT .equ 0x17 +OS_CPU_ARM_MODE_UND .equ 0x1B +OS_CPU_ARM_MODE_SYS .equ 0x1F + +OS_CPU_ARM_EXCEPT_RESET .equ 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR .equ 0x01 +OS_CPU_ARM_EXCEPT_SWI .equ 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT .equ 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT .equ 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT .equ 0x05 +OS_CPU_ARM_EXCEPT_IRQ .equ 0x06 +OS_CPU_ARM_EXCEPT_FIQ .equ 0x07 + +OS_CPU_ARM_FPEXC_EN .equ 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + .text + .state32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + +OS_CPU_ARM_FP_REG_POP .macro rx + POP {rx} + VMSR FPEXC, rx ; ... Pop new task's FPEXC + FLDMIAD SP!, {D16-D31} + FLDMIAD SP!, {D0-D15} ; ... Pop new task's General-Purpose floating point registers. + POP {rx} + VMSR FPSCR, rx ; ... Pop new task's FPSCR. + .endm + +OS_CPU_ARM_FP_REG_PUSH .macro rx + VMRS rx, FPSCR ; ... Save current FPSCR + PUSH {rx} ; ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + FSTMDBD SP!, {D16-D31} + VMRS rx, FPEXC ; ... Save Floating point exception register. + PUSH {rx} + .endm + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSRunningAddr ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, OSTCBHighRdyAddr ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + LDR R0, OSTCBCurAddr ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCur = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCurPtr = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + LDR R3, OSRunningAddr + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + LDR R3, OSTCBCurAddr ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, OS_CPU_ExceptStkBaseAddr ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + LDR R3, OSTCBCurAddr ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #32 + BX LR + diff --git a/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-none.asm b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-none.asm new file mode 100644 index 0000000..6d14dca --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/CCS/os_cpu_a_vfp-none.asm @@ -0,0 +1,694 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-none.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : TI TMS470 COMPILER +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + .global OSRunning + .global OSPrioCur + .global OSPrioHighRdy + .global OSTCBCur + .global OSTCBHighRdy + .global OSIntNesting + .global OSIntExit + .global OSTaskSwHook + .global OS_CPU_ExceptStkBase + .global OS_CPU_ExceptStkPtr + .global OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +OSRunningAddr .word OSRunning +OSPrioCurAddr .word OSPrioCur +OSPrioHighRdyAddr .word OSPrioHighRdy +OSTCBCurAddr .word OSTCBCur +OSTCBHighRdyAddr .word OSTCBHighRdy +OSIntNestingAddr .word OSIntNesting +OSIntExitAddr .word OSIntExit +OSTaskSwHookAddr .word OSTaskSwHook +OS_CPU_ExceptStkBaseAddr .word OS_CPU_ExceptStkBase +OS_CPU_ExceptStkPtrAddr .word OS_CPU_ExceptStkPtr +OS_CPU_ExceptHndlrAddr .word OS_CPU_ExceptHndlr + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + ; Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS .equ 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS .equ 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS .equ 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB .equ 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM .equ 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK .equ 0x1F +OS_CPU_ARM_MODE_USR .equ 0x10 +OS_CPU_ARM_MODE_FIQ .equ 0x11 +OS_CPU_ARM_MODE_IRQ .equ 0x12 +OS_CPU_ARM_MODE_SVC .equ 0x13 +OS_CPU_ARM_MODE_ABT .equ 0x17 +OS_CPU_ARM_MODE_UND .equ 0x1B +OS_CPU_ARM_MODE_SYS .equ 0x1F + +OS_CPU_ARM_EXCEPT_RESET .equ 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR .equ 0x01 +OS_CPU_ARM_EXCEPT_SWI .equ 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT .equ 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT .equ 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT .equ 0x05 +OS_CPU_ARM_EXCEPT_IRQ .equ 0x06 +OS_CPU_ARM_EXCEPT_FIQ .equ 0x07 + +OS_CPU_ARM_FPEXC_EN .equ 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + .text + .state32 + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSRunningAddr ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, OSTCBHighRdyAddr ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX ; Clear exclusive monitor. + + LDR R0, OSTCBCurAddr ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCur = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCurPtr = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + LDR R3, OSRunningAddr + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + LDR R3, OSTCBCurAddr ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, OS_CPU_ExceptStkBaseAddr ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + LDR R3, OSTCBCurAddr ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #0 + BX LR + diff --git a/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu.h b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu.h new file mode 100644 index 0000000..400ba4a --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu.h @@ -0,0 +1,307 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-A Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-A Cortex-A +* Mode : ARM or Thumb +* Toolchain : GNU +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-A line from the A5 to the A15 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.S are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.S +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d32.S +* Suitable for cpus implementing the NEON Media Processing Engine with +* 32 double word registers. +* +* os_cpu_a_vfp-d16.S +* Suitable for cpus with VFP-only support and 16 double word registers. +* Must also be used when the CPACR.D32DIS bit is set and access to registers +* D16-D31 would cause an exception. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if (defined(__BYTE_ORDER__) && \ + (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d16.S b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d16.S new file mode 100644 index 0000000..ae8f652 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d16.S @@ -0,0 +1,746 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARMv7-A Port +@ +@ Filename : os_cpu_a_vfp-d16.S +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARMv7-A Cortex-A +@ Mode : ARM or Thumb +@ Toolchain : GNU +@******************************************************************************************************** +@ Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +@******************************************************************************************************** + +@******************************************************************************************************** +@ EXTERNAL REFERENCE +@******************************************************************************************************** + @ .external references. + .extern OSRunning + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntNesting + .extern OSIntExit + .extern OSTaskSwHook + .extern OS_CPU_ExceptStkBase + .extern OS_CPU_ExceptStkPtr + .extern OS_CPU_ExceptHndlr @ Chip Support/BSP specific exception handler. + + +@******************************************************************************************************** +@ FUNCTIONS +@******************************************************************************************************** + + @ Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + @ Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + + .equ OS_CPU_ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ. + .equ OS_CPU_ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ. + .equ OS_CPU_ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ. + .equ OS_CPU_ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode. + .equ OS_CPU_ARM_CONTROL_ARM, 0x00 @ Set ARM mode. + + .equ OS_CPU_ARM_MODE_MASK, 0x1F + .equ OS_CPU_ARM_MODE_USR, 0x10 + .equ OS_CPU_ARM_MODE_FIQ, 0x11 + .equ OS_CPU_ARM_MODE_IRQ, 0x12 + .equ OS_CPU_ARM_MODE_SVC, 0x13 + .equ OS_CPU_ARM_MODE_ABT, 0x17 + .equ OS_CPU_ARM_MODE_UND, 0x1B + .equ OS_CPU_ARM_MODE_SYS, 0x1F + + .equ OS_CPU_ARM_EXCEPT_RESET, 0x00 + .equ OS_CPU_ARM_EXCEPT_UNDEF_INSTR, 0x01 + .equ OS_CPU_ARM_EXCEPT_SWI, 0x02 + .equ OS_CPU_ARM_EXCEPT_PREFETCH_ABORT, 0x03 + .equ OS_CPU_ARM_EXCEPT_DATA_ABORT, 0x04 + .equ OS_CPU_ARM_EXCEPT_ADDR_ABORT, 0x05 + .equ OS_CPU_ARM_EXCEPT_IRQ, 0x06 + .equ OS_CPU_ARM_EXCEPT_FIQ, 0x07 + + .equ OS_CPU_ARM_FPEXC_EN, 0x40000000 @VFP enable bit. + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .code 32 + + +@******************************************************************************************************** +@ FLOATING POINT REGISTER MACROS +@******************************************************************************************************** + + .macro OS_CPU_ARM_FP_REG_POP rx + POP {\rx} + VMSR FPEXC, \rx @ ... Pop new task's FPEXC + FLDMIAD SP!, {D0-D15} @ ... Pop new task's General-Purpose floating point registers. + POP {\rx} + VMSR FPSCR, \rx @ ... Pop new task's FPSCR. + .endm + + .macro OS_CPU_ARM_FP_REG_PUSH rx + VMRS \rx, FPSCR @ ... Save current FPSCR + PUSH {\rx} @ ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + VMRS \rx, FPEXC @ ... Save Floating point exception register. + PUSH {\rx} + .endm + + +@******************************************************************************************************** +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +@ void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +@ +@ +@ Note(s) : (1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ /* Allocate storage for CPU status register. */ +@ #if (OS_CRITICAL_METHOD == 3) +@ OS_CPU_SR os_cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +@ : +@ : +@ } +@******************************************************************************************************** + + .type OS_CPU_SR_Save, %function +OS_CPU_SR_Save: + + MRS R0, CPSR + CPSID IF @ Set IRQ & FIQ bits in CPSR to DISABLE all interrupts. + DSB + BX LR @ DISABLED, return the original CPSR contents in R0. + + .type OS_CPU_SR_Restore, %function +OS_CPU_SR_Restore: + + DSB + MSR CPSR_c, R0 + BX LR + + +@******************************************************************************************************** +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to OS_STATE_OS_RUNNING, +@ c) Switch to the highest priority task. +@******************************************************************************************************** + + .type OSStartHighRdy, %function +OSStartHighRdy: + @ Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSRunning @ OSRunning = TRUE; + MOVT R0, #:upper16:OSRunning + MOV R1, #1 + STRB R1, [R0] + @ SWITCH TO HIGHEST PRIORITY TASK: + MOVW R0, #:lower16:OSTCBHighRdy @ Get highest priority task TCB address, + MOVT R0, #:upper16:OSTCBHighRdy + LDR R0, [R0] @ Get stack pointer, + LDR SP, [R0] @ Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) Save the current task's context onto the current task's stack, +@ b) OSTCBCur->StkPtr = SP; +@ c) OSTaskSwHook(); +@ d) OSPrioCur = OSPrioHighRdy; +@ e) OSTCBCurPtr = OSTCBHighRdy; +@ f) SP = OSTCBHighRdy->StkPtr; +@ g) Restore the new task's context from the new task's stack, +@ h) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSCtxSw, %function +OSCtxSw: + @ SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} @ Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} @ Push registers, + MRS R0, CPSR @ Push current CPSR, + TST LR, #1 @ See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB @ If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 @ Push FP context + + CLREX @ Clear exclusive monitor. + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur->StkPtr = SP; + MOVT R0, #:upper16:OSTCBCur + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdy->OSTCBStkPtr; + + @ RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 @ Pop new task's FP context. + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) OSTaskSwHook(); +@ b) OSPrioCur = OSPrioHighRdy; +@ c) OSTCBCurPtr = OSTCBHighRdyPtr; +@ d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +@ e) Restore the new task's context from the new task's stack, +@ f) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSIntCtxSw, %function +OSIntCtxSw: + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + CLREX @ Clear the exclusive acess tag for the processor. + + @ RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 @ Pop new task's FP context. + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ UNDEFINED INSTRUCTION EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ SOFTWARE INTERRUPT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI @ Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ PREFETCH ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ DATA ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ ADDRESS ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ @ Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ FAST INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ @ Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ GLOBAL EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Exception's SP +@ +@ Note(s) : 1) An exception can occur in three different circumstances@ in each of these, the +@ SVC stack pointer will point to a different entity : +@ +@ a) CONDITION: An exception occurs before the OS has been fully initialized. +@ SVC STACK: Should point to a stack initialized by the application's startup code. +@ STK USAGE: Interrupted context -- SVC stack. +@ Exception -- SVC stack. +@ Nested exceptions -- SVC stack. +@ +@ b) CONDITION: An exception interrupts a task. +@ SVC STACK: Should point to task stack. +@ STK USAGE: Interrupted context -- Task stack. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@ +@ c) CONDITION: An exception interrupts another exception. +@ SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +@ STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr: + + MRS R1, SPSR @ Save CPSR (i.e. exception's SPSR). + MOV R3, SP @ Save exception's stack pointer. + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + STMFD SP!, {R2} @ Push task's PC, + STMFD SP!, {LR} @ Push task's LR, + STMFD SP!, {R4-R12} @ Push task's R12-R4, + LDMFD R3!, {R5-R8} @ Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} @ Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + + MOVW R3, #:lower16:OSRunning @ if (OSRunning == 1) + MOVT R3, #:upper16:OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr++; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 @ if (OSIntNestingCtr == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: TASK INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask: + + MOVW R3, #:lower16:OSTCBCur @ OSTCBCurPtr->StkPtr = SP; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + STR SP, [R4] + + MOVW R3, #:lower16:OS_CPU_ExceptStkBase @ Switch to exception stack. + MOVT R3, #:upper16:OS_CPU_ExceptStkBase + LDR SP, [R3] + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ Call OSIntExit(). This call MAY never return if a ready + @ task with higher priority than the interrupted one is + @ found. + BL OSIntExit + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + MOVW R3, #:lower16:OSTCBCur @ SP = OSTCBCurPtr->StkPtr; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: EXCEPTION INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr--; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS +@ +@ Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs and FIQs so that +@ nesting can occur. +@ +@ 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_INT_En, %function +OS_CPU_SR_INT_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_INT_Dis, %function +OS_CPU_SR_INT_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE IRQs +@ +@ Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_IRQ_En, %function +OS_CPU_SR_IRQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_IRQ_Dis, %function +OS_CPU_SR_IRQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE FIQs +@ +@ Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_FIQ_En, %function +OS_CPU_SR_FIQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_FIQ_Dis, %function +OS_CPU_SR_FIQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ VFP/NEON REGISTER COUNT +@ +@ Register Usage: R0 Double Register Count +@******************************************************************************************************** + + .type OS_CPU_ARM_DRegCntGet, %function +OS_CPU_ARM_DRegCntGet: + + MOV R0, #16 + BX LR + diff --git a/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d32.S b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d32.S new file mode 100644 index 0000000..dadadd2 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-d32.S @@ -0,0 +1,749 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARMv7-A Port +@ +@ Filename : os_cpu_a_vfp-d32.S +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARMv7-A Cortex-A +@ Mode : ARM or Thumb +@ Toolchain : GNU +@******************************************************************************************************** +@ Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +@******************************************************************************************************** + + +@******************************************************************************************************** +@ EXTERNAL REFERENCE +@******************************************************************************************************** + @ .external references. + .extern OSRunning + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntNesting + .extern OSIntExit + .extern OSTaskSwHook + .extern OS_CPU_ExceptStkBase + .extern OS_CPU_ExceptStkPtr + .extern OS_CPU_ExceptHndlr @ Chip Support/BSP specific exception handler. + + +@******************************************************************************************************** +@ FUNCTIONS +@******************************************************************************************************** + + @ Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + @ Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + + .equ OS_CPU_ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ. + .equ OS_CPU_ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ. + .equ OS_CPU_ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ. + .equ OS_CPU_ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode. + .equ OS_CPU_ARM_CONTROL_ARM, 0x00 @ Set ARM mode. + + .equ OS_CPU_ARM_MODE_MASK, 0x1F + .equ OS_CPU_ARM_MODE_USR, 0x10 + .equ OS_CPU_ARM_MODE_FIQ, 0x11 + .equ OS_CPU_ARM_MODE_IRQ, 0x12 + .equ OS_CPU_ARM_MODE_SVC, 0x13 + .equ OS_CPU_ARM_MODE_ABT, 0x17 + .equ OS_CPU_ARM_MODE_UND, 0x1B + .equ OS_CPU_ARM_MODE_SYS, 0x1F + + .equ OS_CPU_ARM_EXCEPT_RESET, 0x00 + .equ OS_CPU_ARM_EXCEPT_UNDEF_INSTR, 0x01 + .equ OS_CPU_ARM_EXCEPT_SWI, 0x02 + .equ OS_CPU_ARM_EXCEPT_PREFETCH_ABORT, 0x03 + .equ OS_CPU_ARM_EXCEPT_DATA_ABORT, 0x04 + .equ OS_CPU_ARM_EXCEPT_ADDR_ABORT, 0x05 + .equ OS_CPU_ARM_EXCEPT_IRQ, 0x06 + .equ OS_CPU_ARM_EXCEPT_FIQ, 0x07 + + .equ OS_CPU_ARM_FPEXC_EN, 0x40000000 @VFP enable bit. + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .code 32 + + +@******************************************************************************************************** +@ FLOATING POINT REGISTER MACROS +@******************************************************************************************************** + + .macro OS_CPU_ARM_FP_REG_POP rx + POP {\rx} + VMSR FPEXC, \rx @ ... Pop new task's FPEXC + FLDMIAD SP!, {D16-D31} + FLDMIAD SP!, {D0-D15} @ ... Pop new task's General-Purpose floating point registers. + POP {\rx} + VMSR FPSCR, \rx @ ... Pop new task's FPSCR. + .endm + + .macro OS_CPU_ARM_FP_REG_PUSH rx + VMRS \rx, FPSCR @ ... Save current FPSCR + PUSH {\rx} @ ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + FSTMDBD SP!, {D16-D31} + VMRS \rx, FPEXC @ ... Save Floating point exception register. + PUSH {\rx} + .endm + + +@******************************************************************************************************** +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +@ void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +@ +@ +@ Note(s) : (1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ /* Allocate storage for CPU status register. */ +@ #if (OS_CRITICAL_METHOD == 3) +@ OS_CPU_SR os_cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +@ : +@ : +@ } +@******************************************************************************************************** + + .type OS_CPU_SR_Save, %function +OS_CPU_SR_Save: + + MRS R0, CPSR + CPSID IF @ Set IRQ & FIQ bits in CPSR to DISABLE all interrupts. + DSB + BX LR @ DISABLED, return the original CPSR contents in R0. + + .type OS_CPU_SR_Restore, %function +OS_CPU_SR_Restore: + + DSB + MSR CPSR_c, R0 + BX LR + + +@******************************************************************************************************** +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to OS_STATE_OS_RUNNING, +@ c) Switch to the highest priority task. +@******************************************************************************************************** + + .type OSStartHighRdy, %function +OSStartHighRdy: + @ Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSRunning @ OSRunning = TRUE; + MOVT R0, #:upper16:OSRunning + MOV R1, #1 + STRB R1, [R0] + @ SWITCH TO HIGHEST PRIORITY TASK: + MOVW R0, #:lower16:OSTCBHighRdy @ Get highest priority task TCB address, + MOVT R0, #:upper16:OSTCBHighRdy + LDR R0, [R0] @ Get stack pointer, + LDR SP, [R0] @ Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) Save the current task's context onto the current task's stack, +@ b) OSTCBCur->StkPtr = SP; +@ c) OSTaskSwHook(); +@ d) OSPrioCur = OSPrioHighRdy; +@ e) OSTCBCurPtr = OSTCBHighRdy; +@ f) SP = OSTCBHighRdy->StkPtr; +@ g) Restore the new task's context from the new task's stack, +@ h) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSCtxSw, %function +OSCtxSw: + @ SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} @ Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} @ Push registers, + MRS R0, CPSR @ Push current CPSR, + TST LR, #1 @ See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB @ If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 @ Push FP context + + CLREX @ Clear exclusive monitor. + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur->StkPtr = SP; + MOVT R0, #:upper16:OSTCBCur + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdy->OSTCBStkPtr; + + @ RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 @ Pop new task's FP context. + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) OSTaskSwHook(); +@ b) OSPrioCur = OSPrioHighRdy; +@ c) OSTCBCurPtr = OSTCBHighRdyPtr; +@ d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +@ e) Restore the new task's context from the new task's stack, +@ f) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSIntCtxSw, %function +OSIntCtxSw: + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + CLREX @ Clear the exclusive acess tag for the processor. + + @ RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 @ Pop new task's FP context. + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ UNDEFINED INSTRUCTION EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ SOFTWARE INTERRUPT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI @ Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ PREFETCH ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ DATA ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ ADDRESS ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ @ Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ FAST INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ @ Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ GLOBAL EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Exception's SP +@ +@ Note(s) : 1) An exception can occur in three different circumstances@ in each of these, the +@ SVC stack pointer will point to a different entity : +@ +@ a) CONDITION: An exception occurs before the OS has been fully initialized. +@ SVC STACK: Should point to a stack initialized by the application's startup code. +@ STK USAGE: Interrupted context -- SVC stack. +@ Exception -- SVC stack. +@ Nested exceptions -- SVC stack. +@ +@ b) CONDITION: An exception interrupts a task. +@ SVC STACK: Should point to task stack. +@ STK USAGE: Interrupted context -- Task stack. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@ +@ c) CONDITION: An exception interrupts another exception. +@ SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +@ STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr: + + MRS R1, SPSR @ Save CPSR (i.e. exception's SPSR). + MOV R3, SP @ Save exception's stack pointer. + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + STMFD SP!, {R2} @ Push task's PC, + STMFD SP!, {LR} @ Push task's LR, + STMFD SP!, {R4-R12} @ Push task's R12-R4, + LDMFD R3!, {R5-R8} @ Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} @ Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + + MOVW R3, #:lower16:OSRunning @ if (OSRunning == 1) + MOVT R3, #:upper16:OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr++; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 @ if (OSIntNestingCtr == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: TASK INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask: + + MOVW R3, #:lower16:OSTCBCur @ OSTCBCurPtr->StkPtr = SP; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + STR SP, [R4] + + MOVW R3, #:lower16:OS_CPU_ExceptStkBase @ Switch to exception stack. + MOVT R3, #:upper16:OS_CPU_ExceptStkBase + LDR SP, [R3] + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ Call OSIntExit(). This call MAY never return if a ready + @ task with higher priority than the interrupted one is + @ found. + BL OSIntExit + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + MOVW R3, #:lower16:OSTCBCur @ SP = OSTCBCurPtr->StkPtr; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: EXCEPTION INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr--; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS +@ +@ Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs and FIQs so that +@ nesting can occur. +@ +@ 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_INT_En, %function +OS_CPU_SR_INT_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_INT_Dis, %function +OS_CPU_SR_INT_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE IRQs +@ +@ Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_IRQ_En, %function +OS_CPU_SR_IRQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_IRQ_Dis, %function +OS_CPU_SR_IRQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE FIQs +@ +@ Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_FIQ_En, %function +OS_CPU_SR_FIQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_FIQ_Dis, %function +OS_CPU_SR_FIQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ VFP/NEON REGISTER COUNT +@ +@ Register Usage: R0 Double Register Count +@******************************************************************************************************** + + .type OS_CPU_ARM_DRegCntGet, %function +OS_CPU_ARM_DRegCntGet: + + MOV R0, #32 + BX LR + diff --git a/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-none.S b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-none.S new file mode 100644 index 0000000..2273262 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/GNU/os_cpu_a_vfp-none.S @@ -0,0 +1,713 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARMv7-A Port +@ +@ Filename : os_cpu_a_vfp-none.S +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARMv7-A Cortex-A +@ Mode : ARM or Thumb +@ Toolchain : GNU +@******************************************************************************************************** +@ Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +@******************************************************************************************************** + + +@******************************************************************************************************** +@ EXTERNAL REFERENCE +@******************************************************************************************************** + @ .external references. + .extern OSRunning + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntNesting + .extern OSIntExit + .extern OSTaskSwHook + .extern OS_CPU_ExceptStkBase + .extern OS_CPU_ExceptStkPtr + .extern OS_CPU_ExceptHndlr @ Chip Support/BSP specific exception handler. + + +@******************************************************************************************************** +@ FUNCTIONS +@******************************************************************************************************** + + @ Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + @ Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + + .equ OS_CPU_ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ. + .equ OS_CPU_ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ. + .equ OS_CPU_ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ. + .equ OS_CPU_ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode. + .equ OS_CPU_ARM_CONTROL_ARM, 0x00 @ Set ARM mode. + + .equ OS_CPU_ARM_MODE_MASK, 0x1F + .equ OS_CPU_ARM_MODE_USR, 0x10 + .equ OS_CPU_ARM_MODE_FIQ, 0x11 + .equ OS_CPU_ARM_MODE_IRQ, 0x12 + .equ OS_CPU_ARM_MODE_SVC, 0x13 + .equ OS_CPU_ARM_MODE_ABT, 0x17 + .equ OS_CPU_ARM_MODE_UND, 0x1B + .equ OS_CPU_ARM_MODE_SYS, 0x1F + + .equ OS_CPU_ARM_EXCEPT_RESET, 0x00 + .equ OS_CPU_ARM_EXCEPT_UNDEF_INSTR, 0x01 + .equ OS_CPU_ARM_EXCEPT_SWI, 0x02 + .equ OS_CPU_ARM_EXCEPT_PREFETCH_ABORT, 0x03 + .equ OS_CPU_ARM_EXCEPT_DATA_ABORT, 0x04 + .equ OS_CPU_ARM_EXCEPT_ADDR_ABORT, 0x05 + .equ OS_CPU_ARM_EXCEPT_IRQ, 0x06 + .equ OS_CPU_ARM_EXCEPT_FIQ, 0x07 + + .equ OS_CPU_ARM_FPEXC_EN, 0x40000000 @VFP enable bit. + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .code 32 + + +@******************************************************************************************************** +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +@ void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +@ +@ +@ Note(s) : (1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ /* Allocate storage for CPU status register. */ +@ #if (OS_CRITICAL_METHOD == 3) +@ OS_CPU_SR os_cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +@ : +@ : +@ } +@******************************************************************************************************** + + .type OS_CPU_SR_Save, %function +OS_CPU_SR_Save: + + MRS R0, CPSR + CPSID IF @ Set IRQ & FIQ bits in CPSR to DISABLE all interrupts. + DSB + BX LR @ DISABLED, return the original CPSR contents in R0. + + .type OS_CPU_SR_Restore, %function +OS_CPU_SR_Restore: + + DSB + MSR CPSR_c, R0 + BX LR + + +@******************************************************************************************************** +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to OS_STATE_OS_RUNNING, +@ c) Switch to the highest priority task. +@******************************************************************************************************** + + .type OSStartHighRdy, %function +OSStartHighRdy: + @ Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSRunning @ OSRunning = TRUE; + MOVT R0, #:upper16:OSRunning + MOV R1, #1 + STRB R1, [R0] + @ SWITCH TO HIGHEST PRIORITY TASK: + MOVW R0, #:lower16:OSTCBHighRdy @ Get highest priority task TCB address, + MOVT R0, #:upper16:OSTCBHighRdy + LDR R0, [R0] @ Get stack pointer, + LDR SP, [R0] @ Switch to the new stack, + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) Save the current task's context onto the current task's stack, +@ b) OSTCBCur->StkPtr = SP; +@ c) OSTaskSwHook(); +@ d) OSPrioCur = OSPrioHighRdy; +@ e) OSTCBCurPtr = OSTCBHighRdy; +@ f) SP = OSTCBHighRdy->StkPtr; +@ g) Restore the new task's context from the new task's stack, +@ h) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSCtxSw, %function +OSCtxSw: + @ SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} @ Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} @ Push registers, + MRS R0, CPSR @ Push current CPSR, + TST LR, #1 @ See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB @ If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX @ Clear exclusive monitor. + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur->StkPtr = SP; + MOVT R0, #:upper16:OSTCBCur + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdy->OSTCBStkPtr; + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) OSTaskSwHook(); +@ b) OSPrioCur = OSPrioHighRdy; +@ c) OSTCBCurPtr = OSTCBHighRdyPtr; +@ d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +@ e) Restore the new task's context from the new task's stack, +@ f) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSIntCtxSw, %function +OSIntCtxSw: + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + CLREX @ Clear the exclusive acess tag for the processor. + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ UNDEFINED INSTRUCTION EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ SOFTWARE INTERRUPT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI @ Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ PREFETCH ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ DATA ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ ADDRESS ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ @ Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ FAST INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ @ Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ GLOBAL EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Exception's SP +@ +@ Note(s) : 1) An exception can occur in three different circumstances@ in each of these, the +@ SVC stack pointer will point to a different entity : +@ +@ a) CONDITION: An exception occurs before the OS has been fully initialized. +@ SVC STACK: Should point to a stack initialized by the application's startup code. +@ STK USAGE: Interrupted context -- SVC stack. +@ Exception -- SVC stack. +@ Nested exceptions -- SVC stack. +@ +@ b) CONDITION: An exception interrupts a task. +@ SVC STACK: Should point to task stack. +@ STK USAGE: Interrupted context -- Task stack. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@ +@ c) CONDITION: An exception interrupts another exception. +@ SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +@ STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr: + + MRS R1, SPSR @ Save CPSR (i.e. exception's SPSR). + MOV R3, SP @ Save exception's stack pointer. + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + STMFD SP!, {R2} @ Push task's PC, + STMFD SP!, {LR} @ Push task's LR, + STMFD SP!, {R4-R12} @ Push task's R12-R4, + LDMFD R3!, {R5-R8} @ Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} @ Push task's CPSR (i.e. exception SPSR). + + MOVW R3, #:lower16:OSRunning @ if (OSRunning == 1) + MOVT R3, #:upper16:OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr++; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 @ if (OSIntNestingCtr == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: TASK INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask: + + MOVW R3, #:lower16:OSTCBCur @ OSTCBCurPtr->StkPtr = SP; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + STR SP, [R4] + + MOVW R3, #:lower16:OS_CPU_ExceptStkBase @ Switch to exception stack. + MOVT R3, #:upper16:OS_CPU_ExceptStkBase + LDR SP, [R3] + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ Call OSIntExit(). This call MAY never return if a ready + @ task with higher priority than the interrupted one is + @ found. + BL OSIntExit + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + MOVW R3, #:lower16:OSTCBCur @ SP = OSTCBCurPtr->StkPtr; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + LDR SP, [R4] + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: EXCEPTION INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr--; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS +@ +@ Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs and FIQs so that +@ nesting can occur. +@ +@ 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_INT_En, %function +OS_CPU_SR_INT_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_INT_Dis, %function +OS_CPU_SR_INT_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE IRQs +@ +@ Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_IRQ_En, %function +OS_CPU_SR_IRQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_IRQ_Dis, %function +OS_CPU_SR_IRQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE FIQs +@ +@ Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_FIQ_En, %function +OS_CPU_SR_FIQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_FIQ_Dis, %function +OS_CPU_SR_FIQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ VFP/NEON REGISTER COUNT +@ +@ Register Usage: R0 Double Register Count +@******************************************************************************************************** + + .type OS_CPU_ARM_DRegCntGet, %function +OS_CPU_ARM_DRegCntGet: + + MOV R0, #0 + BX LR + diff --git a/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu.h b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu.h new file mode 100644 index 0000000..b06f16c --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu.h @@ -0,0 +1,307 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-A Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-A Cortex-A +* Mode : ARM or Thumb +* Toolchain : IAR EWARM V5.xx and higher +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-A line from the A5 to the A15 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.asm are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.asm +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d32.asm +* Suitable for cpus implementing the NEON Media Processing Engine with +* 32 double word registers. +* +* os_cpu_a_vfp-d16.asm +* Suitable for cpus with VFP-only support and 16 double word registers. +* Must also be used when the CPACR.D32DIS bit is set and access to registers +* D16-D31 would cause an exception. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if (defined(__LITTLE_ENDIAN__) && \ + (__LITTLE_ENDIAN__ == 1)) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d16.asm b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d16.asm new file mode 100644 index 0000000..243733f --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d16.asm @@ -0,0 +1,717 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-d16.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : IAR EWARM V5.xx and higher +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + + ; Functions related to exception handling. + PUBLIC OS_CPU_ARM_ExceptUndefInstrHndlr + PUBLIC OS_CPU_ARM_ExceptSwiHndlr + PUBLIC OS_CPU_ARM_ExceptPrefetchAbortHndlr + PUBLIC OS_CPU_ARM_ExceptDataAbortHndlr + PUBLIC OS_CPU_ARM_ExceptIrqHndlr + PUBLIC OS_CPU_ARM_ExceptFiqHndlr + + PUBLIC OS_CPU_SR_INT_Dis + PUBLIC OS_CPU_SR_INT_En + PUBLIC OS_CPU_SR_FIQ_Dis + PUBLIC OS_CPU_SR_FIQ_En + PUBLIC OS_CPU_SR_IRQ_Dis + PUBLIC OS_CPU_SR_IRQ_En + + PUBLIC OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + RSEG CODE:CODE:NOROOT(2) + AAPCS INTERWORK + PRESERVE8 + REQUIRE8 + CODE32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + +?OS_CPU_ARM_FP_REG_POP MACRO rx + POP {rx} + VMSR FPEXC, rx ; ... Pop new task's FPEXC + FLDMIAS SP!, {S0-S31} ; ... Pop new task's General-Purpose floating point registers. + POP {rx} + VMSR FPSCR, rx ; ... Pop new task's FPSCR. + ENDM + +?OS_CPU_ARM_FP_REG_PUSH MACRO rx + VMRS rx, FPSCR ; ... Save current FPSCR + PUSH {rx} ; ... Save general-purpose floating-point registers. + FSTMDBS SP!, {S0-S31} + VMRS rx, FPEXC ; ... Save Floating point exception register. + PUSH {rx} + ENDM + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + ?OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + ?OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + ?OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + ?OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ?OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #16 + BX LR + + END diff --git a/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d32.asm b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d32.asm new file mode 100644 index 0000000..fe12c0d --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-d32.asm @@ -0,0 +1,719 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-d32.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : IAR EWARM V5.xx and higher +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + + ; Functions related to exception handling. + PUBLIC OS_CPU_ARM_ExceptUndefInstrHndlr + PUBLIC OS_CPU_ARM_ExceptSwiHndlr + PUBLIC OS_CPU_ARM_ExceptPrefetchAbortHndlr + PUBLIC OS_CPU_ARM_ExceptDataAbortHndlr + PUBLIC OS_CPU_ARM_ExceptIrqHndlr + PUBLIC OS_CPU_ARM_ExceptFiqHndlr + + PUBLIC OS_CPU_SR_INT_Dis + PUBLIC OS_CPU_SR_INT_En + PUBLIC OS_CPU_SR_FIQ_Dis + PUBLIC OS_CPU_SR_FIQ_En + PUBLIC OS_CPU_SR_IRQ_Dis + PUBLIC OS_CPU_SR_IRQ_En + + PUBLIC OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + RSEG CODE:CODE:NOROOT(2) + AAPCS INTERWORK + PRESERVE8 + REQUIRE8 + CODE32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + +?OS_CPU_ARM_FP_REG_POP MACRO rx + POP {rx} + VMSR FPEXC, rx ; ... Pop new task's FPEXC + FLDMIAD SP!, {D16-D31} + FLDMIAD SP!, {D0-D15} ; ... Pop new task's General-Purpose floating point registers. + POP {rx} + VMSR FPSCR, rx ; ... Pop new task's FPSCR. + ENDM + +?OS_CPU_ARM_FP_REG_PUSH MACRO rx + VMRS rx, FPSCR ; ... Save current FPSCR + PUSH {rx} ; ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + FSTMDBD SP!, {D16-D31} + VMRS rx, FPEXC ; ... Save Floating point exception register. + PUSH {rx} + ENDM + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + ?OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + ?OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + ?OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + ?OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ?OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #32 + BX LR + + END diff --git a/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-none.asm b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-none.asm new file mode 100644 index 0000000..523030c --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/IAR/os_cpu_a_vfp-none.asm @@ -0,0 +1,684 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-A Port +; +; Filename : os_cpu_a_vfp-none.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-A Cortex-A +; Mode : ARM or Thumb +; Toolchain : IAR EWARM V5.xx and higher +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important information about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + + ; Functions related to exception handling. + PUBLIC OS_CPU_ARM_ExceptUndefInstrHndlr + PUBLIC OS_CPU_ARM_ExceptSwiHndlr + PUBLIC OS_CPU_ARM_ExceptPrefetchAbortHndlr + PUBLIC OS_CPU_ARM_ExceptDataAbortHndlr + PUBLIC OS_CPU_ARM_ExceptIrqHndlr + PUBLIC OS_CPU_ARM_ExceptFiqHndlr + + PUBLIC OS_CPU_SR_INT_Dis + PUBLIC OS_CPU_SR_INT_En + PUBLIC OS_CPU_SR_FIQ_Dis + PUBLIC OS_CPU_SR_FIQ_En + PUBLIC OS_CPU_SR_IRQ_Dis + PUBLIC OS_CPU_SR_IRQ_En + + PUBLIC OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + RSEG CODE:CODE:NOROOT(2) + AAPCS INTERWORK + PRESERVE8 + REQUIRE8 + CODE32 + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #0 + BX LR + + END diff --git a/Ports/ARM-Cortex-A/ARMv7-A/os_cpu_c.c b/Ports/ARM-Cortex-A/ARMv7-A/os_cpu_c.c new file mode 100644 index 0000000..d7a62ff --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv7-A/os_cpu_c.c @@ -0,0 +1,624 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-A Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-A Cortex-A +* Mode : ARM or Thumb +********************************************************************************************************** +*/ + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +* +* Note(s) : 1) ARM_MODE_ARM is the CPSR bit mask for ARM Mode +* 2) ARM_MODE_THUMB is the CPSR bit mask for THUMB Mode +* 3) ARM_SVC_MODE_THUMB is the CPSR bit mask for SVC MODE + THUMB Mode +* 4) ARM_SVC_MODE_ARM is the CPSR bit mask for SVC MODE + ARM Mode +********************************************************************************************************* +*/ + +#if (OS_CPU_ARM_ENDIAN_TYPE == OS_CPU_ARM_ENDIAN_LITTLE) +#define ARM_MODE_ARM 0x00000000u +#define ARM_MODE_THUMB 0x00000020u +#else /* Set bit 9 in big-endian mode. */ +#define ARM_MODE_ARM 0x00000200u +#define ARM_MODE_THUMB 0x00000220u +#endif + +#define ARM_SVC_MODE_THUMB (0x00000013u + ARM_MODE_THUMB) +#define ARM_SVC_MODE_ARM (0x00000013u + ARM_MODE_ARM) + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; + + /* Clear exception stack for stack checking. */ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk++ = (OS_STK)0; + } + /* Align the ISR stack to 8-bytes */ + OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; + OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8); + + OS_CPU_ARM_DRegCnt = OS_CPU_ARM_DRegCntGet(); + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0u + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) Interrupts are enabled when task starts executing. +* +* (2) All tasks run in SVC mode. +* +* (3) There are three differents stack frames depending on whether or not the Floating-Point (FP) co-processor +* is enabled or not. +* +* (a) The stack frame shown in the diagram is used when the FP coprocessor is present and +* OS_OPT_TASK_SAVE_FP is enabled. In this case the FP exception register, the FP registers and the +* FP control/status register are saved in the stack frame. +* +* (b) If the FP co-processor is present but the OS_OPT_TASK_SAVE_FP is not set, only the FP +* exception register is saved in the stack. +* +* (1) The FP exception register is saved twice in the stack frame to keep the 8-byte aligment. +* (See note #4.) +* +* +-----------+ +* | FPEXC | +* +-----------+ +* | S0 | +* +-----------+ +* . +* . +* . +* +-----------+ +* | S29 | +* +-----------+ +* | S30 | +* +-----------+ +-----------+ +* | S31 | | FPEXC | +* +-----------+ +-----------+ +* | FPSCR | | FPEXC | +* +-----------+ +-----------+ +-----------+ +* | CPSR | | CPSR | | CPSR | +* +-----------+ +-----------+ +-----------+ +* | R0 | | R0 | | R0 | +* +-----------+ +-----------+ +-----------+ +* . . . +* . . . +* . . . +* +-----------+ +-----------+ +-----------+ +* | R10 | | R10 | | R10 | +* +-----------+ +-----------+ +-----------+ +* | R11 | | R11 | | R11 | +* +-----------+ +-----------+ +-----------+ +* | R12 | | R12 | | R12 | +* +-----------+ +-----------+ +-----------+ +* | R14 (LR) | | R14 (LR) | | R14 (LR) | +* +-----------+ +-----------+ +-----------+ +* | PC = Task | | PC = Task | | PC = Task | +* +-----------+ +-----------+ +-----------+ +* +* (a) (b) (c) +* +* (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture +* +* (a) Section 2.1 of the ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned +* on entry to AAPCS-Conforming functions states : +* +* The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive +* data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes). +* Doing otherwise creates more problems than it solves. +* +* In return for preserving the natural alignment of data, conforming code is permitted +* to rely on that alignment. To support aligning data allocated on the stack, the stack +* pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In +* practice this requirement is met if: +* +* (1) At each call site, the current size of the calling function's stack frame is a multiple of 8 bytes. +* This places an obligation on compilers and assembly language programmers. +* +* (2) SP is a multiple of 8 when control first enters a program. +* This places an obligation on authors of low level OS, RTOS, and runtime library +* code to align SP at all points at which control first enters +* a body of (AAPCS-conforming) code. +* +* In turn, this requires the value of SP to be aligned to 0 modulo 8: +* +* (3) By exception handlers, before calling AAPCS-conforming code. +* +* (4) By OS/RTOS/run-time system code, before giving control to an application. +* +* (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry +* to AAPCS-conforming functions advisory note also states. +* +* " This requirement extends to operating systems and run-time code for all architecture versions +* prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations +* associated with ARMV7M are discussed in section 2.3.3" +* +* (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned +* to 8-byte boundaries to support legacy execution enviroments. +* +* (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM +* architecture states : "The stack must also conform to the following +* constraint at a public interface: +* +* (1) SP mod 8 = 0. The stack must be double-word aligned" +* +* (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment. +* +* "8 byte stack alignment is a requirement of the ARM Architecture Procedure +* Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte +* aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external +* interfaces. In practice this requirement is met if: +* +* (1) At each external interface, the current stack pointer +* is a multiple of 8 bytes. +* +* (2) Your OS maintains 8 byte stack alignment on its external interfaces +* e.g. on task switches" +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + INT32U task_addr; + INT32U fpu_reg_cnt; + INT8U i; + + + (void)opt; + + p_stk = ptos + 1u; /* Load stack pointer */ + p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u); /* Align stack pointer. */ + task_addr = (INT32U)task & ~1u; /* Mask off lower bit in case task is thumb mode */ + + *--p_stk = (OS_STK)task_addr; /* Entry Point */ + *--p_stk = (OS_STK)OS_TaskReturn; /* R14 (LR) */ + *--p_stk = (OS_STK)0x12121212u; /* R12 */ + *--p_stk = (OS_STK)0x11111111u; /* R11 */ + *--p_stk = (OS_STK)0x10101010u; /* R10 */ + *--p_stk = (OS_STK)0x09090909u; /* R9 */ + *--p_stk = (OS_STK)0x08080808u; /* R8 */ + *--p_stk = (OS_STK)0x07070707u; /* R7 */ + *--p_stk = (OS_STK)0x06060606u; /* R6 */ + *--p_stk = (OS_STK)0x05050505u; /* R5 */ + *--p_stk = (OS_STK)0x04040404u; /* R4 */ + *--p_stk = (OS_STK)0x03030303u; /* R3 */ + *--p_stk = (OS_STK)0x02020202u; /* R2 */ + *--p_stk = (OS_STK)0x01010101u; /* R1 */ + *--p_stk = (OS_STK)p_arg; /* R0 : argument */ + + + if (((INT32U)task & 0x01u) == 0x01u) { /* See if task runs in Thumb or ARM mode */ + *--p_stk = (OS_STK)(ARM_SVC_MODE_THUMB); /* Set Thumb mode. */ + } else { + *--p_stk = (OS_STK)(ARM_SVC_MODE_ARM); + } + + fpu_reg_cnt = OS_CPU_ARM_DRegCntGet(); + + if(fpu_reg_cnt != 0u) { + *--p_stk = (OS_STK)0; /* Initialize Floating point status & control register */ + /* Initialize general-purpose Floating point registers */ + for (i = 0u; i < fpu_reg_cnt * 2u; i++) { + *--p_stk = (OS_STK)0; + } + + *--p_stk = (OS_STK)(0x40000000); /* Initialize Floating-Point Exception Register (Enable)*/ + } + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +* 3) If debug variables are enabled, the current process id is saved into the context ID register +* found in the system control coprocessor. The Embedded Trace Macrocell (ETM) and the debug logic +* use this register. The ETM can broadcast its value to indicate the process that is running currently. +* +* (a) The proccess id is formed by concatenating the current task priority with the lower 24 bits +* from the current task TCB. +* +* 31 24 0 +* +---------------+---------------------+ +* | OSPrioHighRdy | OSTCBHighRdy[23..0] | +* +---------------+---------------------+ +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) + +{ +#if OS_CFG_DBG_EN > 0u + INT32U ctx_id; +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif + + OS_TRACE_TASK_SWITCHED_IN(OSTCBHighRdy); + +#if OS_CFG_DBG_EN > 0u + ctx_id = ((INT32U)(OSPrioHighRdy << 24u) ) + | ((INT32U)(OSTCBHighRdy ) & 0x00FFFFFF); + OS_CPU_ARM_CtxID_Set(ctx_id); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* GET NUMBER OF FREE ENTRIES IN EXCEPTION STACK +* +* Description : This function computes the number of free entries in the exception stack. +* +* Arguments : None. +* +* Returns : The number of free entries in the exception stack. +********************************************************************************************************* +*/ + +INT32U OS_CPU_ExceptStkChk (void) +{ + OS_STK *pchk; + INT32U nfree; + INT32U size; + + + nfree = 0; + size = OS_CPU_EXCEPT_STK_SIZE; + pchk = &OS_CPU_ExceptStk[0]; + while ((*pchk++ == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } + + return (nfree); +} diff --git a/Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu.h b/Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu.h new file mode 100644 index 0000000..14effeb --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu.h @@ -0,0 +1,223 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv8-A Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv8-A Cortex-A +* Mode : ARM64 +* Toolchain : GNU +********************************************************************************************************** +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 1024 OS_STK entries */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if (defined(__BYTE_ORDER__) && \ + (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_INT64U INT64U; /* Unsigned 64 bit quantity */ +typedef CPU_INT64S INT64S; /* Signed 64 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Each stack entry is 32-bit wide */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if (OS_CRITICAL_METHOD == 3u) + +#if (OS_CPU_INT_DIS_MEAS_EN > 0u) + +#define OS_ENTER_CRITICAL() do { cpu_sr = CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {CPU_SR_Restore(cpu_sr);} while (0) + +#endif /* OS_CPU_INT_DIS_MEAS_EN > 0u */ + +#endif /* OS_CRITICAL_METHOD == 3u */ + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if (OS_CPU_INT_DIS_MEAS_EN > 0u) +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if (OS_CRITICAL_METHOD == 3u) /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if (OS_CPU_INT_DIS_MEAS_EN > 0u) + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + INT64U OS_CPU_SPSRGet (void); + INT64U OS_CPU_SIMDGet (void); +#endif diff --git a/Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu_a.S b/Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu_a.S new file mode 100644 index 0000000..beba047 --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv8-A/GNU/os_cpu_a.S @@ -0,0 +1,496 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARMv8-A Port +* +* Filename : os_cpu_a.S +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv8-A Cortex-A +* Mode : ARM64 +* Toolchain : GNU +********************************************************************************************************** +*/ + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + /* External references. */ + .global OSRunning + .global OSPrioCur + .global OSPrioHighRdy + .global OSTCBCurPtr + .global OSTCBHighRdyPtr + .global OSIntNestingCtr + .global OSIntExit + .global OSTaskSwHook + .global OS_CPU_ExceptStkBase + .global OS_CPU_ExceptHndlr + + /* Functions declared in this file. */ + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_SPSRGet + .global OS_CPU_SIMDGet + +/* +********************************************************************************************************* +* EQUATES +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EL3 +#define OS_CPU_EL3 1 +#endif + +#ifndef OS_CPU_SIMD +#define OS_CPU_SIMD 1 +#endif + +/* +********************************************************************************************************* +* CODE GENERATION DIRECTIVES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* REGISTER MACROS +********************************************************************************************************* +*/ + + .macro OS_CPU_ARM_REG_POP + + #if OS_CPU_SIMD == 1 + LDP x28, x29, [sp], #16 + MSR FPSR, x28 + MSR FPCR, x29 + + LDP q0, q1, [sp], #32 + LDP q2, q3, [sp], #32 + LDP q4, q5, [sp], #32 + LDP q6, q7, [sp], #32 + LDP q8, q9, [sp], #32 + LDP q10, q11, [sp], #32 + LDP q12, q13, [sp], #32 + LDP q14, q15, [sp], #32 + LDP q16, q17, [sp], #32 + LDP q18, q19, [sp], #32 + LDP q20, q21, [sp], #32 + LDP q22, q23, [sp], #32 + LDP q24, q25, [sp], #32 + LDP q26, q27, [sp], #32 + LDP q28, q29, [sp], #32 + LDP q30, q31, [sp], #32 + #endif + + LDP x0, x1, [sp], #16 + #if OS_CPU_EL3 == 1 + MSR SPSR_EL3, x1 + #else + MSR SPSR_EL1, x1 + #endif + + LDP x30, x0, [sp], #16 + #if OS_CPU_EL3 == 1 + MSR ELR_EL3, x0 + #else + MSR ELR_EL1, x0 + #endif + + LDP x0, x1, [sp], #16 + LDP x2, x3, [sp], #16 + LDP x4, x5, [sp], #16 + LDP x6, x7, [sp], #16 + LDP x8, x9, [sp], #16 + LDP x10, x11, [sp], #16 + LDP x12, x13, [sp], #16 + LDP x14, x15, [sp], #16 + LDP x16, x17, [sp], #16 + LDP x18, x19, [sp], #16 + LDP x20, x21, [sp], #16 + LDP x22, x23, [sp], #16 + LDP x24, x25, [sp], #16 + LDP x26, x27, [sp], #16 + LDP x28, x29, [sp], #16 + .endm + + .macro OS_CPU_ARM_REG_PUSH + STP x28, x29, [sp, #-16]! + STP x26, x27, [sp, #-16]! + STP x24, x25, [sp, #-16]! + STP x22, x23, [sp, #-16]! + STP x20, x21, [sp, #-16]! + STP x18, x19, [sp, #-16]! + STP x16, x17, [sp, #-16]! + STP x14, x15, [sp, #-16]! + STP x12, x13, [sp, #-16]! + STP x10, x11, [sp, #-16]! + STP x8, x9, [sp, #-16]! + STP x6, x7, [sp, #-16]! + STP x4, x5, [sp, #-16]! + STP x2, x3, [sp, #-16]! + STP x0, x1, [sp, #-16]! + + #if OS_CPU_EL3 == 1 + MRS x0, ELR_EL3 + #else + MRS x0, ELR_EL1 + #endif + + STP x30, x0, [sp, #-16]! + + #if OS_CPU_EL3 == 1 + MRS x0, SPSR_EL3 + #else + MRS x0, SPSR_EL1 + #endif + + MOV x1, x0 + STP x0, x1, [sp, #-16]! + + #if OS_CPU_SIMD == 1 + STP q30, q31, [sp, #-32]! + STP q28, q29, [sp, #-32]! + STP q26, q27, [sp, #-32]! + STP q24, q25, [sp, #-32]! + STP q22, q23, [sp, #-32]! + STP q20, q21, [sp, #-32]! + STP q18, q19, [sp, #-32]! + STP q16, q17, [sp, #-32]! + STP q14, q15, [sp, #-32]! + STP q12, q13, [sp, #-32]! + STP q10, q11, [sp, #-32]! + STP q8, q9, [sp, #-32]! + STP q6, q7, [sp, #-32]! + STP q4, q5, [sp, #-32]! + STP q2, q3, [sp, #-32]! + STP q0, q1, [sp, #-32]! + + MRS x28, FPSR + MRS x29, FPCR + STP x28, x29, [sp, #-16]! + #endif + .endm + + .macro OS_CPU_ARM_REG_PUSHF + STP x28, x29, [sp, #-16]! + STP x26, x27, [sp, #-16]! + STP x24, x25, [sp, #-16]! + STP x22, x23, [sp, #-16]! + STP x20, x21, [sp, #-16]! + STP x18, x19, [sp, #-16]! + SUB sp, sp, #144 + + MOV x0, x30 + STP x30, x0, [sp, #-16]! + + #if OS_CPU_EL3 == 1 + MOV x0, #0x0000020D + #else + MOV x0, #0x00000205 + #endif + MOV x1, x0 + STP x0, x1, [sp, #-16]! + + #if OS_CPU_SIMD == 1 + SUB sp, sp, #256 + STP q14, q15, [sp, #-32]! + STP q12, q13, [sp, #-32]! + STP q10, q11, [sp, #-32]! + STP q8, q9, [sp, #-32]! + SUB sp, sp, #128 + + MRS x28, FPSR + MRS x29, FPCR + STP x28, x29, [sp, #-16]! + #endif + .endm + + +/* +********************************************************************************************************* +* START MULTITASKING +* void OSStartHighRdy(void) +* +* Note(s) : 1) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to OS_STATE_OS_RUNNING, +* c) Switch to the highest priority task. +********************************************************************************************************* +*/ + +OSStartHighRdy: + + BL OSTaskSwHook + + LDR x0, =OSRunning + MOV w1, #1 + STRB w1, [x0] + + LDR x0, =OSTCBHighRdy + LDR x1, [x0] + LDR x2, [x1] + MOV sp, x2 + + #if OS_CPU_SIMD == 1 + LDP x28, x29, [sp], #16 + MSR FPSR, x28 + MSR FPCR, x29 + + LDP q0, q1, [sp], #32 + LDP q2, q3, [sp], #32 + LDP q4, q5, [sp], #32 + LDP q6, q7, [sp], #32 + LDP q8, q9, [sp], #32 + LDP q10, q11, [sp], #32 + LDP q12, q13, [sp], #32 + LDP q14, q15, [sp], #32 + LDP q16, q17, [sp], #32 + LDP q18, q19, [sp], #32 + LDP q20, q21, [sp], #32 + LDP q22, q23, [sp], #32 + LDP q24, q25, [sp], #32 + LDP q26, q27, [sp], #32 + LDP q28, q29, [sp], #32 + LDP q30, q31, [sp], #32 + #endif + + LDP x0, x1, [sp], #16 + LDP x30, x3, [sp], #16 + + MRS x4, CurrentEL + LSR x4, x4, #2 + CMP x4, #3 /* EL3 */ + B.EQ OSStartHighRdy_EL3 + CMP x4, #2 /* EL2 */ + B.EQ OSStartHighRdy_EL2 + CMP x4, #1 /* EL1 */ + B.EQ OSStartHighRdy_EL1 + + B . /* Can't run the kernel from EL0 */ + +OSStartHighRdy_EL3: + MSR SPSR_EL3, x1 + MSR ELR_EL3, x3 + B OSStartHighRdy_Restore + +OSStartHighRdy_EL2: + MSR SPSR_EL2, x1 + MSR ELR_EL2, x3 + B OSStartHighRdy_Restore + +OSStartHighRdy_EL1: + MSR SPSR_EL1, x1 + MSR ELR_EL1, x3 + B OSStartHighRdy_Restore + +OSStartHighRdy_Restore: + #if OS_CPU_EL3 == 0 + MOV x0, sp + SUB x0, x0, #240 + MSR SP_EL1, x0 + #endif + + LDP x0, x1, [sp], #16 + LDP x2, x3, [sp], #16 + LDP x4, x5, [sp], #16 + LDP x6, x7, [sp], #16 + LDP x8, x9, [sp], #16 + LDP x10, x11, [sp], #16 + LDP x12, x13, [sp], #16 + LDP x14, x15, [sp], #16 + LDP x16, x17, [sp], #16 + LDP x18, x19, [sp], #16 + LDP x20, x21, [sp], #16 + LDP x22, x23, [sp], #16 + LDP x24, x25, [sp], #16 + LDP x26, x27, [sp], #16 + LDP x28, x29, [sp], #16 + ERET + + +/* +********************************************************************************************************* +* PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +* +* Note(s) : 1) The pseudo-code for OSCtxSw() is: +* a) Save the current task's context onto the current task's stack, +* b) Update the SP value in current task's TCB, +* c) Call the Task Switch Hook, +* d) Get a reference to the new task, +* e) Load the new task stack into SP, +* f) Restore the new task's context from the stack, +* g) Return to new task's code. +********************************************************************************************************* +*/ + +OSCtxSw: + + OS_CPU_ARM_REG_PUSHF + + LDR x0, =OSTCBCur + LDR x1, [x0] + MOV x2, sp + STR x2, [x1] + + + BL OSTaskSwHook + + + LDR x0, =OSPrioCur + LDR x1, =OSPrioHighRdy + LDRB w2, [x1] + STRB w2, [x0] + + + LDR x0, =OSTCBCur + LDR x1, =OSTCBHighRdy + LDR x2, [x1] + STR x2, [x0] + + + LDR x0, [x2] + MOV sp, x0 + + OS_CPU_ARM_REG_POP + ERET + + +/* +********************************************************************************************************* +* PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +* +* Note(s) : 1) The pseudo-code for OSIntCtxSw() is: +* a) Call the Task Switch Hook, +* b) Get a reference to the new task, +* c) Load the new task stack into SP, +* d) Restore the new task's context from the stack, +* e) Return to new task's code. +********************************************************************************************************* +*/ + +OSIntCtxSw: + + BL OSTaskSwHook + + LDR x0, =OSPrioCur + LDR x1, =OSPrioHighRdy + LDRB w2, [x1] + STRB w2, [x0] + + + LDR x0, =OSTCBCur + LDR x1, =OSTCBHighRdy + LDR x2, [x1] + STR x2, [x0] + + + LDR x0, [x2] + MOV sp, x0 + + OS_CPU_ARM_REG_POP + ERET + + +/* +********************************************************************************************************* +* ARMv8-A IRQ EXCEPTION +********************************************************************************************************* +*/ + +OS_CPU_ARM_ExceptIrqHndlr: + + OS_CPU_ARM_REG_PUSH + + LDR x0, =OSIntNesting + LDRB w1, [x0] + ADD w1, w1, #1 + STRB w1, [x0] + CMP w1, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + LDR x0, =OSTCBCur + LDR x1, [x0] + MOV x2, sp + STR x2, [x1] + + LDR x0, =OS_CPU_ExceptStkBase + LDR x1, [x0] + MOV sp, x1 + + BL OS_CPU_ExceptHndlr + + BL OSIntExit + + LDR x0, =OSTCBCur + LDR x1, [x0] + LDR x2, [x1] + MOV sp, x2 + + OS_CPU_ARM_REG_POP + ERET + + +OS_CPU_ARM_ExceptHndlr_BreakExcept: + + BL OS_CPU_ExceptHndlr + + LDR x0, =OSIntNesting + LDRB w1, [x0] + SUB w1, w1, #1 + STRB w1, [x0] + + OS_CPU_ARM_REG_POP + + ERET + + +/* +********************************************************************************************************* +* HELPER ROUTINES +* +* Note(s) : 1) OS_CPU_SPSRGet and OS_CPU_SIMDGet are used by os_cpu_c.c. +********************************************************************************************************* +*/ +OS_CPU_SPSRGet: + #if OS_CPU_EL3 == 1 + MOV x0, #0x0000000D + #else + MOV x0, #0x00000005 + #endif + + RET + + +OS_CPU_SIMDGet: + #if OS_CPU_SIMD == 1 + MOV x0, #1 + #else + MOV x0, #0 + #endif + + RET + diff --git a/Ports/ARM-Cortex-A/ARMv8-A/os_cpu_c.c b/Ports/ARM-Cortex-A/ARMv8-A/os_cpu_c.c new file mode 100644 index 0000000..c2dfbdc --- /dev/null +++ b/Ports/ARM-Cortex-A/ARMv8-A/os_cpu_c.c @@ -0,0 +1,510 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv8-A Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv8-A Cortex-A +* Mode : ARM64 +********************************************************************************************************** +*/ + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if (OS_CPU_HOOKS_EN == 0u) +#error "ERROR: OS_CPU_HOOKS_EN must be set to 1" +#endif + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define OS_CPU_STK_ALIGN_BYTES (16u) + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_TMR_EN > 0u) +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description : This function is called by OSInit() at the beginning of OSInit(). +* +* Argument(s) : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; + + /* Clear exception stack for stack checking. */ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk++ = (OS_STK)0; + } + /* Align the ISR stack to 16-bytes */ + OS_CPU_ExceptStkBase = (OS_STK *)(OS_CPU_ExceptStk + OS_CPU_EXCEPT_STK_SIZE - 1u); + OS_CPU_ExceptStkBase = (OS_STK *)((CPU_STK)OS_CPU_ExceptStkBase & ~(OS_CPU_STK_ALIGN_BYTES - 1u)); + + +#if (OS_TMR_EN > 0u) + OSTmrCtr = 0u; +#endif +} + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description : This function is called by OSInit() at the end of OSInit(). +* +* Argument(s) : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +void OSInitHookEnd (void) +{ +#if (OS_CPU_INT_DIS_MEAS_EN > 0u) + OS_CPU_IntDisMeasInit(); +#endif +} + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description : This function is called when a task is created. +* +* Argument(s) : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description : This function is called when a task is deleted. +* +* Argument(s) : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description : This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Argument(s) : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +void OSTaskIdleHook (void) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskIdleHook(); +#endif +} + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description : This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Argument(s) : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description : This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Argument(s) : none +* +* Note(s) : none +********************************************************************************************************* +*/ + +void OSTaskStatHook (void) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskStatHook(); +#endif +} + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description : This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Argument(s) : task is a pointer to the task code. +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The full stack frame is shown below. If SIMD is disabled, (OS_CPU_SIMD == 0), +* the stack frame will only contain the core registers. +* +* [LOW MEMORY] +* ****************************** +* -0x320 [ FPSR ] +* -0x318 [ FPCR ] +* ****************************** +* -0x310 [ V0 ] +* -0x300 [ V1 ] +* -0x2F0 [ V2 ] +* -0x2E0 [ V3 ] +* -0x2D0 [ V4 ] +* -0x2C0 [ V5 ] +* -0x2B0 [ V6 ] +* -0x2A0 [ V7 ] +* -0x290 [ V8 ] +* -0x280 [ V9 ] +* -0x270 [ V10 ] +* -0x260 [ V11 ] +* -0x250 [ V12 ] +* -0x240 [ V13 ] +* -0x230 [ V14 ] +* -0x220 [ V15 ] +* -0x210 [ V16 ] +* -0x200 [ V17 ] +* -0x1F0 [ V18 ] +* -0x1E0 [ V19 ] +* -0x1D0 [ V20 ] +* -0x1C0 [ V21 ] +* -0x1B0 [ V22 ] +* -0x1A0 [ V23 ] +* -0x190 [ V24 ] +* -0x180 [ V25 ] +* -0x170 [ V26 ] +* -0x160 [ V27 ] +* -0x150 [ V28 ] +* -0x140 [ V29 ] +* -0x130 [ V30 ] +* -0x120 [ V31 ] +* ****************************** +* -0x110 [PADDING ] +* -0x108 [SPSR_ELx] +* -0x100 [ LR ] +* -0x0F8 [ELR_ELx ] +* ****************************** +* -0x0F0 [ R0 ] +* -0x0E8 [ R1 ] +* -0x0E0 [ R2 ] +* -0x0D8 [ R3 ] +* -0x0D0 [ R4 ] +* -0x0C8 [ R5 ] +* -0x0C0 [ R6 ] +* -0x0B8 [ R7 ] +* -0x0B0 [ R8 ] +* -0x0A8 [ R9 ] +* -0x0A0 [ R10 ] +* -0x098 [ R11 ] +* -0x090 [ R12 ] +* -0x088 [ R13 ] +* -0x080 [ R14 ] +* -0x078 [ R15 ] +* -0x070 [ R16 ] +* -0x068 [ R17 ] +* -0x060 [ R18 ] +* -0x058 [ R19 ] +* -0x050 [ R20 ] +* -0x048 [ R21 ] +* -0x040 [ R22 ] +* -0x038 [ R23 ] +* -0x030 [ R24 ] +* -0x028 [ R25 ] +* -0x020 [ R26 ] +* -0x018 [ R27 ] +* -0x010 [ R28 ] +* -0x008 [ R29 ] +* **********Stack Base********** +* ******SP_BASE MOD 16 = 0****** +* [HIGH MEMORY] +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + OS_STK task_addr; + INT8U i; + + + (void)opt; + + /* Align stack pointer to 16 bytes */ + p_stk = ptos + 1u; + p_stk = (OS_STK *)((OS_STK)p_stk & ~(OS_CPU_STK_ALIGN_BYTES - 1ul)); + + task_addr = (OS_STK)task; + + for (i = 29; i > 0; i--) { + *--p_stk = (INT64U)i; /* Reg X1-X29 */ + } + + *--p_stk = (OS_STK)p_arg; /* Reg X0 : argument */ + + *--p_stk = (OS_STK)task_addr; /* Entry Point */ + *--p_stk = (OS_STK)OS_TaskReturn; /* Reg X30 (LR) */ + + *--p_stk = (OS_STK)OS_CPU_SPSRGet(); + *--p_stk = (OS_STK)OS_CPU_SPSRGet(); + + if (OS_CPU_SIMDGet() == 1u) { + for (i = 64; i > 0; i--) { + *--p_stk = (INT64U)i; /* Reg Q0-Q31 */ + } + + *--p_stk = 0x0000000000000000; /* FPCR */ + *--p_stk = 0x0000000000000000; /* FPSR */ + } + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description : This function is called when a task switch is performed. This allows you to perform +* other operations during a context switch. +* +* Argument(s) : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task +* that will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to +* the task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) + +{ +#if (OS_CFG_DBG_EN > 0u) + INT32U ctx_id; +#endif + +#if (OS_APP_HOOKS_EN > 0u) + App_TaskSwHook(); +#endif + +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description : This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Argument(s) : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description : This function is called every tick. +* +* Argument(s) : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TimeTickHook(); +#endif + +#if (OS_TMR_EN > 0u) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if (OS_CPU_INT_DIS_MEAS_EN > 0u) +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + diff --git a/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu.h b/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu.h new file mode 100644 index 0000000..2344602 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu.h @@ -0,0 +1,207 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv6-M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv6-M Cortex-M0 or Cortex-M0+ +* Mode : Thumb2 +* Toolchain : ARM C Compiler +********************************************************************************************************** +* Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +********************************************************************************************************** +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */ +#endif + + +/* +********************************************************************************************************* +* OS TICK INTERRUPT PRIORITY CONFIGURATION +* +* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt +* should be configured as the highest priority interrupt but won't adversely affect system +* operations. +* +* (2) For systems that need one or more high, real-time interrupts; these should be configured +* higher than the tick interrupt which MAY delay execution of the tick interrupt. +* +* (a) If the higher priority interrupts do NOT continually consume CPU cycles but only +* occasionally delay tick interrupts, then the real-time interrupts can successfully +* handle their intermittent/periodic events with the system not losing tick interrupts +* but only increasing the jitter. +* +* (b) If the higher priority interrupts consume enough CPU cycles to continually delay the +* tick interrupt, then the CPU/system is most likely over-burdened & can't be expected +* to handle all its interrupts/tasks. The system time reference gets compromised as a +* result of losing tick interrupts. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_CFG_SYSTICK_PRIO +#define OS_CPU_CFG_SYSTICK_PRIO 0u +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Cortex-M0 +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* Cortex-M0 Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + /* See OS_CPU_C.C */ +void OS_CPU_SysTickInit (INT32U cnts); +void OS_CPU_SysTickInitFreq (INT32U cpu_freq); + +void OS_CPU_SysTickHandler (void); +void OS_CPU_PendSVHandler (void); + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu_a.asm b/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu_a.asm new file mode 100644 index 0000000..af149d1 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_cpu_a.asm @@ -0,0 +1,281 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv6-M Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv6-M Cortex-M0 or Cortex-M0+ +; Mode : Thumb2 +; Toolchain : ARM C Compiler +;********************************************************************************************************* +; Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +;********************************************************************************************************* + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + + + EXPORT OSStartHighRdy ; Functions declared in this file + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + EXPORT OSCtxSw + EXPORT OSIntCtxSw + EXPORT OS_CPU_PendSVHandler + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register. +NVIC_SYSPRI14 EQU 0xE000ED20 ; System priority register (priority 14). +NVIC_PENDSV_PRI EQU 0x00FF0000 ; PendSV priority value (lowest). +NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception. + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + AREA |.text|, CODE, READONLY, ALIGN=2 + THUMB + REQUIRE8 + PRESERVE8 + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + MRS R0, PRIMASK ; Set prio int mask to mask all (except faults) + CPSID I + BX LR + +OS_CPU_SR_Restore + MSR PRIMASK, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +; the first task to start. +; +; 2) OSStartHighRdy() MUST: +; a) Setup PendSV exception priority to lowest; +; b) Set initial PSP to 0, to tell context switcher this is first run; +; c) Set the main stack to OS_CPU_ExceptStkBase; +; d) Set OSRunning to TRUE; +; e) Trigger PendSV exception; +; f) Enable interrupts (tasks will run with interrupts enabled). +;******************************************************************************************************** + +OSStartHighRdy + LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority + LDR R1, =NVIC_PENDSV_PRI + STR R1, [R0] + + MOVS R0, #0 ; Set the PSP to 0 for initial context switch call + MSR PSP, R0 + BL OSTaskSwHook + + LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase + LDR R1, [R0] + MSR MSP, R1 + + LDR R0, =OSRunning ; OSRunning = TRUE + MOVS R1, #1 + STRB R1, [R0] + + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + + CPSIE I ; Enable interrupts at processor level + +OSStartHang + B OSStartHang ; Should never get here + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +; triggers the PendSV exception which is where the real work is done. +;******************************************************************************************************** + +OSCtxSw + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +; the result of an interrupt. This function simply triggers a PendSV exception which will +; be handled when there are no more interrupts active and interrupts are enabled. +;******************************************************************************************************** + +OSIntCtxSw + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +;******************************************************************************************************** +; HANDLE PendSV EXCEPTION +; void OS_CPU_PendSVHandler(void) +; +; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +; context switches with Cortex-M0. This is because the Cortex-M0 auto-saves half of the +; processor context on any exception, and restores same on return from exception. So only +; saving of R4-R11, LR is required and fixing up the stack pointers. Using the PendSV exception +; this way means that context saving and restoring is identical whether it is initiated from +; a thread or occurs due to an interrupt or exception. +; +; 2) Pseudo-code is: +; a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch); +; b) Adjust SP to make space for R4-R11 and LR register +; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +; d) Save remaining regs R4-R11, LR on process stack; +; e) Call OSTaskSwHook(); +; f) Get current high priority, OSPrioCur = OSPrioHighRdy; +; g) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; h) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; i) Adjust SP to the High Registers(R8-R11) & LR location +; j) Restore R8-R11, and LR from new process stack; +; k) Load PSP with new process SP +; m) Restore remaining R4-R7 from new process stack +; n) Perform exception return which will restore remaining context. +; +; 3) On entry into PendSV handler: +; a) The following have been saved on the process stack (by processor): +; xPSR, PC, LR, R12, R0-R3 +; b) Processor mode is switched to Handler mode (from Thread mode) +; c) Stack is Main stack (switched from Process stack) +; d) OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we +; know that it will only be run when no other exception or interrupt is active, and +; therefore safe to assume that context being switched out was using the process stack (PSP). +;******************************************************************************************************** + +OS_CPU_PendSVHandler + CPSID I ; Prevent interruption during context switch + MRS R0, PSP ; PSP is process stack pointer + + CMP R0, #0 + BEQ OS_CPU_PendSVHandler_nosave ; equivalent code to CBZ from M3 arch to M0 arch + ; Except that it does not change the condition code flags + + SUBS R0, R0, #0x24 ; Adjust SP to make space for Low, High & LR registers + LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R1] + STR R0, [R1] ; R0 is SP of process being switched out + + STMIA R0!, {R4-R7} ; Store R4-R7(Low Registers) on process stack + MOV R4, R8 ; Move R8-R11 values to R4-R7 registers. + MOV R5, R9 + MOV R6, R10 + MOV R7, R11 + STMIA R0!, {R4-R7} ; Store R8-R11(High Registers) on process stack + MOV R3, R14 ; R3 is LR of process being switched out + STMIA R0!, {R3} ; Store LR (EXC_RETURN) on process stack. + + ; At this point, entire context of process has been saved +OS_CPU_PendSVHandler_nosave + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + + ADDS R0, #0x10 ; Adjust SP to High Registers(R8-R11) location + LDMFD R0!, {R4-R7} ; Load R8-R11 values from new process stack into R4-R7 + MOV R8, R4 ; Restore R8-R11 by moving their values from R4-R7 + MOV R9, R5 + MOV R10, R6 + MOV R11, R7 + + LDMFD R0!, {R3} ; R3 has the new process LR; R3 = LR (EXEC_RETURN) + MOV R14, R3 ; Restore LR (EXEC_RETURN) + + MSR PSP, R0 ; Load PSP with new process SP + + SUBS R0, #0x24 ; Adjust SP to Low registers(R4-R7) location + LDMFD R0!, {R4-R7} ; Restore remaining R4-R7 from new process stack + + CPSIE I + BX LR ; Exception return will restore remaining context + + ALIGN ; Ensures that ARM instructions start on four-byte boundary + + END diff --git a/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_dbg.c b/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_dbg.c new file mode 100644 index 0000000..d0a0ca6 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/ARM/os_dbg.c @@ -0,0 +1,325 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* ARMv6-M Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv6-M Cortex-M0 or Cortex-M0+ +* Mode : Thumb2 +* Toolchain : ARM C Compiler +********************************************************************************************************** +* Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +********************************************************************************************************** +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu.h b/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu.h new file mode 100644 index 0000000..7415306 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu.h @@ -0,0 +1,207 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv6-M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv6-M Cortex-M0 or Cortex-M0+ +* Mode : Thumb2 +* Toolchain : GNU C Compiler +********************************************************************************************************** +* Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +********************************************************************************************************** +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */ +#endif + + +/* +********************************************************************************************************* +* OS TICK INTERRUPT PRIORITY CONFIGURATION +* +* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt +* should be configured as the highest priority interrupt but won't adversely affect system +* operations. +* +* (2) For systems that need one or more high, real-time interrupts; these should be configured +* higher than the tick interrupt which MAY delay execution of the tick interrupt. +* +* (a) If the higher priority interrupts do NOT continually consume CPU cycles but only +* occasionally delay tick interrupts, then the real-time interrupts can successfully +* handle their intermittent/periodic events with the system not losing tick interrupts +* but only increasing the jitter. +* +* (b) If the higher priority interrupts consume enough CPU cycles to continually delay the +* tick interrupt, then the CPU/system is most likely over-burdened & can't be expected +* to handle all its interrupts/tasks. The system time reference gets compromised as a +* result of losing tick interrupts. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_CFG_SYSTICK_PRIO +#define OS_CPU_CFG_SYSTICK_PRIO 0u +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Cortex-M0 +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* Cortex-M0 Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + /* See OS_CPU_C.C */ +void OS_CPU_SysTickInit (INT32U cnts); +void OS_CPU_SysTickInitFreq (INT32U cpu_freq); + +void OS_CPU_SysTickHandler (void); +void OS_CPU_PendSVHandler (void); + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu_a.s b/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu_a.s new file mode 100644 index 0000000..fb51ebd --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_cpu_a.s @@ -0,0 +1,286 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARMv6-M Port +@ +@ Filename : os_cpu_a.s +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARMv6-M Cortex-M0 or Cortex-M0+ +@ Mode : Thumb2 +@ Toolchain : GNU C Compiler +@********************************************************************************************************* +@ Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +@********************************************************************************************************* + +@******************************************************************************************************** +@ PUBLIC FUNCTIONS +@******************************************************************************************************** + + .extern OSRunning @ External references + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntExit + .extern OSTaskSwHook + .extern OS_CPU_ExceptStkBase + + + .global OSStartHighRdy @ Functions declared in this file + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSCtxSw + .global OSIntCtxSw + .global OS_CPU_PendSVHandler + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + +.equ NVIC_INT_CTRL, 0xE000ED04 @ Interrupt control state register. +.equ NVIC_SYSPRI14, 0xE000ED20 @ System priority register (priority 14). +.equ NVIC_PENDSV_PRI, 0x00FF0000 @ PendSV priority value (lowest). +.equ NVIC_PENDSVSET, 0x10000000 @ Value to trigger PendSV exception. + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + +.text +.align 2 +.thumb +.syntax unified + +@******************************************************************************************************** +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +@ void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +@ +@ +@ Note(s) : 1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +@ OS_CPU_SR cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +@ : +@ : +@ } +@******************************************************************************************************** + +.thumb_func +OS_CPU_SR_Save: + MRS R0, PRIMASK @ Set prio int mask to mask all (except faults) + CPSID I + BX LR + +.thumb_func +OS_CPU_SR_Restore: + MSR PRIMASK, R0 + BX LR + + +@******************************************************************************************************** +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +@ the first task to start. +@ +@ 2) OSStartHighRdy() MUST: +@ a) Setup PendSV exception priority to lowest; +@ b) Set initial PSP to 0, to tell context switcher this is first run; +@ c) Set the main stack to OS_CPU_ExceptStkBase; +@ d) Set OSRunning to TRUE; +@ e) Trigger PendSV exception; +@ f) Enable interrupts (tasks will run with interrupts enabled). +@******************************************************************************************************** + +.thumb_func +OSStartHighRdy: + LDR R0, =NVIC_SYSPRI14 @ Set the PendSV exception priority + LDR R1, =NVIC_PENDSV_PRI + STR R1, [R0] + + MOVS R0, #0 @ Set the PSP to 0 for initial context switch call + MSR PSP, R0 + BL OSTaskSwHook + + LDR R0, =OS_CPU_ExceptStkBase @ Initialize the MSP to the OS_CPU_ExceptStkBase + LDR R1, [R0] + MSR MSP, R1 + + LDR R0, =OSRunning @ OSRunning = TRUE + MOVS R1, #1 + STRB R1, [R0] + + LDR R0, =NVIC_INT_CTRL @ Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + + CPSIE I @ Enable interrupts at processor level + +OSStartHang: + B OSStartHang @ Should never get here + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +@ triggers the PendSV exception which is where the real work is done. +@******************************************************************************************************** + +.thumb_func +OSCtxSw: + LDR R0, =NVIC_INT_CTRL @ Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Notes: 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +@ the result of an interrupt. This function simply triggers a PendSV exception which will +@ be handled when there are no more interrupts active and interrupts are enabled. +@******************************************************************************************************** + +.thumb_func +OSIntCtxSw: + LDR R0, =NVIC_INT_CTRL @ Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +@******************************************************************************************************** +@ HANDLE PendSV EXCEPTION +@ void OS_CPU_PendSVHandler(void) +@ +@ Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +@ context switches with Cortex-M0. This is because the Cortex-M0 auto-saves half of the +@ processor context on any exception, and restores same on return from exception. So only +@ saving of R4-R11, LR is required and fixing up the stack pointers. Using the PendSV exception +@ this way means that context saving and restoring is identical whether it is initiated from +@ a thread or occurs due to an interrupt or exception. +@ +@ 2) Pseudo-code is: +@ a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch); +@ b) Adjust SP to make space for R4-R11 and LR register +@ c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +@ d) Save remaining regs R4-R11, LR on process stack; +@ e) Call OSTaskSwHook(); +@ f) Get current high priority, OSPrioCur = OSPrioHighRdy; +@ g) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +@ h) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +@ i) Adjust SP to the High Registers(R8-R11) & LR location +@ j) Restore R8-R11, and LR from new process stack; +@ k) Load PSP with new process SP +@ m) Restore remaining R4-R7 from new process stack +@ n) Perform exception return which will restore remaining context. +@ +@ 3) On entry into PendSV handler: +@ a) The following have been saved on the process stack (by processor): +@ xPSR, PC, LR, R12, R0-R3 +@ b) Processor mode is switched to Handler mode (from Thread mode) +@ c) Stack is Main stack (switched from Process stack) +@ d) OSTCBCur points to the OS_TCB of the task to suspend +@ OSTCBHighRdy points to the OS_TCB of the task to resume +@ +@ 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we +@ know that it will only be run when no other exception or interrupt is active, and +@ therefore safe to assume that context being switched out was using the process stack (PSP). +@******************************************************************************************************** + +.thumb_func +OS_CPU_PendSVHandler: + CPSID I @ Prevent interruption during context switch + MRS R0, PSP @ PSP is process stack pointer + + CMP R0, #0 + BEQ OS_CPU_PendSVHandler_nosave @ equivalent code to CBZ from M3 arch to M0 arch + @ Except that it does not change the condition code flags + + SUBS R0, R0, #0x24 @ Adjust SP to make space for Low, High & LR registers + LDR R1, =OSTCBCur @ OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R1] + STR R0, [R1] @ R0 is SP of process being switched out + + STMIA R0!, {R4-R7} @ Store R4-R7(Low Registers) on process stack + MOV R4, R8 @ Move R8-R11 values to R4-R7 registers. + MOV R5, R9 + MOV R6, R10 + MOV R7, R11 + STMIA R0!, {R4-R7} @ Store R8-R11(High Registers) on process stack + MOV R3, R14 @ R3 is LR of process being switched out + STMIA R0!, {R3} @ Store LR (EXC_RETURN) on process stack. + + @ At this point, entire context of process has been saved +OS_CPU_PendSVHandler_nosave: + BL OSTaskSwHook @ OSTaskSwHook(); + + LDR R0, =OSPrioCur @ OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur @ OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR R0, [R2] @ R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + + ADDS R0, #0x10 @ Adjust SP to High Registers(R8-R11) location + LDMFD R0!, {R4-R7} @ Load R8-R11 values from new process stack into R4-R7 + MOV R8, R4 @ Restore R8-R11 by moving their values from R4-R7 + MOV R9, R5 + MOV R10, R6 + MOV R11, R7 + + LDMFD R0!, {R3} @ R3 has the new process LR; R3 = LR (EXEC_RETURN) + MOV R14, R3 @ Restore LR (EXEC_RETURN) + + MSR PSP, R0 @ Load PSP with new process SP + + SUBS R0, #0x24 @ Adjust SP to Low registers(R4-R7) location + LDMFD R0!, {R4-R7} @ Restore remaining R4-R7 from new process stack + + CPSIE I + BX LR @ Exception return will restore remaining context + + + .end diff --git a/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_dbg.c b/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_dbg.c new file mode 100644 index 0000000..0287cb8 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/GNU/os_dbg.c @@ -0,0 +1,325 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* ARMv6-M Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv6-M Cortex-M0 or Cortex-M0+ +* Mode : Thumb2 +* Toolchain : GNU C Compiler +********************************************************************************************************** +* Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +********************************************************************************************************** +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu.h b/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu.h new file mode 100644 index 0000000..51e6845 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu.h @@ -0,0 +1,207 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv6-M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv6-M Cortex-M0 or Cortex-M0+ +* Mode : Thumb2 +* Toolchain : IAR EWARM +********************************************************************************************************** +* Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +********************************************************************************************************** +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */ +#endif + + +/* +********************************************************************************************************* +* OS TICK INTERRUPT PRIORITY CONFIGURATION +* +* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt +* should be configured as the highest priority interrupt but won't adversely affect system +* operations. +* +* (2) For systems that need one or more high, real-time interrupts; these should be configured +* higher than the tick interrupt which MAY delay execution of the tick interrupt. +* +* (a) If the higher priority interrupts do NOT continually consume CPU cycles but only +* occasionally delay tick interrupts, then the real-time interrupts can successfully +* handle their intermittent/periodic events with the system not losing tick interrupts +* but only increasing the jitter. +* +* (b) If the higher priority interrupts consume enough CPU cycles to continually delay the +* tick interrupt, then the CPU/system is most likely over-burdened & can't be expected +* to handle all its interrupts/tasks. The system time reference gets compromised as a +* result of losing tick interrupts. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_CFG_SYSTICK_PRIO +#define OS_CPU_CFG_SYSTICK_PRIO 0u +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Cortex-M0 +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* Cortex-M0 Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + /* See OS_CPU_C.C */ +void OS_CPU_SysTickInit (INT32U cnts); +void OS_CPU_SysTickInitFreq (INT32U cpu_freq); + +void OS_CPU_SysTickHandler (void); +void OS_CPU_PendSVHandler (void); + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu_a.asm b/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu_a.asm new file mode 100644 index 0000000..2fa99a9 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_cpu_a.asm @@ -0,0 +1,278 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv6-M Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv6-M Cortex-M0 or Cortex-M0+ +; Mode : Thumb2 +; Toolchain : IAR EWARM +;********************************************************************************************************* +; Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +;********************************************************************************************************* + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + + + PUBLIC OSStartHighRdy ; Functions declared in this file + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OS_CPU_PendSVHandler + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register. +NVIC_SYSPRI14 EQU 0xE000ED20 ; System priority register (priority 14). +NVIC_PENDSV_PRI EQU 0x00FF0000 ; PendSV priority value (lowest). +NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception. + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + THUMB + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + MRS R0, PRIMASK ; Set prio int mask to mask all (except faults) + CPSID I + BX LR + +OS_CPU_SR_Restore + MSR PRIMASK, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +; the first task to start. +; +; 2) OSStartHighRdy() MUST: +; a) Setup PendSV exception priority to lowest; +; b) Set initial PSP to 0, to tell context switcher this is first run; +; c) Set the main stack to OS_CPU_ExceptStkBase; +; d) Set OSRunning to TRUE; +; e) Trigger PendSV exception; +; f) Enable interrupts (tasks will run with interrupts enabled). +;******************************************************************************************************** + +OSStartHighRdy + LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority + LDR R1, =NVIC_PENDSV_PRI + STR R1, [R0] + + MOVS R0, #0 ; Set the PSP to 0 for initial context switch call + MSR PSP, R0 + BL OSTaskSwHook + + LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase + LDR R1, [R0] + MSR MSP, R1 + + LDR R0, =OSRunning ; OSRunning = TRUE + MOVS R1, #1 + STRB R1, [R0] + + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + + CPSIE I ; Enable interrupts at processor level + +OSStartHang + B OSStartHang ; Should never get here + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +; triggers the PendSV exception which is where the real work is done. +;******************************************************************************************************** + +OSCtxSw + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +; the result of an interrupt. This function simply triggers a PendSV exception which will +; be handled when there are no more interrupts active and interrupts are enabled. +;******************************************************************************************************** + +OSIntCtxSw + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +;******************************************************************************************************** +; HANDLE PendSV EXCEPTION +; void OS_CPU_PendSVHandler(void) +; +; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +; context switches with Cortex-M0. This is because the Cortex-M0 auto-saves half of the +; processor context on any exception, and restores same on return from exception. So only +; saving of R4-R11, LR is required and fixing up the stack pointers. Using the PendSV exception +; this way means that context saving and restoring is identical whether it is initiated from +; a thread or occurs due to an interrupt or exception. +; +; 2) Pseudo-code is: +; a) Get the process SP, if 0 then skip (goto d) the saving part (first context switch); +; b) Adjust SP to make space for R4-R11 and LR register +; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +; d) Save remaining regs R4-R11, LR on process stack; +; e) Call OSTaskSwHook(); +; f) Get current high priority, OSPrioCur = OSPrioHighRdy; +; g) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; h) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; i) Adjust SP to the High Registers(R8-R11) & LR location +; j) Restore R8-R11, and LR from new process stack; +; k) Load PSP with new process SP +; m) Restore remaining R4-R7 from new process stack +; n) Perform exception return which will restore remaining context. +; +; 3) On entry into PendSV handler: +; a) The following have been saved on the process stack (by processor): +; xPSR, PC, LR, R12, R0-R3 +; b) Processor mode is switched to Handler mode (from Thread mode) +; c) Stack is Main stack (switched from Process stack) +; d) OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we +; know that it will only be run when no other exception or interrupt is active, and +; therefore safe to assume that context being switched out was using the process stack (PSP). +;******************************************************************************************************** + +OS_CPU_PendSVHandler + CPSID I ; Prevent interruption during context switch + MRS R0, PSP ; PSP is process stack pointer + + CMP R0, #0 + BEQ OS_CPU_PendSVHandler_nosave ; equivalent code to CBZ from M3 arch to M0 arch + ; Except that it does not change the condition code flags + + SUBS R0, R0, #0x24 ; Adjust SP to make space for Low, High & LR registers + LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R1] + STR R0, [R1] ; R0 is SP of process being switched out + + STMIA R0!, {R4-R7} ; Store R4-R7(Low Registers) on process stack + MOV R4, R8 ; Move R8-R11 values to R4-R7 registers. + MOV R5, R9 + MOV R6, R10 + MOV R7, R11 + STMIA R0!, {R4-R7} ; Store R8-R11(High Registers) on process stack + MOV R3, R14 ; R3 is LR of process being switched out + STMIA R0!, {R3} ; Store LR (EXC_RETURN) on process stack. + + ; At this point, entire context of process has been saved +OS_CPU_PendSVHandler_nosave + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + + ADDS R0, #0x10 ; Adjust SP to High Registers(R8-R11) location + LDMFD R0!, {R4-R7} ; Load R8-R11 values from new process stack into R4-R7 + MOV R8, R4 ; Restore R8-R11 by moving their values from R4-R7 + MOV R9, R5 + MOV R10, R6 + MOV R11, R7 + + LDMFD R0!, {R3} ; R3 has the new process LR; R3 = LR (EXEC_RETURN) + MOV R14, R3 ; Restore LR (EXEC_RETURN) + + MSR PSP, R0 ; Load PSP with new process SP + + SUBS R0, #0x24 ; Adjust SP to Low registers(R4-R7) location + LDMFD R0!, {R4-R7} ; Restore remaining R4-R7 from new process stack + + CPSIE I + BX LR ; Exception return will restore remaining context + + END diff --git a/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_dbg.c b/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_dbg.c new file mode 100644 index 0000000..5421ba7 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/IAR/os_dbg.c @@ -0,0 +1,325 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* ARMv6-M Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv6-M Cortex-M0 or Cortex-M0+ +* Mode : Thumb2 +* Toolchain : IAR EWARM +********************************************************************************************************** +* Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +********************************************************************************************************** +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-M/ARMv6-M/os_cpu_c.c b/Ports/ARM-Cortex-M/ARMv6-M/os_cpu_c.c new file mode 100644 index 0000000..ea0650f --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv6-M/os_cpu_c.c @@ -0,0 +1,543 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv6-M Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv6-M Cortex-M0 or Cortex-M0+ +* Mode : Thumb2 +********************************************************************************************************** +* Note(s) : (1) This port supports the ARM Cortex-M0 and Cortex-M0+ architectures. +********************************************************************************************************** +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* SYS TICK DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_CM0_NVIC_ST_CTRL (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg. */ +#define OS_CPU_CM0_NVIC_ST_RELOAD (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload Value Reg. */ +#define OS_CPU_CM0_NVIC_ST_CURRENT (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */ +#define OS_CPU_CM0_NVIC_ST_CAL (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal Value Reg. */ +#define OS_CPU_CM0_NVIC_PRIO_ST (*((volatile INT32U *)0xE000ED20uL)) /* SysTick Handler Prio Reg. */ + +#define OS_CPU_CM0_NVIC_ST_CTRL_COUNT 0x00010000uL /* Count flag. */ +#define OS_CPU_CM0_NVIC_ST_CTRL_CLK_SRC 0x00000004uL /* Clock Source. */ +#define OS_CPU_CM0_NVIC_ST_CTRL_INTEN 0x00000002uL /* Interrupt enable. */ +#define OS_CPU_CM0_NVIC_ST_CTRL_ENABLE 0x00000001uL /* Counter mode. */ +#define OS_CPU_CM0_NVIC_PRIO_MIN 0xFFu /* Min handler prio. */ + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; + + /* Clear exception stack for stack checking. */ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk++ = (OS_STK)0; + } + + /* Align the ISR stack to 8-bytes */ + OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; + OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8); + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ + +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) Interrupts are enabled when task starts executing. +* +* (2) All tasks run in Thread mode, using process stack. +* +* (3) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture +* +* (a) Section 2.1 of the ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned +* on entry to AAPCS-Conforming functions states : +* +* The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive +* data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes). +* Doing otherwise creates more problems than it solves. +* +* In return for preserving the natural alignment of data, conforming code is permitted +* to rely on that alignment. To support aligning data allocated on the stack, the stack +* pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In +* practice this requirement is met if: +* +* (1) At each call site, the current size of the calling function's stack frame is a multiple of 8 bytes. +* This places an obligation on compilers and assembly language programmers. +* +* (2) SP is a multiple of 8 when control first enters a program. +* This places an obligation on authors of low level OS, RTOS, and runtime library +* code to align SP at all points at which control first enters +* a body of (AAPCS-conforming) code. +* +* In turn, this requires the value of SP to be aligned to 0 modulo 8: +* +* (3) By exception handlers, before calling AAPCS-conforming code. +* +* (4) By OS/RTOS/run-time system code, before giving control to an application. +* +* (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry +* to AAPCS-conforming functions advisory note also states. +* +* " This requirement extends to operating systems and run-time code for all architecture versions +* prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations +* associated with ARMV7M are discussed in section 2.3.3" +* +* (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned +* to 8-byte boundaries to support legacy execution enviroments. +* +* (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM +* architecture states : "The stack must also conform to the following +* constraint at a public interface: +* +* (1) SP mod 8 = 0. The stack must be double-word aligned" +* +* (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment. +* +* "8 byte stack alignment is a requirement of the ARM Architecture Procedure +* Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte +* aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external +* interfaces. In practice this requirement is met if: +* +* (1) At each external interface, the current stack pointer +* is a multiple of 8 bytes. +* +* (2) Your OS maintains 8 byte stack alignment on its external interfaces +* e.g. on task switches" +* +* (4) Exception Return Behavior(EXEC_RETURN) +* 0xFFFFFFF1 Return to Thread mode. Exception return gets state from the Main Stack. +* On Return execution uses the Main Stack. +* +* 0xFFFFFFF9 Return to Thread mode. Exception return gets state from the Main Stack. +* On Return execution uses the Main Stack. +* +* 0xFFFFFFFD Return to Thread mode. Exception return gets state from the Process Stack. +* On Return execution uses the Process Stack. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + + + (void)opt; /* 'opt' is not used, prevent warning */ + p_stk = ptos + 1u; /* Load stack pointer */ + /* Align the stack to 8-bytes. */ + p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u); + /* Registers stacked as if auto-saved on exception */ + *(--p_stk) = (OS_STK)0x01000000uL; /* xPSR */ + *(--p_stk) = (OS_STK)task; /* Entry Point */ + *(--p_stk) = (OS_STK)OS_TaskReturn; /* R14 (LR) */ + *(--p_stk) = (OS_STK)0x12121212uL; /* R12 */ + *(--p_stk) = (OS_STK)0x03030303uL; /* R3 */ + *(--p_stk) = (OS_STK)0x02020202uL; /* R2 */ + *(--p_stk) = (OS_STK)0x01010101uL; /* R1 */ + *(--p_stk) = (OS_STK)p_arg; /* R0 : argument */ + /* Remaining registers saved on process stack */ + *(--p_stk) = (OS_STK)0xFFFFFFFDuL; /* R14: EXEC_RETURN; See Note 4 */ + *(--p_stk) = (OS_STK)0x11111111uL; /* R11 */ + *(--p_stk) = (OS_STK)0x10101010uL; /* R10 */ + *(--p_stk) = (OS_STK)0x09090909uL; /* R9 */ + *(--p_stk) = (OS_STK)0x08080808uL; /* R8 */ + *(--p_stk) = (OS_STK)0x07070707uL; /* R7 */ + *(--p_stk) = (OS_STK)0x06060606uL; /* R6 */ + *(--p_stk) = (OS_STK)0x05050505uL; /* R5 */ + *(--p_stk) = (OS_STK)0x04040404uL; /* R4 */ + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* SYS TICK HANDLER +* +* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick +* interrupt. +* +* Arguments : None. +* +* Note(s) : 1) This function MUST be placed on entry 15 of the Cortex-M0 vector table. +********************************************************************************************************* +*/ + +void OS_CPU_SysTickHandler (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + + + OS_ENTER_CRITICAL(); + OSIntEnter(); /* Tell uC/OS-II that we are starting an ISR */ + OS_EXIT_CRITICAL(); + + OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */ + + OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */ +} + + +/* +********************************************************************************************************* +* INITIALIZE SYS TICK +* +* Description: Initialize the SysTick using the CPU clock frequency. +* +* Arguments : cpu_freq CPU clock frequency. +* +* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization. +* +* 2) Either OS_CPU_SysTickInitFreq or OS_CPU_SysTickInit() can be called. +********************************************************************************************************* +*/ + +void OS_CPU_SysTickInitFreq (INT32U cpu_freq) +{ + INT32U cnts; + + + cnts = (cpu_freq / (INT32U)OS_TICKS_PER_SEC); /* Determine nbr SysTick cnts between two OS tick intr. */ + + OS_CPU_SysTickInit(cnts); +} + + +/* +********************************************************************************************************* +* INITIALIZE SYS TICK +* +* Description: Initialize the SysTick using the number of counts between two ticks. +* +* Arguments : cnts Number of SysTick counts between two OS tick interrupts. +* +* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization. +* +* 2) Either OS_CPU_SysTickInitFreq or OS_CPU_SysTickInit() can be called. +********************************************************************************************************* +*/ + +void OS_CPU_SysTickInit (INT32U cnts) +{ + INT32U prio; + + + OS_CPU_CM0_NVIC_ST_RELOAD = cnts - 1u; + + /* Set SysTick handler prio. */ + prio = OS_CPU_CM0_NVIC_PRIO_ST; + prio &= 0x00FFFFFFu; + prio |= (OS_CPU_CFG_SYSTICK_PRIO << 24u); + + OS_CPU_CM0_NVIC_PRIO_ST = prio; + + /* Enable timer. */ + OS_CPU_CM0_NVIC_ST_CTRL |= OS_CPU_CM0_NVIC_ST_CTRL_CLK_SRC | + OS_CPU_CM0_NVIC_ST_CTRL_ENABLE; + /* Enable timer interrupt. */ + OS_CPU_CM0_NVIC_ST_CTRL |= OS_CPU_CM0_NVIC_ST_CTRL_INTEN; +} diff --git a/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu.h b/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu.h new file mode 100644 index 0000000..6b17c88 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu.h @@ -0,0 +1,236 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : ARM C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +* +* Note(s) : (1) If using uC/CPU then 'cpu_cfg.h' has already this define in its template. The user will +* only need to include 'cpu_cfg.h' in 'app_cfg.h'; otherwise, define CPU_CFG_KA_IPL_BOUNDARY +* and CPU_CFG_NVIC_PRIO_BITS in 'app_cfg.h' +* +* (2) Since the port is using BASEPRI to separate kernel vs non-kernel aware ISR, please make sure +* your external interrupt priorities are set accordingly. For example, if CPU_CFG_KA_IPL_BOUNDARY +* is set to 4 then external interrupt priorities 4-15 will be kernel aware while priorities +* 0-3 will be use as non-kernel aware. +* +* (3) Determines the interrupt programmable priority levels. This is normally specified in the +* Microcontroller reference manual. 4-bits gives us 16 programmable priority levels. +* +* NVIC_IPRx +* 7 0 +* +------------------+ +* | PRIO | +* +------------------+ +* +* Bits[7:4] Priority mask bits +* Bits[3:0] Reserved +* +* In this example our CPU_CFG_NVIC_PRIO_BITS define should be set to 4 due to the processor +* implementing only bits[7:4]. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 256u /* Default exception stack size is 256 OS_STK entries */ +#endif + +#ifndef __TARGET_FPU_SOFTVFP +#define OS_CPU_ARM_FP_EN 1u +#else +#define OS_CPU_ARM_FP_EN 0u +#endif + +#ifndef CPU_CFG_KA_IPL_BOUNDARY +#error "CPU_CFG_KA_IPL_BOUNDARY not #define'd in 'app_cfg.h' " /* See Note # 1 & 2 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY == 0u) +#error "CPU_CFG_KA_IPL_BOUNDARY should be > 0 " +#endif +#endif + +#ifndef CPU_CFG_NVIC_PRIO_BITS +#error "CPU_CFG_NVIC_PRIO_BITS not #define'd in 'app_cfg.h' " /* See Note # 3 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY >= (1u << CPU_CFG_NVIC_PRIO_BITS)) +#error "CPU_CFG_KA_IPL_BOUNDARY should not be set to higher than max programable priority level " +#endif +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Cortex-M +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u + /* Save current BASEPRI priority lvl for exception... */ + /* .. and set BASEPRI to CPU_CFG_KA_IPL_BOUNDARY */ +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS));} while (0) + /* Restore CPU BASEPRI priority level. */ +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* Cortex-M Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + /* See OS_CPU_C.C */ +void OS_CPU_SysTickInit (INT32U cnts); +void OS_CPU_SysTickInitFreq (INT32U cpu_freq); + +void OS_CPU_SysTickHandler (void); +void OS_CPU_PendSVHandler (void); + +#if (OS_CPU_ARM_FP_EN > 0u) +void OS_CPU_FP_Reg_Push (OS_STK *stkPtr); +void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr); +#endif + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm b/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm new file mode 100644 index 0000000..352fb8e --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_cpu_a.asm @@ -0,0 +1,369 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-M Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-M Cortex-M +; Mode : Thumb-2 ISA +; Toolchain : ARM C Compiler +;******************************************************************************************************** +; Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +; (2) It has been tested with the following Hardware Floating Point Unit. +; (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +; (b) Double-precision: FPv5-D16-M +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_KA_BASEPRI_Boundary + + + EXPORT OSStartHighRdy ; Functions declared in this file + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + EXPORT OSCtxSw + EXPORT OSIntCtxSw + EXPORT OS_CPU_PendSVHandler + + IF {FPU} != "SoftVFP" + EXPORT OS_CPU_FP_Reg_Push + EXPORT OS_CPU_FP_Reg_Pop + ENDIF + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register. +NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14). +NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest). +NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception. + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + AREA |.text|, CODE, READONLY, ALIGN=2 + THUMB + REQUIRE8 + PRESERVE8 + + +;******************************************************************************************************** +; FLOATING POINT REGISTERS PUSH +; void OS_CPU_FP_Reg_Push (OS_STK *stkPtr) +; +; Note(s) : 1) This function saves S16-S31 registers of the Floating Point Unit. +; +; 2) Pseudo-code is: +; a) Push remaining FPU regs S16-S31 on process stack; +; b) Update OSTCBCur->OSTCBStkPtr; +;******************************************************************************************************** + + IF {FPU} != "SoftVFP" + +OS_CPU_FP_Reg_Push + MRS R1, PSP ; PSP is process stack pointer + CBZ R1, OS_CPU_FP_nosave ; Skip FP register save the first time + + VSTMDB R0!, {S16-S31} + LDR R1, =OSTCBCur + LDR R2, [R1] + STR R0, [R2] +OS_CPU_FP_nosave + BX LR + + ENDIF + + +;******************************************************************************************************** +; FLOATING POINT REGISTERS POP +; void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr) +; +; Note(s) : 1) This function restores S16-S31 of the Floating Point Unit. +; +; 2) Pseudo-code is: +; a) Restore regs S16-S31 of new process stack; +; b) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack; +;******************************************************************************************************** + + IF {FPU} != "SoftVFP" + +OS_CPU_FP_Reg_Pop + VLDMIA R0!, {S16-S31} + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R0, [R2] + BX LR + + ENDIF + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description : Disable/Enable Kernel aware interrupts by preserving the state of BASEPRI. Generally speaking, +; the state of the BASEPRI interrupt exception processing is stored in the local variable +; 'cpu_sr' & Kernel Aware interrupts are then disabled ('cpu_sr' is allocated in all functions +; that need to disable Kernel aware interrupts). The previous BASEPRI interrupt state is restored +; by copying 'cpu_sr' into the BASEPRI register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SR_Save(new_basepri); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) Increasing priority using a write to BASEPRI does not take effect immediately. +; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +; might incorrectly be preempted by an insufficient high priority exception. +; +; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +; +; CPSID i +; MSR to BASEPRI +; DSB +; ISB +; CPSIE i +;******************************************************************************************************** + +OS_CPU_SR_Save + CPSID I ; Cortex-M7 errata notice. See Note #2 + PUSH {R1} + MRS R1, BASEPRI + MSR BASEPRI, R0 + DSB + ISB + MOV R0, R1 + POP {R1} + CPSIE I + BX LR + +OS_CPU_SR_Restore + CPSID I ; Cortex-M7 errata notice. See Note #2 + MSR BASEPRI, R0 + DSB + ISB + CPSIE I + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +; the first task to start. +; +; 2) During task execution, PSP is used as the stack pointer. +; When an exception occurs, the core will switch to MSP until the exception return. +; +; 3) OSStartHighRdy() MUST: +; a) Setup PendSV exception priority to lowest; +; b) Set initial PSP to 0, to tell context switcher this is first run; +; c) Set the main stack to OS_CPU_ExceptStkBase +; d) Set OSRunning to TRUE; +; e) Get current high priority, OSPrioCur = OSPrioHighRdy; +; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; h) Restore R0-R11 and R14 from new process stack; +; i) Enable interrupts (tasks will run with interrupts enabled). +;******************************************************************************************************** + +OSStartHighRdy + CPSID I ; Prevent interruption during context switch + LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority + LDR R1, =NVIC_PENDSV_PRI + STRB R1, [R0] + + MOVS R0, #0 ; Set the PSP to 0 for initial context switch call + MSR PSP, R0 + + LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase + LDR R1, [R0] + MSR MSP, R1 + + BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop + + LDR R0, =OSRunning ; OSRunning = TRUE + MOVS R1, #1 + STRB R1, [R0] + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + MSR PSP, R0 ; Load PSP with new process SP + + MRS R0, CONTROL + ORR R0, R0, #2 + MSR CONTROL, R0 + ISB ; Sync instruction stream + + LDMFD SP!, {R4-R11, LR} ; Restore r4-11, lr from new process stack + LDMFD SP!, {R0-R3} ; Restore r0, r3 + LDMFD SP!, {R12, LR} ; Load R12 and LR + LDMFD SP!, {R1, R2} ; Load PC and discard xPSR + CPSIE I + BX R1 + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +; triggers the PendSV exception which is where the real work is done. +; +; 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +; the result of an interrupt. This function simply triggers a PendSV exception which will +; be handled when there are no more interrupts active and interrupts are enabled. +;******************************************************************************************************** + +OSCtxSw +OSIntCtxSw + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +;******************************************************************************************************** +; HANDLE PendSV EXCEPTION +; void OS_CPU_PendSVHandler(void) +; +; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +; context switches with Cortex-M. This is because the Cortex-M auto-saves half of the +; processor context on any exception, and restores same on return from exception. So only +; saving of R4-R11 & R14 is required and fixing up the stack pointers. Using the PendSV exception +; this way means that context saving and restoring is identical whether it is initiated from +; a thread or occurs due to an interrupt or exception. +; +; 2) Pseudo-code is: +; a) Get the process SP +; b) Save remaining regs r4-r11 & r14 on process stack; +; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +; d) Call OSTaskSwHook(); +; e) Get current high priority, OSPrioCur = OSPrioHighRdy; +; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; h) Restore R4-R11 and R14 from new process stack; +; i) Perform exception return which will restore remaining context. +; +; 3) On entry into PendSV handler: +; a) The following have been saved on the process stack (by processor): +; xPSR, PC, LR, R12, R0-R3 +; b) Processor mode is switched to Handler mode (from Thread mode) +; c) Stack is Main stack (switched from Process stack) +; d) OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we +; know that it will only be run when no other exception or interrupt is active, and +; therefore safe to assume that context being switched out was using the process stack (PSP). +; +; 5) Increasing priority using a write to BASEPRI does not take effect immediately. +; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +; might incorrectly be preempted by an insufficient high priority exception. +; +; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +; +; CPSID i +; MSR to BASEPRI +; DSB +; ISB +; CPSIE i +;******************************************************************************************************** + +OS_CPU_PendSVHandler + CPSID I ; Cortex-M7 errata notice. See Note #5 + MOV32 R2, OS_KA_BASEPRI_Boundary ; Set BASEPRI priority level required for exception preemption + LDR R1, [R2] + MSR BASEPRI, R1 + DSB + ISB + CPSIE I + + MRS R0, PSP ; PSP is process stack pointer + STMFD R0!, {R4-R11, R14} ; Save remaining regs r4-11, R14 on process stack + + LDR R5, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R5] + STR R0, [R1] ; R0 is SP of process being switched out + + ; At this point, entire context of process has been saved + MOV R4, LR ; Save LR exc_return value + BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R1, =OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy; + LDR R2, [R1] + STR R2, [R5] + + ORR LR, R4, #0x04 ; Ensure exception return uses process stack + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + LDMFD R0!, {R4-R11, R14} ; Restore r4-11, R14 from new process stack + MSR PSP, R0 ; Load PSP with new process SP + + MOV32 R2, #0 ; Restore BASEPRI priority level to 0 + MSR BASEPRI, R2 + BX LR ; Exception return will restore remaining context + + ALIGN ; Removes warning[A1581W]: added of padding at
+ + END diff --git a/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_dbg.c b/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_dbg.c new file mode 100644 index 0000000..b84df4d --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/ARM/os_dbg.c @@ -0,0 +1,328 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : ARM C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu.h b/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu.h new file mode 100644 index 0000000..3c37dc1 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu.h @@ -0,0 +1,236 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : TI C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +* +* Note(s) : (1) If using uC/CPU then 'cpu_cfg.h' has already this define in its template. The user will +* only need to include 'cpu_cfg.h' in 'app_cfg.h'; otherwise, define CPU_CFG_KA_IPL_BOUNDARY +* and CPU_CFG_NVIC_PRIO_BITS in 'app_cfg.h' +* +* (2) Since the port is using BASEPRI to separate kernel vs non-kernel aware ISR, please make sure +* your external interrupt priorities are set accordingly. For example, if CPU_CFG_KA_IPL_BOUNDARY +* is set to 4 then external interrupt priorities 4-15 will be kernel aware while priorities +* 0-3 will be use as non-kernel aware. +* +* (3) Determines the interrupt programmable priority levels. This is normally specified in the +* Microcontroller reference manual. 4-bits gives us 16 programmable priority levels. +* +* NVIC_IPRx +* 7 0 +* +------------------+ +* | PRIO | +* +------------------+ +* +* Bits[7:4] Priority mask bits +* Bits[3:0] Reserved +* +* In this example our CPU_CFG_NVIC_PRIO_BITS define should be set to 4 due to the processor +* implementing only bits[7:4]. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 256u /* Default exception stack size is 256 OS_STK entries */ +#endif + +#ifdef __TI_VFP_SUPPORT__ +#define OS_CPU_ARM_FP_EN 1u +#else +#define OS_CPU_ARM_FP_EN 0u +#endif + +#ifndef CPU_CFG_KA_IPL_BOUNDARY +#error "CPU_CFG_KA_IPL_BOUNDARY not #define'd in 'app_cfg.h' " /* See Note # 1 & 2 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY == 0u) +#error "CPU_CFG_KA_IPL_BOUNDARY should be > 0 " +#endif +#endif + +#ifndef CPU_CFG_NVIC_PRIO_BITS +#error "CPU_CFG_NVIC_PRIO_BITS not #define'd in 'app_cfg.h' " /* See Note # 3 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY >= (1u << CPU_CFG_NVIC_PRIO_BITS)) +#error "CPU_CFG_KA_IPL_BOUNDARY should not be set to higher than max programable priority level " +#endif +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Cortex-M +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u + /* Save current BASEPRI priority lvl for exception... */ + /* .. and set BASEPRI to CPU_CFG_KA_IPL_BOUNDARY */ +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS));} while (0) + /* Restore CPU BASEPRI priority level. */ +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* Cortex-M Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + /* See OS_CPU_C.C */ +void OS_CPU_SysTickInit (INT32U cnts); +void OS_CPU_SysTickInitFreq (INT32U cpu_freq); + +void OS_CPU_SysTickHandler (void); +void OS_CPU_PendSVHandler (void); + +#if (OS_CPU_ARM_FP_EN > 0u) +void OS_CPU_FP_Reg_Push (OS_STK *stkPtr); +void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr); +#endif + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu_a.asm b/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu_a.asm new file mode 100644 index 0000000..966c67f --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_cpu_a.asm @@ -0,0 +1,389 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-M Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-M Cortex-M +; Mode : Thumb-2 ISA +; Toolchain : TI C Compiler +;******************************************************************************************************** +; Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +; (2) It has been tested with the following Hardware Floating Point Unit. +; (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +; (b) Double-precision: FPv5-D16-M +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .ref OSRunning ; External references. + .ref OSPrioCur + .ref OSPrioHighRdy + .ref OSTCBCur + .ref OSTCBHighRdy + .ref OSIntExit + .ref OSTaskSwHook + .ref OS_CPU_ExceptStkBase + .ref OS_KA_BASEPRI_Boundary + +OSRunningAddr: .word OSRunning +OSPrioCurAddr: .word OSPrioCur +OSPrioHighRdyAddr: .word OSPrioHighRdy +OSTCBCurAddr: .word OSTCBCur +OSTCBHighRdyAddr: .word OSTCBHighRdy +OSIntExitAddr: .word OSIntExit +OSTaskSwHookAddr: .word OSTaskSwHook +OS_CPU_ExceptStkBaseAddr: .word OS_CPU_ExceptStkBase +OS_KA_BASEPRI_BoundaryAddr: .word OS_KA_BASEPRI_Boundary + + + .global OSStartHighRdy ; Functions declared in this file + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSCtxSw + .global OSIntCtxSw + .global OS_CPU_PendSVHandler + + .if __TI_VFP_SUPPORT__ + .global OS_CPU_FP_Reg_Push + .global OS_CPU_FP_Reg_Pop + .endif + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +NVIC_INT_CTRL: .word 0xE000ED04 ; Interrupt control state register. +NVIC_SYSPRI14: .word 0xE000ED22 ; System priority register (priority 14). +NVIC_PENDSV_PRI: .word 0xFF ; PendSV priority value (lowest). +NVIC_PENDSVSET: .word 0x10000000 ; Value to trigger PendSV exception. + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .text + .align 2 + .thumb + + +;******************************************************************************************************** +; FLOATING POINT REGISTERS PUSH +; void OS_CPU_FP_Reg_Push (OS_STK *stkPtr) +; +; Note(s) : 1) This function saves S16-S31 registers of the Floating Point Unit. +; +; 2) Pseudo-code is: +; a) Push remaining FPU regs S16-S31 on process stack; +; b) Update OSTCBCur->OSTCBStkPtr; +;******************************************************************************************************** + + .if __TI_VFP_SUPPORT__ + .asmfunc +OS_CPU_FP_Reg_Push: + MRS R1, PSP ; PSP is process stack pointer + CBZ R1, OS_CPU_FP_nosave ; Skip FP register save the first time + + VSTMDB R0!, {S16-S31} + LDR R1, OSTCBCurAddr + LDR R2, [R1] + STR R0, [R2] + .endasmfunc + + .asmfunc +OS_CPU_FP_nosave: + BX LR + .endasmfunc + .endif + + +;******************************************************************************************************** +; FLOATING POINT REGISTERS POP +; void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr) +; +; Note(s) : 1) This function restores S16-S31 of the Floating Point Unit. +; +; 2) Pseudo-code is: +; a) Restore regs S16-S31 of new process stack; +; b) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack; +;******************************************************************************************************** + + .if __TI_VFP_SUPPORT__ + .asmfunc +OS_CPU_FP_Reg_Pop: + VLDMIA R0!, {S16-S31} + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R0, [R2] + BX LR + .endasmfunc + .endif + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description : Disable/Enable Kernel aware interrupts by preserving the state of BASEPRI. Generally speaking, +; the state of the BASEPRI interrupt exception processing is stored in the local variable +; 'cpu_sr' & Kernel Aware interrupts are then disabled ('cpu_sr' is allocated in all functions +; that need to disable Kernel aware interrupts). The previous BASEPRI interrupt state is restored +; by copying 'cpu_sr' into the BASEPRI register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SR_Save(new_basepri); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) Increasing priority using a write to BASEPRI does not take effect immediately. +; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +; might incorrectly be preempted by an insufficient high priority exception. +; +; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +; +; CPSID i +; MSR to BASEPRI +; DSB +; ISB +; CPSIE i +;******************************************************************************************************** + + .asmfunc +OS_CPU_SR_Save: + CPSID I ; Cortex-M7 errata notice. See Note #2 + PUSH {R1} + MRS R1, BASEPRI + MSR BASEPRI, R0 + DSB + ISB + MOV R0, R1 + POP {R1} + CPSIE I + BX LR + .endasmfunc + + .asmfunc +OS_CPU_SR_Restore: + CPSID I ; Cortex-M7 errata notice. See Note #2 + MSR BASEPRI, R0 + DSB + ISB + CPSIE I + BX LR + .endasmfunc + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +; the first task to start. +; +; 2) During task execution, PSP is used as the stack pointer. +; When an exception occurs, the core will switch to MSP until the exception return. +; +; 3) OSStartHighRdy() MUST: +; a) Setup PendSV exception priority to lowest; +; b) Set initial PSP to 0, to tell context switcher this is first run; +; c) Set the main stack to OS_CPU_ExceptStkBase +; d) Set OSRunning to TRUE; +; e) Get current high priority, OSPrioCur = OSPrioHighRdy; +; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; h) Restore R0-R11 and R14 from new process stack; +; i) Enable interrupts (tasks will run with interrupts enabled). +;******************************************************************************************************** + + .asmfunc +OSStartHighRdy: + CPSID I ; Prevent interruption during context switch + LDR R0, NVIC_SYSPRI14 ; Set the PendSV exception priority + LDR R1, NVIC_PENDSV_PRI + STRB R1, [R0] + + MOVS R0, #0 ; Set the PSP to 0 for initial context switch call + MSR PSP, R0 + + LDR R0, OS_CPU_ExceptStkBaseAddr ; Initialize the MSP to the OS_CPU_ExceptStkBase + LDR R1, [R0] + MSR MSP, R1 + + BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop + + LDR R0, OSRunningAddr ; OSRunning = TRUE; + MOVS R1, #1 + STRB R1, [R0] + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCur = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + MSR PSP, R0 ; Load PSP with new process SP + + MRS R0, CONTROL + ORR R0, R0, #2 + MSR CONTROL, R0 + ISB ; Sync instruction stream + + LDMFD SP!, {R4-R11, LR} ; Restore r4-11, lr from new process stack + LDMFD SP!, {R0-R3} ; Restore r0, r3 + LDMFD SP!, {R12, LR} ; Load R12 and LR + LDMFD SP!, {R1, R2} ; Load PC and discard xPSR + CPSIE I + BX R1 + .endasmfunc + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +; triggers the PendSV exception which is where the real work is done. +; +; 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +; the result of an interrupt. This function simply triggers a PendSV exception which will +; be handled when there are no more interrupts active and interrupts are enabled. +;******************************************************************************************************** + + .asmfunc +OSCtxSw: +OSIntCtxSw: + LDR R0, NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, NVIC_PENDSVSET + STR R1, [R0] + BX LR + .endasmfunc + + +;******************************************************************************************************** +; HANDLE PendSV EXCEPTION +; void OS_CPU_PendSVHandler(void) +; +; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +; context switches with Cortex-M. This is because the Cortex-M auto-saves half of the +; processor context on any exception, and restores same on return from exception. So only +; saving of R4-R11 & R14 is required and fixing up the stack pointers. Using the PendSV exception +; this way means that context saving and restoring is identical whether it is initiated from +; a thread or occurs due to an interrupt or exception. +; +; 2) Pseudo-code is: +; a) Get the process SP +; b) Save remaining regs r4-r11 & r14 on process stack; +; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +; d) Call OSTaskSwHook(); +; e) Get current high priority, OSPrioCur = OSPrioHighRdy; +; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; h) Restore R4-R11 and R14 from new process stack; +; i) Perform exception return which will restore remaining context. +; +; 3) On entry into PendSV handler: +; a) The following have been saved on the process stack (by processor): +; xPSR, PC, LR, R12, R0-R3 +; b) Processor mode is switched to Handler mode (from Thread mode) +; c) Stack is Main stack (switched from Process stack) +; d) OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we +; know that it will only be run when no other exception or interrupt is active, and +; therefore safe to assume that context being switched out was using the process stack (PSP). +; +; 5) Increasing priority using a write to BASEPRI does not take effect immediately. +; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +; might incorrectly be preempted by an insufficient high priority exception. +; +; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +; +; CPSID i +; MSR to BASEPRI +; DSB +; ISB +; CPSIE i +;******************************************************************************************************** + + .asmfunc +OS_CPU_PendSVHandler: + CPSID I ; Cortex-M7 errata notice. See Note #5 + LDR R2, OS_KA_BASEPRI_BoundaryAddr ; Set BASEPRI priority level required for exception preemption + LDR R1, [R2] + MSR BASEPRI, R1 + DSB + ISB + CPSIE I + + MRS R0, PSP ; PSP is process stack pointer + STMFD R0!, {R4-R11, R14} ; Save remaining regs r4-11, R14 on process stack + + LDR R5, OSTCBCurAddr ; OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R5] + STR R0, [R1] ; R0 is SP of process being switched out + + ; At this point, entire context of process has been saved + MOV R4, LR ; Save LR exc_return value + BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R1, OSTCBHighRdyAddr ; OSTCBCur = OSTCBHighRdy; + LDR R2, [R1] + STR R2, [R5] + + ORR LR, R4, #0x04 ; Ensure exception return uses process stack + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + LDMFD R0!, {R4-R11, R14} ; Restore r4-11, R14 from new process stack + MSR PSP, R0 ; Load PSP with new process SP + + MOV R2, #0 ; Restore BASEPRI priority level to 0 + MSR BASEPRI, R2 + BX LR ; Exception return will restore remaining context + .endasmfunc + +.end diff --git a/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_dbg.c b/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_dbg.c new file mode 100644 index 0000000..1f956cc --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/CCS/os_dbg.c @@ -0,0 +1,328 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : TI C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu.h b/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu.h new file mode 100644 index 0000000..afab2ad --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu.h @@ -0,0 +1,236 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : GNU C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +* +* Note(s) : (1) If using uC/CPU then 'cpu_cfg.h' has already this define in its template. The user will +* only need to include 'cpu_cfg.h' in 'app_cfg.h'; otherwise, define CPU_CFG_KA_IPL_BOUNDARY +* and CPU_CFG_NVIC_PRIO_BITS in 'app_cfg.h' +* +* (2) Since the port is using BASEPRI to separate kernel vs non-kernel aware ISR, please make sure +* your external interrupt priorities are set accordingly. For example, if CPU_CFG_KA_IPL_BOUNDARY +* is set to 4 then external interrupt priorities 4-15 will be kernel aware while priorities +* 0-3 will be use as non-kernel aware. +* +* (3) Determines the interrupt programmable priority levels. This is normally specified in the +* Microcontroller reference manual. 4-bits gives us 16 programmable priority levels. +* +* NVIC_IPRx +* 7 0 +* +------------------+ +* | PRIO | +* +------------------+ +* +* Bits[7:4] Priority mask bits +* Bits[3:0] Reserved +* +* In this example our CPU_CFG_NVIC_PRIO_BITS define should be set to 4 due to the processor +* implementing only bits[7:4]. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 256u /* Default exception stack size is 256 OS_STK entries */ +#endif + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) +#define OS_CPU_ARM_FP_EN 1u +#else +#define OS_CPU_ARM_FP_EN 0u +#endif + +#ifndef CPU_CFG_KA_IPL_BOUNDARY +#error "CPU_CFG_KA_IPL_BOUNDARY not #define'd in 'app_cfg.h' " /* See Note # 1 & 2 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY == 0u) +#error "CPU_CFG_KA_IPL_BOUNDARY should be > 0 " +#endif +#endif + +#ifndef CPU_CFG_NVIC_PRIO_BITS +#error "CPU_CFG_NVIC_PRIO_BITS not #define'd in 'app_cfg.h' " /* See Note # 3 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY >= (1u << CPU_CFG_NVIC_PRIO_BITS)) +#error "CPU_CFG_KA_IPL_BOUNDARY should not be set to higher than max programable priority level " +#endif +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Cortex-M +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u + /* Save current BASEPRI priority lvl for exception... */ + /* .. and set BASEPRI to CPU_CFG_KA_IPL_BOUNDARY */ +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS));} while (0) + /* Restore CPU BASEPRI priority level. */ +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* Cortex-M Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + /* See OS_CPU_C.C */ +void OS_CPU_SysTickInit (INT32U cnts); +void OS_CPU_SysTickInitFreq (INT32U cpu_freq); + +void OS_CPU_SysTickHandler (void); +void OS_CPU_PendSVHandler (void); + +#if (OS_CPU_ARM_FP_EN > 0u) +void OS_CPU_FP_Reg_Push (OS_STK *stkPtr); +void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr); +#endif + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu_a.S b/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu_a.S new file mode 100644 index 0000000..bcc1a26 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_cpu_a.S @@ -0,0 +1,385 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARMv7-M Port +@ +@ Filename : os_cpu_a.S +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARMv7-M Cortex-M +@ Mode : Thumb-2 ISA +@ Toolchain : GNU C Compiler +@******************************************************************************************************** +@ Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +@ (2) It has been tested with the following Hardware Floating Point Unit. +@ (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +@ (b) Double-precision: FPv5-D16-M +@******************************************************************************************************** + +@******************************************************************************************************** +@ PUBLIC FUNCTIONS +@******************************************************************************************************** + + .extern OSRunning @ External references + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntExit + .extern OSTaskSwHook + .extern OS_CPU_ExceptStkBase + .extern OS_KA_BASEPRI_Boundary + + + .global OSStartHighRdy @ Functions declared in this file + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSCtxSw + .global OSIntCtxSw + .global OS_CPU_PendSVHandler + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) + .global OS_CPU_FP_Reg_Push + .global OS_CPU_FP_Reg_Pop +#endif + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + +.equ NVIC_INT_CTRL, 0xE000ED04 @ Interrupt control state register. +.equ NVIC_SYSPRI14, 0xE000ED22 @ System priority register (priority 14). +.equ NVIC_PENDSV_PRI, 0xFF @ PendSV priority value (lowest). +.equ NVIC_PENDSVSET, 0x10000000 @ Value to trigger PendSV exception. + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .text + .align 2 + .thumb + .syntax unified + + +@******************************************************************************************************** +@ FLOATING POINT REGISTERS PUSH +@ void OS_CPU_FP_Reg_Push (OS_STK *stkPtr) +@ +@ Note(s) : 1) This function saves S16-S31 registers of the Floating Point Unit. +@ +@ 2) Pseudo-code is: +@ a) Push remaining FPU regs S16-S31 on process stack; +@ b) Update OSTCBCur->OSTCBStkPtr; +@******************************************************************************************************** + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) + +.thumb_func +OS_CPU_FP_Reg_Push: + MRS R1, PSP @ PSP is process stack pointer + CBZ R1, OS_CPU_FP_nosave @ Skip FP register save the first time + + VSTMDB R0!, {S16-S31} + LDR R1, =OSTCBCur + LDR R2, [R1] + STR R0, [R2] +OS_CPU_FP_nosave: + BX LR +#endif + + +@******************************************************************************************************** +@ FLOATING POINT REGISTERS POP +@ void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr) +@ +@ Note(s) : 1) This function restores S16-S31 of the Floating Point Unit. +@ +@ 2) Pseudo-code is: +@ a) Restore regs S16-S31 of new process stack; +@ b) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack; +@******************************************************************************************************** + +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) + +.thumb_func +OS_CPU_FP_Reg_Pop: + VLDMIA R0!, {S16-S31} + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R0, [R2] + BX LR +#endif + + +@******************************************************************************************************** +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description : Disable/Enable Kernel aware interrupts by preserving the state of BASEPRI. Generally speaking, +@ the state of the BASEPRI interrupt exception processing is stored in the local variable +@ 'cpu_sr' & Kernel Aware interrupts are then disabled ('cpu_sr' is allocated in all functions +@ that need to disable Kernel aware interrupts). The previous BASEPRI interrupt state is restored +@ by copying 'cpu_sr' into the BASEPRI register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save(OS_CPU_SR new_basepri); +@ void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +@ +@ +@ Note(s) : 1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +@ OS_CPU_SR cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SR_Save(new_basepri); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +@ : +@ : +@ } +@ +@ 2) Increasing priority using a write to BASEPRI does not take effect immediately. +@ (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +@ might incorrectly be preempted by an insufficient high priority exception. +@ +@ (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +@ +@ CPSID i +@ MSR to BASEPRI +@ DSB +@ ISB +@ CPSIE i +@******************************************************************************************************** + +.thumb_func +OS_CPU_SR_Save: + CPSID I @ Cortex-M7 errata notice. See Note #2 + PUSH {R1} + MRS R1, BASEPRI + MSR BASEPRI, R0 + DSB + ISB + MOV R0, R1 + POP {R1} + CPSIE I + BX LR + +.thumb_func +OS_CPU_SR_Restore: + CPSID I @ Cortex-M7 errata notice. See Note #2 + MSR BASEPRI, R0 + DSB + ISB + CPSIE I + BX LR + + +@******************************************************************************************************** +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +@ the first task to start. +@ +@ 2) During task execution, PSP is used as the stack pointer. +@ When an exception occurs, the core will switch to MSP until the exception return. +@ +@ 3) OSStartHighRdy() MUST: +@ a) Setup PendSV exception priority to lowest; +@ b) Set initial PSP to 0, to tell context switcher this is first run; +@ c) Set the main stack to OS_CPU_ExceptStkBase +@ d) Set OSRunning to TRUE; +@ e) Get current high priority, OSPrioCur = OSPrioHighRdy; +@ f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +@ g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +@ h) Restore R0-R11 and R14 from new process stack; +@ i) Enable interrupts (tasks will run with interrupts enabled). +@******************************************************************************************************** + +.thumb_func +OSStartHighRdy: + CPSID I @ Prevent interruption during context switch + MOVW R0, #:lower16:NVIC_SYSPRI14 @ Set the PendSV exception priority + MOVT R0, #:upper16:NVIC_SYSPRI14 + + MOVW R1, #:lower16:NVIC_PENDSV_PRI + MOVT R1, #:upper16:NVIC_PENDSV_PRI + STRB R1, [R0] + + MOVS R0, #0 @ Set the PSP to 0 for initial context switch call + MSR PSP, R0 + + MOVW R0, #:lower16:OS_CPU_ExceptStkBase @ Initialize the MSP to the OS_CPU_ExceptStkBase + MOVT R0, #:upper16:OS_CPU_ExceptStkBase + LDR R1, [R0] + MSR MSP, R1 + + BL OSTaskSwHook @ Call OSTaskSwHook() for FPU Push & Pop + + LDR R0, =OSRunning @ OSRunning = TRUE + MOVS R1, #1 + STRB R1, [R0] + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR R0, [R2] @ R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + MSR PSP, R0 @ Load PSP with new process SP + + MRS R0, CONTROL + ORR R0, R0, #2 + MSR CONTROL, R0 + ISB @ Sync instruction stream + + LDMFD SP!, {R4-R11, LR} @ Restore r4-11, lr from new process stack + LDMFD SP!, {R0-R3} @ Restore r0, r3 + LDMFD SP!, {R12, LR} @ Load R12 and LR + LDMFD SP!, {R1, R2} @ Load PC and discard xPSR + CPSIE I + BX R1 + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +@ triggers the PendSV exception which is where the real work is done. +@ +@ 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +@ the result of an interrupt. This function simply triggers a PendSV exception which will +@ be handled when there are no more interrupts active and interrupts are enabled. +@******************************************************************************************************** + +.thumb_func +OSCtxSw: +OSIntCtxSw: + LDR R0, =NVIC_INT_CTRL @ Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +@******************************************************************************************************** +@ HANDLE PendSV EXCEPTION +@ void OS_CPU_PendSVHandler(void) +@ +@ Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +@ context switches with Cortex-M. This is because the Cortex-M auto-saves half of the +@ processor context on any exception, and restores same on return from exception. So only +@ saving of R4-R11 & R14 is required and fixing up the stack pointers. Using the PendSV exception +@ this way means that context saving and restoring is identical whether it is initiated from +@ a thread or occurs due to an interrupt or exception. +@ +@ 2) Pseudo-code is: +@ a) Get the process SP +@ b) Save remaining regs r4-r11 & r14 on process stack; +@ c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +@ d) Call OSTaskSwHook(); +@ e) Get current high priority, OSPrioCur = OSPrioHighRdy; +@ f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +@ g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +@ h) Restore R4-R11 and R14 from new process stack; +@ i) Perform exception return which will restore remaining context. +@ +@ 3) On entry into PendSV handler: +@ a) The following have been saved on the process stack (by processor): +@ xPSR, PC, LR, R12, R0-R3 +@ b) Processor mode is switched to Handler mode (from Thread mode) +@ c) Stack is Main stack (switched from Process stack) +@ d) OSTCBCur points to the OS_TCB of the task to suspend +@ OSTCBHighRdy points to the OS_TCB of the task to resume +@ +@ 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we +@ know that it will only be run when no other exception or interrupt is active, and +@ therefore safe to assume that context being switched out was using the process stack (PSP). +@ +@ 5) Increasing priority using a write to BASEPRI does not take effect immediately. +@ (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +@ might incorrectly be preempted by an insufficient high priority exception. +@ +@ (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +@ +@ CPSID i +@ MSR to BASEPRI +@ DSB +@ ISB +@ CPSIE i +@******************************************************************************************************** + +.thumb_func +OS_CPU_PendSVHandler: + CPSID I @ Cortex-M7 errata notice. See Note #5 + MOVW R2, #:lower16:OS_KA_BASEPRI_Boundary @ Set BASEPRI priority level required for exception preemption + MOVT R2, #:upper16:OS_KA_BASEPRI_Boundary + LDR R1, [R2] + MSR BASEPRI, R1 + DSB + ISB + CPSIE I + + MRS R0, PSP @ PSP is process stack pointer + STMFD R0!, {R4-R11, R14} @ Save remaining regs r4-11, R14 on process stack + + MOVW R5, #:lower16:OSTCBCur @ OSTCBCur->OSTCBStkPtr = SP; + MOVT R5, #:upper16:OSTCBCur + LDR R1, [R5] + STR R0, [R1] @ R0 is SP of process being switched out + + @ At this point, entire context of process has been saved + MOV R4, LR @ Save LR exc_return value + BL OSTaskSwHook @ Call OSTaskSwHook() for FPU Push & Pop + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R1, #:lower16:OSTCBHighRdy @ OSTCBCur = OSTCBHighRdy; + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R5] + + ORR LR, R4, #0x04 @ Ensure exception return uses process stack + LDR R0, [R2] @ R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + LDMFD R0!, {R4-R11, R14} @ Restore r4-11, R14 from new process stack + MSR PSP, R0 @ Load PSP with new process SP + + MOV R2, #0 @ Restore BASEPRI priority level to 0 + MSR BASEPRI, R2 + BX LR @ Exception return will restore remaining context + +.end diff --git a/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_dbg.c b/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_dbg.c new file mode 100644 index 0000000..02c4d5f --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/GNU/os_dbg.c @@ -0,0 +1,328 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : GNU C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu.h b/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu.h new file mode 100644 index 0000000..544ab8c --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu.h @@ -0,0 +1,236 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : IAR EWARM +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +* +* Note(s) : (1) If using uC/CPU then 'cpu_cfg.h' has already this define in its template. The user will +* only need to include 'cpu_cfg.h' in 'app_cfg.h'; otherwise, define CPU_CFG_KA_IPL_BOUNDARY +* and CPU_CFG_NVIC_PRIO_BITS in 'app_cfg.h' +* +* (2) Since the port is using BASEPRI to separate kernel vs non-kernel aware ISR, please make sure +* your external interrupt priorities are set accordingly. For example, if CPU_CFG_KA_IPL_BOUNDARY +* is set to 4 then external interrupt priorities 4-15 will be kernel aware while priorities +* 0-3 will be use as non-kernel aware. +* +* (3) Determines the interrupt programmable priority levels. This is normally specified in the +* Microcontroller reference manual. 4-bits gives us 16 programmable priority levels. +* +* NVIC_IPRx +* 7 0 +* +------------------+ +* | PRIO | +* +------------------+ +* +* Bits[7:4] Priority mask bits +* Bits[3:0] Reserved +* +* In this example our CPU_CFG_NVIC_PRIO_BITS define should be set to 4 due to the processor +* implementing only bits[7:4]. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 256u /* Default exception stack size is 256 OS_STK entries */ +#endif + +#ifdef __ARMVFP__ +#define OS_CPU_ARM_FP_EN 1u +#else +#define OS_CPU_ARM_FP_EN 0u +#endif + +#ifndef CPU_CFG_KA_IPL_BOUNDARY +#error "CPU_CFG_KA_IPL_BOUNDARY not #define'd in 'app_cfg.h' " /* See Note # 1 & 2 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY == 0u) +#error "CPU_CFG_KA_IPL_BOUNDARY should be > 0 " +#endif +#endif + +#ifndef CPU_CFG_NVIC_PRIO_BITS +#error "CPU_CFG_NVIC_PRIO_BITS not #define'd in 'app_cfg.h' " /* See Note # 3 */ +#else +#if (CPU_CFG_KA_IPL_BOUNDARY >= (1u << CPU_CFG_NVIC_PRIO_BITS)) +#error "CPU_CFG_KA_IPL_BOUNDARY should not be set to higher than max programable priority level " +#endif +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Cortex-M +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u + /* Save current BASEPRI priority lvl for exception... */ + /* .. and set BASEPRI to CPU_CFG_KA_IPL_BOUNDARY */ +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS));} while (0) + /* Restore CPU BASEPRI priority level. */ +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* Cortex-M Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + /* See OS_CPU_C.C */ +void OS_CPU_SysTickInit (INT32U cnts); +void OS_CPU_SysTickInitFreq (INT32U cpu_freq); + +void OS_CPU_SysTickHandler (void); +void OS_CPU_PendSVHandler (void); + +#if (OS_CPU_ARM_FP_EN > 0u) +void OS_CPU_FP_Reg_Push (OS_STK *stkPtr); +void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr); +#endif + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu_a.asm b/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu_a.asm new file mode 100644 index 0000000..36df763 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_cpu_a.asm @@ -0,0 +1,361 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-M Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-M Cortex-M +; Mode : Thumb-2 ISA +; Toolchain : IAR EWARM +;******************************************************************************************************** +; Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +; (2) It has been tested with the following Hardware Floating Point Unit. +; (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +; (b) Double-precision: FPv5-D16-M +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_KA_BASEPRI_Boundary + + + PUBLIC OSStartHighRdy ; Functions declared in this file + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OS_CPU_PendSVHandler + +#ifdef __ARMVFP__ + PUBLIC OS_CPU_FP_Reg_Push + PUBLIC OS_CPU_FP_Reg_Pop +#endif + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +NVIC_INT_CTRL EQU 0xE000ED04 ; Interrupt control state register. +NVIC_SYSPRI14 EQU 0xE000ED22 ; System priority register (priority 14). +NVIC_PENDSV_PRI EQU 0xFF ; PendSV priority value (lowest). +NVIC_PENDSVSET EQU 0x10000000 ; Value to trigger PendSV exception. + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + THUMB + + +;******************************************************************************************************** +; FLOATING POINT REGISTERS PUSH +; void OS_CPU_FP_Reg_Push (OS_STK *stkPtr) +; +; Note(s) : 1) This function saves S16-S31 registers of the Floating Point Unit. +; +; 2) Pseudo-code is: +; a) Push remaining FPU regs S16-S31 on process stack; +; b) Update OSTCBCur->OSTCBStkPtr; +;******************************************************************************************************** + +#ifdef __ARMVFP__ +OS_CPU_FP_Reg_Push + MRS R1, PSP ; PSP is process stack pointer + CBZ R1, OS_CPU_FP_nosave ; Skip FP register save the first time + + VSTMDB R0!, {S16-S31} + LDR R1, =OSTCBCur + LDR R2, [R1] + STR R0, [R2] +OS_CPU_FP_nosave + BX LR +#endif + + +;******************************************************************************************************** +; FLOATING POINT REGISTERS POP +; void OS_CPU_FP_Reg_Pop (OS_STK *stkPtr) +; +; Note(s) : 1) This function restores S16-S31 of the Floating Point Unit. +; +; 2) Pseudo-code is: +; a) Restore regs S16-S31 of new process stack; +; b) Update OSTCBHighRdy->OSTCBStkPtr pointer of new proces stack; +;******************************************************************************************************** + +#ifdef __ARMVFP__ +OS_CPU_FP_Reg_Pop + VLDMIA R0!, {S16-S31} + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R0, [R2] + BX LR +#endif + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description : Disable/Enable Kernel aware interrupts by preserving the state of BASEPRI. Generally speaking, +; the state of the BASEPRI interrupt exception processing is stored in the local variable +; 'cpu_sr' & Kernel Aware interrupts are then disabled ('cpu_sr' is allocated in all functions +; that need to disable Kernel aware interrupts). The previous BASEPRI interrupt state is restored +; by copying 'cpu_sr' into the BASEPRI register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (OS_CPU_SR new_basepri); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SR_Save(new_basepri); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) Increasing priority using a write to BASEPRI does not take effect immediately. +; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +; might incorrectly be preempted by an insufficient high priority exception. +; +; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +; +; CPSID i +; MSR to BASEPRI +; DSB +; ISB +; CPSIE i +;******************************************************************************************************** + +OS_CPU_SR_Save + CPSID I ; Cortex-M7 errata notice. See Note #2 + PUSH {R1} + MRS R1, BASEPRI + MSR BASEPRI, R0 + DSB + ISB + MOV R0, R1 + POP {R1} + CPSIE I + BX LR + +OS_CPU_SR_Restore + CPSID I ; Cortex-M7 errata notice. See Note #2 + MSR BASEPRI, R0 + DSB + ISB + CPSIE I + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +; the first task to start. +; +; 2) During task execution, PSP is used as the stack pointer. +; When an exception occurs, the core will switch to MSP until the exception return. +; +; 3) OSStartHighRdy() MUST: +; a) Setup PendSV exception priority to lowest; +; b) Set initial PSP to 0, to tell context switcher this is first run; +; c) Set the main stack to OS_CPU_ExceptStkBase +; d) Set OSRunning to TRUE; +; e) Get current high priority, OSPrioCur = OSPrioHighRdy; +; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; h) Restore R0-R11 and R14 from new process stack; +; i) Enable interrupts (tasks will run with interrupts enabled). +;******************************************************************************************************** + +OSStartHighRdy + CPSID I ; Prevent interruption during context switch + LDR R0, =NVIC_SYSPRI14 ; Set the PendSV exception priority + LDR R1, =NVIC_PENDSV_PRI + STRB R1, [R0] + + MOVS R0, #0 ; Set the PSP to 0 for initial context switch call + MSR PSP, R0 + + LDR R0, =OS_CPU_ExceptStkBase ; Initialize the MSP to the OS_CPU_ExceptStkBase + LDR R1, [R0] + MSR MSP, R1 + + BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop + + LDR R0, =OSRunning ; OSRunning = TRUE + MOVS R1, #1 + STRB R1, [R0] + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + MSR PSP, R0 ; Load PSP with new process SP + + MRS R0, CONTROL + ORR R0, R0, #2 + MSR CONTROL, R0 + ISB ; Sync instruction stream + + LDMFD SP!, {R4-R11, LR} ; Restore r4-11, lr from new process stack + LDMFD SP!, {R0-R3} ; Restore r0, r3 + LDMFD SP!, {R12, LR} ; Load R12 and LR + LDMFD SP!, {R1, R2} ; Load PC and discard xPSR + CPSIE I + BX R1 + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +; triggers the PendSV exception which is where the real work is done. +; +; 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +; the result of an interrupt. This function simply triggers a PendSV exception which will +; be handled when there are no more interrupts active and interrupts are enabled. +;******************************************************************************************************** + +OSCtxSw +OSIntCtxSw + LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch) + LDR R1, =NVIC_PENDSVSET + STR R1, [R0] + BX LR + + +;******************************************************************************************************** +; HANDLE PendSV EXCEPTION +; void OS_CPU_PendSVHandler(void) +; +; Note(s) : 1) PendSV is used to cause a context switch. This is a recommended method for performing +; context switches with Cortex-M. This is because the Cortex-M auto-saves half of the +; processor context on any exception, and restores same on return from exception. So only +; saving of R4-R11 & R14 is required and fixing up the stack pointers. Using the PendSV exception +; this way means that context saving and restoring is identical whether it is initiated from +; a thread or occurs due to an interrupt or exception. +; +; 2) Pseudo-code is: +; a) Get the process SP +; b) Save remaining regs r4-r11 & r14 on process stack; +; c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +; d) Call OSTaskSwHook(); +; e) Get current high priority, OSPrioCur = OSPrioHighRdy; +; f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; h) Restore R4-R11 and R14 from new process stack; +; i) Perform exception return which will restore remaining context. +; +; 3) On entry into PendSV handler: +; a) The following have been saved on the process stack (by processor): +; xPSR, PC, LR, R12, R0-R3 +; b) Processor mode is switched to Handler mode (from Thread mode) +; c) Stack is Main stack (switched from Process stack) +; d) OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 4) Since PendSV is set to lowest priority in the system (by OSStartHighRdy() above), we +; know that it will only be run when no other exception or interrupt is active, and +; therefore safe to assume that context being switched out was using the process stack (PSP). +; +; 5) Increasing priority using a write to BASEPRI does not take effect immediately. +; (a) IMPLICATION This erratum means that the instruction after an MSR to boost BASEPRI +; might incorrectly be preempted by an insufficient high priority exception. +; +; (b) WORKAROUND The MSR to boost BASEPRI can be replaced by the following code sequence: +; +; CPSID i +; MSR to BASEPRI +; DSB +; ISB +; CPSIE i +;******************************************************************************************************** + +OS_CPU_PendSVHandler + CPSID I ; Cortex-M7 errata notice. See Note #5 + MOV32 R2, OS_KA_BASEPRI_Boundary ; Set BASEPRI priority level required for exception preemption + LDR R1, [R2] + MSR BASEPRI, R1 + DSB + ISB + CPSIE I + + MRS R0, PSP ; PSP is process stack pointer + STMFD R0!, {R4-R11, R14} ; Save remaining regs r4-11, R14 on process stack + + LDR R5, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R5] + STR R0, [R1] ; R0 is SP of process being switched out + + ; At this point, entire context of process has been saved + MOV R4, LR ; Save LR exc_return value + BL OSTaskSwHook ; Call OSTaskSwHook() for FPU Push & Pop + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R1, =OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy; + LDR R2, [R1] + STR R2, [R5] + + ORR LR, R4, #0x04 ; Ensure exception return uses process stack + LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr; + LDMFD R0!, {R4-R11, R14} ; Restore r4-11, R14 from new process stack + MSR PSP, R0 ; Load PSP with new process SP + + MOV32 R2, #0 ; Restore BASEPRI priority level to 0 + MSR BASEPRI, R2 + BX LR ; Exception return will restore remaining context + + END diff --git a/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_dbg.c b/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_dbg.c new file mode 100644 index 0000000..61f741c --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/IAR/os_dbg.c @@ -0,0 +1,328 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +* Toolchain : IAR EWARM +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c b/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c new file mode 100644 index 0000000..318d2d3 --- /dev/null +++ b/Ports/ARM-Cortex-M/ARMv7-M/os_cpu_c.c @@ -0,0 +1,727 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-M Port +* +* File : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-M Cortex-M +* Mode : Thumb-2 ISA +********************************************************************************************************* +* Note(s) : (1) This port supports the ARM Cortex-M3, Cortex-M4 and Cortex-M7 architectures. +* (2) It has been tested with the following Hardware Floating Point Unit. +* (a) Single-precision: FPv4-SP-D16-M and FPv5-SP-D16-M +* (b) Double-precision: FPv5-D16-M +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + +INT32U OS_KA_BASEPRI_Boundary; /* Base Priority boundary. */ + + +/* +********************************************************************************************************* +* SYS TICK DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_CM_SYST_CSR (*((volatile INT32U *)0xE000E010uL)) /* SysTick Ctrl & Status Reg. */ +#define OS_CPU_CM_SYST_RVR (*((volatile INT32U *)0xE000E014uL)) /* SysTick Reload Value Reg. */ +#define OS_CPU_CM_SYST_CVR (*((volatile INT32U *)0xE000E018uL)) /* SysTick Current Value Reg. */ +#define OS_CPU_CM_SYST_CALIB (*((volatile INT32U *)0xE000E01CuL)) /* SysTick Cal Value Reg. */ +#define OS_CPU_CM_SCB_SHPRI1 (*((volatile INT32U *)0xE000ED18uL)) /* System Handlers 4 to 7 Prio. */ +#define OS_CPU_CM_SCB_SHPRI2 (*((volatile INT32U *)0xE000ED1CuL)) /* System Handlers 8 to 11 Prio. */ +#define OS_CPU_CM_SCB_SHPRI3 (*((volatile INT32U *)0xE000ED20uL)) /* System Handlers 12 to 15 Prio. */ + + +#define OS_CPU_CM_SYST_CSR_COUNTFLAG 0x00010000uL /* Count flag. */ +#define OS_CPU_CM_SYST_CSR_CLKSOURCE 0x00000004uL /* Clock Source. */ +#define OS_CPU_CM_SYST_CSR_TICKINT 0x00000002uL /* Interrupt enable. */ +#define OS_CPU_CM_SYST_CSR_ENABLE 0x00000001uL /* Counter mode. */ + + +/* +********************************************************************************************************* +* FLOATING POINT DEFINES +* +* Note(s) : 1) Enabled FP lazy stacking and enable automatic state saving. +********************************************************************************************************* +*/ + +#define OS_CPU_CM_FP_FPCCR (*((volatile INT32U *)0xE000EF34uL)) /* Floating-Point Context Control Reg. */ +#define OS_CPU_CM_FPCCR_LAZY_STK 0xC0000000uL /* See Note 1. */ + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +* 2) When using hardware floating point please do the following during the reset handler: +* a) Set full access for CP10 & CP11 bits in CPACR register. +* b) Set bits ASPEN and LSPEN in FPCCR register. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; +#if (OS_CPU_ARM_FP_EN > 0u) + INT32U reg_val; +#endif + /* Clear exception stack for stack checking. */ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk++ = (OS_STK)0; + } + + /* Align the ISR stack to 8-bytes */ + OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; + OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8); + +#if (OS_CPU_ARM_FP_EN > 0u) + reg_val = OS_CPU_CM_FP_FPCCR; /* Check the floating point mode. */ + if ((reg_val & OS_CPU_CM_FPCCR_LAZY_STK) != OS_CPU_CM_FPCCR_LAZY_STK) { + while (1u) { /* See Note (2). */ + ; + } + } +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif + + /* Set BASEPRI boundary from the configuration. */ + OS_KA_BASEPRI_Boundary = (INT32U)(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS)); +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ + +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) Interrupts are enabled when task starts executing. +* +* (2) All tasks run in Thread mode, using process stack. +* +* (3) There are two different stack frames depending on whether the Floating-Point(FP) +* co-processor is enabled or not. +* +* (a) The stack frame shown in the diagram is used when the Co-processor Access Control +* Register(CPACR) is disabling the Floating Point Unit. In this case, the FP +* registers(S0- S31) & FP Status Control(FPSCR) register are not saved in the stack frame. +* +* (b) The stack frame shown in the diagram is used when the Floating Point Unit is enabled, +* that is, CP10 and CP11 field in CPACR are ones and FPCCR sets bits ASPEN and LSPEN to 1. +* +* (1) When enabling the FPU through CPACR, make sure to set bits ASPEN and LSPEN in the +* Floating-Point Context Control Register (FPCCR). +* +* +-------------+ +* | | +* +-------------+ +* | | +* +-------------+ +* | FPSCR | +* +-------------+ +* | S15 | +* +-------------+ +* | S14 | +* +-------------+ +* | S13 | +* +-------------+ +* . +* . +* . +* +-------------+ +* | S2 | +* +-------------+ +* | S1 | +* +-------------+ +-------------+ +* | | | S0 | +* +-------------+ +-------------+ +* | xPSR | | xPSR | +* +-------------+ +-------------+ +* | Return Addr | | Return Addr | +* +-------------+ +-------------+ +* | LR(R14) | | LR(R14) | +* +-------------+ +-------------+ +* | R12 | | R12 | +* +-------------+ +-------------+ +* | R3 | | R3 | +* +-------------+ +-------------+ +* | R2 | | R0 | +* +-------------+ +-------------+ +* | R1 | | R1 | +* +-------------+ +-------------+ +* | R0 | | R0 | +* +-------------+ +-------------+ +* | EXEC_RETURN | | EXEC_RETURN | +* +-------------+ +-------------+ +* | R11 | | R11 | +* +-------------+ +-------------+ +* | R10 | | R10 | +* +-------------+ +-------------+ +* | R9 | | R9 | +* +-------------+ +-------------+ +* | R8 | | R8 | +* +-------------+ +-------------+ +* | R7 | | R7 | +* +-------------+ +-------------+ +* | R6 | | R6 | +* +-------------+ +-------------+ +* | R5 | | R5 | +* +-------------+ +-------------+ +* | R4 | | R4 | +* +-------------+ +-------------+ +* (a) | S31 | +* +-------------+ +* | S30 | +* +-------------+ +* | S29 | + +-------------+ +* . +* . +* . +* +-------------+ +* | S17 | + +-------------+ +* | S16 | +* +-------------+ +* (b) +* +* (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture +* +* (a) Section 2.1 of the ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned +* on entry to AAPCS-Conforming functions states : +* +* The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive +* data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes). +* Doing otherwise creates more problems than it solves. +* +* In return for preserving the natural alignment of data, conforming code is permitted +* to rely on that alignment. To support aligning data allocated on the stack, the stack +* pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In +* practice this requirement is met if: +* +* (1) At each call site, the current size of the calling function's stack frame is a multiple of 8 bytes. +* This places an obligation on compilers and assembly language programmers. +* +* (2) SP is a multiple of 8 when control first enters a program. +* This places an obligation on authors of low level OS, RTOS, and runtime library +* code to align SP at all points at which control first enters +* a body of (AAPCS-conforming) code. +* +* In turn, this requires the value of SP to be aligned to 0 modulo 8: +* +* (3) By exception handlers, before calling AAPCS-conforming code. +* +* (4) By OS/RTOS/run-time system code, before giving control to an application. +* +* (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry +* to AAPCS-conforming functions advisory note also states. +* +* " This requirement extends to operating systems and run-time code for all architecture versions +* prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations +* associated with ARMV7M are discussed in section 2.3.3" +* +* (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned +* to 8-byte boundaries to support legacy execution enviroments. +* +* (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM +* architecture states : "The stack must also conform to the following +* constraint at a public interface: +* +* (1) SP mod 8 = 0. The stack must be double-word aligned" +* +* (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment. +* +* "8 byte stack alignment is a requirement of the ARM Architecture Procedure +* Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte +* aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external +* interfaces. In practice this requirement is met if: +* +* (1) At each external interface, the current stack pointer +* is a multiple of 8 bytes. +* +* (2) Your OS maintains 8 byte stack alignment on its external interfaces +* e.g. on task switches" +* +* (5) Exception Return Behavior(EXEC_RETURN) +* 0xFFFFFFFD Return to Thread mode, exception return uses non-floating point state +* from the PSP and execution uses PSP after return. +* +* 0xFFFFFFED Return to Thread mode, exception return uses floating point state +* from the PSP and execution uses PSP after return. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + + + (void)opt; /* 'opt' is not used, prevent warning */ + p_stk = ptos + 1u; /* Load stack pointer */ + /* Align the stack to 8-bytes. */ + p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u); + /* Registers stacked as if auto-saved on exception */ +#if (OS_CPU_ARM_FP_EN > 0u) /* FPU auto-saved registers. */ + --p_stk; + *(--p_stk) = (OS_STK)0x02000000u; /* FPSCR */ + /* Initialize S0-S15 floating point registers */ + *(--p_stk) = (OS_STK)0x41700000u; /* S15 */ + *(--p_stk) = (OS_STK)0x41600000u; /* S14 */ + *(--p_stk) = (OS_STK)0x41500000u; /* S13 */ + *(--p_stk) = (OS_STK)0x41400000u; /* S12 */ + *(--p_stk) = (OS_STK)0x41300000u; /* S11 */ + *(--p_stk) = (OS_STK)0x41200000u; /* S10 */ + *(--p_stk) = (OS_STK)0x41100000u; /* S9 */ + *(--p_stk) = (OS_STK)0x41000000u; /* S8 */ + *(--p_stk) = (OS_STK)0x40E00000u; /* S7 */ + *(--p_stk) = (OS_STK)0x40C00000u; /* S6 */ + *(--p_stk) = (OS_STK)0x40A00000u; /* S5 */ + *(--p_stk) = (OS_STK)0x40800000u; /* S4 */ + *(--p_stk) = (OS_STK)0x40400000u; /* S3 */ + *(--p_stk) = (OS_STK)0x40000000u; /* S2 */ + *(--p_stk) = (OS_STK)0x3F800000u; /* S1 */ + *(--p_stk) = (OS_STK)0x00000000u; /* S0 */ +#endif + *(--p_stk) = (OS_STK)0x01000000uL; /* xPSR */ + *(--p_stk) = (OS_STK)task; /* Entry Point */ + *(--p_stk) = (OS_STK)OS_TaskReturn; /* R14 (LR) */ + *(--p_stk) = (OS_STK)0x12121212uL; /* R12 */ + *(--p_stk) = (OS_STK)0x03030303uL; /* R3 */ + *(--p_stk) = (OS_STK)0x02020202uL; /* R2 */ + *(--p_stk) = (OS_STK)0x01010101uL; /* R1 */ + *(--p_stk) = (OS_STK)p_arg; /* R0 : argument */ + +#if (OS_CPU_ARM_FP_EN > 0u) + *(--p_stk) = (OS_STK)0xFFFFFFEDuL; /* R14: EXEC_RETURN; See Note 5 */ +#else + *(--p_stk) = (OS_STK)0xFFFFFFFDuL; /* R14: EXEC_RETURN; See Note 5 */ +#endif + /* Remaining registers saved on process stack */ + *(--p_stk) = (OS_STK)0x11111111uL; /* R11 */ + *(--p_stk) = (OS_STK)0x10101010uL; /* R10 */ + *(--p_stk) = (OS_STK)0x09090909uL; /* R9 */ + *(--p_stk) = (OS_STK)0x08080808uL; /* R8 */ + *(--p_stk) = (OS_STK)0x07070707uL; /* R7 */ + *(--p_stk) = (OS_STK)0x06060606uL; /* R6 */ + *(--p_stk) = (OS_STK)0x05050505uL; /* R5 */ + *(--p_stk) = (OS_STK)0x04040404uL; /* R4 */ + +#if (OS_CPU_ARM_FP_EN > 0u) + /* Initialize S16-S31 floating point registers */ + *(--p_stk) = (OS_STK)0x41F80000u; /* S31 */ + *(--p_stk) = (OS_STK)0x41F00000u; /* S30 */ + *(--p_stk) = (OS_STK)0x41E80000u; /* S29 */ + *(--p_stk) = (OS_STK)0x41E00000u; /* S28 */ + *(--p_stk) = (OS_STK)0x41D80000u; /* S27 */ + *(--p_stk) = (OS_STK)0x41D00000u; /* S26 */ + *(--p_stk) = (OS_STK)0x41C80000u; /* S25 */ + *(--p_stk) = (OS_STK)0x41C00000u; /* S24 */ + *(--p_stk) = (OS_STK)0x41B80000u; /* S23 */ + *(--p_stk) = (OS_STK)0x41B00000u; /* S22 */ + *(--p_stk) = (OS_STK)0x41A80000u; /* S21 */ + *(--p_stk) = (OS_STK)0x41A00000u; /* S20 */ + *(--p_stk) = (OS_STK)0x41980000u; /* S19 */ + *(--p_stk) = (OS_STK)0x41900000u; /* S18 */ + *(--p_stk) = (OS_STK)0x41880000u; /* S17 */ + *(--p_stk) = (OS_STK)0x41800000u; /* S16 */ +#endif + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ + +#if (OS_CPU_ARM_FP_EN > 0u) + OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr); /* Push the FP registers of the current task. */ +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif + + OS_TRACE_TASK_SWITCHED_IN(OSTCBHighRdy); + +#if (OS_CPU_ARM_FP_EN > 0u) + OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr); /* Pop the FP registers of the highest ready task. */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* SYS TICK HANDLER +* +* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick +* interrupt. +* +* Arguments : None. +* +* Note(s) : 1) This function MUST be placed on entry 15 of the Cortex-M vector table. +********************************************************************************************************* +*/ + +void OS_CPU_SysTickHandler (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + + + OS_ENTER_CRITICAL(); + OSIntEnter(); /* Tell uC/OS-II that we are starting an ISR */ + OS_EXIT_CRITICAL(); + + OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */ + + OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */ +} + + +/* +********************************************************************************************************* +* INITIALIZE SYS TICK +* +* Description: Initialize the SysTick using the CPU clock frequency. +* +* Arguments : cpu_freq CPU clock frequency. +* +* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization. +* +* 2) Either OS_CPU_SysTickInitFreq or OS_CPU_SysTickInit() can be called. +********************************************************************************************************* +*/ + +void OS_CPU_SysTickInitFreq (INT32U cpu_freq) +{ + INT32U cnts; + + + cnts = (cpu_freq / (INT32U)OS_TICKS_PER_SEC); /* Determine nbr SysTick cnts between two OS tick intr. */ + + OS_CPU_SysTickInit(cnts); +} + + +/* +********************************************************************************************************* +* INITIALIZE SYS TICK +* +* Description: Initialize the SysTick using the number of counts between two ticks. +* +* Arguments : cnts Number of SysTick counts between two OS tick interrupts. +* +* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization. +* +* 2) Either OS_CPU_SysTickInitFreq or OS_CPU_SysTickInit() can be called. +********************************************************************************************************* +*/ + +void OS_CPU_SysTickInit (INT32U cnts) +{ + INT32U prio; + INT32U basepri; + + + /* Set BASEPRI boundary from the configuration. */ + basepri = (INT32U)(CPU_CFG_KA_IPL_BOUNDARY << (8u - CPU_CFG_NVIC_PRIO_BITS)); + OS_CPU_CM_SYST_RVR = cnts - 1u; /* Set Reload register. */ + + /* Set SysTick handler prio. */ + prio = OS_CPU_CM_SCB_SHPRI3; + prio &= 0x00FFFFFFu; + prio |= (basepri << 24u); + OS_CPU_CM_SCB_SHPRI3 = prio; + + /* Enable timer. */ + OS_CPU_CM_SYST_CSR |= OS_CPU_CM_SYST_CSR_CLKSOURCE | + OS_CPU_CM_SYST_CSR_ENABLE; + /* Enable timer interrupt. */ + OS_CPU_CM_SYST_CSR |= OS_CPU_CM_SYST_CSR_TICKINT; +} diff --git a/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu.h b/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu.h new file mode 100644 index 0000000..7ab7ca8 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu.h @@ -0,0 +1,300 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-R Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-R Cortex-R +* Mode : ARM or Thumb +* Toolchain : ARM C Compiler +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-R line from the R4 to the R8 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.s are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.s +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d16.s +* Suitable for cpus with VFP support and 16 double word registers. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if (defined(__BIG_ENDIAN)) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-d16.s b/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-d16.s new file mode 100644 index 0000000..246a634 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-d16.s @@ -0,0 +1,719 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-R Port +; +; Filename : os_cpu_a_vfp-d16.s +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-R Cortex-R +; Mode : ARM or Thumb +; Toolchain : ARM C Compiler +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + + EXPORT OSStartHighRdy + EXPORT OSCtxSw + EXPORT OSIntCtxSw + + ; Functions related to exception handling. + EXPORT OS_CPU_ARM_ExceptUndefInstrHndlr + EXPORT OS_CPU_ARM_ExceptSwiHndlr + EXPORT OS_CPU_ARM_ExceptPrefetchAbortHndlr + EXPORT OS_CPU_ARM_ExceptDataAbortHndlr + EXPORT OS_CPU_ARM_ExceptIrqHndlr + EXPORT OS_CPU_ARM_ExceptFiqHndlr + + EXPORT OS_CPU_SR_INT_Dis + EXPORT OS_CPU_SR_INT_En + EXPORT OS_CPU_SR_FIQ_Dis + EXPORT OS_CPU_SR_FIQ_En + EXPORT OS_CPU_SR_IRQ_Dis + EXPORT OS_CPU_SR_IRQ_En + + EXPORT OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + REQUIRE8 + PRESERVE8 + + AREA CODE, CODE, READONLY + CODE32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + + MACRO + OS_CPU_ARM_FP_REG_POP $rx + POP {$rx} + VMSR FPEXC, $rx ; ... Pop new task's FPEXC + FLDMIAD SP!, {D0-D15} ; ... Pop new task's General-Purpose floating point registers. + POP {$rx} + VMSR FPSCR, $rx ; ... Pop new task's FPSCR. + MEND + + MACRO + OS_CPU_ARM_FP_REG_PUSH $rx + VMRS $rx, FPSCR ; ... Save current FPSCR + PUSH {$rx} ; ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + VMRS $rx, FPEXC ; ... Save Floating point exception register. + PUSH {$rx} + MEND + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #16 + BX LR + + END diff --git a/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-none.s b/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-none.s new file mode 100644 index 0000000..018278f --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/ARM/os_cpu_a_vfp-none.s @@ -0,0 +1,684 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-R Port +; +; Filename : os_cpu_a_vfp-none.s +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-R Cortex-R +; Mode : ARM or Thumb +; Toolchain : ARM C Compiler +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + + EXPORT OSStartHighRdy + EXPORT OSCtxSw + EXPORT OSIntCtxSw + + ; Functions related to exception handling. + EXPORT OS_CPU_ARM_ExceptUndefInstrHndlr + EXPORT OS_CPU_ARM_ExceptSwiHndlr + EXPORT OS_CPU_ARM_ExceptPrefetchAbortHndlr + EXPORT OS_CPU_ARM_ExceptDataAbortHndlr + EXPORT OS_CPU_ARM_ExceptIrqHndlr + EXPORT OS_CPU_ARM_ExceptFiqHndlr + + EXPORT OS_CPU_SR_INT_Dis + EXPORT OS_CPU_SR_INT_En + EXPORT OS_CPU_SR_FIQ_Dis + EXPORT OS_CPU_SR_FIQ_En + EXPORT OS_CPU_SR_IRQ_Dis + EXPORT OS_CPU_SR_IRQ_En + + EXPORT OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + REQUIRE8 + PRESERVE8 + + AREA CODE, CODE, READONLY + CODE32 + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #0 + BX LR + + END diff --git a/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu.h b/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu.h new file mode 100644 index 0000000..d3329d9 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu.h @@ -0,0 +1,300 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-R Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-R Cortex-R +* Mode : ARM or Thumb +* Toolchain : TI TMS470 COMPILER +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-R line from the R4 to the R8 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.asm are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.asm +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d16.asm +* Suitable for cpus with VFP support and 16 double word registers. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if defined(__big_endian__) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-d16.asm b/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-d16.asm new file mode 100644 index 0000000..fad644b --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-d16.asm @@ -0,0 +1,726 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-R Port +; +; Filename : os_cpu_a_vfp-d16.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-R Cortex-R +; Mode : ARM or Thumb +; Toolchain : TI TMS470 COMPILER +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + .global OSRunning + .global OSPrioCur + .global OSPrioHighRdy + .global OSTCBCur + .global OSTCBHighRdy + .global OSIntNesting + .global OSIntExit + .global OSTaskSwHook + .global OS_CPU_ExceptStkBase + .global OS_CPU_ExceptStkPtr + .global OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +OSRunningAddr .word OSRunning +OSPrioCurAddr .word OSPrioCur +OSPrioHighRdyAddr .word OSPrioHighRdy +OSTCBCurAddr .word OSTCBCur +OSTCBHighRdyAddr .word OSTCBHighRdy +OSIntNestingAddr .word OSIntNesting +OSIntExitAddr .word OSIntExit +OSTaskSwHookAddr .word OSTaskSwHook +OS_CPU_ExceptStkBaseAddr .word OS_CPU_ExceptStkBase +OS_CPU_ExceptStkPtrAddr .word OS_CPU_ExceptStkPtr +OS_CPU_ExceptHndlrAddr .word OS_CPU_ExceptHndlr + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + ; Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS .equ 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS .equ 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS .equ 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB .equ 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM .equ 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK .equ 0x1F +OS_CPU_ARM_MODE_USR .equ 0x10 +OS_CPU_ARM_MODE_FIQ .equ 0x11 +OS_CPU_ARM_MODE_IRQ .equ 0x12 +OS_CPU_ARM_MODE_SVC .equ 0x13 +OS_CPU_ARM_MODE_ABT .equ 0x17 +OS_CPU_ARM_MODE_UND .equ 0x1B +OS_CPU_ARM_MODE_SYS .equ 0x1F + +OS_CPU_ARM_EXCEPT_RESET .equ 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR .equ 0x01 +OS_CPU_ARM_EXCEPT_SWI .equ 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT .equ 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT .equ 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT .equ 0x05 +OS_CPU_ARM_EXCEPT_IRQ .equ 0x06 +OS_CPU_ARM_EXCEPT_FIQ .equ 0x07 + +OS_CPU_ARM_FPEXC_EN .equ 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + .text + .state32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + +OS_CPU_ARM_FP_REG_POP .macro rx + POP {rx} + VMSR FPEXC, rx ; ... Pop new task's FPEXC + FLDMIAD SP!, {D0-D15} ; ... Pop new task's General-Purpose floating point registers. + POP {rx} + VMSR FPSCR, rx ; ... Pop new task's FPSCR. + .endm + +OS_CPU_ARM_FP_REG_PUSH .macro rx + VMRS rx, FPSCR ; ... Save current FPSCR + PUSH {rx} ; ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + VMRS rx, FPEXC ; ... Save Floating point exception register. + PUSH {rx} + .endm + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSRunningAddr ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, OSTCBHighRdyAddr ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + LDR R0, OSTCBCurAddr ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCur = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCurPtr = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + LDR R3, OSRunningAddr + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + LDR R3, OSTCBCurAddr ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, OS_CPU_ExceptStkBaseAddr ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + LDR R3, OSTCBCurAddr ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #16 + BX LR + diff --git a/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-none.asm b/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-none.asm new file mode 100644 index 0000000..13020b4 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/CCS/os_cpu_a_vfp-none.asm @@ -0,0 +1,694 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARMv7-R Port +; +; Filename : os_cpu_a_vfp-none.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-R Cortex-R +; Mode : ARM or Thumb +; Toolchain : TI TMS470 COMPILER +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +;******************************************************************************************************** + + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + .global OSRunning + .global OSPrioCur + .global OSPrioHighRdy + .global OSTCBCur + .global OSTCBHighRdy + .global OSIntNesting + .global OSIntExit + .global OSTaskSwHook + .global OS_CPU_ExceptStkBase + .global OS_CPU_ExceptStkPtr + .global OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +OSRunningAddr .word OSRunning +OSPrioCurAddr .word OSPrioCur +OSPrioHighRdyAddr .word OSPrioHighRdy +OSTCBCurAddr .word OSTCBCur +OSTCBHighRdyAddr .word OSTCBHighRdy +OSIntNestingAddr .word OSIntNesting +OSIntExitAddr .word OSIntExit +OSTaskSwHookAddr .word OSTaskSwHook +OS_CPU_ExceptStkBaseAddr .word OS_CPU_ExceptStkBase +OS_CPU_ExceptStkPtrAddr .word OS_CPU_ExceptStkPtr +OS_CPU_ExceptHndlrAddr .word OS_CPU_ExceptHndlr + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + ; Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS .equ 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS .equ 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS .equ 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB .equ 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM .equ 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK .equ 0x1F +OS_CPU_ARM_MODE_USR .equ 0x10 +OS_CPU_ARM_MODE_FIQ .equ 0x11 +OS_CPU_ARM_MODE_IRQ .equ 0x12 +OS_CPU_ARM_MODE_SVC .equ 0x13 +OS_CPU_ARM_MODE_ABT .equ 0x17 +OS_CPU_ARM_MODE_UND .equ 0x1B +OS_CPU_ARM_MODE_SYS .equ 0x1F + +OS_CPU_ARM_EXCEPT_RESET .equ 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR .equ 0x01 +OS_CPU_ARM_EXCEPT_SWI .equ 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT .equ 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT .equ 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT .equ 0x05 +OS_CPU_ARM_EXCEPT_IRQ .equ 0x06 +OS_CPU_ARM_EXCEPT_FIQ .equ 0x07 + +OS_CPU_ARM_FPEXC_EN .equ 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + .text + .state32 + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSRunningAddr ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, OSTCBHighRdyAddr ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX ; Clear exclusive monitor. + + LDR R0, OSTCBCurAddr ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCur = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R0, OSPrioCurAddr ; OSPrioCur = OSPrioHighRdy; + LDR R1, OSPrioHighRdyAddr + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, OSTCBCurAddr ; OSTCBCurPtr = OSTCBHighRdy; + LDR R1, OSTCBHighRdyAddr + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + LDR R3, OSRunningAddr + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + LDR R3, OSTCBCurAddr ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, OS_CPU_ExceptStkBaseAddr ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + LDR R3, OSTCBCurAddr ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R3, OSIntNestingAddr ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #0 + BX LR + diff --git a/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu.h b/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu.h new file mode 100644 index 0000000..b87f099 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu.h @@ -0,0 +1,302 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARMv7-R Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-R Cortex-R +* Mode : ARM or Thumb +* Toolchain : GNU +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-R line from the R4 to the R8 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.S are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.S +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d16.S +* Suitable for cpus with VFP support and 16 double word registers. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if (defined(__BYTE_ORDER__) && \ + (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-d16.S b/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-d16.S new file mode 100644 index 0000000..d719aa2 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-d16.S @@ -0,0 +1,746 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARMv7-R Port +@ +@ Filename : os_cpu_a_vfp-d16.S +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARMv7-R Cortex-R +@ Mode : ARM or Thumb +@ Toolchain : GNU +@******************************************************************************************************** +@ Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +@******************************************************************************************************** + +@******************************************************************************************************** +@ EXTERNAL REFERENCE +@******************************************************************************************************** + @ .external references. + .extern OSRunning + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntNesting + .extern OSIntExit + .extern OSTaskSwHook + .extern OS_CPU_ExceptStkBase + .extern OS_CPU_ExceptStkPtr + .extern OS_CPU_ExceptHndlr @ Chip Support/BSP specific exception handler. + + +@******************************************************************************************************** +@ FUNCTIONS +@******************************************************************************************************** + + @ Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + @ Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + + .equ OS_CPU_ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ. + .equ OS_CPU_ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ. + .equ OS_CPU_ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ. + .equ OS_CPU_ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode. + .equ OS_CPU_ARM_CONTROL_ARM, 0x00 @ Set ARM mode. + + .equ OS_CPU_ARM_MODE_MASK, 0x1F + .equ OS_CPU_ARM_MODE_USR, 0x10 + .equ OS_CPU_ARM_MODE_FIQ, 0x11 + .equ OS_CPU_ARM_MODE_IRQ, 0x12 + .equ OS_CPU_ARM_MODE_SVC, 0x13 + .equ OS_CPU_ARM_MODE_ABT, 0x17 + .equ OS_CPU_ARM_MODE_UND, 0x1B + .equ OS_CPU_ARM_MODE_SYS, 0x1F + + .equ OS_CPU_ARM_EXCEPT_RESET, 0x00 + .equ OS_CPU_ARM_EXCEPT_UNDEF_INSTR, 0x01 + .equ OS_CPU_ARM_EXCEPT_SWI, 0x02 + .equ OS_CPU_ARM_EXCEPT_PREFETCH_ABORT, 0x03 + .equ OS_CPU_ARM_EXCEPT_DATA_ABORT, 0x04 + .equ OS_CPU_ARM_EXCEPT_ADDR_ABORT, 0x05 + .equ OS_CPU_ARM_EXCEPT_IRQ, 0x06 + .equ OS_CPU_ARM_EXCEPT_FIQ, 0x07 + + .equ OS_CPU_ARM_FPEXC_EN, 0x40000000 @VFP enable bit. + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .code 32 + + +@******************************************************************************************************** +@ FLOATING POINT REGISTER MACROS +@******************************************************************************************************** + + .macro OS_CPU_ARM_FP_REG_POP rx + POP {\rx} + VMSR FPEXC, \rx @ ... Pop new task's FPEXC + FLDMIAD SP!, {D0-D15} @ ... Pop new task's General-Purpose floating point registers. + POP {\rx} + VMSR FPSCR, \rx @ ... Pop new task's FPSCR. + .endm + + .macro OS_CPU_ARM_FP_REG_PUSH rx + VMRS \rx, FPSCR @ ... Save current FPSCR + PUSH {\rx} @ ... Save general-purpose floating-point registers. + FSTMDBD SP!, {D0-D15} + VMRS \rx, FPEXC @ ... Save Floating point exception register. + PUSH {\rx} + .endm + + +@******************************************************************************************************** +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +@ void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +@ +@ +@ Note(s) : (1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ /* Allocate storage for CPU status register. */ +@ #if (OS_CRITICAL_METHOD == 3) +@ OS_CPU_SR os_cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +@ : +@ : +@ } +@******************************************************************************************************** + + .type OS_CPU_SR_Save, %function +OS_CPU_SR_Save: + + MRS R0, CPSR + CPSID IF @ Set IRQ & FIQ bits in CPSR to DISABLE all interrupts. + DSB + BX LR @ DISABLED, return the original CPSR contents in R0. + + .type OS_CPU_SR_Restore, %function +OS_CPU_SR_Restore: + + DSB + MSR CPSR_c, R0 + BX LR + + +@******************************************************************************************************** +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to OS_STATE_OS_RUNNING, +@ c) Switch to the highest priority task. +@******************************************************************************************************** + + .type OSStartHighRdy, %function +OSStartHighRdy: + @ Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSRunning @ OSRunning = TRUE; + MOVT R0, #:upper16:OSRunning + MOV R1, #1 + STRB R1, [R0] + @ SWITCH TO HIGHEST PRIORITY TASK: + MOVW R0, #:lower16:OSTCBHighRdy @ Get highest priority task TCB address, + MOVT R0, #:upper16:OSTCBHighRdy + LDR R0, [R0] @ Get stack pointer, + LDR SP, [R0] @ Switch to the new stack, + + OS_CPU_ARM_FP_REG_POP R0 + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) Save the current task's context onto the current task's stack, +@ b) OSTCBCur->StkPtr = SP; +@ c) OSTaskSwHook(); +@ d) OSPrioCur = OSPrioHighRdy; +@ e) OSTCBCurPtr = OSTCBHighRdy; +@ f) SP = OSTCBHighRdy->StkPtr; +@ g) Restore the new task's context from the new task's stack, +@ h) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSCtxSw, %function +OSCtxSw: + @ SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} @ Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} @ Push registers, + MRS R0, CPSR @ Push current CPSR, + TST LR, #1 @ See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB @ If yes, set the T-bit. + STMFD SP!, {R0} + + OS_CPU_ARM_FP_REG_PUSH R0 @ Push FP context + + CLREX @ Clear exclusive monitor. + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur->StkPtr = SP; + MOVT R0, #:upper16:OSTCBCur + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdy->OSTCBStkPtr; + + @ RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 @ Pop new task's FP context. + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) OSTaskSwHook(); +@ b) OSPrioCur = OSPrioHighRdy; +@ c) OSTCBCurPtr = OSTCBHighRdyPtr; +@ d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +@ e) Restore the new task's context from the new task's stack, +@ f) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSIntCtxSw, %function +OSIntCtxSw: + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + CLREX @ Clear the exclusive acess tag for the processor. + + @ RESTORE NEW TASK'S CONTEXT: + OS_CPU_ARM_FP_REG_POP R0 @ Pop new task's FP context. + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ UNDEFINED INSTRUCTION EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ SOFTWARE INTERRUPT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI @ Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ PREFETCH ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ DATA ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ ADDRESS ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ @ Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ FAST INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ @ Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ GLOBAL EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Exception's SP +@ +@ Note(s) : 1) An exception can occur in three different circumstances@ in each of these, the +@ SVC stack pointer will point to a different entity : +@ +@ a) CONDITION: An exception occurs before the OS has been fully initialized. +@ SVC STACK: Should point to a stack initialized by the application's startup code. +@ STK USAGE: Interrupted context -- SVC stack. +@ Exception -- SVC stack. +@ Nested exceptions -- SVC stack. +@ +@ b) CONDITION: An exception interrupts a task. +@ SVC STACK: Should point to task stack. +@ STK USAGE: Interrupted context -- Task stack. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@ +@ c) CONDITION: An exception interrupts another exception. +@ SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +@ STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr: + + MRS R1, SPSR @ Save CPSR (i.e. exception's SPSR). + MOV R3, SP @ Save exception's stack pointer. + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + STMFD SP!, {R2} @ Push task's PC, + STMFD SP!, {LR} @ Push task's LR, + STMFD SP!, {R4-R12} @ Push task's R12-R4, + LDMFD R3!, {R5-R8} @ Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} @ Push task's CPSR (i.e. exception SPSR). + + OS_CPU_ARM_FP_REG_PUSH R1 + + MOVW R3, #:lower16:OSRunning @ if (OSRunning == 1) + MOVT R3, #:upper16:OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr++; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 @ if (OSIntNestingCtr == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: TASK INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask: + + MOVW R3, #:lower16:OSTCBCur @ OSTCBCurPtr->StkPtr = SP; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + STR SP, [R4] + + MOVW R3, #:lower16:OS_CPU_ExceptStkBase @ Switch to exception stack. + MOVT R3, #:upper16:OS_CPU_ExceptStkBase + LDR SP, [R3] + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ Call OSIntExit(). This call MAY never return if a ready + @ task with higher priority than the interrupted one is + @ found. + BL OSIntExit + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + MOVW R3, #:lower16:OSTCBCur @ SP = OSTCBCurPtr->StkPtr; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + LDR SP, [R4] + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: EXCEPTION INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr--; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + OS_CPU_ARM_FP_REG_POP R0 + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS +@ +@ Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs and FIQs so that +@ nesting can occur. +@ +@ 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_INT_En, %function +OS_CPU_SR_INT_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_INT_Dis, %function +OS_CPU_SR_INT_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE IRQs +@ +@ Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_IRQ_En, %function +OS_CPU_SR_IRQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_IRQ_Dis, %function +OS_CPU_SR_IRQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE FIQs +@ +@ Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_FIQ_En, %function +OS_CPU_SR_FIQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_FIQ_Dis, %function +OS_CPU_SR_FIQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ VFP/NEON REGISTER COUNT +@ +@ Register Usage: R0 Double Register Count +@******************************************************************************************************** + + .type OS_CPU_ARM_DRegCntGet, %function +OS_CPU_ARM_DRegCntGet: + + MOV R0, #16 + BX LR + diff --git a/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-none.S b/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-none.S new file mode 100644 index 0000000..0eb6bce --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/GNU/os_cpu_a_vfp-none.S @@ -0,0 +1,712 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARMv7-R Port +@ +@ Filename : os_cpu_a_vfp-none.S +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARMv7-R Cortex-R +@ Mode : ARM or Thumb +@ Toolchain : GNU +@******************************************************************************************************** +@ Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +@******************************************************************************************************** + +@******************************************************************************************************** +@ EXTERNAL REFERENCE +@******************************************************************************************************** + @ .external references. + .extern OSRunning + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntNesting + .extern OSIntExit + .extern OSTaskSwHook + .extern OS_CPU_ExceptStkBase + .extern OS_CPU_ExceptStkPtr + .extern OS_CPU_ExceptHndlr @ Chip Support/BSP specific exception handler. + + +@******************************************************************************************************** +@ FUNCTIONS +@******************************************************************************************************** + + @ Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + @ Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_En + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .global OS_CPU_ARM_DRegCntGet + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + + .equ OS_CPU_ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ. + .equ OS_CPU_ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ. + .equ OS_CPU_ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ. + .equ OS_CPU_ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode. + .equ OS_CPU_ARM_CONTROL_ARM, 0x00 @ Set ARM mode. + + .equ OS_CPU_ARM_MODE_MASK, 0x1F + .equ OS_CPU_ARM_MODE_USR, 0x10 + .equ OS_CPU_ARM_MODE_FIQ, 0x11 + .equ OS_CPU_ARM_MODE_IRQ, 0x12 + .equ OS_CPU_ARM_MODE_SVC, 0x13 + .equ OS_CPU_ARM_MODE_ABT, 0x17 + .equ OS_CPU_ARM_MODE_UND, 0x1B + .equ OS_CPU_ARM_MODE_SYS, 0x1F + + .equ OS_CPU_ARM_EXCEPT_RESET, 0x00 + .equ OS_CPU_ARM_EXCEPT_UNDEF_INSTR, 0x01 + .equ OS_CPU_ARM_EXCEPT_SWI, 0x02 + .equ OS_CPU_ARM_EXCEPT_PREFETCH_ABORT, 0x03 + .equ OS_CPU_ARM_EXCEPT_DATA_ABORT, 0x04 + .equ OS_CPU_ARM_EXCEPT_ADDR_ABORT, 0x05 + .equ OS_CPU_ARM_EXCEPT_IRQ, 0x06 + .equ OS_CPU_ARM_EXCEPT_FIQ, 0x07 + + .equ OS_CPU_ARM_FPEXC_EN, 0x40000000 @VFP enable bit. + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .code 32 + + +@******************************************************************************************************** +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +@ void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +@ +@ +@ Note(s) : (1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ /* Allocate storage for CPU status register. */ +@ #if (OS_CRITICAL_METHOD == 3) +@ OS_CPU_SR os_cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +@ : +@ : +@ } +@******************************************************************************************************** + + .type OS_CPU_SR_Save, %function +OS_CPU_SR_Save: + + MRS R0, CPSR + CPSID IF @ Set IRQ & FIQ bits in CPSR to DISABLE all interrupts. + DSB + BX LR @ DISABLED, return the original CPSR contents in R0. + + .type OS_CPU_SR_Restore, %function +OS_CPU_SR_Restore: + + DSB + MSR CPSR_c, R0 + BX LR + + +@******************************************************************************************************** +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to OS_STATE_OS_RUNNING, +@ c) Switch to the highest priority task. +@******************************************************************************************************** + + .type OSStartHighRdy, %function +OSStartHighRdy: + @ Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSRunning @ OSRunning = TRUE; + MOVT R0, #:upper16:OSRunning + MOV R1, #1 + STRB R1, [R0] + @ SWITCH TO HIGHEST PRIORITY TASK: + MOVW R0, #:lower16:OSTCBHighRdy @ Get highest priority task TCB address, + MOVT R0, #:upper16:OSTCBHighRdy + LDR R0, [R0] @ Get stack pointer, + LDR SP, [R0] @ Switch to the new stack, + + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) Save the current task's context onto the current task's stack, +@ b) OSTCBCur->StkPtr = SP; +@ c) OSTaskSwHook(); +@ d) OSPrioCur = OSPrioHighRdy; +@ e) OSTCBCurPtr = OSTCBHighRdy; +@ f) SP = OSTCBHighRdy->StkPtr; +@ g) Restore the new task's context from the new task's stack, +@ h) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSCtxSw, %function +OSCtxSw: + @ SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} @ Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} @ Push registers, + MRS R0, CPSR @ Push current CPSR, + TST LR, #1 @ See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB @ If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX @ Clear exclusive monitor. + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur->StkPtr = SP; + MOVT R0, #:upper16:OSTCBCur + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdy->OSTCBStkPtr; + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) OSTaskSwHook(); +@ b) OSPrioCur = OSPrioHighRdy; +@ c) OSTCBCurPtr = OSTCBHighRdyPtr; +@ d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +@ e) Restore the new task's context from the new task's stack, +@ f) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCurPtr points to the OS_TCB of the task to suspend, +@ OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +@******************************************************************************************************** + + .type OSIntCtxSw, %function +OSIntCtxSw: + + BL OSTaskSwHook @ OSTaskSwHook(); + + MOVW R0, #:lower16:OSPrioCur @ OSPrioCur = OSPrioHighRdy; + MOVT R0, #:upper16:OSPrioCur + MOVW R1, #:lower16:OSPrioHighRdy + MOVT R1, #:upper16:OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOVW R0, #:lower16:OSTCBCur @ OSTCBCur = OSTCBHighRdy; + MOVT R0, #:upper16:OSTCBCur + MOVW R1, #:lower16:OSTCBHighRdy + MOVT R1, #:upper16:OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + CLREX @ Clear the exclusive acess tag for the processor. + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ UNDEFINED INSTRUCTION EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ SOFTWARE INTERRUPT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI @ Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ PREFETCH ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ DATA ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ ADDRESS ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ @ Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ FAST INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ @ Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + + +@******************************************************************************************************** +@ GLOBAL EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Exception's SP +@ +@ Note(s) : 1) An exception can occur in three different circumstances@ in each of these, the +@ SVC stack pointer will point to a different entity : +@ +@ a) CONDITION: An exception occurs before the OS has been fully initialized. +@ SVC STACK: Should point to a stack initialized by the application's startup code. +@ STK USAGE: Interrupted context -- SVC stack. +@ Exception -- SVC stack. +@ Nested exceptions -- SVC stack. +@ +@ b) CONDITION: An exception interrupts a task. +@ SVC STACK: Should point to task stack. +@ STK USAGE: Interrupted context -- Task stack. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@ +@ c) CONDITION: An exception interrupts another exception. +@ SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +@ STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr: + + MRS R1, SPSR @ Save CPSR (i.e. exception's SPSR). + MOV R3, SP @ Save exception's stack pointer. + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX @ Clear exclusive monitor. + + STMFD SP!, {R2} @ Push task's PC, + STMFD SP!, {LR} @ Push task's LR, + STMFD SP!, {R4-R12} @ Push task's R12-R4, + LDMFD R3!, {R5-R8} @ Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} @ Push task's CPSR (i.e. exception SPSR). + + MOVW R3, #:lower16:OSRunning @ if (OSRunning == 1) + MOVT R3, #:upper16:OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr++; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 @ if (OSIntNestingCtr == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: TASK INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask: + + MOVW R3, #:lower16:OSTCBCur @ OSTCBCurPtr->StkPtr = SP; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + STR SP, [R4] + + MOVW R3, #:lower16:OS_CPU_ExceptStkBase @ Switch to exception stack. + MOVT R3, #:upper16:OS_CPU_ExceptStkBase + LDR SP, [R3] + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ Call OSIntExit(). This call MAY never return if a ready + @ task with higher priority than the interrupted one is + @ found. + BL OSIntExit + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + MOVW R3, #:lower16:OSTCBCur @ SP = OSTCBCurPtr->StkPtr; + MOVT R3, #:upper16:OSTCBCur + LDR R4, [R3] + LDR SP, [R4] + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: EXCEPTION INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + MOVW R3, #:lower16:OSIntNesting @ OSIntNestingCtr--; + MOVT R3, #:upper16:OSIntNesting + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@ EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing: + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + @ EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + + +@******************************************************************************************************** +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS +@ +@ Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs and FIQs so that +@ nesting can occur. +@ +@ 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_INT_En, %function +OS_CPU_SR_INT_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_INT_Dis, %function +OS_CPU_SR_INT_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE IRQs +@ +@ Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_IRQ_En, %function +OS_CPU_SR_IRQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_IRQ_Dis, %function +OS_CPU_SR_IRQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ ENABLE & DISABLE FIQs +@ +@ Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the .external +@ interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +@******************************************************************************************************** + + .type OS_CPU_SR_FIQ_En, %function +OS_CPU_SR_FIQ_En: + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + .type OS_CPU_SR_FIQ_Dis, %function +OS_CPU_SR_FIQ_Dis: + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +@******************************************************************************************************** +@ VFP/NEON REGISTER COUNT +@ +@ Register Usage: R0 Double Register Count +@******************************************************************************************************** + + .type OS_CPU_ARM_DRegCntGet, %function +OS_CPU_ARM_DRegCntGet: + + MOV R0, #0 + BX LR + diff --git a/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu.h b/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu.h new file mode 100644 index 0000000..bc0e280 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu.h @@ -0,0 +1,302 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARMv7-R Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-R Cortex-R +* Mode : ARM or Thumb +* Toolchain : IAR EWARM V5.xx and higher +********************************************************************************************************* +* Note(s) : (1) This port supports the entire 32-bit ARM Cortex-R line from the R4 to the R8 +* with every possible VFP/NEON coprocessor option. +* +* (2) To support the various FPUs three versions of os_cpu_a.asm are provided. +* Only one of them must be used at a time as outlined below. +* +* os_cpu_a_vfp-none.asm +* Suitable when there is no VFP/NEON support or they are deactivated. +* Can also be used when saving the VFP/NEON register bank isn't required. +* +* os_cpu_a_vfp-d16.asm +* Suitable for cpus with VFP support and 16 double word registers. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 1024u /* Default exception stack size is 128 OS_STK entries. */ +#endif + + +/* +********************************************************************************************************* +* CONFIGURATION DEFAULTS +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_CPU_ARM_ENDIAN_LITTLE 1u +#define OS_CPU_ARM_ENDIAN_BIG 2u + + +#if (defined(__LITTLE_ENDIAN__) && \ + (__LITTLE_ENDIAN__ == 1)) +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_LITTLE +#else +#define OS_CPU_ARM_ENDIAN_TYPE OS_CPU_ARM_ENDIAN_BIG +#endif + +#ifndef OS_CPU_INT_DIS_MEAS_EN +#define OS_CPU_INT_DIS_MEAS_EN 0u /* Intrrupt dis time measurement disabled by default */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + + +/* +********************************************************************************************************* +* ARM EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + + + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_VECT_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_RST (OS_CPU_ARM_EXCEPT_RST * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_UND (OS_CPU_ARM_EXCEPT_UND * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_SWI (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_PREFETCH (OS_CPU_ARM_EXCEPT_ABORT_PREFETCH * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_ABORT_DATA (OS_CPU_ARM_EXCEPT_ABORT_DATA * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_IRQ (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_HANDLER_ADDR_FIQ (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEu + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018u + +#define OS_CPU_ARM_BIT_CPSR_N (1u << 31u) +#define OS_CPU_ARM_BIT_CPSR_Z (1u << 30u) +#define OS_CPU_ARM_BIT_CPSR_C (1u << 29u) +#define OS_CPU_ARM_BIT_CPSR_V (1u << 28u) +#define OS_CPU_ARM_BIT_CPSR_Q (1u << 27u) +#define OS_CPU_ARM_BIT_CPSR_J (1u << 24u) +#define OS_CPU_ARM_MSK_CPSR_GE (0xF << 16u) + +#define OS_CPU_ARM_BIT_CPSR_E (1u << 9u) +#define OS_CPU_ARM_BIT_CPSR_A (1u << 8u) +#define OS_CPU_ARM_BIT_CPSR_I (1u << 7u) +#define OS_CPU_ARM_BIT_CPSR_F (1u << 6u) +#define OS_CPU_ARM_BIT_CPSR_T (1u << 5u) +#define OS_CPU_ARM_MSK_CPSR_MODE 0x1Fu +#define OS_CPU_ARM_BIT_CPSR_MODE_USER 0x10u +#define OS_CPU_ARM_BIT_CPSR_MODE_FIQ 0x11u +#define OS_CPU_ARM_BIT_CPSR_MODE_IRQ 0x12u +#define OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u +#define OS_CPU_ARM_BIT_CPSR_MODE_ABORT 0x17u +#define OS_CPU_ARM_BIT_CPSR_MODE_UNDEFINED 0x1Bu +#define OS_CPU_ARM_BIT_CPSR_MODE_SYSTEM 0x1Fu + +#define OS_CPU_ARM_BIT_FPEXC_EN (1u << 30u) + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_TASK_SW() OSCtxSw() +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr); } while (0) + +#else + +#define OS_ENTER_CRITICAL() do {cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do {OS_CPU_SR_Restore(cpu_sr);} while (0) + +#endif + +#endif + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +OS_CPU_EXT INT32U OS_CPU_ARM_DRegCnt; /* VFP/NEON register count */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ + OS_CPU_SR OS_CPU_SR_Save (void); + void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + + void OS_CPU_SR_INT_Dis (void); + void OS_CPU_SR_INT_En (void); + void OS_CPU_SR_FIQ_Dis (void); + void OS_CPU_SR_FIQ_En (void); + void OS_CPU_SR_IRQ_Dis (void); + void OS_CPU_SR_IRQ_En (void); + + void OSCtxSw (void); + void OSIntCtxSw (void); + void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + + void OS_CPU_ARM_ExceptUndefInstrHndlr (void); + void OS_CPU_ARM_ExceptSwiHndlr (void); + void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); + void OS_CPU_ARM_ExceptDataAbortHndlr (void); + void OS_CPU_ARM_ExceptIrqHndlr (void); + void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U src_id); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + + INT32U OS_CPU_ARM_DRegCntGet (void); + +#endif diff --git a/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-d16.asm b/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-d16.asm new file mode 100644 index 0000000..f5dd8dd --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-d16.asm @@ -0,0 +1,718 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + + +;******************************************************************************************************** +; +; ARMv7-R Port +; +; Filename : os_cpu_a_vfp-d16.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-R Cortex-R +; Mode : ARM or Thumb +; Toolchain : IAR EWARM V5.xx and higher +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + + ; Functions related to exception handling. + PUBLIC OS_CPU_ARM_ExceptUndefInstrHndlr + PUBLIC OS_CPU_ARM_ExceptSwiHndlr + PUBLIC OS_CPU_ARM_ExceptPrefetchAbortHndlr + PUBLIC OS_CPU_ARM_ExceptDataAbortHndlr + PUBLIC OS_CPU_ARM_ExceptIrqHndlr + PUBLIC OS_CPU_ARM_ExceptFiqHndlr + + PUBLIC OS_CPU_SR_INT_Dis + PUBLIC OS_CPU_SR_INT_En + PUBLIC OS_CPU_SR_FIQ_Dis + PUBLIC OS_CPU_SR_FIQ_En + PUBLIC OS_CPU_SR_IRQ_Dis + PUBLIC OS_CPU_SR_IRQ_En + + PUBLIC OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + RSEG CODE:CODE:NOROOT(2) + AAPCS INTERWORK + PRESERVE8 + REQUIRE8 + CODE32 + + +;******************************************************************************************************** +; FLOATING POINT REGISTER MACROS +;******************************************************************************************************** + +?OS_CPU_ARM_FP_REG_POP MACRO rx + POP {rx} + VMSR FPEXC, rx ; ... Pop new task's FPEXC + FLDMIAS SP!, {S0-S31} ; ... Pop new task's General-Purpose floating point registers. + POP {rx} + VMSR FPSCR, rx ; ... Pop new task's FPSCR. + ENDM + +?OS_CPU_ARM_FP_REG_PUSH MACRO rx + VMRS rx, FPSCR ; ... Save current FPSCR + PUSH {rx} ; ... Save general-purpose floating-point registers. + FSTMDBS SP!, {S0-S31} + VMRS rx, FPEXC ; ... Save Floating point exception register. + PUSH {rx} + ENDM + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + ?OS_CPU_ARM_FP_REG_POP R0 + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + ?OS_CPU_ARM_FP_REG_PUSH R0 ; Push FP context + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + ?OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + ?OS_CPU_ARM_FP_REG_POP R0 ; Pop new task's FP context. + + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ?OS_CPU_ARM_FP_REG_PUSH R1 + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ?OS_CPU_ARM_FP_REG_POP R0 + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #16 + BX LR + + END diff --git a/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-none.asm b/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-none.asm new file mode 100644 index 0000000..25692a0 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/IAR/os_cpu_a_vfp-none.asm @@ -0,0 +1,685 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + + +;******************************************************************************************************** +; +; ARMv7-R Port +; +; Filename : os_cpu_a_vfp-none.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARMv7-R Cortex-R +; Mode : ARM or Thumb +; Toolchain : IAR EWARM V5.xx and higher +;******************************************************************************************************** +; Note(s) : (1) See Note #2 of os_cpu.h for important informations about this file. +;******************************************************************************************************** + +;******************************************************************************************************** +; EXTERNAL REFERENCE +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + EXTERN OS_CPU_ExceptHndlr ; Chip Support/BSP specific exception handler. + + +;******************************************************************************************************** +; FUNCTIONS +;******************************************************************************************************** + + ; Functions declared in this file. + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + + ; Functions related to exception handling. + PUBLIC OS_CPU_ARM_ExceptUndefInstrHndlr + PUBLIC OS_CPU_ARM_ExceptSwiHndlr + PUBLIC OS_CPU_ARM_ExceptPrefetchAbortHndlr + PUBLIC OS_CPU_ARM_ExceptDataAbortHndlr + PUBLIC OS_CPU_ARM_ExceptIrqHndlr + PUBLIC OS_CPU_ARM_ExceptFiqHndlr + + PUBLIC OS_CPU_SR_INT_Dis + PUBLIC OS_CPU_SR_INT_En + PUBLIC OS_CPU_SR_FIQ_Dis + PUBLIC OS_CPU_SR_FIQ_En + PUBLIC OS_CPU_SR_IRQ_Dis + PUBLIC OS_CPU_SR_IRQ_En + + PUBLIC OS_CPU_ARM_DRegCntGet + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +OS_CPU_ARM_FPEXC_EN EQU 0x40000000 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + RSEG CODE:CODE:NOROOT(2) + AAPCS INTERWORK + PRESERVE8 + REQUIRE8 + CODE32 + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + + MRS R0, CPSR + CPSID IF ; Set IRQ & FIQ bits in CPSR to DISABLE all interrupts + DSB + BX LR ; DISABLED, return the original CPSR contents in R0 + +OS_CPU_SR_Restore ; See Note #2 + + DSB + MSR CPSR_c, R0 + BX LR + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to OS_STATE_OS_RUNNING, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + ; SWITCH TO HIGHEST PRIORITY TASK: + MOV32 R0, OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->StkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCurPtr = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->StkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + CLREX ; Clear exclusive monitor. + + MOV32 R0, OSTCBCur ; OSTCBCur->StkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCur = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCurPtr = OSTCBHighRdyPtr; +; d) SP = OSTCBHighRdyPtr->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCurPtr points to the OS_TCB of the task to suspend, +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + + BL OSTaskSwHook ; OSTaskSwHook(); + + MOV32 R0, OSPrioCur ; OSPrioCur = OSPrioHighRdy; + MOV32 R1, OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + MOV32 R0, OSTCBCur ; OSTCBCurPtr = OSTCBHighRdy; + MOV32 R1, OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdyPtr->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An exception can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An exception interrupts another exception. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R3, SP ; Save exception's stack pointer. + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + CLREX ; Clear exclusive monitor. + + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + MOV32 R3, OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_ExceptHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_ExceptHndlr_BreakExcept + + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakTask + + MOV32 R3, OSTCBCur ; OSTCBCurPtr->StkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + MOV32 R3, OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + BL OSIntExit + + + MOV32 R3, OSTCBCur ; SP = OSTCBCurPtr->StkPtr; + LDR R4, [R3] + LDR SP, [R4] + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakExcept + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + MOV32 R3, OSIntNesting ; OSIntNestingCtr--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +; EXCEPTION HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BreakNothing + + MOV R1, SP + AND R1, R1, #4 + SUB SP, SP, R1 + STMFD SP!, {R1, LR} + + ; EXECUTE EXCEPTION HANDLER: + BL OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + + LDMIA SP!, {R1, LR} + ADD SP, SP, R1 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_INT_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_IRQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + + DSB + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + + +OS_CPU_SR_FIQ_Dis + + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + DSB + BX LR + + +;******************************************************************************************************** +; VFP/NEON REGISTER COUNT +; +; Register Usage: R0 Double Register Count +;******************************************************************************************************** + +OS_CPU_ARM_DRegCntGet + + MOV R0, #0 + BX LR + + END diff --git a/Ports/ARM-Cortex-R/ARMv7-R/os_cpu_c.c b/Ports/ARM-Cortex-R/ARMv7-R/os_cpu_c.c new file mode 100644 index 0000000..f2be3b3 --- /dev/null +++ b/Ports/ARM-Cortex-R/ARMv7-R/os_cpu_c.c @@ -0,0 +1,624 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ARMv7-R Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARMv7-R Cortex-R +* Mode : ARM or Thumb +********************************************************************************************************** +*/ + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +* +* Note(s) : 1) ARM_MODE_ARM is the CPSR bit mask for ARM Mode +* 2) ARM_MODE_THUMB is the CPSR bit mask for THUMB Mode +* 3) ARM_SVC_MODE_THUMB is the CPSR bit mask for SVC MODE + THUMB Mode +* 4) ARM_SVC_MODE_ARM is the CPSR bit mask for SVC MODE + ARM Mode +********************************************************************************************************* +*/ + +#if (OS_CPU_ARM_ENDIAN_TYPE == OS_CPU_ARM_ENDIAN_LITTLE) +#define ARM_MODE_ARM 0x00000000u +#define ARM_MODE_THUMB 0x00000020u +#else /* Set bit 9 in big-endian mode. */ +#define ARM_MODE_ARM 0x00000200u +#define ARM_MODE_THUMB 0x00000220u +#endif + +#define ARM_SVC_MODE_THUMB (0x00000013u + ARM_MODE_THUMB) +#define ARM_SVC_MODE_ARM (0x00000013u + ARM_MODE_ARM) + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; + + /* Clear exception stack for stack checking. */ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk++ = (OS_STK)0; + } + /* Align the ISR stack to 8-bytes */ + OS_CPU_ExceptStkBase = (OS_STK *)&OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; + OS_CPU_ExceptStkBase = (OS_STK *)((OS_STK)(OS_CPU_ExceptStkBase) & 0xFFFFFFF8); + + OS_CPU_ARM_DRegCnt = OS_CPU_ARM_DRegCntGet(); + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0u + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) Interrupts are enabled when task starts executing. +* +* (2) All tasks run in SVC mode. +* +* (3) There are three differents stack frames depending on whether or not the Floating-Point (FP) co-processor +* is enabled or not. +* +* (a) The stack frame shown in the diagram is used when the FP coprocessor is present and +* OS_OPT_TASK_SAVE_FP is enabled. In this case the FP exception register, the FP registers and the +* FP control/status register are saved in the stack frame. +* +* (b) If the FP co-processor is present but the OS_OPT_TASK_SAVE_FP is not set, only the FP +* exception register is saved in the stack. +* +* (1) The FP exception register is saved twice in the stack frame to keep the 8-byte aligment. +* (See note #4.) +* +* +-----------+ +* | FPEXC | +* +-----------+ +* | S0 | +* +-----------+ +* . +* . +* . +* +-----------+ +* | S29 | +* +-----------+ +* | S30 | +* +-----------+ +-----------+ +* | S31 | | FPEXC | +* +-----------+ +-----------+ +* | FPSCR | | FPEXC | +* +-----------+ +-----------+ +-----------+ +* | CPSR | | CPSR | | CPSR | +* +-----------+ +-----------+ +-----------+ +* | R0 | | R0 | | R0 | +* +-----------+ +-----------+ +-----------+ +* . . . +* . . . +* . . . +* +-----------+ +-----------+ +-----------+ +* | R10 | | R10 | | R10 | +* +-----------+ +-----------+ +-----------+ +* | R11 | | R11 | | R11 | +* +-----------+ +-----------+ +-----------+ +* | R12 | | R12 | | R12 | +* +-----------+ +-----------+ +-----------+ +* | R14 (LR) | | R14 (LR) | | R14 (LR) | +* +-----------+ +-----------+ +-----------+ +* | PC = Task | | PC = Task | | PC = Task | +* +-----------+ +-----------+ +-----------+ +* +* (a) (b) (c) +* +* (4) The SP must be 8-byte aligned in conforming to the Procedure Call Standard for the ARM architecture +* +* (a) Section 2.1 of the ABI for the ARM Architecture Advisory Note. SP must be 8-byte aligned +* on entry to AAPCS-Conforming functions states : +* +* The Procedure Call Standard for the ARM Architecture [AAPCS] requires primitive +* data types to be naturally aligned according to their sizes (for size = 1, 2, 4, 8 bytes). +* Doing otherwise creates more problems than it solves. +* +* In return for preserving the natural alignment of data, conforming code is permitted +* to rely on that alignment. To support aligning data allocated on the stack, the stack +* pointer (SP) is required to be 8-byte aligned on entry to a conforming function. In +* practice this requirement is met if: +* +* (1) At each call site, the current size of the calling function's stack frame is a multiple of 8 bytes. +* This places an obligation on compilers and assembly language programmers. +* +* (2) SP is a multiple of 8 when control first enters a program. +* This places an obligation on authors of low level OS, RTOS, and runtime library +* code to align SP at all points at which control first enters +* a body of (AAPCS-conforming) code. +* +* In turn, this requires the value of SP to be aligned to 0 modulo 8: +* +* (3) By exception handlers, before calling AAPCS-conforming code. +* +* (4) By OS/RTOS/run-time system code, before giving control to an application. +* +* (b) Section 2.3.1 corrective steps from the the SP must be 8-byte aligned on entry +* to AAPCS-conforming functions advisory note also states. +* +* " This requirement extends to operating systems and run-time code for all architecture versions +* prior to ARMV7 and to the A, R and M architecture profiles thereafter. Special considerations +* associated with ARMV7M are discussed in section 2.3.3" +* +* (1) Even if the SP 8-byte aligment is not a requirement for the ARMv7M profile, the stack is aligned +* to 8-byte boundaries to support legacy execution enviroments. +* +* (c) Section 5.2.1.2 from the Procedure Call Standard for the ARM +* architecture states : "The stack must also conform to the following +* constraint at a public interface: +* +* (1) SP mod 8 = 0. The stack must be double-word aligned" +* +* (d) From the ARM Technical Support Knowledge Base. 8 Byte stack aligment. +* +* "8 byte stack alignment is a requirement of the ARM Architecture Procedure +* Call Standard [AAPCS]. This specifies that functions must maintain an 8 byte +* aligned stack address (e.g. 0x00, 0x08, 0x10, 0x18, 0x20) on all external +* interfaces. In practice this requirement is met if: +* +* (1) At each external interface, the current stack pointer +* is a multiple of 8 bytes. +* +* (2) Your OS maintains 8 byte stack alignment on its external interfaces +* e.g. on task switches" +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + INT32U task_addr; + INT32U fpu_reg_cnt; + INT8U i; + + + (void)opt; + + p_stk = ptos + 1u; /* Load stack pointer */ + p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF8u); /* Align stack pointer. */ + task_addr = (INT32U)task & ~1u; /* Mask off lower bit in case task is thumb mode */ + + *--p_stk = (OS_STK)task_addr; /* Entry Point */ + *--p_stk = (OS_STK)OS_TaskReturn; /* R14 (LR) */ + *--p_stk = (OS_STK)0x12121212u; /* R12 */ + *--p_stk = (OS_STK)0x11111111u; /* R11 */ + *--p_stk = (OS_STK)0x10101010u; /* R10 */ + *--p_stk = (OS_STK)0x09090909u; /* R9 */ + *--p_stk = (OS_STK)0x08080808u; /* R8 */ + *--p_stk = (OS_STK)0x07070707u; /* R7 */ + *--p_stk = (OS_STK)0x06060606u; /* R6 */ + *--p_stk = (OS_STK)0x05050505u; /* R5 */ + *--p_stk = (OS_STK)0x04040404u; /* R4 */ + *--p_stk = (OS_STK)0x03030303u; /* R3 */ + *--p_stk = (OS_STK)0x02020202u; /* R2 */ + *--p_stk = (OS_STK)0x01010101u; /* R1 */ + *--p_stk = (OS_STK)p_arg; /* R0 : argument */ + + + if (((INT32U)task & 0x01u) == 0x01u) { /* See if task runs in Thumb or ARM mode */ + *--p_stk = (OS_STK)(ARM_SVC_MODE_THUMB); /* Set Thumb mode. */ + } else { + *--p_stk = (OS_STK)(ARM_SVC_MODE_ARM); + } + + fpu_reg_cnt = OS_CPU_ARM_DRegCntGet(); + + if(fpu_reg_cnt != 0u) { + *--p_stk = (OS_STK)0; /* Initialize Floating point status & control register */ + /* Initialize general-purpose Floating point registers */ + for (i = 0u; i < fpu_reg_cnt * 2u; i++) { + *--p_stk = (OS_STK)0; + } + + *--p_stk = (OS_STK)(0x40000000); /* Initialize Floating-Point Exception Register (Enable)*/ + } + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +* 3) If debug variables are enabled, the current process id is saved into the context ID register +* found in the system control coprocessor. The Embedded Trace Macrocell (ETM) and the debug logic +* use this register. The ETM can broadcast its value to indicate the process that is running currently. +* +* (a) The proccess id is formed by concatenating the current task priority with the lower 24 bits +* from the current task TCB. +* +* 31 24 0 +* +---------------+---------------------+ +* | OSPrioHighRdy | OSTCBHighRdy[23..0] | +* +---------------+---------------------+ +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) + +{ +#if OS_CFG_DBG_EN > 0u + INT32U ctx_id; +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif + + OS_TRACE_TASK_SWITCHED_IN(OSTCBHighRdy); + +#if OS_CFG_DBG_EN > 0u + ctx_id = ((INT32U)(OSPrioHighRdy << 24u) ) + | ((INT32U)(OSTCBHighRdy ) & 0x00FFFFFF); + OS_CPU_ARM_CtxID_Set(ctx_id); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* GET NUMBER OF FREE ENTRIES IN EXCEPTION STACK +* +* Description : This function computes the number of free entries in the exception stack. +* +* Arguments : None. +* +* Returns : The number of free entries in the exception stack. +********************************************************************************************************* +*/ + +INT32U OS_CPU_ExceptStkChk (void) +{ + OS_STK *pchk; + INT32U nfree; + INT32U size; + + + nfree = 0; + size = OS_CPU_EXCEPT_STK_SIZE; + pchk = &OS_CPU_ExceptStk[0]; + while ((*pchk++ == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } + + return (nfree); +} diff --git a/Ports/ARM/Generic/GNU/os_cpu.h b/Ports/ARM/Generic/GNU/os_cpu.h new file mode 100644 index 0000000..afed4bd --- /dev/null +++ b/Ports/ARM/Generic/GNU/os_cpu.h @@ -0,0 +1,242 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Generic ARM Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : GNU GCC +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#ifndef OS_CPU_FPU_EN +#define OS_CPU_FPU_EN 0u /* HW floating point support disabled by default */ +#endif + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */ +#endif + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT +********************************************************************************************************* +*/ + +#define OS_CPU_INT_DIS_MEAS_EN 0u + + +/* +********************************************************************************************************* +* EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_RESET_VECT_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_RESET_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEuL + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018uL + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart();} +#define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr);} + +#else + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} + +#endif + +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OS_CPU_SR_INT_Dis (void); +void OS_CPU_SR_INT_En (void); +void OS_CPU_SR_FIQ_Dis (void); +void OS_CPU_SR_FIQ_En (void); +void OS_CPU_SR_IRQ_Dis (void); +void OS_CPU_SR_IRQ_En (void); + +#if OS_CPU_FPU_EN > 0u /* See OS_CPU_C.C */ +void OS_CPU_FP_Init (void); +void OS_CPU_FP_Restore (void *pblk); +void OS_CPU_FP_Save (void *pblk); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +void OS_CPU_InitExceptVectAddr (INT32U addr); +void OS_CPU_InitExceptVect (void); + +void OS_CPU_ARM_ExceptUndefInstrHndlr (void); +void OS_CPU_ARM_ExceptSwiHndlr (void); +void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); +void OS_CPU_ARM_ExceptDataAbortHndlr (void); +void OS_CPU_ARM_ExceptAddrAbortHndlr (void); +void OS_CPU_ARM_ExceptIrqHndlr (void); +void OS_CPU_ARM_ExceptFiqHndlr (void); + +void OS_CPU_ExceptHndlr (INT32U except_type); + +INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void); +void OS_CPU_IntDisMeasStart (void); +void OS_CPU_IntDisMeasStop (void); +INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#endif diff --git a/Ports/ARM/Generic/GNU/os_cpu_a.s b/Ports/ARM/Generic/GNU/os_cpu_a.s new file mode 100644 index 0000000..10354a6 --- /dev/null +++ b/Ports/ARM/Generic/GNU/os_cpu_a.s @@ -0,0 +1,846 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ Generic ARM Port +@ +@ Filename : os_cpu.h +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARM7 or ARM9 +@ Mode : ARM or Thumb +@ Toolchain : GNU GCC +@******************************************************************************************************** + +@******************************************************************************************************** +@ PUBLIC FUNCTIONS +@******************************************************************************************************** + @ External references. + .extern OSRunning + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntNesting + .extern OSIntExit + .extern OSTaskSwHook + + .extern OS_CPU_ExceptStkBase + .extern OS_CPU_ExceptStkPtr + + @ Functions declared in this file. + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + @ Functions related to exception handling. + .global OS_CPU_ARM_ExceptUndefInstrHndlr + .global OS_CPU_ARM_ExceptSwiHndlr + .global OS_CPU_ARM_ExceptPrefetchAbortHndlr + .global OS_CPU_ARM_ExceptDataAbortHndlr + .global OS_CPU_ARM_ExceptAddrAbortHndlr + .global OS_CPU_ARM_ExceptIrqHndlr + .global OS_CPU_ARM_ExceptFiqHndlr + + @ Functions related to interrupt enabling/disabling. + .global OS_CPU_SR_INT_Dis + .global OS_CPU_SR_INT_EN + .global OS_CPU_SR_FIQ_Dis + .global OS_CPU_SR_FIQ_En + .global OS_CPU_SR_IRQ_Dis + .global OS_CPU_SR_IRQ_En + + .extern OS_CPU_ExceptHndlr + + +@******************************************************************************************************** +@ EQUATES +@******************************************************************************************************** + + .equ OS_CPU_ARM_CONTROL_INT_DIS, 0xC0 @ Disable both FIQ and IRQ. + .equ OS_CPU_ARM_CONTROL_FIQ_DIS, 0x40 @ Disable FIQ. + .equ OS_CPU_ARM_CONTROL_IRQ_DIS, 0x80 @ Disable IRQ. + .equ OS_CPU_ARM_CONTROL_THUMB, 0x20 @ Set THUMB mode. + .equ OS_CPU_ARM_CONTROL_ARM, 0x00 @ Set ARM mode. + + .equ OS_CPU_ARM_MODE_MASK, 0x1F + .equ OS_CPU_ARM_MODE_USR, 0x10 + .equ OS_CPU_ARM_MODE_FIQ, 0x11 + .equ OS_CPU_ARM_MODE_IRQ, 0x12 + .equ OS_CPU_ARM_MODE_SVC, 0x13 + .equ OS_CPU_ARM_MODE_ABT, 0x17 + .equ OS_CPU_ARM_MODE_UND, 0x1B + .equ OS_CPU_ARM_MODE_SYS, 0x1F + + .equ OS_CPU_ARM_EXCEPT_RESET, 0x00 + .equ OS_CPU_ARM_EXCEPT_UNDEF_INSTR, 0x01 + .equ OS_CPU_ARM_EXCEPT_SWI, 0x02 + .equ OS_CPU_ARM_EXCEPT_PREFETCH_ABORT, 0x03 + .equ OS_CPU_ARM_EXCEPT_DATA_ABORT, 0x04 + .equ OS_CPU_ARM_EXCEPT_ADDR_ABORT, 0x05 + .equ OS_CPU_ARM_EXCEPT_IRQ, 0x06 + .equ OS_CPU_ARM_EXCEPT_FIQ, 0x07 + + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .code 32 + + + +@********************************************************************************************************* +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +@ void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +@ +@ +@ Note(s) : (1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ /* Allocate storage for CPU status register. */ +@ #if (OS_CRITICAL_METHOD == 3) +@ OS_CPU_SR os_cpu_sr; +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +@ : +@ : +@ OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +@ : +@ : +@ } +@********************************************************************************************************* + +OS_CPU_SR_Save: + MRS R0, CPSR + ORR R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R1 + BX LR @ Disabled, return the original CPSR contents in R0. + + +OS_CPU_SR_Restore: + MSR CPSR_c, R0 + BX LR + + +@********************************************************************************************************* +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note(s) : 1) OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to TRUE, +@ c) Switch to the highest priority task. +@********************************************************************************************************* + +OSStartHighRdy: + + @ Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + LDR R0, =OSTaskSwHook @ OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSRunning @ OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + + @ SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, =OSTCBHighRdy @ Get highest priority task TCB address, + LDR R0, [R0] @ Get stack pointer, + LDR SP, [R0] @ Switch to the new stack, + + LDR R0, [SP], #4 @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@********************************************************************************************************* +@ PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +@ +@ Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) Save the current task's context onto the current task's stack, +@ b) OSTCBCur->OSTCBStkPtr = SP; +@ c) OSTaskSwHook(); +@ d) OSPrioCur = OSPrioHighRdy; +@ e) OSTCBCur = OSTCBHighRdy; +@ f) SP = OSTCBHighRdy->OSTCBStkPtr; +@ g) Restore the new task's context from the new task's stack, +@ h) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCur points to the OS_TCB of the task to suspend, +@ OSTCBHighRdy points to the OS_TCB of the task to resume. +@********************************************************************************************************* + +OSCtxSw: + @ SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} @ Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} @ Push registers, + MRS R0, CPSR @ Push current CPSR, + TST LR, #1 @ See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB @ If yes, set the T-bit. + STMFD SP!, {R0} + + LDR R0, =OSTCBCur @ OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + LDR R0, =OSTaskSwHook @ OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSPrioCur @ OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur @ OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdy->OSTCBStkPtr; + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@********************************************************************************************************* +@ PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +@ +@ Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +@ +@ 2) The pseudo-code for OSCtxSw() is: +@ a) OSTaskSwHook(); +@ b) OSPrioCur = OSPrioHighRdy; +@ c) OSTCBCur = OSTCBHighRdy; +@ d) SP = OSTCBHighRdy->OSTCBStkPtr; +@ e) Restore the new task's context from the new task's stack, +@ f) Return to new task's code. +@ +@ 3) Upon entry: +@ OSTCBCur points to the OS_TCB of the task to suspend, +@ OSTCBHighRdy points to the OS_TCB of the task to resume. +@********************************************************************************************************* + +OSIntCtxSw: + LDR R0, =OSTaskSwHook @ OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSPrioCur @ OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur @ OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] @ SP = OSTCBHighRdy->OSTCBStkPtr; + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@******************************************************************************************************** +@ EXCEPTION HANDLERS +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ UNDEFINED INSTRUCTION EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R12, LR} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR @ Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + +@******************************************************************************************************** +@ SOFTWARE INTERRUPT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr: + @ LR offset to return from this exception: 0. + STMFD SP!, {R0-R12, LR} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI @ Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + +@******************************************************************************************************** +@ PREFETCH ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R12, LR} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + +@******************************************************************************************************** +@ DATA ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R12, LR} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + +@******************************************************************************************************** +@ ADDRESS ABORT EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr: + SUB LR, LR, #8 @ LR offset to return from this exception: -8. + STMFD SP!, {R0-R12, LR} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT @ Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + +@******************************************************************************************************** +@ FAST INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 Return PC +@******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R12, LR} @ Push working registers. + MOV R2, LR @ Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ @ Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr @ Branch to global exception handler. + +@******************************************************************************************************** +@******************************************************************************************************** +@ GLOBAL EXCEPTION HANDLER +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ GLOBAL EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Old CPU mode +@ +@ Note(s) : 1) An exception can occur in four different circumstances; in each of these, the +@ SVC stack pointer will point to a different entity : +@ +@ a) CONDITION: An exception occurs before the OS has been fully initialized. +@ SVC STACK: Should point to a stack initialized by the application's startup code. +@ +@ b) CONDITION: An exception interrupts a task. +@ SVC STACK: Should point to task stack. +@ +@ c) CONDITION: An exception interrupts another exception, or an IRQ before it +@ switches to the exception stack. +@ SVC STACK: Should point to location in an exception-mode stack. +@ +@ d) CONDITION: An exception interrupts an an IRQ after it switches to the exception +@ stack, 'OS_CPU_ExceptStk[]'. +@ SVC STACK: Should point to location in an exception stack, 'OS_CPU_ExceptStk[]'. +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr: + MRS R1, SPSR @ Save CPSR (i.e. exception's SPSR). + + @ DETERMINE IF WE INTERRUPTED A TASK/IRQ OR ANOTHER LOWER PRIORITY EXCEPTION: + @ SPSR.Mode = SVC : task or IRQ handled in SVC mode, + @ SPSR.Mode = FIQ, IRQ, ABT, UND : other exceptions, + @ SPSR.Mode = USR : *unsupported state*. + AND R3, R1, #OS_CPU_ARM_MODE_MASK + CMP R3, #OS_CPU_ARM_MODE_SVC + BNE OS_CPU_ARM_ExceptHndlr_BrkExcept + +@******************************************************************************************************** +@ EXCEPTION HANDLER: TASK INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Exception's CPSR +@ R4 Exception's SP +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkTask: + MRS R3, CPSR @ Save exception's CPSR. + MOV R4, SP @ Save exception's stack pointer. + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ SAVE TASK'S CONTEXT ONTO TASK'S STACK: + STMFD SP!, {R2} @ Push task's PC, + STMFD SP!, {LR} @ Push task's LR, + STMFD SP!, {R5-R12} @ Push task's R12-R5, + LDMFD R4!, {R5-R9} @ Move task's R4-R0 from exception stack to task's stack. + STMFD SP!, {R5-R9} + STMFD SP!, {R1} @ Push task's CPSR (i.e. exception SPSR). + + @ if (OSRunning == 1) + LDR R1, =OSRunning + LDRB R1, [R1] + CMP R1, #1 + BNE OS_CPU_ARM_ExceptHndlr_BrkTask_1 + + @ HANDLE NESTING COUNTER: + LDR R1, =OSIntNesting @ OSIntNesting++; + LDRB R2, [R1] + ADD R2, R2, #1 + STRB R2, [R1] + + CMP R2, #1 @ if (OSIntNesting > 1) + BNE OS_CPU_ARM_ExceptHndlr_BrkIRQ @ IRQ has been interrupted. + + LDR R1, =OSTCBCur @ OSTCBCur->OSTCBStkPtr = SP; + LDR R2, [R1] + STR SP, [R2] + +OS_CPU_ARM_ExceptHndlr_BrkTask_1: + MSR CPSR_cxsf, R3 @ RESTORE INTERRUPTED MODE. + + @ EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R1 + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(14 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ Call OSIntExit(). This call MAY never return if a ready + @ task with higher priority than the interrupted one is + @ found. + LDR R0, =OSIntExit + MOV LR, PC + BX R0 + + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + +@******************************************************************************************************** +@ EXCEPTION HANDLER: EXCEPTION INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkExcept: + STMFD SP!, {R1} @ Push exception's SPSR. + + MRS R3, CPSR @ Push exception's CPSR. + STMFD SP!, {R3} + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting @ OSIntNesting++; + LDRB R4, [R2] + ADD R4, R4, #1 + STRB R4, [R2] + + MSR CPSR_cxsf, R3 @ RESTORE INTERRUPTED MODE. + + @ EXECUTE EXCEPTION HANDLER: + LDR R2, =OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R2 + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting @ OSIntNesting--; + LDRB R4, [R2] + SUB R4, R4, #1 + STRB R4, [R2] + + LDMFD SP!, {R3} + MSR CPSR_cxsf, R3 @ RESTORE INTERRUPTED MODE. + + @ RESTORE INTERRUPTED EXCEPTIONS' CONTEXT: + LDMFD SP!, {R0} @ Pop exception's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, PC}^ @ Pull working registers and return from exception. + +@******************************************************************************************************** +@ EXCEPTION HANDLER: IRQ INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkIRQ: + MSR CPSR_cxsf, R3 @ RESTORE INTERRUPTED MODE. + + @ EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R1 + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring IRQ context. + ADD SP, SP, #(14 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting @ OSIntNesting--; + LDRB R4, [R2] + SUB R4, R4, #1 + STRB R4, [R2] + + @ RESTORE IRQ'S CONTEXT: + LDMFD SP!, {R0} @ Pop IRQ's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop IRQ's context. + +@******************************************************************************************************** +@******************************************************************************************************** +@ IRQ HANDLER +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ INTERRUPT REQUEST EXCEPTION HANDLER +@ +@ Register Usage: R0 Exception Type +@ R1 Exception's SPSR +@ R2 Return PC +@ R3 Exception's SP +@ +@ Note(s) : 1) An IRQ can occur in three different circumstances; in each of these, the +@ SVC stack pointer will point to a different entity : +@ +@ a) CONDITION: An exception occurs before the OS has been fully initialized. +@ SVC STACK: Should point to a stack initialized by the application's startup code. +@ STK USAGE: Interrupted context -- SVC stack. +@ Exception -- SVC stack. +@ Nested exceptions -- SVC stack. +@ +@ b) CONDITION: An IRQ interrupts a task. +@ SVC STACK: Should point to task stack. +@ STK USAGE: Interrupted context -- Task stack. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@ +@ c) CONDITION: An IRQ interrupts another IRQ. +@ SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +@ STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +@ Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +@******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr: + SUB LR, LR, #4 @ LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} @ Push working registers. + + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ @ Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + MRS R1, SPSR @ Save CPSR (i.e. exception's SPSR). + MOV R2, LR @ Save link register. + MOV R3, SP @ Save exception's stack pointer. + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ SAVE CONTEXT ONTO SVC STACK: + STMFD SP!, {R2} @ Push task's PC, + STMFD SP!, {LR} @ Push task's LR, + STMFD SP!, {R4-R12} @ Push task's R12-R4, + LDMFD R3!, {R5-R8} @ Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} @ Push task's CPSR (i.e. exception SPSR). + + @ if (OSRunning == 1) + LDR R3, =OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_IRQHndlr_BrkNothing + + @ HANDLE NESTING COUNTER: + LDR R3, =OSIntNesting @ OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 @ if (OSIntNesting == 1) + BNE OS_CPU_ARM_IRQHndlr_BreakIRQ + +@******************************************************************************************************** +@ IRQ HANDLER: TASK INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakTask: + LDR R3, =OSTCBCur @ OSTCBCur->OSTCBStkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, =OS_CPU_ExceptStkBase @ Switch to exception stack. + LDR SP, [R3] + + @ EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R1 + + @ Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ) + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ Call OSIntExit(). This call MAY never return if a ready + @ task with higher priority than the interrupted one is + @ found. + LDR R0, =OSIntExit + MOV LR, PC + BX R0 + + LDR R3, =OSTCBCur @ SP = OSTCBCur->OSTCBStkPtr; + LDR R4, [R3] + LDR SP, [R4] + @ RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} @ Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pop new task's context. + + +@******************************************************************************************************** +@ IRQ HANDLER: IRQ INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakIRQ: + LDR R3, =OS_CPU_ExceptStkPtr @ OS_CPU_ExceptStkPtr = SP; + STR SP, [R3] + + @ EXECUTE EXCEPTION HANDLER: + LDR R3, =OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R3 + + @ Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ) + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ HANDLE NESTING COUNTER: + LDR R3, =OSIntNesting @ OSIntNesting--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + +@******************************************************************************************************** +@ IRQ HANDLER: 'NOTHING' INTERRUPTED +@ +@ Register Usage: R0 Exception Type +@ R1 +@ R2 +@ R3 +@******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakNothing: + @ EXECUTE EXCEPTION HANDLER: + LDR R3, =OS_CPU_ExceptHndlr @ OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R3 + + @ Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ) + + @ Adjust exception stack pointer. This is needed because + @ exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + @ Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + @ RESTORE OLD CONTEXT: + LDMFD SP!, {R0} @ Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ @ Pull working registers and return from exception. + +@******************************************************************************************************** +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +@******************************************************************************************************** +@******************************************************************************************************** + +@******************************************************************************************************** +@ ENABLE & DISABLE INTERRUPTS +@ +@ Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +@ interrupt source has been cleared. This function will enable IRQs and FIQs so that +@ nesting can occur. +@ +@ 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +@******************************************************************************************************** + +OS_CPU_SR_INT_En: + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_INT_Dis: + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS @ Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + BX LR + +@******************************************************************************************************** +@ ENABLE & DISABLE IRQs +@ +@ Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +@ interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +@******************************************************************************************************** + +OS_CPU_SR_IRQ_En: + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_IRQ_Dis: + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS @ Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + BX LR + +@******************************************************************************************************** +@ ENABLE & DISABLE FIQs +@ +@ Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +@ interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +@ can occur. +@ +@ 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +@******************************************************************************************************** + +OS_CPU_SR_FIQ_En: + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_FIQ_Dis: + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS @ Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + BX LR + + + .ltorg diff --git a/Ports/ARM/Generic/GNU/os_cpu_c.c b/Ports/ARM/Generic/GNU/os_cpu_c.c new file mode 100644 index 0000000..4a64ab5 --- /dev/null +++ b/Ports/ARM/Generic/GNU/os_cpu_c.c @@ -0,0 +1,596 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Generic ARM Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : GNU GCC +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +* +* Note(s) : 1) ARM_MODE_ARM is the CPSR bit mask for ARM Mode +* 2) ARM_MODE_THUMB is the CPSR bit mask for THUMB Mode +* 3) ARM_SVC_MODE_THUMB is the CPSR bit mask for SVC MODE + THUMB Mode +* 4) ARM_SVC_MODE_ARM is the CPSR bit mask for SVC MODE + ARM Mode + 5) OS_NTASKS_FP establishes the number of tasks capable of supporting floating-point. One +* task is removed for the idle task because it doesn't do floating-point at all. +* 6) OS_FP_STORAGE_SIZE currently allocates 128 bytes of storage in order to accomodate +* thirty-two single-precision 32-bit, or sixteen double-precision 64-bit VFP registers. +********************************************************************************************************* +*/ + +#define ARM_MODE_ARM 0x00000000u +#define ARM_MODE_THUMB 0x00000020u + +#define ARM_SVC_MODE_THUMB (0x00000013uL + ARM_MODE_THUMB) +#define ARM_SVC_MODE_ARM (0x00000013uL + ARM_MODE_ARM) + +#define OS_NTASKS_FP (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u) +#define OS_FP_STORAGE_SIZE 128u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + +#if OS_CPU_FPU_EN > 0u +static OS_MEM *OSFPPartPtr; /* Ptr to memory partition for storing FPU registers */ +static INT32U OSFPPart[OS_NTASKS_FP][OS_FP_STORAGE_SIZE / sizeof(INT32U)]; +#endif + + +/* +********************************************************************************************************* +* INITIALIZE FP SUPPORT +* +* Description: This function initializes the memory partition used to save FPU registers +* during a context switch. This function MUST be called AFTER calling +* OSInit(). OS_CPU_FPU_EN must be defined > 0 in order to compile FPU support into the +* build. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) Tasks that are to use FP support MUST be created with OSTaskCreateExt(). +* 2) For the ARM VFP, 128 bytes are required to save the VFP context. +* The INT32U data type is used to ensure that storage is aligned on a 32-bit boundary. +* 3) If you need to perform floating point operations from within the OSStatTaskHook(), +* then you must change the 'Options' attribute for OSTaskCreatExt() when creating +* the statistics task. This only applies if OS_TaskStat() was created with OSTaskCreateExt(). +********************************************************************************************************* +*/ + +#if OS_CPU_FPU_EN > 0u +void OS_CPU_FP_Init (void) +{ + INT8U err; +#if (OS_TASK_STAT_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) + OS_TCB *ptcb; + void *pblk; +#endif + + + OSFPPartPtr = OSMemCreate(&OSFPPart[0][0], OS_NTASKS_FP, OS_FP_STORAGE_SIZE, &err); + +#if (OS_TASK_STAT_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)/* CHANGE 'OPTIONS' for OS_TaskStat() */ + ptcb = OSTCBPrioTbl[OS_TASK_STAT_PRIO]; + ptcb->OSTCBOpt |= OS_TASK_OPT_SAVE_FP; /* Allow floating-point support for Stat task*/ + pblk = OSMemGet(OSFPPartPtr, &err); /* Get storage for VFP registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; + + /* Clear exception stack for stack checking.*/ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk = (OS_STK)0; + } + +#if OS_STK_GROWTH == 1u + OS_CPU_ExceptStkBase = &OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE - 1u]; +#else + OS_CPU_ExceptStkBase = &OS_CPU_ExceptStk[0]; +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0u + OS_CPU_IntDisMeasInit(); +#endif + +#if OS_CPU_FPU_EN > 0u + OS_CPU_FP_Init(); /* Initialize support for VFP register save / restore */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_CPU_FPU_EN > 0u + INT8U err; + void *pblk; +#endif + + +#if OS_CPU_FPU_EN > 0u + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task needs FP support */ + pblk = OSMemGet(OSFPPartPtr, &err); /* Yes, Get storage for VFP registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_CPU_FPU_EN > 0u + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task had FP support */ + if (ptcb->OSTCBExtPtr != (void *)0) { /* Yes, OSTCBExtPtr must not be NULL */ + OSMemPut(OSFPPartPtr, ptcb->OSTCBExtPtr); /* Return memory block to free pool */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SVC mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + INT32U task_addr; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + task_addr = (INT32U)task & ~1u; /* Mask off lower bit in case task is thumb mode */ + *(stk) = (INT32U)task_addr; /* Entry Point */ + *(--stk) = (INT32U)OS_TaskReturn; /* R14 (LR) */ + *(--stk) = (INT32U)0x12121212uL; /* R12 */ + *(--stk) = (INT32U)0x11111111uL; /* R11 */ + *(--stk) = (INT32U)0x10101010uL; /* R10 */ + *(--stk) = (INT32U)0x09090909uL; /* R9 */ + *(--stk) = (INT32U)0x08080808uL; /* R8 */ + *(--stk) = (INT32U)0x07070707uL; /* R7 */ + *(--stk) = (INT32U)0x06060606uL; /* R6 */ + *(--stk) = (INT32U)0x05050505uL; /* R5 */ + *(--stk) = (INT32U)0x04040404uL; /* R4 */ + *(--stk) = (INT32U)0x03030303uL; /* R3 */ + *(--stk) = (INT32U)0x02020202uL; /* R2 */ + *(--stk) = (INT32U)0x01010101uL; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + if ((INT32U)task & 0x01u) { /* See if task runs in Thumb or ARM mode */ + *(--stk) = (INT32U)ARM_SVC_MODE_THUMB; /* CPSR (Enable IRQ and FIQ interrupts, THUMB-mode) */ + } else { + *(--stk) = (INT32U)ARM_SVC_MODE_ARM; /* CPSR (Enable IRQ and FIQ interrupts, ARM-mode) */ + } + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_CPU_FPU_EN > 0u + void *pblk; +#endif + +#if OS_CPU_FPU_EN > 0u /* Save VFP context of preempted task */ + if (OSRunning == OS_TRUE) { /* Don't save on OSStart()! */ + if (OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task used FP */ + pblk = OSTCBCur->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } + } + } + /* Restore VFP context of new task */ + if (OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if new task uses FP */ + pblk = OSTCBHighRdy->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OS_CPU_FP_Restore(pblk); /* Get contents of VFP registers */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE EXCEPTION VECTORS +* +* Description : This function initialize exception vectors to the default handlers. +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OS_CPU_InitExceptVect (void) +{ + (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptUndefInstrHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptSwiHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptPrefetchAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptDataAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptAddrAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptIrqHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptFiqHndlr; +} + + +/* +********************************************************************************************************* +* GET NUMBER OF FREE ENTRIES IN EXCEPTION STACK +* +* Description : This function computes the number of free entries in the exception stack. +* +* Arguments : None. +* +* Returns : The number of free entries in the exception stack. +********************************************************************************************************* +*/ + +INT32U OS_CPU_ExceptStkChk (void) +{ + OS_STK *pchk; + INT32U nfree; + INT32U size; + + + nfree = 0; + size = OS_CPU_EXCEPT_STK_SIZE; +#if OS_STK_GROWTH == 1u + pchk = &OS_CPU_ExceptStk[0]; + while ((*pchk++ == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } +#else + pchk = &OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE - 1u]; + while ((*pchk-- == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } +#endif + return (nfree); +} diff --git a/Ports/ARM/Generic/GNU/os_cpu_fpu_a.s b/Ports/ARM/Generic/GNU/os_cpu_fpu_a.s new file mode 100644 index 0000000..b809885 --- /dev/null +++ b/Ports/ARM/Generic/GNU/os_cpu_fpu_a.s @@ -0,0 +1,81 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ Generic ARM Port +@ VFP SUPPORT +@ +@ Filename : os_cpu.h +@ Version : V2.93.00 +@******************************************************************************************************** +@ For : ARM7 or ARM9 +@ Mode : ARM or Thumb +@ Toolchain : GNU GCC +@******************************************************************************************************** + + +@******************************************************************************************************** +@ PUBLIC FUNCTIONS +@******************************************************************************************************** + + .global OS_CPU_FP_Restore + .global OS_CPU_FP_Save + +@******************************************************************************************************** +@ CODE GENERATION DIRECTIVES +@******************************************************************************************************** + + .code 32 + +@********************************************************************************************************* +@ RESTORE VFP REGISTERS +@ void OS_CPU_FP_Restore(void *pblk) +@ +@ Description : This function is called to restore the contents of the VFP registers during a context +@ switch. It is assumed that a pointer to a storage area for the VFP registers is placed +@ in the task's TCB (i.e. .OSTCBExtPtr). +@ +@ Arguments : pblk is passed to this function in R0 when called. +@ +@ Notes : Floating point math should NEVER be performed within an ISR as this will corrupt +@ the state of the VFP registers for the last VFP task that ran. Instead, all floating +@ point math should be performed within floating point enabled tasks ONLY. +@********************************************************************************************************* + +OS_CPU_FP_Restore: + FLDMIAS R0!, {S0-S31} @ Restore the VFP registers from pblk + BX LR @ Return to calling function + +@********************************************************************************************************* +@ SAVE VFP REGISTERS +@ void OS_CPU_FP_Save(void *pblk) +@ +@ Description : This function is called to save the contents of the VFP registers during a context +@ switch. It is assumed that a pointer to a storage area for the VFP registers is placed +@ in the task's TCB (i.e. .OSTCBExtPtr). +@ +@ Arguments : pblk is passed to this function in R0 when called. +@ +@ Notes : Floating point math should NEVER be performed within an ISR as this will corrupt +@ the state of the VFP registers for the last VFP task that ran. Instead, all floating +@ point math should be performed within floating point enabled tasks ONLY. +@********************************************************************************************************* + +OS_CPU_FP_Save: + FSTMIAS R0!, {S0-S31} @ Save the VFP registers in pblk + BX LR @ Return to calling function + + + .ltorg diff --git a/Ports/ARM/Generic/GNU/os_dbg.c b/Ports/ARM/Generic/GNU/os_dbg.c new file mode 100644 index 0000000..195eee8 --- /dev/null +++ b/Ports/ARM/Generic/GNU/os_dbg.c @@ -0,0 +1,321 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* Generic ARM Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : GNU GCC +********************************************************************************************************* +*/ + +#include + + /* The following #define could tell the compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM/Generic/IAR/os_cpu.h b/Ports/ARM/Generic/IAR/os_cpu.h new file mode 100644 index 0000000..ab0ab6d --- /dev/null +++ b/Ports/ARM/Generic/IAR/os_cpu.h @@ -0,0 +1,250 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Generic ARM Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : IAR's EWARM V4.11a and higher +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#ifndef OS_CPU_FPU_EN +#define OS_CPU_FPU_EN 0u /* HW floating point support disabled by default */ +#endif + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */ +#endif + +#ifndef OS_CPU_ARM_DCC_EN +#define OS_CPU_ARM_DCC_EN 0u /* DCC support disabled by default */ +#endif + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT +********************************************************************************************************* +*/ + +#define OS_CPU_INT_DIS_MEAS_EN 0u + + +/* +********************************************************************************************************* +* EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_RESET_VECT_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_RESET_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEuL + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018uL + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart();} +#define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr);} + +#else + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} + +#endif + +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +__arm OS_CPU_SR OS_CPU_SR_Save (void); +__arm void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +__arm void OS_CPU_SR_INT_Dis (void); +__arm void OS_CPU_SR_INT_En (void); +__arm void OS_CPU_SR_FIQ_Dis (void); +__arm void OS_CPU_SR_FIQ_En (void); +__arm void OS_CPU_SR_IRQ_Dis (void); +__arm void OS_CPU_SR_IRQ_En (void); + +#if OS_CPU_FPU_EN > 0u /* See OS_CPU_C.C */ + void OS_CPU_FP_Init (void); +__arm void OS_CPU_FP_Restore (void *pblk); +__arm void OS_CPU_FP_Save (void *pblk); +#endif + +__arm void OSCtxSw (void); +__arm void OSIntCtxSw (void); +__arm void OSStartHighRdy (void); + + void OS_CPU_InitExceptVect (void); + void OS_CPU_InitExceptVectAddr (INT32U addr); + +__arm void OS_CPU_ARM_ExceptUndefInstrHndlr (void); +__arm void OS_CPU_ARM_ExceptSwiHndlr (void); +__arm void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); +__arm void OS_CPU_ARM_ExceptDataAbortHndlr (void); +__arm void OS_CPU_ARM_ExceptAddrAbortHndlr (void); +__arm void OS_CPU_ARM_ExceptIrqHndlr (void); +__arm void OS_CPU_ARM_ExceptFiqHndlr (void); + + void OS_CPU_ExceptHndlr (INT32U except_type); + + INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + void OS_CPU_IntDisMeasInit (void); + void OS_CPU_IntDisMeasStart (void); + void OS_CPU_IntDisMeasStop (void); + INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + void OSDCC_Handler (void); +#endif + +#endif diff --git a/Ports/ARM/Generic/IAR/os_cpu_a.asm b/Ports/ARM/Generic/IAR/os_cpu_a.asm new file mode 100644 index 0000000..77555dd --- /dev/null +++ b/Ports/ARM/Generic/IAR/os_cpu_a.asm @@ -0,0 +1,838 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Generic ARM Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARM7 or ARM9 +; Mode : ARM or Thumb +; Toolchain : IAR's EWARM V4.11a and higher +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + ; External references. + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN OSTaskSwHook + + EXTERN OS_CPU_ExceptStkBase + EXTERN OS_CPU_ExceptStkPtr + + ; Functions declared in this file. + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + + ; Functions related to exception handling. + PUBLIC OS_CPU_ARM_ExceptUndefInstrHndlr + PUBLIC OS_CPU_ARM_ExceptSwiHndlr + PUBLIC OS_CPU_ARM_ExceptPrefetchAbortHndlr + PUBLIC OS_CPU_ARM_ExceptDataAbortHndlr + PUBLIC OS_CPU_ARM_ExceptAddrAbortHndlr + PUBLIC OS_CPU_ARM_ExceptIrqHndlr + PUBLIC OS_CPU_ARM_ExceptFiqHndlr + + ; Functions related to interrupt enabling/disabling. + PUBLIC OS_CPU_SR_INT_Dis + PUBLIC OS_CPU_SR_INT_En + PUBLIC OS_CPU_SR_FIQ_Dis + PUBLIC OS_CPU_SR_FIQ_En + PUBLIC OS_CPU_SR_IRQ_Dis + PUBLIC OS_CPU_SR_IRQ_En + + EXTERN OS_CPU_ExceptHndlr + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + MRS R0, CPSR + ORR R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R1 + BX LR ; Disabled, return the original CPSR contents in R0. + + +OS_CPU_SR_Restore + MSR CPSR_c, R0 + BX LR + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + LDR R0, =OSTaskSwHook ; OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + + ; SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, =OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + LDR R0, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + LDR R0, =OSTaskSwHook ; OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + LDR R0, =OSTaskSwHook ; OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +;******************************************************************************************************** +; EXCEPTION HANDLERS +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Old CPU mode +; +; Note(s) : 1) An exception can occur in four different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; +; c) CONDITION: An exception interrupts another exception, or an IRQ before it +; switches to the exception stack. +; SVC STACK: Should point to location in an exception-mode stack. +; +; d) CONDITION: An exception interrupts an an IRQ after it switches to the exception +; stack, 'OS_CPU_ExceptStk[]'. +; SVC STACK: Should point to location in an exception stack, 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + + ; DETERMINE IF WE INTERRUPTED A TASK/IRQ OR ANOTHER LOWER PRIORITY EXCEPTION: + ; SPSR.Mode = SVC : task or IRQ handled in SVC mode, + ; SPSR.Mode = FIQ, IRQ, ABT, UND : other exceptions, + ; SPSR.Mode = USR : *unsupported state*. + AND R3, R1, #OS_CPU_ARM_MODE_MASK + CMP R3, #OS_CPU_ARM_MODE_SVC + BNE OS_CPU_ARM_ExceptHndlr_BrkExcept + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's CPSR +; R4 Exception's SP +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkTask + MRS R3, CPSR ; Save exception's CPSR. + MOV R4, SP ; Save exception's stack pointer. + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; SAVE TASK'S CONTEXT ONTO TASK'S STACK: + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R5-R12} ; Push task's R12-R5, + LDMFD R4!, {R5-R9} ; Move task's R4-R0 from exception stack to task's stack. + STMFD SP!, {R5-R9} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + LDR R1, =OSRunning + LDRB R1, [R1] + CMP R1, #1 + BNE OS_CPU_ARM_ExceptHndlr_BrkTask_1 + + ; HANDLE NESTING COUNTER: + LDR R1, =OSIntNesting ; OSIntNesting++; + LDRB R2, [R1] + ADD R2, R2, #1 + STRB R2, [R1] + + CMP R2, #1 ; if (OSIntNesting > 1) + BNE OS_CPU_ARM_ExceptHndlr_BrkIRQ ; IRQ has been interrupted. + + LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R2, [R1] + STR SP, [R2] + +OS_CPU_ARM_ExceptHndlr_BrkTask_1 + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R1 + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(14 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + LDR R0, =OSIntExit + MOV LR, PC + BX R0 + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkExcept + STMFD SP!, {R1} ; Push exception's SPSR. + + MRS R3, CPSR ; Push exception's CPSR. + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + STMFD SP!, {R3} + ; HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting ; OSIntNesting++; + LDRB R4, [R2] + ADD R4, R4, #1 + STRB R4, [R2] + + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; EXECUTE EXCEPTION HANDLER: + LDR R2, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R2 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting ; OSIntNesting--; + LDRB R4, [R2] + SUB R4, R4, #1 + STRB R4, [R2] + + LDMFD SP!, {R3} + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; RESTORE INTERRUPTED EXCEPTIONS' CONTEXT: + LDMFD SP!, {R0} ; Pop exception's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, PC}^ ; Pull working registers and return from exception. + +;******************************************************************************************************** +; EXCEPTION HANDLER: IRQ INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkIRQ + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R1 + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring IRQ context. + ADD SP, SP, #(14 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting ; OSIntNesting--; + LDRB R4, [R2] + SUB R4, R4, #1 + STRB R4, [R2] + + ; RESTORE IRQ'S CONTEXT: + LDMFD SP!, {R0} ; Pop IRQ's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop IRQ's context. + +;******************************************************************************************************** +;******************************************************************************************************** +; IRQ HANDLER +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An IRQ can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An IRQ interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An IRQ interrupts another IRQ. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R2, LR ; Save link register. + MOV R3, SP ; Save exception's stack pointer. + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; SAVE CONTEXT ONTO SVC STACK: + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + LDR R3, =OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_IRQHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + LDR R3, =OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_IRQHndlr_BreakIRQ + +;******************************************************************************************************** +; IRQ HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakTask + LDR R3, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, =OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R1 + + ; Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ) + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + LDR R0, =OSIntExit + MOV LR, PC + BX R0 + + LDR R3, =OSTCBCur ; SP = OSTCBCur->OSTCBStkPtr; + LDR R4, [R3] + LDR SP, [R4] + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + + +;******************************************************************************************************** +; IRQ HANDLER: IRQ INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakIRQ + LDR R3, =OS_CPU_ExceptStkPtr ; OS_CPU_ExceptStkPtr = SP; + STR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + LDR R3, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R3 + + ; Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ) + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R3, =OSIntNesting ; OSIntNesting--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + +;******************************************************************************************************** +; IRQ HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakNothing + ; EXECUTE EXCEPTION HANDLER: + LDR R3, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R3 + + ; Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_IRQ) + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS | OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_INT_Dis + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + BX LR + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_IRQ_Dis + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + BX LR + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_FIQ_Dis + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + BX LR + + + END diff --git a/Ports/ARM/Generic/IAR/os_cpu_c.c b/Ports/ARM/Generic/IAR/os_cpu_c.c new file mode 100644 index 0000000..7528963 --- /dev/null +++ b/Ports/ARM/Generic/IAR/os_cpu_c.c @@ -0,0 +1,639 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Generic ARM Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : IAR's EWARM V4.11a and higher +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +* +* Note(s) : 1) ARM_MODE_ARM is the CPSR bit mask for ARM Mode +* 2) ARM_MODE_THUMB is the CPSR bit mask for THUMB Mode +* 3) ARM_SVC_MODE_THUMB is the CPSR bit mask for SVC MODE + THUMB Mode +* 4) ARM_SVC_MODE_ARM is the CPSR bit mask for SVC MODE + ARM Mode + 5) OS_NTASKS_FP establishes the number of tasks capable of supporting floating-point. One +* task is removed for the idle task because it doesn't do floating-point at all. +* 6) OS_FP_STORAGE_SIZE currently allocates 128 bytes of storage in order to accomodate +* thirty-two single-precision 32-bit, or sixteen double-precision 64-bit VFP registers. +********************************************************************************************************* +*/ + +#define ARM_MODE_ARM 0x00000000u +#define ARM_MODE_THUMB 0x00000020u + +#define ARM_SVC_MODE_THUMB (0x00000013uL + ARM_MODE_THUMB) +#define ARM_SVC_MODE_ARM (0x00000013uL + ARM_MODE_ARM) + +#define OS_NTASKS_FP (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u) +#define OS_FP_STORAGE_SIZE 128u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + +#if OS_CPU_FPU_EN > 0u +static OS_MEM *OSFPPartPtr; /* Ptr to memory partition for storing FPU registers */ +static INT32U OSFPPart[OS_NTASKS_FP][OS_FP_STORAGE_SIZE / sizeof(INT32U)]; +#endif + + +/* +********************************************************************************************************* +* INITIALIZE FP SUPPORT +* +* Description: This function initializes the memory partition used to save FPU registers +* during a context switch. This function MUST be called AFTER calling +* OSInit(). OS_CPU_FPU_EN must be defined > 0 in order to compile FPU support into the +* build. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) Tasks that are to use FP support MUST be created with OSTaskCreateExt(). +* 2) For the ARM VFP, 128 bytes are required to save the VFP context. +* The INT32U data type is used to ensure that storage is aligned on a 32-bit boundary. +* 3) If you need to perform floating point operations from within the OSStatTaskHook(), +* then you must change the 'Options' attribute for OSTaskCreatExt() when creating +* the statistics task. This only applies if OS_TaskStat() was created with OSTaskCreateExt(). +********************************************************************************************************* +*/ + +#if OS_CPU_FPU_EN > 0u +void OS_CPU_FP_Init (void) +{ + INT8U err; +#if (OS_TASK_STAT_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) + OS_TCB *ptcb; + void *pblk; +#endif + + + OSFPPartPtr = OSMemCreate(&OSFPPart[0][0], OS_NTASKS_FP, OS_FP_STORAGE_SIZE, &err); + +#if (OS_TASK_STAT_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)/* CHANGE 'OPTIONS' for OS_TaskStat() */ + ptcb = OSTCBPrioTbl[OS_TASK_STAT_PRIO]; + ptcb->OSTCBOpt |= OS_TASK_OPT_SAVE_FP; /* Allow floating-point support for Stat task*/ + pblk = OSMemGet(OSFPPartPtr, &err); /* Get storage for VFP registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; + + /* Clear exception stack for stack checking.*/ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk++ = (OS_STK)0; + } + +#if OS_STK_GROWTH == 1u + OS_CPU_ExceptStkBase = &OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE - 1u]; +#else + OS_CPU_ExceptStkBase = &OS_CPU_ExceptStk[0]; +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0u + OS_CPU_IntDisMeasInit(); +#endif + +#if OS_CPU_FPU_EN > 0u + OS_CPU_FP_Init(); /* Initialize support for VFP register save / restore */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_CPU_FPU_EN > 0u + INT8U err; + void *pblk; +#endif + + +#if OS_CPU_FPU_EN > 0u + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task needs FP support */ + pblk = OSMemGet(OSFPPartPtr, &err); /* Yes, Get storage for VFP registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_CPU_FPU_EN > 0u + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task had FP support */ + if (ptcb->OSTCBExtPtr != (void *)0) { /* Yes, OSTCBExtPtr must not be NULL */ + OSMemPut(OSFPPartPtr, ptcb->OSTCBExtPtr); /* Return memory block to free pool */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_CPU_ARM_DCC_EN > 0u + OSDCC_Handler(); +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SVC mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + INT32U task_addr; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + task_addr = (INT32U)task & ~1u; /* Mask off lower bit in case task is thumb mode */ + *(stk) = (INT32U)task_addr; /* Entry Point */ + *(--stk) = (INT32U)OS_TaskReturn; /* R14 (LR) */ + *(--stk) = (INT32U)0x12121212uL; /* R12 */ + *(--stk) = (INT32U)0x11111111uL; /* R11 */ + *(--stk) = (INT32U)0x10101010uL; /* R10 */ + *(--stk) = (INT32U)0x09090909uL; /* R9 */ + *(--stk) = (INT32U)0x08080808uL; /* R8 */ + *(--stk) = (INT32U)0x07070707uL; /* R7 */ + *(--stk) = (INT32U)0x06060606uL; /* R6 */ + *(--stk) = (INT32U)0x05050505uL; /* R5 */ + *(--stk) = (INT32U)0x04040404uL; /* R4 */ + *(--stk) = (INT32U)0x03030303uL; /* R3 */ + *(--stk) = (INT32U)0x02020202uL; /* R2 */ + *(--stk) = (INT32U)0x01010101uL; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + if ((INT32U)task & 0x01u) { /* See if task runs in Thumb or ARM mode */ + *(--stk) = (INT32U)ARM_SVC_MODE_THUMB; /* CPSR (Enable IRQ and FIQ interrupts, THUMB-mode) */ + } else { + *(--stk) = (INT32U)ARM_SVC_MODE_ARM; /* CPSR (Enable IRQ and FIQ interrupts, ARM-mode) */ + } + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_CPU_FPU_EN > 0u + void *pblk; +#endif + +#if OS_CPU_FPU_EN > 0u /* Save VFP context of preempted task */ + if (OSRunning == OS_TRUE) { /* Don't save on OSStart()! */ + if (OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task used FP */ + pblk = OSTCBCur->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } + } + } + /* Restore VFP context of new task */ + if (OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if new task uses FP */ + pblk = OSTCBHighRdy->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OS_CPU_FP_Restore(pblk); /* Get contents of VFP registers */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif + +#if OS_CPU_ARM_DCC_EN > 0u + OSDCC_Handler(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE EXCEPTION VECTORS +* +* Description : This function initialize exception vectors to the default handlers. +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OS_CPU_InitExceptVect (void) +{ + (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptUndefInstrHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptSwiHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptPrefetchAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptDataAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptAddrAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptIrqHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptFiqHndlr; +} + + +/* +********************************************************************************************************* +* INITIALIZE EXCEPTION VECTORS +* +* Description : This function initialize exception vectors to the default handlers at a specific address. +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OS_CPU_InitExceptVectAddr (INT32U addr) +{ + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptUndefInstrHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptSwiHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptPrefetchAbortHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptDataAbortHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptAddrAbortHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptIrqHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptFiqHndlr; +} + + +/* +********************************************************************************************************* +* GET NUMBER OF FREE ENTRIES IN EXCEPTION STACK +* +* Description : This function computes the number of free entries in the exception stack. +* +* Arguments : None. +* +* Returns : The number of free entries in the exception stack. +********************************************************************************************************* +*/ + +INT32U OS_CPU_ExceptStkChk (void) +{ + OS_STK *pchk; + INT32U nfree; + INT32U size; + + + nfree = 0; + size = OS_CPU_EXCEPT_STK_SIZE; +#if OS_STK_GROWTH == 1u + pchk = &OS_CPU_ExceptStk[0]; + while ((*pchk++ == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } +#else + pchk = &OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE - 1u]; + while ((*pchk-- == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } +#endif + return (nfree); +} diff --git a/Ports/ARM/Generic/IAR/os_cpu_fpu_a.asm b/Ports/ARM/Generic/IAR/os_cpu_fpu_a.asm new file mode 100644 index 0000000..5ef865e --- /dev/null +++ b/Ports/ARM/Generic/IAR/os_cpu_fpu_a.asm @@ -0,0 +1,81 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Generic ARM Port +; VFP SUPPORT +; +; Filename : os_cpu_fpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARM7 or ARM9 +; Mode : ARM or Thumb +; Toolchain : IAR's EWARM V4.11a and higher +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + PUBLIC OS_CPU_FP_Restore + PUBLIC OS_CPU_FP_Save + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +;********************************************************************************************************* +; RESTORE VFP REGISTERS +; void OS_CPU_FP_Restore(void *pblk) +; +; Description : This function is called to restore the contents of the VFP registers during a context +; switch. It is assumed that a pointer to a storage area for the VFP registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). + +; Arguments : pblk is passed to this function in R0 when called. +; +; Notes : Floating point math should NEVER be performed within an ISR as this will corrupt +; the state of the VFP registers for the last VFP task that ran. Instead, all floating +; point math should be performed within floating point enabled tasks ONLY. +;********************************************************************************************************* + +OS_CPU_FP_Restore + FLDMIAS R0!, {S0-S31} ; Restore the VFP registers from pblk + BX LR ; Return to calling function + +;********************************************************************************************************* +; SAVE VFP REGISTERS +; void OS_CPU_FP_Save(void *pblk) +; +; Description : This function is called to save the contents of the VFP registers during a context +; switch. It is assumed that a pointer to a storage area for the VFP registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). +; +; Arguments : pblk is passed to this function in R0 when called. +; +; Notes : Floating point math should NEVER be performed within an ISR as this will corrupt +; the state of the VFP registers for the last VFP task that ran. Instead, all floating +; point math should be performed within floating point enabled tasks ONLY. +;********************************************************************************************************* + +OS_CPU_FP_Save + FSTMIAS R0!, {S0-S31} ; Save the VFP registers in pblk + BX LR ; Return to calling function + + + END diff --git a/Ports/ARM/Generic/IAR/os_dbg.c b/Ports/ARM/Generic/IAR/os_dbg.c new file mode 100644 index 0000000..d71187c --- /dev/null +++ b/Ports/ARM/Generic/IAR/os_dbg.c @@ -0,0 +1,321 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* Generic ARM Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : IAR's EWARM V4.11a and higher +********************************************************************************************************* +*/ + +#include + + /* The following #define tells the IAR compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM/Generic/IAR/os_dcc.c b/Ports/ARM/Generic/IAR/os_dcc.c new file mode 100644 index 0000000..1bb2946 --- /dev/null +++ b/Ports/ARM/Generic/IAR/os_dcc.c @@ -0,0 +1,230 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Generic ARM Port +* DCC Communication +* +* Filename : os_dcc.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : IAR's EWARM V4.40a and higher +********************************************************************************************************* +*/ + +#include + /* This directive suppresses warnings for non-... */ +#pragma diag_suppress=Pe940 /* ...void functions with no return values. */ + +#if OS_CPU_ARM_DCC_EN > 0 + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#define OS_DCC_OP_READ_U32 0x01000000 +#define OS_DCC_OP_READ_U16 0x02000000 +#define OS_DCC_OP_READ_U8 0x04000000 +#define OS_DCC_OP_GET_CAPS 0x08000000 +#define OS_DCC_OP_WRITE_U32 0x10000000 +#define OS_DCC_OP_WRITE_U16 0x20000000 +#define OS_DCC_OP_WRITE_U8 0x40000000 +#define OS_DCC_OP_ODD_ADDR 0x80000000 +#define OS_DCC_OP_COMMAND 0x00000001 + +#define OS_DCC_COMM_CTRL_RD 0x00000001 +#define OS_DCC_COMM_CTRL_WR 0x00000002 + +#define OS_DCC_SIGNATURE 0x91CA0000 +#define OS_DCC_CONFIG 0x00000077 + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +static INT32U OSDCC_Cmd; +static INT32U OSDCC_Addr; +static INT32U OSDCC_ItemCnt; +static INT32U OSDCC_Data; + +/* +********************************************************************************************************* +* OSDCC_ReadCtrl() +* +* Description: This function retrieves data from the comms control register. +* +* Arguments : none +* +* Returns : The contents of the comms control register +* +* Notes : 1) This function uses a coprocessor register transfer instruction to place the contents +* of the comms control register in R0. Thus, the function does not contain an +* explicit return statement. "#pragma diag_suppress=Pe940", which appears at the +* top of this file, is used to suppress the warning that normally results from non- +* void functions lacking return statements. +********************************************************************************************************* +*/ + +static __arm INT32U OSDCC_ReadCtrl (void) +{ + __asm("mrc P14,0,R0,C0,C0"); +} + +/* +********************************************************************************************************* +* OSDCC_Read() +* +* Description: This function retrieves data from the comms data read register. +* +* Arguments : none +* +* Returns : The contents of the comms data read register +* +* Notes : 1) This function uses a coprocessor register transfer instruction to place the contents +* of the comms data read register in R0. Thus, the function does not contain an +* explicit return statement. "#pragma diag_suppress=Pe940", which appears at the +* top of this file, is used to suppress the warning that normally results from non- +* void functions lacking return statements. +********************************************************************************************************* +*/ + +static __arm INT32U OSDCC_Read (void) +{ + __asm("mrc P14,0,R0,C1,C0"); +} + +/* +********************************************************************************************************* +* OSDCC_Write() +* +* Description: This function places data in the comms data write register. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static __arm void OSDCC_Write (INT32U data) +{ + __asm("mcr P14,0,R0,C1,C0"); +} + +/* +********************************************************************************************************* +* OSDCC_Handler() +* +* Description: This function reads commands from the DCC comms data read register. Data may be +* transferred to or from memory based on those commands. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function should be called periodically. If OS_CPU_ARM_DCC_EN is '1', this +* function will be called from both the idle task hook and the tick interrupt hook. +********************************************************************************************************* +*/ + +void OSDCC_Handler (void) +{ + INT32U reg_val; +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0; +#endif + + + OS_ENTER_CRITICAL(); /* Disable interrupts */ + + /* Check for the presence of new data */ + if ((OSDCC_ReadCtrl() & OS_DCC_COMM_CTRL_RD) != 0) { + reg_val = OSDCC_Read(); /* Read the new data */ + + if ((reg_val & OS_DCC_OP_COMMAND) != 0) { /* Determine whether a command has been received */ + OSDCC_Cmd = reg_val; + /* Check for an odd address in the next operation */ + if ((OSDCC_Cmd & OS_DCC_OP_ODD_ADDR) != 0) { + OSDCC_Addr |= 1; + } + /* If data will be read, adjust OSDCC_ItemCnt */ + if ((OSDCC_Cmd & (OS_DCC_OP_READ_U32 | OS_DCC_OP_READ_U16 | OS_DCC_OP_READ_U8 + | OS_DCC_OP_GET_CAPS)) != 0) { + OSDCC_ItemCnt = (OSDCC_Cmd >> 2) & 0xffff; + } else { /* Data will be written; initialize OSDCC_Data */ + if ((OSDCC_Cmd & OS_DCC_OP_WRITE_U32) != 0) { + OSDCC_Data |= (OSDCC_Cmd << 14) & 0xffff0000; + } else { + OSDCC_Data = (OSDCC_Cmd >> 2) & 0xffff; + } + /* Write a single byte */ + if ((OSDCC_Cmd & OS_DCC_OP_WRITE_U8) != 0) { + *(INT8U *)OSDCC_Addr = OSDCC_Data; + OSDCC_Addr += 1; + } + /* Write two bytes */ + if ((OSDCC_Cmd & OS_DCC_OP_WRITE_U16) != 0) { + *(INT16U *)OSDCC_Addr = OSDCC_Data; + OSDCC_Addr += 2; + } + /* Write four bytes */ + if ((OSDCC_Cmd & OS_DCC_OP_WRITE_U32) != 0) { + *(INT32U *)OSDCC_Addr =OSDCC_Data; + OSDCC_Addr += 4; + } + } + OS_EXIT_CRITICAL(); + return; + } + OSDCC_Addr = reg_val; /* An address was received; OSDCC_Addr is updated */ + } + /* Determine whether data must be read */ + if (OSDCC_ItemCnt != 0) { + /* Confirm that the comms data write register... */ + /* ...is free from the processor point of view */ + if ((OSDCC_ReadCtrl() & OS_DCC_COMM_CTRL_WR) == 0) { + reg_val = (OS_DCC_CONFIG | OS_DCC_SIGNATURE); + /* Read a single byte */ + if ((OSDCC_Cmd & OS_DCC_OP_READ_U8) != 0) { + reg_val = *(INT8U *)OSDCC_Addr; + OSDCC_Addr += 1; + } + /* Read two bytes */ + if ((OSDCC_Cmd & OS_DCC_OP_READ_U16) != 0) { + reg_val = *(INT16U *)OSDCC_Addr; + OSDCC_Addr += 2; + } + /* Read four bytes */ + if ((OSDCC_Cmd & OS_DCC_OP_READ_U32) != 0) { + reg_val = *(INT32U *)OSDCC_Addr; + OSDCC_Addr += 4; + } + + OSDCC_Write(reg_val); /* Place data in the comms data write register */ + OSDCC_ItemCnt--; /* Decrement the number of items to be read */ + } + } + OS_EXIT_CRITICAL(); +} + +#endif diff --git a/Ports/ARM/Generic/RealView/os_cpu.h b/Ports/ARM/Generic/RealView/os_cpu.h new file mode 100644 index 0000000..e7fa60f --- /dev/null +++ b/Ports/ARM/Generic/RealView/os_cpu.h @@ -0,0 +1,246 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Generic ARM Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : RealView Development Suite +* RealView Microcontroller Development Kit (MDK) +* ARM Developer Suite (ADS) +* Keil uVision +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#ifndef OS_CPU_FPU_EN +#define OS_CPU_FPU_EN 0u /* HW floating point support disabled by default */ +#endif + +#ifndef OS_CPU_EXCEPT_STK_SIZE +#define OS_CPU_EXCEPT_STK_SIZE 128u /* Default exception stack size is 128 OS_STK entries */ +#endif + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT +********************************************************************************************************* +*/ + +#define OS_CPU_INT_DIS_MEAS_EN 0u + + +/* +********************************************************************************************************* +* EXCEPTION DEFINES +********************************************************************************************************* +*/ + + /* ARM exception IDs */ +#define OS_CPU_ARM_EXCEPT_RESET 0x00u +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01u +#define OS_CPU_ARM_EXCEPT_SWI 0x02u +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03u +#define OS_CPU_ARM_EXCEPT_DATA_ABORT 0x04u +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05u +#define OS_CPU_ARM_EXCEPT_IRQ 0x06u +#define OS_CPU_ARM_EXCEPT_FIQ 0x07u +#define OS_CPU_ARM_EXCEPT_NBR 0x08u + /* ARM exception vectors addresses */ +#define OS_CPU_ARM_EXCEPT_RESET_VECT_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x00u) +#define OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x00u) + + /* ARM exception handlers addresses */ +#define OS_CPU_ARM_EXCEPT_RESET_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04u + 0x20u) +#define OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04u + 0x20u) + + /* ARM "Jump To Self" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFEuL + /* ARM "Jump To Exception Handler" asm instruction */ +#define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018uL + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + + +#if OS_CRITICAL_METHOD == 3u + +#if OS_CPU_INT_DIS_MEAS_EN > 0u + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart();} +#define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr);} + +#else + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} + +#endif + +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0u +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsDelta; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsOvrhd; +#endif + +OS_CPU_EXT OS_STK OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE]; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkBase; +OS_CPU_EXT OS_STK *OS_CPU_ExceptStkPtr; + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OS_CPU_SR_INT_Dis (void); +void OS_CPU_SR_INT_En (void); +void OS_CPU_SR_FIQ_Dis (void); +void OS_CPU_SR_FIQ_En (void); +void OS_CPU_SR_IRQ_Dis (void); +void OS_CPU_SR_IRQ_En (void); + +#if OS_CPU_FPU_EN > 0u /* See OS_CPU_C.C */ +void OS_CPU_FP_Init (void); +void OS_CPU_FP_Restore (void *pblk); +void OS_CPU_FP_Save (void *pblk); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +void OS_CPU_InitExceptVect (void); +void OS_CPU_InitExceptVectAddr (INT32U addr); + +void OS_CPU_ARM_ExceptUndefInstrHndlr (void); +void OS_CPU_ARM_ExceptSwiHndlr (void); +void OS_CPU_ARM_ExceptPrefetchAbortHndlr(void); +void OS_CPU_ARM_ExceptDataAbortHndlr (void); +void OS_CPU_ARM_ExceptAddrAbortHndlr (void); +void OS_CPU_ARM_ExceptIrqHndlr (void); +void OS_CPU_ARM_ExceptFiqHndlr (void); + +void OS_CPU_ExceptHndlr (INT32U except_type); + +INT32U OS_CPU_ExceptStkChk (void); + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void); +void OS_CPU_IntDisMeasStart (void); +void OS_CPU_IntDisMeasStop (void); +INT16U OS_CPU_IntDisMeasTmrRd (void); +#endif + +#endif diff --git a/Ports/ARM/Generic/RealView/os_cpu_a.asm b/Ports/ARM/Generic/RealView/os_cpu_a.asm new file mode 100644 index 0000000..eac4a49 --- /dev/null +++ b/Ports/ARM/Generic/RealView/os_cpu_a.asm @@ -0,0 +1,846 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Generic ARM Port +; +; Filename : os_cpu_fpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARM7 or ARM9 +; Mode : ARM or Thumb +; Toolchain : RealView Development Suite +; RealView Microcontroller Development Kit (MDK) +; ARM Developer Suite (ADS) +; Keil uVision +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + ; External references. + IMPORT OSRunning + IMPORT OSPrioCur + IMPORT OSPrioHighRdy + IMPORT OSTCBCur + IMPORT OSTCBHighRdy + IMPORT OSIntNesting + IMPORT OSIntExit + IMPORT OSTaskSwHook + + IMPORT OS_CPU_ExceptStkBase + IMPORT OS_CPU_ExceptStkPtr + + ; Functions declared in this file. + EXPORT OS_CPU_SR_Save + EXPORT OS_CPU_SR_Restore + EXPORT OSStartHighRdy + EXPORT OSCtxSw + EXPORT OSIntCtxSw + + ; Functions related to exception handling. + EXPORT OS_CPU_ARM_ExceptUndefInstrHndlr + EXPORT OS_CPU_ARM_ExceptSwiHndlr + EXPORT OS_CPU_ARM_ExceptPrefetchAbortHndlr + EXPORT OS_CPU_ARM_ExceptDataAbortHndlr + EXPORT OS_CPU_ARM_ExceptAddrAbortHndlr + EXPORT OS_CPU_ARM_ExceptIrqHndlr + EXPORT OS_CPU_ARM_ExceptFiqHndlr + + ; Functions related to interrupt enabling/disabling. + EXPORT OS_CPU_SR_INT_Dis + EXPORT OS_CPU_SR_INT_En + EXPORT OS_CPU_SR_FIQ_Dis + EXPORT OS_CPU_SR_FIQ_En + EXPORT OS_CPU_SR_IRQ_Dis + EXPORT OS_CPU_SR_IRQ_En + + IMPORT OS_CPU_ExceptHndlr + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + +OS_CPU_ARM_CONTROL_INT_DIS EQU 0xC0 ; Disable both FIQ and IRQ. +OS_CPU_ARM_CONTROL_FIQ_DIS EQU 0x40 ; Disable FIQ. +OS_CPU_ARM_CONTROL_IRQ_DIS EQU 0x80 ; Disable IRQ. +OS_CPU_ARM_CONTROL_THUMB EQU 0x20 ; Set THUMB mode. +OS_CPU_ARM_CONTROL_ARM EQU 0x00 ; Set ARM mode. + +OS_CPU_ARM_MODE_MASK EQU 0x1F +OS_CPU_ARM_MODE_USR EQU 0x10 +OS_CPU_ARM_MODE_FIQ EQU 0x11 +OS_CPU_ARM_MODE_IRQ EQU 0x12 +OS_CPU_ARM_MODE_SVC EQU 0x13 +OS_CPU_ARM_MODE_ABT EQU 0x17 +OS_CPU_ARM_MODE_UND EQU 0x1B +OS_CPU_ARM_MODE_SYS EQU 0x1F + +OS_CPU_ARM_EXCEPT_RESET EQU 0x00 +OS_CPU_ARM_EXCEPT_UNDEF_INSTR EQU 0x01 +OS_CPU_ARM_EXCEPT_SWI EQU 0x02 +OS_CPU_ARM_EXCEPT_PREFETCH_ABORT EQU 0x03 +OS_CPU_ARM_EXCEPT_DATA_ABORT EQU 0x04 +OS_CPU_ARM_EXCEPT_ADDR_ABORT EQU 0x05 +OS_CPU_ARM_EXCEPT_IRQ EQU 0x06 +OS_CPU_ARM_EXCEPT_FIQ EQU 0x07 + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + REQUIRE8 + PRESERVE8 + + AREA CODE, CODE, READONLY + CODE32 + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + MRS R0, CPSR + ORR R1, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R1 + BX LR ; Disabled, return the original CPSR contents in R0. + + +OS_CPU_SR_Restore + MSR CPSR_c, R0 + BX LR + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + ; Change to SVC mode. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + LDR R0, =OSTaskSwHook ; OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSRunning ; OSRunning = TRUE; + MOV R1, #1 + STRB R1, [R0] + + ; SWITCH TO HIGHEST PRIORITY TASK: + LDR R0, =OSTCBHighRdy ; Get highest priority task TCB address, + LDR R0, [R0] ; Get stack pointer, + LDR SP, [R0] ; Switch to the new stack, + + LDR R0, [SP], #4 ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw + ; SAVE CURRENT TASK'S CONTEXT: + STMFD SP!, {LR} ; Push return address, + STMFD SP!, {LR} + STMFD SP!, {R0-R12} ; Push registers, + MRS R0, CPSR ; Push current CPSR, + TST LR, #1 ; See if called from Thumb mode, + ORRNE R0, R0, #OS_CPU_ARM_CONTROL_THUMB ; If yes, set the T-bit. + STMFD SP!, {R0} + + LDR R0, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R1, [R0] + STR SP, [R1] + + LDR R0, =OSTaskSwHook ; OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw + LDR R0, =OSTaskSwHook ; OSTaskSwHook(); + MOV LR, PC + BX R0 + + LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy; + LDR R1, =OSPrioHighRdy + LDRB R2, [R1] + STRB R2, [R0] + + LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy; + LDR R1, =OSTCBHighRdy + LDR R2, [R1] + STR R2, [R0] + + LDR SP, [R2] ; SP = OSTCBHighRdy->OSTCBStkPtr; + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +;******************************************************************************************************** +; EXCEPTION HANDLERS +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; UNDEFINED INSTRUCTION EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptUndefInstrHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_UNDEF_INSTR ; Set exception ID to OS_CPU_ARM_EXCEPT_UNDEF_INSTR. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; SOFTWARE INTERRUPT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptSwiHndlr + ; LR offset to return from this exception: 0. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_SWI ; Set exception ID to OS_CPU_ARM_EXCEPT_SWI. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; PREFETCH ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptPrefetchAbortHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_PREFETCH_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_PREFETCH_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; DATA ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptDataAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_DATA_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_DATA_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; ADDRESS ABORT EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptAddrAbortHndlr + SUB LR, LR, #8 ; LR offset to return from this exception: -8. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_ADDR_ABORT ; Set exception ID to OS_CPU_ARM_EXCEPT_ADDR_ABORT. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +; FAST INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 +; R2 Return PC +;******************************************************************************************************** + +OS_CPU_ARM_ExceptFiqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R12, LR} ; Push working registers. + MOV R2, LR ; Save link register. + MOV R0, #OS_CPU_ARM_EXCEPT_FIQ ; Set exception ID to OS_CPU_ARM_EXCEPT_FIQ. + B OS_CPU_ARM_ExceptHndlr ; Branch to global exception handler. + +;******************************************************************************************************** +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; GLOBAL EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Old CPU mode +; +; Note(s) : 1) An exception can occur in four different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; +; b) CONDITION: An exception interrupts a task. +; SVC STACK: Should point to task stack. +; +; c) CONDITION: An exception interrupts another exception, or an IRQ before it +; switches to the exception stack. +; SVC STACK: Should point to location in an exception-mode stack. +; +; d) CONDITION: An exception interrupts an an IRQ after it switches to the exception +; stack, 'OS_CPU_ExceptStk[]'. +; SVC STACK: Should point to location in an exception stack, 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + + ; DETERMINE IF WE INTERRUPTED A TASK/IRQ OR ANOTHER LOWER PRIORITY EXCEPTION: + ; SPSR.Mode = SVC : task or IRQ handled in SVC mode, + ; SPSR.Mode = FIQ, IRQ, ABT, UND : other exceptions, + ; SPSR.Mode = USR : *unsupported state*. + AND R3, R1, #OS_CPU_ARM_MODE_MASK + CMP R3, #OS_CPU_ARM_MODE_SVC + BNE OS_CPU_ARM_ExceptHndlr_BrkExcept + +;******************************************************************************************************** +; EXCEPTION HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's CPSR +; R4 Exception's SP +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkTask + MRS R3, CPSR ; Save exception's CPSR. + MOV R4, SP ; Save exception's stack pointer. + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; SAVE TASK'S CONTEXT ONTO TASK'S STACK: + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R5-R12} ; Push task's R12-R5, + LDMFD R4!, {R5-R9} ; Move task's R4-R0 from exception stack to task's stack. + STMFD SP!, {R5-R9} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + LDR R1, =OSRunning + LDRB R1, [R1] + CMP R1, #1 + BNE OS_CPU_ARM_ExceptHndlr_BrkTask_1 + + ; HANDLE NESTING COUNTER: + LDR R1, =OSIntNesting ; OSIntNesting++; + LDRB R2, [R1] + ADD R2, R2, #1 + STRB R2, [R1] + + CMP R2, #1 ; if (OSIntNesting > 1) + BNE OS_CPU_ARM_ExceptHndlr_BrkIRQ ; IRQ has been interrupted. + + LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R2, [R1] + STR SP, [R2] + +OS_CPU_ARM_ExceptHndlr_BrkTask_1 + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R1 + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(14 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + LDR R0, =OSIntExit + MOV LR, PC + BX R0 + + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +; EXCEPTION HANDLER: EXCEPTION INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkExcept + STMFD SP!, {R1} ; Push exception's SPSR. + + MRS R3, CPSR ; Push exception's CPSR. + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + STMFD SP!, {R3} + + ; HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting ; OSIntNesting++; + LDRB R4, [R2] + ADD R4, R4, #1 + STRB R4, [R2] + + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; EXECUTE EXCEPTION HANDLER: + LDR R2, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R2 + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting ; OSIntNesting--; + LDRB R4, [R2] + SUB R4, R4, #1 + STRB R4, [R2] + + LDMFD SP!, {R3} + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; RESTORE INTERRUPTED EXCEPTIONS' CONTEXT: + LDMFD SP!, {R0} ; Pop exception's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, PC}^ ; Pull working registers and return from exception. + +;******************************************************************************************************** +; EXCEPTION HANDLER: IRQ INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_ExceptHndlr_BrkIRQ + MSR CPSR_cxsf, R3 ; RESTORE INTERRUPTED MODE. + + ; EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0); + MOV LR, PC + BX R1 + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring IRQ context. + ADD SP, SP, #(14 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R2, =OSIntNesting ; OSIntNesting--; + LDRB R4, [R2] + SUB R4, R4, #1 + STRB R4, [R2] + + ; RESTORE IRQ'S CONTEXT: + LDMFD SP!, {R0} ; Pop IRQ's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop IRQ's context. + +;******************************************************************************************************** +;******************************************************************************************************** +; IRQ HANDLER +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; INTERRUPT REQUEST EXCEPTION HANDLER +; +; Register Usage: R0 Exception Type +; R1 Exception's SPSR +; R2 Return PC +; R3 Exception's SP +; +; Note(s) : 1) An IRQ can occur in three different circumstances; in each of these, the +; SVC stack pointer will point to a different entity : +; +; a) CONDITION: An exception occurs before the OS has been fully initialized. +; SVC STACK: Should point to a stack initialized by the application's startup code. +; STK USAGE: Interrupted context -- SVC stack. +; Exception -- SVC stack. +; Nested exceptions -- SVC stack. +; +; b) CONDITION: An IRQ interrupts a task. +; SVC STACK: Should point to task stack. +; STK USAGE: Interrupted context -- Task stack. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +; +; c) CONDITION: An IRQ interrupts another IRQ. +; SVC STACK: Should point to location in exception stack, 'OS_CPU_ExceptStk[]'. +; STK USAGE: Interrupted context -- Exception stack 'OS_CPU_ExceptStk[]'. +; Exception -- Exception stack 'OS_CPU_ExceptStk[]'. +; Nested exceptions -- Exception stack 'OS_CPU_ExceptStk[]'. +;******************************************************************************************************** + +OS_CPU_ARM_ExceptIrqHndlr + SUB LR, LR, #4 ; LR offset to return from this exception: -4. + STMFD SP!, {R0-R3} ; Push working registers. + + MOV R0, #OS_CPU_ARM_EXCEPT_IRQ ; Set exception ID to OS_CPU_ARM_EXCEPT_IRQ. + MRS R1, SPSR ; Save CPSR (i.e. exception's SPSR). + MOV R2, LR ; Save link register. + MOV R3, SP ; Save exception's stack pointer. + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; SAVE CONTEXT ONTO SVC STACK: + STMFD SP!, {R2} ; Push task's PC, + STMFD SP!, {LR} ; Push task's LR, + STMFD SP!, {R4-R12} ; Push task's R12-R4, + LDMFD R3!, {R5-R8} ; Move task's R3-R0 from exception stack to task's stack. + STMFD SP!, {R5-R8} + STMFD SP!, {R1} ; Push task's CPSR (i.e. exception SPSR). + + ; if (OSRunning == 1) + LDR R3, =OSRunning + LDRB R4, [R3] + CMP R4, #1 + BNE OS_CPU_ARM_IRQHndlr_BreakNothing + + ; HANDLE NESTING COUNTER: + LDR R3, =OSIntNesting ; OSIntNesting++; + LDRB R4, [R3] + ADD R4, R4, #1 + STRB R4, [R3] + + CMP R4, #1 ; if (OSIntNesting == 1) + BNE OS_CPU_ARM_IRQHndlr_BreakIRQ + +;******************************************************************************************************** +; IRQ HANDLER: TASK INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakTask + LDR R3, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP; + LDR R4, [R3] + STR SP, [R4] + + LDR R3, =OS_CPU_ExceptStkBase ; Switch to exception stack. + LDR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + LDR R1, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R1 + + ; Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_IRQ) + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; Call OSIntExit(). This call MAY never return if a ready + ; task with higher priority than the interrupted one is + ; found. + LDR R0, =OSIntExit + MOV LR, PC + BX R0 + + LDR R3, =OSTCBCur ; SP = OSTCBCur->OSTCBStkPtr; + LDR R4, [R3] + LDR SP, [R4] + ; RESTORE NEW TASK'S CONTEXT: + LDMFD SP!, {R0} ; Pop new task's CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pop new task's context. + +;******************************************************************************************************** +; IRQ HANDLER: IRQ INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakIRQ + LDR R3, =OS_CPU_ExceptStkPtr ; OS_CPU_ExceptStkPtr = SP; + STR SP, [R3] + + ; EXECUTE EXCEPTION HANDLER: + LDR R3, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R3 + + ; Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_IRQ) + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; HANDLE NESTING COUNTER: + LDR R3, =OSIntNesting ; OSIntNesting--; + LDRB R4, [R3] + SUB R4, R4, #1 + STRB R4, [R3] + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + +;******************************************************************************************************** +; IRQ HANDLER: 'NOTHING' INTERRUPTED +; +; Register Usage: R0 Exception Type +; R1 +; R2 +; R3 +;******************************************************************************************************** + +OS_CPU_ARM_IRQHndlr_BreakNothing + ; EXECUTE EXCEPTION HANDLER: + LDR R3, =OS_CPU_ExceptHndlr ; OS_CPU_ExceptHndlr(except_type = R0) + MOV LR, PC + BX R3 + + ; Change to IRQ mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_IRQ) + + ; Adjust exception stack pointer. This is needed because + ; exception stack is not used when restoring task context. + ADD SP, SP, #(4 * 4) + + ; Change to SVC mode & disable interruptions. + MSR CPSR_c, #(OS_CPU_ARM_CONTROL_INT_DIS :OR: OS_CPU_ARM_MODE_SVC) + + ; RESTORE OLD CONTEXT: + LDMFD SP!, {R0} ; Pop old CPSR, + MSR SPSR_cxsf, R0 + + LDMFD SP!, {R0-R12, LR, PC}^ ; Pull working registers and return from exception. + +;******************************************************************************************************** +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS, IRQs, FIQs +;******************************************************************************************************** +;******************************************************************************************************** + +;******************************************************************************************************** +; ENABLE & DISABLE INTERRUPTS +; +; Note(s) : 1) OS_CPU_SR_INT_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs and FIQs so that +; nesting can occur. +; +; 2) OS_CPU_ARM_INT_Dis() can be called to disable IRQs and FIQs so that nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_INT_En + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Clear IRQ and FIQ bits in CPSR to enable all interrupts. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_INT_Dis + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_INT_DIS ; Set IRQ and FIQ bits in CPSR to disable all interrupts. + MSR CPSR_c, R0 + BX LR + +;******************************************************************************************************** +; ENABLE & DISABLE IRQs +; +; Note(s) : 1) OS_CPU_SR_IRQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable IRQs so that IRQ nesting +; can occur. +; +; 2) OS_CPU_ARM_IRQ_Dis() can be called to disable IRQs so that IRQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_IRQ_En + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Clear IRQ bit in CPSR to enable IRQs. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_IRQ_Dis + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_IRQ_DIS ; Set IRQ bit in CPSR to disable IRQs. + MSR CPSR_c, R0 + BX LR + +;******************************************************************************************************** +; ENABLE & DISABLE FIQs +; +; Note(s) : 1) OS_CPU_SR_FIQ_En() can be called by OS_CPU_ExceptHndlr() AFTER the external +; interrupt source has been cleared. This function will enable FIQs so that FIQ nesting +; can occur. +; +; 2) OS_CPU_ARM_FIQ_Dis() can be called to disable FIQs so that FIQ nesting will not occur. +;******************************************************************************************************** + +OS_CPU_SR_FIQ_En + MRS R0, CPSR + BIC R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Clear FIQ bit in CPSR to enable FIQs. + MSR CPSR_c, R0 + BX LR + +OS_CPU_SR_FIQ_Dis + MRS R0, CPSR + ORR R0, R0, #OS_CPU_ARM_CONTROL_FIQ_DIS ; Set FIQ bit in CPSR to disable FIQs. + MSR CPSR_c, R0 + BX LR + + + END diff --git a/Ports/ARM/Generic/RealView/os_cpu_c.c b/Ports/ARM/Generic/RealView/os_cpu_c.c new file mode 100644 index 0000000..eefef16 --- /dev/null +++ b/Ports/ARM/Generic/RealView/os_cpu_c.c @@ -0,0 +1,635 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* Generic ARM Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : RealView Development Suite +* RealView Microcontroller Development Kit (MDK) +* ARM Developer Suite (ADS) +* Keil uVision +********************************************************************************************************* +*/ + + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +* +* Note(s) : 1) ARM_MODE_ARM is the CPSR bit mask for ARM Mode +* 2) ARM_MODE_THUMB is the CPSR bit mask for THUMB Mode +* 3) ARM_SVC_MODE_THUMB is the CPSR bit mask for SVC MODE + THUMB Mode +* 4) ARM_SVC_MODE_ARM is the CPSR bit mask for SVC MODE + ARM Mode + 5) OS_NTASKS_FP establishes the number of tasks capable of supporting floating-point. One +* task is removed for the idle task because it doesn't do floating-point at all. +* 6) OS_FP_STORAGE_SIZE currently allocates 128 bytes of storage in order to accomodate +* thirty-two single-precision 32-bit, or sixteen double-precision 64-bit VFP registers. +********************************************************************************************************* +*/ + +#define ARM_MODE_ARM 0x00000000u +#define ARM_MODE_THUMB 0x00000020u + +#define ARM_SVC_MODE_THUMB (0x00000013uL + ARM_MODE_THUMB) +#define ARM_SVC_MODE_ARM (0x00000013uL + ARM_MODE_ARM) + +#define OS_NTASKS_FP (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u) +#define OS_FP_STORAGE_SIZE 128u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + +#if OS_CPU_FPU_EN > 0u +static OS_MEM *OSFPPartPtr; /* Ptr to memory partition for storing FPU registers */ +static INT32U OSFPPart[OS_NTASKS_FP][OS_FP_STORAGE_SIZE / sizeof(INT32U)]; +#endif + + +/* +********************************************************************************************************* +* INITIALIZE FP SUPPORT +* +* Description: This function initializes the memory partition used to save FPU registers +* during a context switch. This function MUST be called AFTER calling +* OSInit(). OS_CPU_FPU_EN must be defined > 0 in order to compile FPU support into the +* build. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) Tasks that are to use FP support MUST be created with OSTaskCreateExt(). +* 2) For the ARM VFP, 128 bytes are required to save the VFP context. +* The INT32U data type is used to ensure that storage is aligned on a 32-bit boundary. +* 3) If you need to perform floating point operations from within the OSStatTaskHook(), +* then you must change the 'Options' attribute for OSTaskCreatExt() when creating +* the statistics task. This only applies if OS_TaskStat() was created with OSTaskCreateExt(). +********************************************************************************************************* +*/ + +#if OS_CPU_FPU_EN > 0u +void OS_CPU_FP_Init (void) +{ + INT8U err; +#if (OS_TASK_STAT_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) + OS_TCB *ptcb; + void *pblk; +#endif + + + OSFPPartPtr = OSMemCreate(&OSFPPart[0][0], OS_NTASKS_FP, OS_FP_STORAGE_SIZE, &err); + +#if (OS_TASK_STAT_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u)/* CHANGE 'OPTIONS' for OS_TaskStat() */ + ptcb = OSTCBPrioTbl[OS_TASK_STAT_PRIO]; + ptcb->OSTCBOpt |= OS_TASK_OPT_SAVE_FP; /* Allow floating-point support for Stat task*/ + pblk = OSMemGet(OSFPPartPtr, &err); /* Get storage for VFP registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U size; + OS_STK *pstk; + + /* Clear exception stack for stack checking.*/ + pstk = &OS_CPU_ExceptStk[0]; + size = OS_CPU_EXCEPT_STK_SIZE; + while (size > 0u) { + size--; + *pstk++ = (OS_STK)0; + } + +#if OS_STK_GROWTH == 1u + OS_CPU_ExceptStkBase = &OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE - 1u]; +#else + OS_CPU_ExceptStkBase = &OS_CPU_ExceptStk[0]; +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0u + OS_CPU_IntDisMeasInit(); +#endif + +#if OS_CPU_FPU_EN > 0u + OS_CPU_FP_Init(); /* Initialize support for VFP register save / restore */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_CPU_FPU_EN > 0u + INT8U err; + void *pblk; +#endif + + +#if OS_CPU_FPU_EN > 0u + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task needs FP support */ + pblk = OSMemGet(OSFPPartPtr, &err); /* Yes, Get storage for VFP registers */ + if (pblk != (void *)0) { /* Did we get a memory block? */ + ptcb->OSTCBExtPtr = pblk; /* Yes, Link to task's TCB */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_CPU_FPU_EN > 0u + if (ptcb->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task had FP support */ + if (ptcb->OSTCBExtPtr != (void *)0) { /* Yes, OSTCBExtPtr must not be NULL */ + OSMemPut(OSFPPartPtr, ptcb->OSTCBExtPtr); /* Return memory block to free pool */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SVC mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + INT32U task_addr; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + task_addr = (INT32U)task & ~1u; /* Mask off lower bit in case task is thumb mode */ + *(stk) = (INT32U)task_addr; /* Entry Point */ + *(--stk) = (INT32U)OS_TaskReturn; /* R14 (LR) */ + *(--stk) = (INT32U)0x12121212uL; /* R12 */ + *(--stk) = (INT32U)0x11111111uL; /* R11 */ + *(--stk) = (INT32U)0x10101010uL; /* R10 */ + *(--stk) = (INT32U)0x09090909uL; /* R9 */ + *(--stk) = (INT32U)0x08080808uL; /* R8 */ + *(--stk) = (INT32U)0x07070707uL; /* R7 */ + *(--stk) = (INT32U)0x06060606uL; /* R6 */ + *(--stk) = (INT32U)0x05050505uL; /* R5 */ + *(--stk) = (INT32U)0x04040404uL; /* R4 */ + *(--stk) = (INT32U)0x03030303uL; /* R3 */ + *(--stk) = (INT32U)0x02020202uL; /* R2 */ + *(--stk) = (INT32U)0x01010101uL; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + if ((INT32U)task & 0x01u) { /* See if task runs in Thumb or ARM mode */ + *(--stk) = (INT32U)ARM_SVC_MODE_THUMB; /* CPSR (Enable IRQ and FIQ interrupts, THUMB-mode) */ + } else { + *(--stk) = (INT32U)ARM_SVC_MODE_ARM; /* CPSR (Enable IRQ and FIQ interrupts, ARM-mode) */ + } + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_CPU_FPU_EN > 0u + void *pblk; +#endif + +#if OS_CPU_FPU_EN > 0u /* Save VFP context of preempted task */ + if (OSRunning == OS_TRUE) { /* Don't save on OSStart()! */ + if (OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if task used FP */ + pblk = OSTCBCur->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OS_CPU_FP_Save(pblk); /* Save the VFP registers in block */ + } + } + } + /* Restore VFP context of new task */ + if (OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) { /* See if new task uses FP */ + pblk = OSTCBHighRdy->OSTCBExtPtr; /* Yes, Get pointer to FP storage area */ + if (pblk != (void *)0) { /* Make sure we have storage */ + OS_CPU_FP_Restore(pblk); /* Get contents of VFP registers */ + } + } +#endif + +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE EXCEPTION VECTORS +* +* Description : This function initialize exception vectors to the default handlers. +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OS_CPU_InitExceptVect (void) +{ + (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptUndefInstrHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptSwiHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptPrefetchAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptDataAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptAddrAbortHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptIrqHndlr; + + (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptFiqHndlr; +} + + +/* +********************************************************************************************************* +* INITIALIZE EXCEPTION VECTORS +* +* Description : This function initialize exception vectors to the default handlers at a specific address. +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OS_CPU_InitExceptVectAddr (INT32U addr) +{ + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptUndefInstrHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptSwiHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptPrefetchAbortHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptDataAbortHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptAddrAbortHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptIrqHndlr; + + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR)) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER; + (*(INT32U *)(addr + OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR)) = (INT32U)OS_CPU_ARM_ExceptFiqHndlr; +} + + +/* +********************************************************************************************************* +* GET NUMBER OF FREE ENTRIES IN EXCEPTION STACK +* +* Description : This function computes the number of free entries in the exception stack. +* +* Arguments : None. +* +* Returns : The number of free entries in the exception stack. +********************************************************************************************************* +*/ + +INT32U OS_CPU_ExceptStkChk (void) +{ + OS_STK *pchk; + INT32U nfree; + INT32U size; + + + nfree = 0; + size = OS_CPU_EXCEPT_STK_SIZE; +#if OS_STK_GROWTH == 1u + pchk = &OS_CPU_ExceptStk[0]; + while ((*pchk++ == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } +#else + pchk = &OS_CPU_ExceptStk[OS_CPU_EXCEPT_STK_SIZE - 1u]; + while ((*pchk-- == (OS_STK)0) && (size > 0u)) { /* Compute the number of zero entries on the stk */ + nfree++; + size--; + } +#endif + return (nfree); +} diff --git a/Ports/ARM/Generic/RealView/os_cpu_fpu_a.asm b/Ports/ARM/Generic/RealView/os_cpu_fpu_a.asm new file mode 100644 index 0000000..984f107 --- /dev/null +++ b/Ports/ARM/Generic/RealView/os_cpu_fpu_a.asm @@ -0,0 +1,85 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Generic ARM Port +; VFP SUPPORT +; +; Filename : os_cpu_fpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : ARM7 or ARM9 +; Mode : ARM or Thumb +; Toolchain : RealView Development Suite +; RealView Microcontroller Development Kit (MDK) +; ARM Developer Suite (ADS) +; Keil uVision +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXPORT OS_CPU_FP_Restore + EXPORT OS_CPU_FP_Save + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + AREA CODE, CODE, READONLY + CODE32 + +;********************************************************************************************************* +; RESTORE VFP REGISTERS +; void OS_CPU_FP_Restore(void *pblk) +; +; Description : This function is called to restore the contents of the VFP registers during a context +; switch. It is assumed that a pointer to a storage area for the VFP registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). + +; Arguments : pblk is passed to this function in R0 when called. +; +; Notes : Floating point math should NEVER be performed within an ISR as this will corrupt +; the state of the VFP registers for the last VFP task that ran. Instead, all floating +; point math should be performed within floating point enabled tasks ONLY. +;********************************************************************************************************* + +OS_CPU_FP_Restore + FLDMIAS R0!, {S0-S31} ; Restore the VFP registers from pblk + BX LR ; Return to calling function + +;********************************************************************************************************* +; SAVE VFP REGISTERS +; void OS_CPU_FP_Save(void *pblk) +; +; Description : This function is called to save the contents of the VFP registers during a context +; switch. It is assumed that a pointer to a storage area for the VFP registers is placed +; in the task's TCB (i.e. .OSTCBExtPtr). +; +; Arguments : pblk is passed to this function in R0 when called. +; +; Notes : Floating point math should NEVER be performed within an ISR as this will corrupt +; the state of the VFP registers for the last VFP task that ran. Instead, all floating +; point math should be performed within floating point enabled tasks ONLY. +;********************************************************************************************************* + +OS_CPU_FP_Save + FSTMIAS R0!, {S0-S31} ; Save the VFP registers in pblk + BX LR ; Return to calling function + + + END diff --git a/Ports/ARM/Generic/RealView/os_dbg.c b/Ports/ARM/Generic/RealView/os_dbg.c new file mode 100644 index 0000000..80bc92e --- /dev/null +++ b/Ports/ARM/Generic/RealView/os_dbg.c @@ -0,0 +1,326 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* Generic ARM Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : ARM7 or ARM9 +* Mode : ARM or Thumb +* Toolchain : RealView Development Suite +* RealView Microcontroller Development Kit (MDK) +* ARM Developer Suite (ADS) +* Keil uVision +********************************************************************************************************* +*/ + +#include + +#pragma O0 /* Do not optimize this file. */ + + /* The following #define could tell the compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM7/AT91/ARM/IAR/os_cpu.h b/Ports/ARM7/AT91/ARM/IAR/os_cpu.h new file mode 100644 index 0000000..4614826 --- /dev/null +++ b/Ports/ARM7/AT91/ARM/IAR/os_cpu.h @@ -0,0 +1,113 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: NOT IMPLEMENTED +* Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: NOT IMPLEMENTED +* Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. This is the prefered method to disable interrupts. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Restore interrupts */ +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT32U OSIntCtxSwFlag; /* Used to flag a context switch */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +#endif diff --git a/Ports/ARM7/AT91/ARM/IAR/os_cpu_a.s b/Ports/ARM7/AT91/ARM/IAR/os_cpu_a.s new file mode 100644 index 0000000..0534e10 --- /dev/null +++ b/Ports/ARM7/AT91/ARM/IAR/os_cpu_a.s @@ -0,0 +1,262 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARM7 Port +; IAR C Compiler +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntCtxSwFlag + + EXTERN OSIntEnter + EXTERN OSIntExit + + EXTERN OSTaskSwHook + + + PUBLIC OSStartHighRdy ; Functions declared in this file + + PUBLIC OSCtxSw + PUBLIC OS_IntCtxSw + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + +NO_INT EQU 0xC0 ; Mask used to disable interrupts (Both FIR and IRQ) + + + +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + + RSEG NEARFUNC_A:CODE:NOROOT(2) + CODE32 + +OSStartHighRdy + + BL OSTaskSwHook ; Call user defined task switch hook + + LDR R4,??OS_Running ; OSRunning = TRUE + MOV R5,#1 + STRB R5,[R4] + + LDR R4,??OS_TCBHighRdy ; Get highest priority task TCB address + LDR R4,[R4] ; get stack pointer + LDR SP,[R4] ; switch to the new stack + + LDMFD SP!,{R4} ; pop new task's spsr + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's CPSR + MSR CPSR_cxsf,R4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's r0-r12,lr & pc + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; +; Note(s): Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +;********************************************************************************************************* + + RSEG NEARFUNC_A:CODE:NOROOT(2) + CODE32 + +OSCtxSw + STMFD SP!,{LR} ; push pc (lr should be pushed in place of PC) + STMFD SP!,{R0-R12,LR} ; push lr & register file + MRS R4,CPSR + STMFD SP!,{R4} ; push current psr + MRS R4,SPSR + STMFD SP!,{R4} ; push current spsr + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R6,[r5] + STRB R6,[r4] + + LDR R4,??OS_TCBCur ; Get current task's OS_TCB address + LDR R5,[r4] + STR SP,[r5] ; store sp in preempted tasks's TCB + + BL OSTaskSwHook ; call Task Switch Hook + + LDR R6,??OS_TCBHighRdy ; Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] ; get new task's stack pointer + + STR R6,[R4] ; OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} ; pop new task's spsr + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's psr + MSR CPSR_cxsf,r4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's r0-r12,lr & pc + + +;********************************************************************************************************* +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) OS_CPU_SaveSR() is implemented as recommended by Atmel's application note: +; +; "Disabling Interrupts at Processor Level" +;********************************************************************************************************* + +OS_CPU_SR_Save + MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts + ORR R1,R0,#NO_INT + MSR CPSR_c,R1 + MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags + AND R1,R1,#NO_INT + CMP R1,#NO_INT + BNE OS_CPU_SR_Save ; Not properly disabled (try again) + MOV PC,LR ; Disabled, return the original CPSR contents in R0 + + +OS_CPU_SR_Restore + MSR CPSR_c,R0 + MOV PC,LR + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description: This code performs a context switch if a higher priority task has been made ready-to-run +; during an ISR. +;********************************************************************************************************* + +OS_IntCtxSw + LDR R0,??OS_IntCtxSwFlag ; OSIntCtxSwFlag = FALSE + MOV R1,#0 + STR R1,[R0] + + LDMFD SP!,{R0-R3,R12,LR} ; Clean up IRQ stack + STMFD SP!,{R0-R3} ; We will use R0-R3 as temporary registers + MOV R1,SP + ADD SP,SP,#16 + SUB R2,LR,#4 + + MRS R3,SPSR ; Disable interrupts for when we go back to SVC mode + ORR R0,R3,#NO_INT + MSR SPSR_c,R0 + + LDR R0,=.+8 ; Switch back to SVC mode (Code below, current location + 2 instructions) + MOVS PC,R0 ; Restore PC and CPSR + + ; SAVE OLD TASK'S CONTEXT ONTO OLD TASK'S STACK + STMFD SP!,{R2} ; Push task's PC + STMFD SP!,{R4-R12,LR} ; Push task's LR,R12-R4 + MOV R4,R1 ; Move R0-R3 from IRQ stack to SVC stack + MOV R5,R3 + LDMFD R4!,{R0-R3} ; Load R0-R3 from IRQ stack + STMFD SP!,{R0-R3} ; Push R0-R3 + STMFD SP!,{R5} ; Push task's CPSR + MRS R4,SPSR + STMFD SP!,{R4} ; Push task's SPSR + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R5,[R5] + STRB R5,[R4] + + LDR R4,??OS_TCBCur ; Get current task's OS_TCB address + LDR R5,[R4] + STR SP,[R5] ; store sp in preempted tasks's TCB + + BL OSTaskSwHook ; call Task Switch Hook + + LDR R6,??OS_TCBHighRdy ; Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] ; get new task's stack pointer + + STR R6,[R4] ; OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} ; pop new task's spsr + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's psr + MSR CPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's r0-r12,lr & pc + + + +;********************************************************************************************************* +; POINTERS TO VARIABLES +;********************************************************************************************************* + + DATA + +??OS_IntCtxSwFlag: + DC32 OSIntCtxSwFlag + +??OS_PrioCur: + DC32 OSPrioCur + +??OS_PrioHighRdy: + DC32 OSPrioHighRdy + +??OS_Running: + DC32 OSRunning + +??OS_TCBCur: + DC32 OSTCBCur + +??OS_TCBHighRdy: + DC32 OSTCBHighRdy + + END diff --git a/Ports/ARM7/AT91/ARM/IAR/os_cpu_c.c b/Ports/ARM7/AT91/ARM/IAR/os_cpu_c.c new file mode 100644 index 0000000..70aa3b7 --- /dev/null +++ b/Ports/ARM7/AT91/ARM/IAR/os_cpu_c.c @@ -0,0 +1,280 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARM7 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#define ARM_SYS_MODE (0x0000001FL) + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSIntCtxSwFlag = 0; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SYS mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + *(stk) = (OS_STK)task; /* Entry Point */ + *(--stk) = (INT32U)0x14141414L; /* LR */ + *(--stk) = (INT32U)0x12121212L; /* R12 */ + *(--stk) = (INT32U)0x11111111L; /* R11 */ + *(--stk) = (INT32U)0x10101010L; /* R10 */ + *(--stk) = (INT32U)0x09090909L; /* R9 */ + *(--stk) = (INT32U)0x08080808L; /* R8 */ + *(--stk) = (INT32U)0x07070707L; /* R7 */ + *(--stk) = (INT32U)0x06060606L; /* R6 */ + *(--stk) = (INT32U)0x05050505L; /* R5 */ + *(--stk) = (INT32U)0x04040404L; /* R4 */ + *(--stk) = (INT32U)0x03030303L; /* R3 */ + *(--stk) = (INT32U)0x02020202L; /* R2 */ + *(--stk) = (INT32U)0x01010101L; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* CPSR (Enable both IRQ and FIQ interrupts) */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* SPSR */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* ARM SPECIFIC CODE +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description : This function is called by the OSIntExit() to perform a context switch at the completion +* of an ISR. However, instead of actually doing the context switch from within OSIntExit(), +* we simply set a flag (OSIntCtxSwFlag) and defer the actual context switch until the actual +* ISR completes (see OS_CPU_IRQ_ISR()). +* +* Arguments : none +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSIntCtxSwFlag = TRUE; /* Indicate that a context switch from ISR is needed */ +} diff --git a/Ports/ARM7/AT91/ARM/IAR/os_dbg.c b/Ports/ARM7/AT91/ARM/IAR/os_dbg.c new file mode 100644 index 0000000..a9e72ff --- /dev/null +++ b/Ports/ARM7/AT91/ARM/IAR/os_dbg.c @@ -0,0 +1,268 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM7/AT91/Thumb/IAR/os_cpu.h b/Ports/ARM7/AT91/Thumb/IAR/os_cpu.h new file mode 100644 index 0000000..1cbceb6 --- /dev/null +++ b/Ports/ARM7/AT91/Thumb/IAR/os_cpu.h @@ -0,0 +1,105 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: NOT IMPLEMENTED +* Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: NOT IMPLEMENTED +* Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. This is the prefered method to disable interrupts. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Restore interrupts */ +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OSCPUSaveSR(void); +void OSCPURestoreSR(OS_CPU_SR cpu_sr); +#endif + +#endif diff --git a/Ports/ARM7/AT91/Thumb/IAR/os_cpu_a.s b/Ports/ARM7/AT91/Thumb/IAR/os_cpu_a.s new file mode 100644 index 0000000..7fa2745 --- /dev/null +++ b/Ports/ARM7/AT91/Thumb/IAR/os_cpu_a.s @@ -0,0 +1,338 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARM7 Port, Thumb Mode +; IAR C Compiler +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntNesting + + EXTERN OSIntEnter + EXTERN OSIntExit + + EXTERN OSTaskSwHook + + EXTERN Tmr_TickHandler + + + PUBLIC OSStartHighRdy ; Functions declared in this file + + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSCPUSaveSR + PUBLIC OSCPURestoreSR + PUBLIC OSTickISR + + +NO_INT EQU 0xC0 ; Mask used to disable interrupts (Both FIR and IRQ) + + + +;********************************************************************************************************* +; INTERRUPT VECTORS +;********************************************************************************************************* + + + COMMON INTVEC:CODE:ROOT(2) + CODE32 + ORG 0x18 + LDR PC,[PC,#-0x0F20] ; Vector to the proper ISR for the AT91 using the AIC. + + ORG 0x1C + LDR PC,[PC,#-0x0F20] + + +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + + RSEG NEARFUNC_A:CODE:NOROOT(2) + CODE32 + +OSStartHighRdy: + LDR R4,??OSTaskSwHook ; OSTaskSwHook() + MOV LR,PC + BX R4 + + LDR R4,??OS_Running ; OSRunning = TRUE + MOV R5,#1 + STRB R5,[R4] + + LDR R4,??OS_TCBHighRdy ; SP = OSTCBHighRdy->OSTCBStkPtr + LDR R4,[R4] + LDR SP,[R4] + + ; ---- RESTORE CONTEXT OF HIGH PRIORITY TASK ---- + LDMFD SP!,{R4} ; Pop new task's SPSR + MSR SPSR_cxsf,R4 ; T-bit should be 1 indicating Task will run in Thumb mode + + LDMFD SP!,{R0-R12,LR,PC}^ ; Pop new task's R0-R12, LR, PC and copy SPSR into CPSR + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; +; Note(s): 1) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; 2) It is assumed that OSCtxSw() is called from Thumb code and thus bit 0 of the LR register is +; set to 1. +; 3) We need to save the context of the current task as if the task was interrupted and all the +; registers were saved on the stack of that task. For that, the SPSR T-bit must be set and the +; LR must point at the return PC of the Thumb task. Upon calling OSCtxSw(), the LR contains PC+1 +; (indicating that the caller is in Thumb mode). We don't need that information since we will +; alter the SPSR to reflect that the caller is a Thumb mode function. +;********************************************************************************************************* + +OSCtxSw: + ; ---- SAVE CONTEXT OF CURRENT TASK ---- + BIC LR,LR,#1 ; Correct return address + STMFD SP!,{LR} ; Push return PC + + ADD LR,LR,#1 + STMFD SP!,{LR} ; Push original LR + + STMFD SP!,{R0-R12} ; Push remaining registers + + MRS R4,CPSR ; Push the SPSR (a copy of the CPSR but with the T-bit set) + ORR R4,R4,#0x20 + STMFD SP!,{R4} + + LDR R4,??OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP + LDR R5,[r4] + STR SP,[r5] + + LDR R6,??OSTaskSwHook ; OSTaskSwHook() + MOV LR,PC + BX R6 + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R5,[R5] + STRB R5,[R4] + + LDR R6,??OS_TCBHighRdy ; OSTCBCur = OSTCBHighRdy + LDR R4,??OS_TCBCur + LDR R6,[R6] + STR R6,[R4] + + LDR SP,[R6] ; SP = OSTCBHighRdy->OSTCBStkPtr + + ; ---- RESTORE CONTEXT OF HIGH PRIORITY TASK ---- + LDMFD SP!,{R4} ; Pop new task's SPSR + MSR SPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC}^ ; Pop new task's R0-R12,LR and PC + + +;********************************************************************************************************* +; IRQ HANDLER +; +; Description: This handles all the IRQs +;********************************************************************************************************* + +OSTickISR: + ; ---- SAVE CONTEXT OF CURRENT TASK ---- + ; IRQ Mode: + STMFD SP!,{R0-R3,R12,LR} ; Push working registers on the IRQ stack + + MOV R1,SP ; Save IRQ SP + ADD SP,SP,#(6*4) ; Clean up IRQ stack + + SUB R2,LR,#4 ; Correct return address and save + + MRS R3,SPSR ; Save SPSR of interrupted task + + MOV R0,#0xD3 ; Disable interrupts for when we go back to SVC mode + MSR SPSR_c,R0 ; Prepare to switch to SVC mode + + LDR R0,=.+8 ; Setup PC for SVC mode code (see below), current location + 2 instructions + MOVS PC,R0 ; Restore PC and CPSR + + ; SVC Mode: + STMFD SP!,{R2} ; Push task's returns address + STMFD SP!,{LR} ; Push task's LR + STMFD SP!,{R4-R12} ; Push task's R12-R4 + MOV R4,R1 ; Move R0-R3 from IRQ stack to SVC stack + MOV R5,R3 + LDMFD R4!,{R0-R3} ; Load R0-R3 from IRQ stack + STMFD SP!,{R0-R3} ; Push R0-R3 + STMFD SP!,{R5} ; Push task's SPSR + + ; ---- HANDLE NESTING COUNTER ---- + LDR R0,??OSIntNesting ; OSIntNesting++; + LDRB R1,[R0] + ADD R1,R1,#1 + STRB R1,[R0] + + CMP R1,#1 ; if (OSIntNesting == 1) { + BNE OSTickISR_1 + + LDR R4,??OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP + LDR R5,[R4] + STR SP,[R5] + +OSTickISR_1: ; } + + LDR R3,??Tmr_TickHandler ; Handle timer interrupt (see BSP.C) + MOV LR,PC + BX R3 + + ; ---- EXIT INTERRUPT ---- + LDR R3,??OSIntExit ; OSIntExit() + MOV LR,PC + BX R3 + ; ---- RESTORE CONTEXT OF HIGH PRIORITY TASK ---- + LDMFD SP!,{R4} ; Pop new task's SPSR + MSR SPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC}^ ; Pop new task's R0-R12,LR and PC + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description: This code performs a context switch if a higher priority task has been made ready-to-run +; during an ISR. +;********************************************************************************************************* + +OSIntCtxSw: + LDR R6,??OSTaskSwHook ; OSTaskSwHook() + MOV LR,PC + BX R6 + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R5,[R5] + STRB R5,[R4] + + LDR R6,??OS_TCBHighRdy ; OSTCBCur = OSTCBHighRdy + LDR R4,??OS_TCBCur + LDR R6,[R6] + STR R6,[R4] + + LDR SP,[R6] ; SP = OSTCBHighRdy->OSTCBStkPtr + + ; ---- RESTORE CONTEXT OF HIGH PRIORITY TASK ---- + LDMFD SP!,{R4} ; Pop new task's SPSR + MSR SPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC}^ ; Pop new task's R0-R12,LR and return from IRQ (SPSR copied to CPSR) + + +;********************************************************************************************************* +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OSCPUSaveSR(void); +; void OSCPURestoreSR(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OSCPUSaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OSCPURestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) OSCPUSaveSR() is implemented as recommended by Atmel's application note: +; +; "Disabling Interrupts at Processor Level" +;********************************************************************************************************* + +OSCPUSaveSR: + MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts + ORR R1,R0,#NO_INT + MSR CPSR_c,R1 + MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags + AND R1,R1,#NO_INT + CMP R1,#NO_INT + BNE OSCPUSaveSR ; Not properly disabled (try again) + BX LR ; Disabled, return the original CPSR contents in R0 + + +OSCPURestoreSR: + MSR CPSR_c,R0 + BX LR + + +;********************************************************************************************************* +; POINTERS TO VARIABLES +;********************************************************************************************************* + + DATA + +??OSIntEnter: + DC32 OSIntEnter | 0x01 + +??OSIntExit: + DC32 OSIntExit | 0x01 + +??Tmr_TickHandler: + DC32 Tmr_TickHandler | 0x01 + +??OSTaskSwHook: + DC32 OSTaskSwHook + +??OSIntNesting: + DC32 OSIntNesting + +??OS_PrioCur: + DC32 OSPrioCur + +??OS_PrioHighRdy: + DC32 OSPrioHighRdy + +??OS_Running: + DC32 OSRunning + +??OS_TCBCur: + DC32 OSTCBCur + +??OS_TCBHighRdy: + DC32 OSTCBHighRdy + + END diff --git a/Ports/ARM7/AT91/Thumb/IAR/os_cpu_c.c b/Ports/ARM7/AT91/Thumb/IAR/os_cpu_c.c new file mode 100644 index 0000000..216c6fb --- /dev/null +++ b/Ports/ARM7/AT91/Thumb/IAR/os_cpu_c.c @@ -0,0 +1,252 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARM7 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#define ARM_SVC_THUMB_MODE (0x00000033L) + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SVC mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + *(--stk) = ((INT32U)task & ~0x01); /* PC */ + *(--stk) = (INT32U)0x14141414L; /* LR */ + *(--stk) = (INT32U)0x12121212L; /* R12 */ + *(--stk) = (INT32U)0x11111111L; /* R11 */ + *(--stk) = (INT32U)0x10101010L; /* R10 */ + *(--stk) = (INT32U)0x09090909L; /* R9 */ + *(--stk) = (INT32U)0x08080808L; /* R8 */ + *(--stk) = (INT32U)0x07070707L; /* R7 */ + *(--stk) = (INT32U)0x06060606L; /* R6 */ + *(--stk) = (INT32U)0x05050505L; /* R5 */ + *(--stk) = (INT32U)0x04040404L; /* R4 */ + *(--stk) = (INT32U)0x03030303L; /* R3 */ + *(--stk) = (INT32U)0x02020202L; /* R2 */ + *(--stk) = (INT32U)0x01010101L; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + *(--stk) = (INT32U)ARM_SVC_THUMB_MODE; /* SPSR (Enable both IRQ and FIQ interrupts) */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/ARM7/AT91/Thumb/IAR/os_dbg.c b/Ports/ARM7/AT91/Thumb/IAR/os_dbg.c new file mode 100644 index 0000000..a9e72ff --- /dev/null +++ b/Ports/ARM7/AT91/Thumb/IAR/os_dbg.c @@ -0,0 +1,268 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM7/Generic/ARM/IAR/os_cpu.h b/Ports/ARM7/Generic/ARM/IAR/os_cpu.h new file mode 100644 index 0000000..f671d05 --- /dev/null +++ b/Ports/ARM7/Generic/ARM/IAR/os_cpu.h @@ -0,0 +1,128 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Restore interrupts */ +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT32U OSIntCtxSwFlag; /* Used to flag a context switch */ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0 +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +#endif + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +#if OS_CPU_INT_DIS_MEAS_EN > 0 +void OS_CPU_IntDisMeasInit(void); +void OS_CPU_IntDisMeasStart(void); +void OS_CPU_IntDisMeasStop(void); +INT16U OS_CPU_IntDisMeasTmrRd(void); +#endif + +#endif diff --git a/Ports/ARM7/Generic/ARM/IAR/os_cpu_a.s b/Ports/ARM7/Generic/ARM/IAR/os_cpu_a.s new file mode 100644 index 0000000..2945fc9 --- /dev/null +++ b/Ports/ARM7/Generic/ARM/IAR/os_cpu_a.s @@ -0,0 +1,269 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARM7 Port +; IAR C Compiler +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntCtxSwFlag + + EXTERN OSIntEnter + EXTERN OSIntExit + + EXTERN OSTaskSwHook + + + PUBLIC OSStartHighRdy ; Functions declared in this file + + PUBLIC OSCtxSw + PUBLIC OS_IntCtxSw + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + +NO_INT EQU 0xC0 ; Mask used to disable interrupts (Both FIR and IRQ) + + + +;********************************************************************************************************* +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) OS_CPU_SaveSR() is implemented as recommended by Atmel's application note: +; +; "Disabling Interrupts at Processor Level" +;********************************************************************************************************* + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +OS_CPU_SR_Save + MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts + ORR R1,R0,#NO_INT + MSR CPSR_c,R1 + MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags + AND R1,R1,#NO_INT + CMP R1,#NO_INT + BNE OS_CPU_SR_Save ; Not properly disabled (try again) + MOV PC,LR ; Disabled, return the original CPSR contents in R0 + + +OS_CPU_SR_Restore + MSR CPSR_c,R0 + MOV PC,LR + + +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +OSStartHighRdy + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R4,??OS_Running ; OSRunning = TRUE + MOV R5,#1 + STRB R5,[R4] + + LDR R4,??OS_TCBHighRdy ; Get highest priority task TCB address + LDR R4,[R4] ; get stack pointer + LDR SP,[R4] ; switch to the new stack + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's CPSR + MSR CPSR_cxsf,R4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; +; Note(s): Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +;********************************************************************************************************* + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +OSCtxSw + STMFD SP!,{LR} ; push PC (lr should be pushed in place of PC) + STMFD SP!,{R0-R12,LR} ; push LR & register file + MRS R4,CPSR + STMFD SP!,{R4} ; push current PSR + MRS R4,SPSR + STMFD SP!,{R4} ; push current SPSR + + LDR R4,??OS_TCBCur ; Get current task's OS_TCB address + LDR R5,[R4] + STR SP,[R5] ; store SP in preempted tasks's TCB + + BL OSTaskSwHook ; OSTaskSwHook(); + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R6,[R5] + STRB R6,[R4] + + LDR R4,??OS_TCBCur ; Get the current task's OS_TCB address + LDR R6,??OS_TCBHighRdy ; Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] ; get new task's stack pointer + + STR R6,[R4] ; OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's PSR + MSR CPSR_cxsf,r4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description: This code performs a context switch if a higher priority task has been made ready-to-run +; during an ISR. +;********************************************************************************************************* + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +OS_IntCtxSw + LDR R0,??OS_IntCtxSwFlag ; OSIntCtxSwFlag = FALSE + MOV R1,#0 + STR R1,[R0] + + LDMFD SP!,{R0-R3,R12,LR} ; Clean up IRQ stack + STMFD SP!,{R0-R3} ; We will use R0-R3 as temporary registers + MOV R1,SP + ADD SP,SP,#16 + SUB R2,LR,#4 + + MRS R3,SPSR ; Disable interrupts for when we go back to SYS mode + ORR R0,R3,#NO_INT + MSR SPSR_c,R0 + + LDR R0,=.+8 ; Switch back to SYS mode (Code below, current location + 2 instructions) + MOVS PC,R0 ; Restore PC and CPSR + + ; SAVE OLD TASK'S CONTEXT ONTO OLD TASK'S STACK + STMFD SP!,{R2} ; Push task's PC + STMFD SP!,{R4-R12,LR} ; Push task's LR,R12-R4 + MOV R4,R1 ; Move R0-R3 from IRQ stack to SYS stack + MOV R5,R3 + LDMFD R4!,{R0-R3} ; Load R0-R3 from IRQ stack + STMFD SP!,{R0-R3} ; Push R0-R3 + STMFD SP!,{R5} ; Push task's CPSR + MRS R4,SPSR + STMFD SP!,{R4} ; Push task's SPSR + + LDR R4,??OS_TCBCur ; OSTCBCur->OSTCBStkPtr = SP + LDR R5,[R4] + STR SP,[R5] + + BL OSTaskSwHook ; call Task Switch Hook + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R6,[R5] + STRB R6,[R4] + + LDR R4,??OS_TCBCur ; OSTCBCur = OSTCBHighRdy + LDR R6,??OS_TCBHighRdy + LDR R6,[R6] + LDR SP,[R6] + + STR R6,[R4] + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's PSR + MSR CPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + +;********************************************************************************************************* +; POINTERS TO VARIABLES +;********************************************************************************************************* + + DATA + +??OS_IntCtxSwFlag: + DC32 OSIntCtxSwFlag + +??OS_PrioCur: + DC32 OSPrioCur + +??OS_PrioHighRdy: + DC32 OSPrioHighRdy + +??OS_Running: + DC32 OSRunning + +??OS_TCBCur: + DC32 OSTCBCur + +??OS_TCBHighRdy: + DC32 OSTCBHighRdy + + END diff --git a/Ports/ARM7/Generic/ARM/IAR/os_cpu_c.c b/Ports/ARM7/Generic/ARM/IAR/os_cpu_c.c new file mode 100644 index 0000000..1e4a8aa --- /dev/null +++ b/Ports/ARM7/Generic/ARM/IAR/os_cpu_c.c @@ -0,0 +1,346 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARM7 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif + +#define ARM_SYS_MODE (0x0000001FL) + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSIntCtxSwFlag = 0; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SYS mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + *(stk) = (OS_STK)task; /* Entry Point */ + *(--stk) = (INT32U)0x14141414L; /* R14 (LR) */ + *(--stk) = (INT32U)0x12121212L; /* R12 */ + *(--stk) = (INT32U)0x11111111L; /* R11 */ + *(--stk) = (INT32U)0x10101010L; /* R10 */ + *(--stk) = (INT32U)0x09090909L; /* R9 */ + *(--stk) = (INT32U)0x08080808L; /* R8 */ + *(--stk) = (INT32U)0x07070707L; /* R7 */ + *(--stk) = (INT32U)0x06060606L; /* R6 */ + *(--stk) = (INT32U)0x05050505L; /* R5 */ + *(--stk) = (INT32U)0x04040404L; /* R4 */ + *(--stk) = (INT32U)0x03030303L; /* R3 */ + *(--stk) = (INT32U)0x02020202L; /* R2 */ + *(--stk) = (INT32U)0x01010101L; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* CPSR (Enable both IRQ and FIQ interrupts) */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* SPSR */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* ARM SPECIFIC CODE +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* ARM SPECIFIC CODE +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0 +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0; + OS_CPU_IntDisMeasCntsEnter = 0; + OS_CPU_IntDisMeasCntsExit = 0; + OS_CPU_IntDisMeasCntsMax = 0; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1) { + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + INT16U delta; + + + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasNestingCtr--; + if (OS_CPU_IntDisMeasNestingCtr == 0) { + delta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (delta > OS_CPU_IntDisMeasCntsMax) { + OS_CPU_IntDisMeasCntsMax = delta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description : This function is called by the OSIntExit() to perform a context switch at the completion +* of an ISR. However, instead of actually doing the context switch from within OSIntExit(), +* we simply set a flag (OSIntCtxSwFlag) and defer the actual context switch until the actual +* ISR completes (see OS_CPU_IRQ_ISR()). +* +* Arguments : none +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSIntCtxSwFlag = TRUE; /* Indicate that a context switch from ISR is needed */ +} diff --git a/Ports/ARM7/Generic/ARM/IAR/os_dbg.c b/Ports/ARM7/Generic/ARM/IAR/os_dbg.c new file mode 100644 index 0000000..8678915 --- /dev/null +++ b/Ports/ARM7/Generic/ARM/IAR/os_dbg.c @@ -0,0 +1,268 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu.h b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu.h new file mode 100644 index 0000000..5f8c92a --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu.h @@ -0,0 +1,115 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: NOT IMPLEMENTED +* Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: NOT IMPLEMENTED +* Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. This is the prefered method to disable interrupts. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_RestoreSR(cpu_sr)) /* Restore interrupts */ +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT32U OSIntCtxSwFlag; /* Used to flag a context switch */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OS_CPU_SaveSR(void); +void OS_CPU_RestoreSR(OS_CPU_SR cpu_sr); +#endif + +void OS_CPU_Tick_ISR(void); + +#endif diff --git a/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_a.s b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_a.s new file mode 100644 index 0000000..ba7450b --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_a.s @@ -0,0 +1,254 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARM7 Port +@ Sharp LH79520 +@ GNU C Compiler +@ +@ Filename : os_cpu_a.s +@ Version : V2.93.00 +@******************************************************************************************************** + + .extern OSRunning @ .external references + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSIntCtxSwFlag + + .extern OSIntEnter + .extern OSIntExit + + .extern OSTaskSwHook + + .extern Tmr_TickHandler + + + .global OSStartHighRdy @ Functions declared in this file + + .global OSCtxSw + .global OS_IntCtxSw + + .global OS_CPU_SaveSR + .global OS_CPU_RestoreSR + .global OS_CPU_Tick_ISR + + .equ NO_INT, 0xC0 @ Mask used to disable interrupts (Both FIQ and IRQ) + +@********************************************************************************************************* +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note : OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to TRUE, +@ c) Switch to the highest priority task. +@********************************************************************************************************* + + .code 32 + +OSStartHighRdy: + + BL OSTaskSwHook @ Call user defined task switch hook + + LDR R4,=OSRunning @ OSRunning = TRUE + MOV R5,#1 + STRB R5,[R4] + + LDR R4,=OSTCBHighRdy @ Get highest priority task TCB address + LDR R4,[R4] @ get stack pointer + LDR SP,[R4] @ switch to the new stack + + LDMFD SP!,{R4} @ pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} @ pop new task's CPSR + MSR CPSR_cxsf,R4 + LDMFD SP!,{R0-R12,LR,PC} @ pop new task's R0-R12,LR & PC + +@********************************************************************************************************* +@ PERFORM A CONTEXT SWITCH (From task level) +@ +@ Note(s): Upon entry: +@ OSTCBCur points to the OS_TCB of the task to suspend +@ OSTCBHighRdy points to the OS_TCB of the task to resume +@********************************************************************************************************* + + .code 32 + +OSCtxSw: + STMFD SP!,{LR} @ push pc (lr should be pushed in place of PC) + STMFD SP!,{R0-R12,LR} @ push lr & register file + MRS R4,CPSR + STMFD SP!,{R4} @ push current PSR + MRS R4,SPSR + STMFD SP!,{R4} @ push current SPSR + + LDR R4,=OSPrioCur @ OSPrioCur = OSPrioHighRdy + LDR R5,=OSPrioHighRdy + LDRB R6,[r5] + STRB R6,[r4] + + LDR R4,=OSTCBCur @ Get current task's OS_TCB address + LDR R5,[r4] + STR SP,[r5] @ store sp in preempted tasks's TCB + + BL OSTaskSwHook @ call Task Switch Hook + + LDR R6,=OSTCBHighRdy @ Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] @ get new task's stack pointer + + STR R6,[R4] @ OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} @ pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} @ pop new task's PSR + MSR CPSR_cxsf,r4 + LDMFD SP!,{R0-R12,LR,PC} @ pop new task's R0-R12,LR & PC + +@********************************************************************************************************* +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SaveSR(void)@ +@ void OS_CPU_RestoreSR(OS_CPU_SR cpu_sr)@ +@ +@ +@ Note(s) : 1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +@ OS_CPU_SR cpu_sr@ +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL()@ /* cpu_sr = OS_CPU_SaveSR()@ */ +@ : +@ : +@ OS_EXIT_CRITICAL()@ /* OS_CPU_RestoreSR(cpu_sr)@ */ +@ : +@ : +@ } +@ +@ 2) OS_CPU_SaveSR() is implemented as recommended by Atmel's application note: +@ +@ "Disabling Interrupts at Processor Level" +@********************************************************************************************************* + +OS_CPU_SaveSR: + MRS R0,CPSR @ Set IRQ and FIQ bits in CPSR to disable all interrupts + ORR R1,R0,#NO_INT + MSR CPSR_c,R1 + MRS R1,CPSR @ Confirm that CPSR contains the proper interrupt disable flags + AND R1,R1,#NO_INT + CMP R1,#NO_INT + BNE OS_CPU_SaveSR @ Not properly disabled (try again) + MOV PC,LR @ Disabled, return the original CPSR contents in R0 + +OS_CPU_RestoreSR: + MSR CPSR_c,R0 + MOV PC,LR + +@********************************************************************************************************* +@ TICK HANDLER +@ +@ Description: This handles all the Timer #0 interrupt which is used to generate the uC/OS-II tick. +@********************************************************************************************************* + +OS_CPU_Tick_ISR: + + STMFD SP!,{R0-R3,R12,LR} + + BL OSIntEnter @ Indicate beginning of ISR + BL Tmr_TickHandler @ Handle interrupt (see BSP.C) + BL OSIntExit @ Indicate end of ISR + + LDR R0,=OSIntCtxSwFlag @ See if we need to do a context switch + LDR R1,[R0] + CMP R1,#1 + BEQ OS_IntCtxSw @ Yes, Switch to Higher Priority Task + + LDMFD SP!,{R0-R3,R12,LR} @ No, Restore registers of interrupted task's stack + SUBS PC,LR,#4 @ Return from IRQ + +@********************************************************************************************************* +@ INTERRUPT LEVEL CONTEXT SWITCH +@ +@ Description: This code performs a context switch if a higher priority task has been made ready-to-run +@ during an ISR. +@********************************************************************************************************* + +OS_IntCtxSw: + LDR R0,=OSIntCtxSwFlag @ OSIntCtxSwFlag = FALSE + MOV R1,#0 + STR R1,[R0] + + LDMFD SP!,{R0-R3,R12,LR} @ Clean up IRQ stack + STMFD SP!,{R0-R3} @ We will use R0-R3 as temporary registers + MOV R1,SP + ADD SP,SP,#16 + SUB R2,LR,#4 + + MRS R3,SPSR @ Disable interrupts for when we go back to SVC mode + ORR R0,R3,#NO_INT + MSR SPSR_c,R0 + + LDR R0,=.+8 @ Switch back to SVC mode (Code below, current location + 2 instructions) + MOVS PC,R0 @ Restore PC and CPSR + + @ SAVE OLD TASK'S CONTEXT ONTO OLD TASK'S STACK + STMFD SP!,{R2} @ Push task's PC + STMFD SP!,{R4-R12,LR} @ Push task's LR,R12-R4 + MOV R4,R1 @ Move R0-R3 from IRQ stack to SVC stack + MOV R5,R3 + LDMFD R4!,{R0-R3} @ Load R0-R3 from IRQ stack + STMFD SP!,{R0-R3} @ Push R0-R3 + STMFD SP!,{R5} @ Push task's CPSR + MRS R4,SPSR + STMFD SP!,{R4} @ Push task's SPSR + + LDR R4,=OSPrioCur @ OSPrioCur = OSPrioHighRdy + LDR R5,=OSPrioHighRdy + LDRB R5,[R5] + STRB R5,[R4] + + LDR R4,=OSTCBCur @ Get current task's OS_TCB address + LDR R5,[R4] + STR SP,[R5] @ store sp in preempted tasks's TCB + + BL OSTaskSwHook @ call Task Switch Hook + + LDR R6,=OSTCBHighRdy @ Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] @ get new task's stack pointer + + STR R6,[R4] @ OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} @ pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} @ pop new task's PSR + MSR CPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC} @ pop new task's R0-R12,LR & PC + + .ltorg diff --git a/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_c.c b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_c.c new file mode 100644 index 0000000..0f0a002 --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_cpu_c.c @@ -0,0 +1,280 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARM7 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#define ARM_SVC_MODE (0x00000013L) + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSIntCtxSwFlag = 0; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SVC mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + *(stk) = (OS_STK)task; /* Entry Point */ + *(--stk) = (INT32U)0x14141414L; /* LR */ + *(--stk) = (INT32U)0x12121212L; /* R12 */ + *(--stk) = (INT32U)0x11111111L; /* R11 */ + *(--stk) = (INT32U)0x10101010L; /* R10 */ + *(--stk) = (INT32U)0x09090909L; /* R9 */ + *(--stk) = (INT32U)0x08080808L; /* R8 */ + *(--stk) = (INT32U)0x07070707L; /* R7 */ + *(--stk) = (INT32U)0x06060606L; /* R6 */ + *(--stk) = (INT32U)0x05050505L; /* R5 */ + *(--stk) = (INT32U)0x04040404L; /* R4 */ + *(--stk) = (INT32U)0x03030303L; /* R3 */ + *(--stk) = (INT32U)0x02020202L; /* R2 */ + *(--stk) = (INT32U)0x01010101L; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + *(--stk) = (INT32U)ARM_SVC_MODE; /* CPSR (Enable both IRQ and FIQ interrupts) */ + *(--stk) = (INT32U)ARM_SVC_MODE; /* SPSR */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* ARM SPECIFIC CODE +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description : This function is called by the OSIntExit() to perform a context switch at the completion +* of an ISR. However, instead of actually doing the context switch from within OSIntExit(), +* we simply set a flag (OSIntCtxSwFlag) and defer the actual context switch until the actual +* ISR completes (see OS_CPU_IRQ_ISR()). +* +* Arguments : none +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSIntCtxSwFlag = TRUE; /* Indicate that a context switch from ISR is needed */ +} diff --git a/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_dbg.c b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_dbg.c new file mode 100644 index 0000000..d5a1dd1 --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/GNU-XTools/Source/os_dbg.c @@ -0,0 +1,270 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Debugger Constants +* GNU C Compiler +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSIntExitY) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM7/LH79520/ARM/IAR/os_cpu.h b/Ports/ARM7/LH79520/ARM/IAR/os_cpu.h new file mode 100644 index 0000000..6ea51e0 --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/IAR/os_cpu.h @@ -0,0 +1,140 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: NOT IMPLEMENTED +* Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: NOT IMPLEMENTED +* Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. This is the prefered method to disable interrupts. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 +#define OS_CPU_INT_DIS_MEAS_EN 0 /* Interrupt disable time measurement (Enable(1) or Disable(0)) */ + + +#if OS_CRITICAL_METHOD == 3 + +#if OS_CPU_INT_DIS_MEAS_EN == 0 +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} + +#else + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart();} +#define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr);} +#endif +#endif +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT32U OSIntCtxSwFlag; /* Used to flag a context switch */ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0 +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +#endif + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); + +#if OS_CPU_INT_DIS_MEAS_EN > 0 +void OS_CPU_IntDisMeasInit(void); +void OS_CPU_IntDisMeasStart(void); +void OS_CPU_IntDisMeasStop(void); +INT16U OS_CPU_IntDisMeasTmrRd(void); +#endif + +void OS_CPU_Tick_ISR(void); + +#endif +#endif diff --git a/Ports/ARM7/LH79520/ARM/IAR/os_cpu_a.s b/Ports/ARM7/LH79520/ARM/IAR/os_cpu_a.s new file mode 100644 index 0000000..21830e2 --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/IAR/os_cpu_a.s @@ -0,0 +1,290 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARM7 Port +; IAR C Compiler +; Sharp LH79520 +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntCtxSwFlag + + EXTERN OSIntEnter + EXTERN OSIntExit + + EXTERN OSTaskSwHook + + EXTERN Tmr_TickHandler + + + PUBLIC OSStartHighRdy ; Functions declared in this file + + PUBLIC OSCtxSw + PUBLIC OS_IntCtxSw + + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OS_CPU_Tick_ISR + + +NO_INT EQU 0xC0 ; Mask used to disable interrupts (Both FIQ and IRQ) + + + +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +OSStartHighRdy + + BL OSTaskSwHook ; Call user defined task switch hook + + LDR R4,??OS_Running ; OSRunning = TRUE + MOV R5,#1 + STRB R5,[R4] + + LDR R4,??OS_TCBHighRdy ; Get highest priority task TCB address + LDR R4,[R4] ; get stack pointer + LDR SP,[R4] ; switch to the new stack + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's CPSR + MSR CPSR_cxsf,R4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; +; Note(s): Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +;********************************************************************************************************* + + RSEG CODE:CODE:NOROOT(2) + CODE32 + +OSCtxSw + STMFD SP!,{LR} ; push pc (lr should be pushed in place of PC) + STMFD SP!,{R0-R12,LR} ; push lr & register file + MRS R4,CPSR + STMFD SP!,{R4} ; push current PSR + MRS R4,SPSR + STMFD SP!,{R4} ; push current SPSR + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R6,[r5] + STRB R6,[r4] + + LDR R4,??OS_TCBCur ; Get current task's OS_TCB address + LDR R5,[r4] + STR SP,[r5] ; store sp in preempted tasks's TCB + + BL OSTaskSwHook ; call Task Switch Hook + + LDR R6,??OS_TCBHighRdy ; Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] ; get new task's stack pointer + + STR R6,[R4] ; OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's PSR + MSR CPSR_cxsf,r4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + +;********************************************************************************************************* +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) OS_CPU_SR_Save() is implemented as recommended by Atmel's application note: +; +; "Disabling Interrupts at Processor Level" +;********************************************************************************************************* + +OS_CPU_SR_Save + MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts + ORR R1,R0,#NO_INT + MSR CPSR_c,R1 + MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags + AND R1,R1,#NO_INT + CMP R1,#NO_INT + BNE OS_CPU_SR_Save ; Not properly disabled (try again) + MOV PC,LR ; Disabled, return the original CPSR contents in R0 + + +OS_CPU_SR_Restore + MSR CPSR_c,R0 + MOV PC,LR + + +;********************************************************************************************************* +; TICK HANDLER +; +; Description: This handles all the Timer #0 interrupt which is used to generate the uC/OS-II tick. +;********************************************************************************************************* + +OS_CPU_Tick_ISR + + STMFD SP!,{R0-R3,R12,LR} + + BL OSIntEnter ; Indicate beginning of ISR + BL Tmr_TickHandler ; Handle interrupt (see BSP.C) + BL OSIntExit ; Indicate end of ISR + + LDR R0,??OS_IntCtxSwFlag ; See if we need to do a context switch + LDR R1,[R0] + CMP R1,#1 + BEQ OS_IntCtxSw ; Yes, Switch to Higher Priority Task + + LDMFD SP!,{R0-R3,R12,LR} ; No, Restore registers of interrupted task's stack + SUBS PC,LR,#4 ; Return from IRQ + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description: This code performs a context switch if a higher priority task has been made ready-to-run +; during an ISR. +;********************************************************************************************************* + +OS_IntCtxSw + LDR R0,??OS_IntCtxSwFlag ; OSIntCtxSwFlag = FALSE + MOV R1,#0 + STR R1,[R0] + + LDMFD SP!,{R0-R3,R12,LR} ; Clean up IRQ stack + STMFD SP!,{R0-R3} ; We will use R0-R3 as temporary registers + MOV R1,SP + ADD SP,SP,#16 + SUB R2,LR,#4 + + MRS R3,SPSR ; Disable interrupts for when we go back to SVC mode + ORR R0,R3,#NO_INT + MSR SPSR_c,R0 + + LDR R0,=.+8 ; Switch back to SVC mode (Code below, current location + 2 instructions) + MOVS PC,R0 ; Restore PC and CPSR + + ; SAVE OLD TASK'S CONTEXT ONTO OLD TASK'S STACK + STMFD SP!,{R2} ; Push task's PC + STMFD SP!,{R4-R12,LR} ; Push task's LR,R12-R4 + MOV R4,R1 ; Move R0-R3 from IRQ stack to SVC stack + MOV R5,R3 + LDMFD R4!,{R0-R3} ; Load R0-R3 from IRQ stack + STMFD SP!,{R0-R3} ; Push R0-R3 + STMFD SP!,{R5} ; Push task's CPSR + MRS R4,SPSR + STMFD SP!,{R4} ; Push task's SPSR + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R5,[R5] + STRB R5,[R4] + + LDR R4,??OS_TCBCur ; Get current task's OS_TCB address + LDR R5,[R4] + STR SP,[R5] ; store sp in preempted tasks's TCB + + BL OSTaskSwHook ; call Task Switch Hook + + LDR R6,??OS_TCBHighRdy ; Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] ; get new task's stack pointer + + STR R6,[R4] ; OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's PSR + MSR CPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + + +;********************************************************************************************************* +; POINTERS TO VARIABLES +;********************************************************************************************************* + + DATA + +??OS_IntCtxSwFlag: + DC32 OSIntCtxSwFlag + +??OS_PrioCur: + DC32 OSPrioCur + +??OS_PrioHighRdy: + DC32 OSPrioHighRdy + +??OS_Running: + DC32 OSRunning + +??OS_TCBCur: + DC32 OSTCBCur + +??OS_TCBHighRdy: + DC32 OSTCBHighRdy + + END diff --git a/Ports/ARM7/LH79520/ARM/IAR/os_cpu_c.c b/Ports/ARM7/LH79520/ARM/IAR/os_cpu_c.c new file mode 100644 index 0000000..af89674 --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/IAR/os_cpu_c.c @@ -0,0 +1,334 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARM7 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#define ARM_SYS_MODE (0x0000001FL) + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSIntCtxSwFlag = 0; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + ptcb = ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SYS mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + *(stk) = (OS_STK)task; /* Entry Point */ + *(--stk) = (INT32U)0x14141414L; /* LR */ + *(--stk) = (INT32U)0x12121212L; /* R12 */ + *(--stk) = (INT32U)0x11111111L; /* R11 */ + *(--stk) = (INT32U)0x10101010L; /* R10 */ + *(--stk) = (INT32U)0x09090909L; /* R9 */ + *(--stk) = (INT32U)0x08080808L; /* R8 */ + *(--stk) = (INT32U)0x07070707L; /* R7 */ + *(--stk) = (INT32U)0x06060606L; /* R6 */ + *(--stk) = (INT32U)0x05050505L; /* R5 */ + *(--stk) = (INT32U)0x04040404L; /* R4 */ + *(--stk) = (INT32U)0x03030303L; /* R3 */ + *(--stk) = (INT32U)0x02020202L; /* R2 */ + *(--stk) = (INT32U)0x01010101L; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* CPSR (Enable both IRQ and FIQ interrupts) */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* SPSR */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* ARM SPECIFIC CODE +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0 +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0; + OS_CPU_IntDisMeasCntsEnter = 0; + OS_CPU_IntDisMeasCntsExit = 0; + OS_CPU_IntDisMeasCntsMax = 0; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1) { + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + INT16U delta; + + + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasNestingCtr--; + if (OS_CPU_IntDisMeasNestingCtr == 0) { + delta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (delta > OS_CPU_IntDisMeasCntsMax) { + OS_CPU_IntDisMeasCntsMax = delta; + } + } +} +#endif + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description : This function is called by the OSIntExit() to perform a context switch at the completion +* of an ISR. However, instead of actually doing the context switch from within OSIntExit(), +* we simply set a flag (OSIntCtxSwFlag) and defer the actual context switch until the actual +* ISR completes (see OS_CPU_IRQ_ISR()). +* +* Arguments : none +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSIntCtxSwFlag = TRUE; /* Indicate that a context switch from ISR is needed */ +} diff --git a/Ports/ARM7/LH79520/ARM/IAR/os_dbg.c b/Ports/ARM7/LH79520/ARM/IAR/os_dbg.c new file mode 100644 index 0000000..02b0070 --- /dev/null +++ b/Ports/ARM7/LH79520/ARM/IAR/os_dbg.c @@ -0,0 +1,268 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if OS_EVENT_EN && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if OS_EVENT_EN && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu.h b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu.h new file mode 100644 index 0000000..5f8c92a --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu.h @@ -0,0 +1,115 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: NOT IMPLEMENTED +* Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: NOT IMPLEMENTED +* Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. This is the prefered method to disable interrupts. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_RestoreSR(cpu_sr)) /* Restore interrupts */ +#endif + +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT32U OSIntCtxSwFlag; /* Used to flag a context switch */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OS_CPU_SaveSR(void); +void OS_CPU_RestoreSR(OS_CPU_SR cpu_sr); +#endif + +void OS_CPU_Tick_ISR(void); + +#endif diff --git a/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_a.s b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_a.s new file mode 100644 index 0000000..a7a10fb --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_a.s @@ -0,0 +1,254 @@ +@******************************************************************************************************** +@ uC/OS-II +@ The Real-Time Kernel +@ +@ Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +@ +@ SPDX-License-Identifier: APACHE-2.0 +@ +@ This software is subject to an open source license and is distributed by +@ Silicon Laboratories Inc. pursuant to the terms of the Apache License, +@ Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +@ +@******************************************************************************************************** + +@******************************************************************************************************** +@ +@ ARM9 Port +@ Sharp LH79520 +@ GNU C Compiler +@ +@ Filename : os_cpu_a.s +@ Version : V2.93.00 +@******************************************************************************************************** + + .extern OSRunning @ .external references + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSIntCtxSwFlag + + .extern OSIntEnter + .extern OSIntExit + + .extern OSTaskSwHook + + .extern Tmr_TickHandler + + + .global OSStartHighRdy @ Functions declared in this file + + .global OSCtxSw + .global OS_IntCtxSw + + .global OS_CPU_SaveSR + .global OS_CPU_RestoreSR + .global OS_CPU_Tick_ISR + + .equ NO_INT, 0xC0 @ Mask used to disable interrupts (Both FIQ and IRQ) + +@********************************************************************************************************* +@ START MULTITASKING +@ void OSStartHighRdy(void) +@ +@ Note : OSStartHighRdy() MUST: +@ a) Call OSTaskSwHook() then, +@ b) Set OSRunning to TRUE, +@ c) Switch to the highest priority task. +@********************************************************************************************************* + + .code 32 + +OSStartHighRdy: + + BL OSTaskSwHook @ Call user defined task switch hook + + LDR R4,=OSRunning @ OSRunning = TRUE + MOV R5,#1 + STRB R5,[R4] + + LDR R4,=OSTCBHighRdy @ Get highest priority task TCB address + LDR R4,[R4] @ get stack pointer + LDR SP,[R4] @ switch to the new stack + + LDMFD SP!,{R4} @ pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} @ pop new task's CPSR + MSR CPSR_cxsf,R4 + LDMFD SP!,{R0-R12,LR,PC} @ pop new task's R0-R12,LR & PC + +@********************************************************************************************************* +@ PERFORM A CONTEXT SWITCH (From task level) +@ +@ Note(s): Upon entry: +@ OSTCBCur points to the OS_TCB of the task to suspend +@ OSTCBHighRdy points to the OS_TCB of the task to resume +@********************************************************************************************************* + + .code 32 + +OSCtxSw: + STMFD SP!,{LR} @ push pc (lr should be pushed in place of PC) + STMFD SP!,{R0-R12,LR} @ push lr & register file + MRS R4,CPSR + STMFD SP!,{R4} @ push current PSR + MRS R4,SPSR + STMFD SP!,{R4} @ push current SPSR + + LDR R4,=OSPrioCur @ OSPrioCur = OSPrioHighRdy + LDR R5,=OSPrioHighRdy + LDRB R6,[r5] + STRB R6,[r4] + + LDR R4,=OSTCBCur @ Get current task's OS_TCB address + LDR R5,[r4] + STR SP,[r5] @ store sp in preempted tasks's TCB + + BL OSTaskSwHook @ call Task Switch Hook + + LDR R6,=OSTCBHighRdy @ Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] @ get new task's stack pointer + + STR R6,[R4] @ OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} @ pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} @ pop new task's PSR + MSR CPSR_cxsf,r4 + LDMFD SP!,{R0-R12,LR,PC} @ pop new task's R0-R12,LR & PC + +@********************************************************************************************************* +@ CRITICAL SECTION METHOD 3 FUNCTIONS +@ +@ Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +@ would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +@ disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +@ disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +@ into the CPU's status register. +@ +@ Prototypes : OS_CPU_SR OS_CPU_SaveSR(void)@ +@ void OS_CPU_RestoreSR(OS_CPU_SR cpu_sr)@ +@ +@ +@ Note(s) : 1) These functions are used in general like this: +@ +@ void Task (void *p_arg) +@ { +@ #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +@ OS_CPU_SR cpu_sr@ +@ #endif +@ +@ : +@ : +@ OS_ENTER_CRITICAL()@ /* cpu_sr = OS_CPU_SaveSR()@ */ +@ : +@ : +@ OS_EXIT_CRITICAL()@ /* OS_CPU_RestoreSR(cpu_sr)@ */ +@ : +@ : +@ } +@ +@ 2) OS_CPU_SaveSR() is implemented as recommended by Atmel's application note: +@ +@ "Disabling Interrupts at Processor Level" +@********************************************************************************************************* + +OS_CPU_SaveSR: + MRS R0,CPSR @ Set IRQ and FIQ bits in CPSR to disable all interrupts + ORR R1,R0,#NO_INT + MSR CPSR_c,R1 + MRS R1,CPSR @ Confirm that CPSR contains the proper interrupt disable flags + AND R1,R1,#NO_INT + CMP R1,#NO_INT + BNE OS_CPU_SaveSR @ Not properly disabled (try again) + MOV PC,LR @ Disabled, return the original CPSR contents in R0 + +OS_CPU_RestoreSR: + MSR CPSR_c,R0 + MOV PC,LR + +@********************************************************************************************************* +@ TICK HANDLER +@ +@ Description: This handles all the Timer #0 interrupt which is used to generate the uC/OS-II tick. +@********************************************************************************************************* + +OS_CPU_Tick_ISR: + + STMFD SP!,{R0-R3,R12,LR} + + BL OSIntEnter @ Indicate beginning of ISR + BL Tmr_TickHandler @ Handle interrupt (see BSP.C) + BL OSIntExit @ Indicate end of ISR + + LDR R0,=OSIntCtxSwFlag @ See if we need to do a context switch + LDR R1,[R0] + CMP R1,#1 + BEQ OS_IntCtxSw @ Yes, Switch to Higher Priority Task + + LDMFD SP!,{R0-R3,R12,LR} @ No, Restore registers of interrupted task's stack + SUBS PC,LR,#4 @ Return from IRQ + +@********************************************************************************************************* +@ INTERRUPT LEVEL CONTEXT SWITCH +@ +@ Description: This code performs a context switch if a higher priority task has been made ready-to-run +@ during an ISR. +@********************************************************************************************************* + +OS_IntCtxSw: + LDR R0,=OSIntCtxSwFlag @ OSIntCtxSwFlag = FALSE + MOV R1,#0 + STR R1,[R0] + + LDMFD SP!,{R0-R3,R12,LR} @ Clean up IRQ stack + STMFD SP!,{R0-R3} @ We will use R0-R3 as temporary registers + MOV R1,SP + ADD SP,SP,#16 + SUB R2,LR,#4 + + MRS R3,SPSR @ Disable interrupts for when we go back to SVC mode + ORR R0,R3,#NO_INT + MSR SPSR_c,R0 + + LDR R0,=.+8 @ Switch back to SVC mode (Code below, current location + 2 instructions) + MOVS PC,R0 @ Restore PC and CPSR + + @ SAVE OLD TASK'S CONTEXT ONTO OLD TASK'S STACK + STMFD SP!,{R2} @ Push task's PC + STMFD SP!,{R4-R12,LR} @ Push task's LR,R12-R4 + MOV R4,R1 @ Move R0-R3 from IRQ stack to SVC stack + MOV R5,R3 + LDMFD R4!,{R0-R3} @ Load R0-R3 from IRQ stack + STMFD SP!,{R0-R3} @ Push R0-R3 + STMFD SP!,{R5} @ Push task's CPSR + MRS R4,SPSR + STMFD SP!,{R4} @ Push task's SPSR + + LDR R4,=OSPrioCur @ OSPrioCur = OSPrioHighRdy + LDR R5,=OSPrioHighRdy + LDRB R5,[R5] + STRB R5,[R4] + + LDR R4,=OSTCBCur @ Get current task's OS_TCB address + LDR R5,[R4] + STR SP,[R5] @ store sp in preempted tasks's TCB + + BL OSTaskSwHook @ call Task Switch Hook + + LDR R6,=OSTCBHighRdy @ Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] @ get new task's stack pointer + + STR R6,[R4] @ OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} @ pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} @ pop new task's PSR + MSR CPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC} @ pop new task's R0-R12,LR & PC + + .ltorg diff --git a/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_c.c b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_c.c new file mode 100644 index 0000000..60f4668 --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_cpu_c.c @@ -0,0 +1,280 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARM9 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#define ARM_SVC_MODE (0x00000013L) + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSIntCtxSwFlag = 0; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SVC mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + *(stk) = (OS_STK)task; /* Entry Point */ + *(--stk) = (INT32U)0x14141414L; /* LR */ + *(--stk) = (INT32U)0x12121212L; /* R12 */ + *(--stk) = (INT32U)0x11111111L; /* R11 */ + *(--stk) = (INT32U)0x10101010L; /* R10 */ + *(--stk) = (INT32U)0x09090909L; /* R9 */ + *(--stk) = (INT32U)0x08080808L; /* R8 */ + *(--stk) = (INT32U)0x07070707L; /* R7 */ + *(--stk) = (INT32U)0x06060606L; /* R6 */ + *(--stk) = (INT32U)0x05050505L; /* R5 */ + *(--stk) = (INT32U)0x04040404L; /* R4 */ + *(--stk) = (INT32U)0x03030303L; /* R3 */ + *(--stk) = (INT32U)0x02020202L; /* R2 */ + *(--stk) = (INT32U)0x01010101L; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + *(--stk) = (INT32U)ARM_SVC_MODE; /* CPSR (Enable both IRQ and FIQ interrupts) */ + *(--stk) = (INT32U)ARM_SVC_MODE; /* SPSR */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* ARM SPECIFIC CODE +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description : This function is called by the OSIntExit() to perform a context switch at the completion +* of an ISR. However, instead of actually doing the context switch from within OSIntExit(), +* we simply set a flag (OSIntCtxSwFlag) and defer the actual context switch until the actual +* ISR completes (see OS_CPU_IRQ_ISR()). +* +* Arguments : none +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSIntCtxSwFlag = TRUE; /* Indicate that a context switch from ISR is needed */ +} diff --git a/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_dbg.c b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_dbg.c new file mode 100644 index 0000000..d5a1dd1 --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/GNU-XTools/Source/os_dbg.c @@ -0,0 +1,270 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Debugger Constants +* GNU C Compiler +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSIntExitY) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu.h b/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu.h new file mode 100644 index 0000000..6ea51e0 --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu.h @@ -0,0 +1,140 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + +/* +********************************************************************************************************* +* ARM +* +* Method #1: NOT IMPLEMENTED +* Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: NOT IMPLEMENTED +* Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. This is the prefered method to disable interrupts. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 +#define OS_CPU_INT_DIS_MEAS_EN 0 /* Interrupt disable time measurement (Enable(1) or Disable(0)) */ + + +#if OS_CRITICAL_METHOD == 3 + +#if OS_CPU_INT_DIS_MEAS_EN == 0 +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} + +#else + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save(); \ + OS_CPU_IntDisMeasStart();} +#define OS_EXIT_CRITICAL() {OS_CPU_IntDisMeasStop(); \ + OS_CPU_SR_Restore(cpu_sr);} +#endif +#endif +/* +********************************************************************************************************* +* ARM Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on ARM */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT INT32U OSIntCtxSwFlag; /* Used to flag a context switch */ + + /* Variables used to measure interrupt disable time */ +#if OS_CPU_INT_DIS_MEAS_EN > 0 +OS_CPU_EXT INT16U OS_CPU_IntDisMeasNestingCtr; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsEnter; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsExit; +OS_CPU_EXT INT16U OS_CPU_IntDisMeasCntsMax; +#endif + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); + +#if OS_CPU_INT_DIS_MEAS_EN > 0 +void OS_CPU_IntDisMeasInit(void); +void OS_CPU_IntDisMeasStart(void); +void OS_CPU_IntDisMeasStop(void); +INT16U OS_CPU_IntDisMeasTmrRd(void); +#endif + +void OS_CPU_Tick_ISR(void); + +#endif +#endif diff --git a/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_a.s b/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_a.s new file mode 100644 index 0000000..780d86e --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_a.s @@ -0,0 +1,290 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ARM9 Port +; IAR C Compiler +; Sharp LH79520 +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + EXTERN OSRunning ; External references + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntCtxSwFlag + + EXTERN OSIntEnter + EXTERN OSIntExit + + EXTERN OSTaskSwHook + + EXTERN Tmr_TickHandler + + + PUBLIC OSStartHighRdy ; Functions declared in this file + + PUBLIC OSCtxSw + PUBLIC OS_IntCtxSw + + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OS_CPU_Tick_ISR + + +NO_INT EQU 0xC0 ; Mask used to disable interrupts (Both FIQ and IRQ) + + + +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + + RSEG NEARFUNC_A:CODE:NOROOT(2) + CODE32 + +OSStartHighRdy + + BL OSTaskSwHook ; Call user defined task switch hook + + LDR R4,??OS_Running ; OSRunning = TRUE + MOV R5,#1 + STRB R5,[R4] + + LDR R4,??OS_TCBHighRdy ; Get highest priority task TCB address + LDR R4,[R4] ; get stack pointer + LDR SP,[R4] ; switch to the new stack + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's CPSR + MSR CPSR_cxsf,R4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; +; Note(s): Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +;********************************************************************************************************* + + RSEG NEARFUNC_A:CODE:NOROOT(2) + CODE32 + +OSCtxSw + STMFD SP!,{LR} ; push pc (lr should be pushed in place of PC) + STMFD SP!,{R0-R12,LR} ; push lr & register file + MRS R4,CPSR + STMFD SP!,{R4} ; push current PSR + MRS R4,SPSR + STMFD SP!,{R4} ; push current SPSR + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R6,[r5] + STRB R6,[r4] + + LDR R4,??OS_TCBCur ; Get current task's OS_TCB address + LDR R5,[r4] + STR SP,[r5] ; store sp in preempted tasks's TCB + + BL OSTaskSwHook ; call Task Switch Hook + + LDR R6,??OS_TCBHighRdy ; Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] ; get new task's stack pointer + + STR R6,[R4] ; OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's PSR + MSR CPSR_cxsf,r4 + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + +;********************************************************************************************************* +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +; +; 2) OS_CPU_SR_Save() is implemented as recommended by Atmel's application note: +; +; "Disabling Interrupts at Processor Level" +;********************************************************************************************************* + +OS_CPU_SR_Save + MRS R0,CPSR ; Set IRQ and FIQ bits in CPSR to disable all interrupts + ORR R1,R0,#NO_INT + MSR CPSR_c,R1 + MRS R1,CPSR ; Confirm that CPSR contains the proper interrupt disable flags + AND R1,R1,#NO_INT + CMP R1,#NO_INT + BNE OS_CPU_SR_Save ; Not properly disabled (try again) + MOV PC,LR ; Disabled, return the original CPSR contents in R0 + + +OS_CPU_SR_Restore + MSR CPSR_c,R0 + MOV PC,LR + + +;********************************************************************************************************* +; TICK HANDLER +; +; Description: This handles all the Timer #0 interrupt which is used to generate the uC/OS-II tick. +;********************************************************************************************************* + +OS_CPU_Tick_ISR + + STMFD SP!,{R0-R3,R12,LR} + + BL OSIntEnter ; Indicate beginning of ISR + BL Tmr_TickHandler ; Handle interrupt (see BSP.C) + BL OSIntExit ; Indicate end of ISR + + LDR R0,??OS_IntCtxSwFlag ; See if we need to do a context switch + LDR R1,[R0] + CMP R1,#1 + BEQ OS_IntCtxSw ; Yes, Switch to Higher Priority Task + + LDMFD SP!,{R0-R3,R12,LR} ; No, Restore registers of interrupted task's stack + SUBS PC,LR,#4 ; Return from IRQ + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description: This code performs a context switch if a higher priority task has been made ready-to-run +; during an ISR. +;********************************************************************************************************* + +OS_IntCtxSw + LDR R0,??OS_IntCtxSwFlag ; OSIntCtxSwFlag = FALSE + MOV R1,#0 + STR R1,[R0] + + LDMFD SP!,{R0-R3,R12,LR} ; Clean up IRQ stack + STMFD SP!,{R0-R3} ; We will use R0-R3 as temporary registers + MOV R1,SP + ADD SP,SP,#16 + SUB R2,LR,#4 + + MRS R3,SPSR ; Disable interrupts for when we go back to SVC mode + ORR R0,R3,#NO_INT + MSR SPSR_c,R0 + + LDR R0,=.+8 ; Switch back to SVC mode (Code below, current location + 2 instructions) + MOVS PC,R0 ; Restore PC and CPSR + + ; SAVE OLD TASK'S CONTEXT ONTO OLD TASK'S STACK + STMFD SP!,{R2} ; Push task's PC + STMFD SP!,{R4-R12,LR} ; Push task's LR,R12-R4 + MOV R4,R1 ; Move R0-R3 from IRQ stack to SVC stack + MOV R5,R3 + LDMFD R4!,{R0-R3} ; Load R0-R3 from IRQ stack + STMFD SP!,{R0-R3} ; Push R0-R3 + STMFD SP!,{R5} ; Push task's CPSR + MRS R4,SPSR + STMFD SP!,{R4} ; Push task's SPSR + + LDR R4,??OS_PrioCur ; OSPrioCur = OSPrioHighRdy + LDR R5,??OS_PrioHighRdy + LDRB R5,[R5] + STRB R5,[R4] + + LDR R4,??OS_TCBCur ; Get current task's OS_TCB address + LDR R5,[R4] + STR SP,[R5] ; store sp in preempted tasks's TCB + + BL OSTaskSwHook ; call Task Switch Hook + + LDR R6,??OS_TCBHighRdy ; Get highest priority task's OS_TCB address + LDR R6,[R6] + LDR SP,[R6] ; get new task's stack pointer + + STR R6,[R4] ; OSTCBCur = OSTCBHighRdy + + LDMFD SP!,{R4} ; pop new task's SPSR + MSR SPSR_cxsf,R4 + LDMFD SP!,{R4} ; pop new task's PSR + MSR CPSR_cxsf,R4 + + LDMFD SP!,{R0-R12,LR,PC} ; pop new task's R0-R12,LR & PC + + + +;********************************************************************************************************* +; POINTERS TO VARIABLES +;********************************************************************************************************* + + DATA + +??OS_IntCtxSwFlag: + DC32 OSIntCtxSwFlag + +??OS_PrioCur: + DC32 OSPrioCur + +??OS_PrioHighRdy: + DC32 OSPrioHighRdy + +??OS_Running: + DC32 OSRunning + +??OS_TCBCur: + DC32 OSTCBCur + +??OS_TCBHighRdy: + DC32 OSTCBHighRdy + + END diff --git a/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_c.c b/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_c.c new file mode 100644 index 0000000..3b662eb --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/IAR/os_cpu_c.c @@ -0,0 +1,334 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ARM9 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#define ARM_SYS_MODE (0x0000001FL) + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + OSIntCtxSwFlag = 0; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#ifdef OS_VIEW_MODULE + OSView_TaskCreateHook(ptcb); +#else + ptcb = ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SYS mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + *(stk) = (OS_STK)task; /* Entry Point */ + *(--stk) = (INT32U)0x14141414L; /* LR */ + *(--stk) = (INT32U)0x12121212L; /* R12 */ + *(--stk) = (INT32U)0x11111111L; /* R11 */ + *(--stk) = (INT32U)0x10101010L; /* R10 */ + *(--stk) = (INT32U)0x09090909L; /* R9 */ + *(--stk) = (INT32U)0x08080808L; /* R8 */ + *(--stk) = (INT32U)0x07070707L; /* R7 */ + *(--stk) = (INT32U)0x06060606L; /* R6 */ + *(--stk) = (INT32U)0x05050505L; /* R5 */ + *(--stk) = (INT32U)0x04040404L; /* R4 */ + *(--stk) = (INT32U)0x03030303L; /* R3 */ + *(--stk) = (INT32U)0x02020202L; /* R2 */ + *(--stk) = (INT32U)0x01010101L; /* R1 */ + *(--stk) = (INT32U)p_arg; /* R0 : argument */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* CPSR (Enable both IRQ and FIQ interrupts) */ + *(--stk) = (INT32U)ARM_SYS_MODE; /* SPSR */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#ifdef OS_VIEW_MODULE + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#ifdef OS_VIEW_MODULE + OSView_TickHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* ARM SPECIFIC CODE +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0 +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0; + OS_CPU_IntDisMeasCntsEnter = 0; + OS_CPU_IntDisMeasCntsExit = 0; + OS_CPU_IntDisMeasCntsMax = 0; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1) { + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + INT16U delta; + + + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasNestingCtr--; + if (OS_CPU_IntDisMeasNestingCtr == 0) { + delta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (delta > OS_CPU_IntDisMeasCntsMax) { + OS_CPU_IntDisMeasCntsMax = delta; + } + } +} +#endif + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description : This function is called by the OSIntExit() to perform a context switch at the completion +* of an ISR. However, instead of actually doing the context switch from within OSIntExit(), +* we simply set a flag (OSIntCtxSwFlag) and defer the actual context switch until the actual +* ISR completes (see OS_CPU_IRQ_ISR()). +* +* Arguments : none +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSIntCtxSwFlag = TRUE; /* Indicate that a context switch from ISR is needed */ +} diff --git a/Ports/ARM9/AT91RM9200/ARM/IAR/os_dbg.c b/Ports/ARM9/AT91RM9200/ARM/IAR/os_dbg.c new file mode 100644 index 0000000..02b0070 --- /dev/null +++ b/Ports/ARM9/AT91RM9200/ARM/IAR/os_dbg.c @@ -0,0 +1,268 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if OS_EVENT_EN && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if OS_EVENT_EN && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR/ATmega128/IAR/os_cpu.h b/Ports/AVR/ATmega128/IAR/os_cpu.h new file mode 100644 index 0000000..093d341 --- /dev/null +++ b/Ports/AVR/ATmega128/IAR/os_cpu.h @@ -0,0 +1,135 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************** +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 8 bits) */ + +/* +********************************************************************************************************* +* Atmel AVR +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. The IAR compiler does not support inline assembly so I'm +* using the _OPC() intrinsic function. Here are the instructions: +* +* OS_ENTER_CRITICAL: +* ST -Y,R16 +* IN R16,SREG +* CLI +* PUSH R16 +* LD R16,Y+ +* +* OS_EXIT_CRITICAL: +* ST -Y,R16 +* POP R16 +* OUT SREG,R16 +* LD R16,Y+ +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() _CLI() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() _SEI() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() _OPC(0x930A);_OPC(0xB70F);_CLI();_OPC(0x930F);_OPC(0x9109) +#define OS_EXIT_CRITICAL() _OPC(0x930A);_OPC(0x910F),_OPC(0xBF0F);_OPC(0x9109) +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************** +* AVR Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************** +* GLOBAL VARIABLES +********************************************************************************************************** +*/ + +OS_CPU_EXT INT16U OSTaskStkSize; +OS_CPU_EXT INT16U OSTaskStkSizeHard; + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy(void); +void OSCtxSw(void); +void OSIntCtxSw(void); diff --git a/Ports/AVR/ATmega128/IAR/os_cpu_a.s90 b/Ports/AVR/ATmega128/IAR/os_cpu_a.s90 new file mode 100644 index 0000000..0bceefc --- /dev/null +++ b/Ports/AVR/ATmega128/IAR/os_cpu_a.s90 @@ -0,0 +1,275 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATMEL AVR Specific code +; +; Filename : os_cpu_a.s90 +; Version : V2.93.00 +;******************************************************************************************************** + +#include + + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + MODULE OS_CPU_A + + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + + +;******************************************************************************************************** +; DISABLE/ENABLE INTERRUPTS USING OS_CRITICAL_METHOD #3 +; +; Description : These functions are used to disable and enable interrupts using OS_CRITICAL_METHOD #3. +; +; OS_CPU_SR OSCPUSaveSR (void) +; Get current value of SREG +; Disable interrupts +; Return original value of SREG +; +; void OSCPURestoreSR (OS_CPU_SR cpu_sr) +; Set SREG to cpu_sr +; Return +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(1) + +OS_CPU_SR_Save: IN R16,SREG ; Get current state of interrupts disable flag + CLI ; Disable interrupts + RET ; Return original SREG value in R16 + + +OS_CPU_SR_Restore: OUT SREG,R16 ; Restore SREG + RET ; Return + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Note(s) : 1) The (data)stack frame is assumed to look as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; where the stack pointer points to the task start address. +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: CALL OSTaskSwHook ; Invoke user defined context switch hook + LDS R16,OSRunning ; Indicate that we are multitasking + INC R16 ; + STS OSRunning,R16 ; + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + LD R28,Z+ ; Load Y (R29:R28) pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + POP_SREG_INT ; Restore status register (DISABLE interrupts) + POP_ALL ; Restore all registers + RETI + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP+0 --> LSB of task code address +; +1 MSB of task code address (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +;******************************************************************************************************** + +OSCtxSw: PUSH_ALL ; Save current task's context + PUSH_SREG + PUSH_SP + + LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr + LDS R31,OSTCBCur+1 ; + ST Z+,R28 ; Save Y (R29:R28) pointer + ST Z+,R29 ; + + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +OSCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (L) | +; | +; | +; OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +;********************************************************************************************************* + +OSIntCtxSw: + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSIntCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +OSIntCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + END diff --git a/Ports/AVR/ATmega128/IAR/os_cpu_c.c b/Ports/AVR/ATmega128/IAR/os_cpu_c.c new file mode 100644 index 0000000..34a1b91 --- /dev/null +++ b/Ports/AVR/ATmega128/IAR/os_cpu_c.c @@ -0,0 +1,358 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega128 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* SREG to 0x00 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable interrupts. +* Failure to do this will make your system crash! +* +* The AVR return stack is placed OS_TASK_STK_SIZE_HARD bytes before the bottom of the task's +* stack. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *psoft_stk; + INT8U *phard_stk; /* Temp. variable used for setting up AVR hardware stack */ + INT16U tmp; + + + (void)opt; /* 'opt' is not used, prevent warning */ + psoft_stk = (INT8U *)ptos; + phard_stk = (INT8U *)ptos + - OSTaskStkSize /* Task stack size */ + + OSTaskStkSizeHard; /* AVR return stack ("hardware stack") */ + tmp = (INT16U)task; + /* Put task start address on top of "hardware stack" */ + *phard_stk-- = (INT8U)(tmp & 0xFF); /* Save PC return address */ + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + + *psoft_stk-- = (INT8U)0x00; /* R0 = 0x00 */ + *psoft_stk-- = (INT8U)0x01; /* R1 = 0x01 */ + *psoft_stk-- = (INT8U)0x02; /* R2 = 0x02 */ + *psoft_stk-- = (INT8U)0x03; /* R3 = 0x03 */ + *psoft_stk-- = (INT8U)0x04; /* R4 = 0x04 */ + *psoft_stk-- = (INT8U)0x05; /* R5 = 0x05 */ + *psoft_stk-- = (INT8U)0x06; /* R6 = 0x06 */ + *psoft_stk-- = (INT8U)0x07; /* R7 = 0x07 */ + *psoft_stk-- = (INT8U)0x08; /* R8 = 0x08 */ + *psoft_stk-- = (INT8U)0x09; /* R9 = 0x09 */ + *psoft_stk-- = (INT8U)0x10; /* R10 = 0x10 */ + *psoft_stk-- = (INT8U)0x11; /* R11 = 0x11 */ + *psoft_stk-- = (INT8U)0x12; /* R12 = 0x12 */ + *psoft_stk-- = (INT8U)0x13; /* R13 = 0x13 */ + *psoft_stk-- = (INT8U)0x14; /* R14 = 0x14 */ + *psoft_stk-- = (INT8U)0x15; /* R15 = 0x15 */ + tmp = (INT16U)p_arg; + *psoft_stk-- = (INT8U)tmp; /* 'p_arg' passed in R17:R16 */ + *psoft_stk-- = (INT8U)(tmp >> 8); + *psoft_stk-- = (INT8U)0x18; /* R18 = 0x18 */ + *psoft_stk-- = (INT8U)0x19; /* R19 = 0x19 */ + *psoft_stk-- = (INT8U)0x20; /* R20 = 0x20 */ + *psoft_stk-- = (INT8U)0x21; /* R21 = 0x21 */ + *psoft_stk-- = (INT8U)0x22; /* R22 = 0x22 */ + *psoft_stk-- = (INT8U)0x23; /* R23 = 0x23 */ + *psoft_stk-- = (INT8U)0x24; /* R24 = 0x24 */ + *psoft_stk-- = (INT8U)0x25; /* R25 = 0x25 */ + *psoft_stk-- = (INT8U)0x26; /* R26 = 0x26 */ + *psoft_stk-- = (INT8U)0x27; /* R27 = 0x27 */ + /* R28 R29:R28 is the software stack which gets ... */ + /* R29 ... in the TCB. */ + *psoft_stk-- = (INT8U)0x30; /* R30 = 0x30 */ + *psoft_stk-- = (INT8U)0x31; /* R31 = 0x31 */ + *psoft_stk-- = (INT8U)0xAA; /* RAMPZ = 0xAA */ + *psoft_stk-- = (INT8U)0x80; /* SREG = Interrupts enabled */ + tmp = (INT16U)phard_stk; + *psoft_stk-- = (INT8U)(tmp >> 8); /* SPH */ + *psoft_stk = (INT8U)(tmp & 0xFF); /* SPL */ + return ((OS_STK *)psoft_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/AVR/ATmega128/IAR/os_cpu_i.s90 b/Ports/AVR/ATmega128/IAR/os_cpu_i.s90 new file mode 100644 index 0000000..26b0ba6 --- /dev/null +++ b/Ports/AVR/ATmega128/IAR/os_cpu_i.s90 @@ -0,0 +1,155 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega128 Specific code +; +; INCLUDE FILE +; +; Filename : os_cpu_i.s90 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; BIT DEFINITIONS +;******************************************************************************************************** + +BIT00 = 0x01 +BIT01 = 0x02 +BIT02 = 0x04 +BIT03 = 0x08 +BIT04 = 0x10 +BIT05 = 0x20 +BIT06 = 0x40 +BIT07 = 0x80 + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +SREG = 0x3F +SPH = 0x3E +SPL = 0x3D +RAMPZ = 0x3B + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + +PUSH_ALL MACRO ; Save all registers + ST -Y,R0 + ST -Y,R1 + ST -Y,R2 + ST -Y,R3 + ST -Y,R4 + ST -Y,R5 + ST -Y,R6 + ST -Y,R7 + ST -Y,R8 + ST -Y,R9 + ST -Y,R10 + ST -Y,R11 + ST -Y,R12 + ST -Y,R13 + ST -Y,R14 + ST -Y,R15 + ST -Y,R16 + ST -Y,R17 + ST -Y,R18 + ST -Y,R19 + ST -Y,R20 + ST -Y,R21 + ST -Y,R22 + ST -Y,R23 + ST -Y,R24 + ST -Y,R25 + ST -Y,R26 + ST -Y,R27 + ST -Y,R30 + ST -Y,R31 + IN R16,RAMPZ + ST -Y,R16 + ENDM + +POP_ALL MACRO ; Restore all registers + LD R16,Y+ + OUT RAMPZ,R16 + LD R31,Y+ + LD R30,Y+ + LD R27,Y+ + LD R26,Y+ + LD R25,Y+ + LD R24,Y+ + LD R23,Y+ + LD R22,Y+ + LD R21,Y+ + LD R20,Y+ + LD R19,Y+ + LD R18,Y+ + LD R17,Y+ + LD R16,Y+ + LD R15,Y+ + LD R14,Y+ + LD R13,Y+ + LD R12,Y+ + LD R11,Y+ + LD R10,Y+ + LD R9,Y+ + LD R8,Y+ + LD R7,Y+ + LD R6,Y+ + LD R5,Y+ + LD R4,Y+ + LD R3,Y+ + LD R2,Y+ + LD R1,Y+ + LD R0,Y+ + ENDM + +PUSH_SP MACRO ; Save stack pointer + IN R16,SPH + ST -Y,R16 + IN R16,SPL + ST -Y,R16 + ENDM + +POP_SP MACRO ; Restore stack pointer + LD R16,Y+ + OUT SPL,R16 + LD R16,Y+ + OUT SPH,R16 + ENDM + +PUSH_SREG MACRO ; Save status register + IN R16,SREG + ST -Y,R16 + ENDM + +POP_SREG MACRO ; Restore status registers + LD R16,Y+ + OUT SREG,R16 + ENDM + +PUSH_SREG_INT MACRO ; Save status register with interrupts ENABLED + IN R16,SREG + SBR R16,BIT07 + ST -Y,R16 + ENDM + +POP_SREG_INT MACRO ; Restore status registers but DISABLE interrupts + LD R16,Y+ + CBR R16,BIT07 + OUT SREG,R16 + ENDM diff --git a/Ports/AVR/ATmega128/IAR/os_dbg.c b/Ports/AVR/ATmega128/IAR/os_dbg.c new file mode 100644 index 0000000..7ec8326 --- /dev/null +++ b/Ports/AVR/ATmega128/IAR/os_dbg.c @@ -0,0 +1,269 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventEn = 0; +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR/ATmega128/ICC/os_cpu.h b/Ports/AVR/ATmega128/ICC/os_cpu.h new file mode 100644 index 0000000..87be1ac --- /dev/null +++ b/Ports/AVR/ATmega128/ICC/os_cpu.h @@ -0,0 +1,126 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega128 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************** +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 8 bits) */ + +/* +********************************************************************************************************* +* Atmel AVR +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. The IAR compiler does not support inline assembly so I'm +* using the _OPC() intrinsic function. Here are the instructions: +* +* OS_ENTER_CRITICAL: +* ST -Y,R16 +* IN R16,SREG +* CLI +* PUSH R16 +* LD R16,Y+ +* +* OS_EXIT_CRITICAL: +* ST -Y,R16 +* POP R16 +* OUT SREG,R16 +* LD R16,Y+ +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************** +* AVR Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************** +* GLOBAL VARIABLES +********************************************************************************************************** +*/ + +OS_CPU_EXT INT16U OSTaskStkSize; /* Used to set the total stack size of a task */ +OS_CPU_EXT INT16U OSTaskStkSizeHard; /* Used to set the hardware stack size of a task */ + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy(void); +void OSCtxSw(void); +void OSIntCtxSw(void); diff --git a/Ports/AVR/ATmega128/ICC/os_cpu_a.s b/Ports/AVR/ATmega128/ICC/os_cpu_a.s new file mode 100644 index 0000000..00b69a3 --- /dev/null +++ b/Ports/AVR/ATmega128/ICC/os_cpu_a.s @@ -0,0 +1,236 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega128 Specific code +; ICC AVR Compiler +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + .include "os_cpu_i.h" + .area text(rel) + + +;******************************************************************************************************** +; DISABLE/ENABLE INTERRUPTS USING OS_CRITICAL_METHOD #3 +; +; Description : These functions are used to disable and enable interrupts using OS_CRITICAL_METHOD #3. +; +; OS_CPU_SR OSCPUSaveSR (void) +; Get current value of SREG +; Disable interrupts +; Return original value of SREG +; +; void OSCPURestoreSR (OS_CPU_SR cpu_sr) +; Set SREG to cpu_sr +; Return +;******************************************************************************************************** + +_OS_CPU_SR_Save:: + IN R16,SREG ; Get current state of interrupts disable flag + CLI ; Disable interrupts + RET ; Return original SREG value in R16 + + +_OS_CPU_SR_Restore:: + OUT SREG,R16 ; Restore SREG + RET ; Return + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Note(s) : 1) The (data)stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +; +; where the stack pointer points to the task start address. +; +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +_OSStartHighRdy:: + CALL _OSTaskSwHook ; Invoke user defined context switch hook + LDS R16,_OSRunning ; Indicate that we are multitasking + INC R16 ; + STS _OSRunning,R16 ; + + LDS R30,_OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,_OSTCBHighRdy+1 ; ready to run + LD R28,Z+ ; Load Y (R29:R28) pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + POP_SREG_INT ; Restore status register (Disable Interrupts) + POP_ALL ; Restore all registers + RETI ; Start task + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP+0 --> LSB of task code address +; +1 MSB of task code address (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +;******************************************************************************************************** + +_OSCtxSw:: + PUSH_ALL ; Save current task's context + PUSH_SREG + PUSH_SP + + LDS R30,_OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr + LDS R31,_OSTCBCur+1 ; + ST Z+,R28 ; Save Y (R29:R28) pointer + ST Z+,R29 ; + + CALL _OSTaskSwHook ; Call user defined task switch hook + + LDS R16,_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS _OSPrioCur,R16 + + LDS R30,_OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,_OSTCBHighRdy+1 ; ready to run + STS _OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS _OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction if interrupts DISABLED + RJMP _OSCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +_OSCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +;********************************************************************************************************* + +_OSIntCtxSw:: + CALL _OSTaskSwHook ; Call user defined task switch hook + + LDS R16,_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS _OSPrioCur,R16 ; + + LDS R30,_OSTCBHighRdy ; Z = OSTCBHighRdy->OSTCBStkPtr + LDS R31,_OSTCBHighRdy+1 ; + STS _OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS _OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction if interrupts DISABLED + RJMP _OSIntCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +_OSIntCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI diff --git a/Ports/AVR/ATmega128/ICC/os_cpu_c.c b/Ports/AVR/ATmega128/ICC/os_cpu_c.c new file mode 100644 index 0000000..e556520 --- /dev/null +++ b/Ports/AVR/ATmega128/ICC/os_cpu_c.c @@ -0,0 +1,332 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega128 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OS_CPU_TmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + ptcb = ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* SREG to 0x00 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable interrupts. +* Failure to do this will make your system crash! +* +* The AVR return stack is placed OS_TASK_HARD_STK_SIZE bytes before the bottom of the task's +* stack. +* +* (1) IMPORTANT: The ICC compiler handles function pointers by actually passing the pointer +* to a location in Flash that actually contains the pointer to the function. +* +* (2) IMPORTANT: You MUST set OSTaskStkSize and OSTaskStkSizeHard BEFORE calling OSInit() +* to initialize the Idle and statistic tasks stacks. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *psoft_stk; + INT8U *phard_stk; /* Temp. variable used for setting up AVR hardware stack */ + INT16U tmp; + + + (void)opt; /* 'opt' is not used, prevent warning */ + psoft_stk = (INT8U *)ptos; + phard_stk = (INT8U *)ptos + - OSTaskStkSize /* Task stack size */ + + OSTaskStkSizeHard; /* AVR return stack ("hardware stack") */ + + tmp = *(INT16U const *)task; /* (1) ICC compiler handles function pointers indirectly! */ + + *phard_stk-- = (INT8U)(tmp & 0xFF); /* Put task start address on top of "hardware stack" */ + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + + *psoft_stk-- = (INT8U)0x00; /* R0 = 0x00 */ + *psoft_stk-- = (INT8U)0x01; /* R1 = 0x01 */ + *psoft_stk-- = (INT8U)0x02; /* R2 = 0x02 */ + *psoft_stk-- = (INT8U)0x03; /* R3 = 0x03 */ + *psoft_stk-- = (INT8U)0x04; /* R4 = 0x04 */ + *psoft_stk-- = (INT8U)0x05; /* R5 = 0x05 */ + *psoft_stk-- = (INT8U)0x06; /* R6 = 0x06 */ + *psoft_stk-- = (INT8U)0x07; /* R7 = 0x07 */ + *psoft_stk-- = (INT8U)0x08; /* R8 = 0x08 */ + *psoft_stk-- = (INT8U)0x09; /* R9 = 0x09 */ + *psoft_stk-- = (INT8U)0x10; /* R10 = 0x10 */ + *psoft_stk-- = (INT8U)0x11; /* R11 = 0x11 */ + *psoft_stk-- = (INT8U)0x12; /* R12 = 0x12 */ + *psoft_stk-- = (INT8U)0x13; /* R13 = 0x13 */ + *psoft_stk-- = (INT8U)0x14; /* R14 = 0x14 */ + *psoft_stk-- = (INT8U)0x15; /* R15 = 0x15 */ + tmp = (INT16U)p_arg; + *psoft_stk-- = (INT8U)(tmp & 0xFF); /* 'p_arg' passed in R17:R16 */ + tmp >>= 8; + *psoft_stk-- = (INT8U)(tmp & 0xFF); + *psoft_stk-- = (INT8U)0x18; /* R18 = 0x18 */ + *psoft_stk-- = (INT8U)0x19; /* R19 = 0x19 */ + *psoft_stk-- = (INT8U)0x20; /* R20 = 0x20 */ + *psoft_stk-- = (INT8U)0x21; /* R21 = 0x21 */ + *psoft_stk-- = (INT8U)0x22; /* R22 = 0x22 */ + *psoft_stk-- = (INT8U)0x23; /* R23 = 0x23 */ + *psoft_stk-- = (INT8U)0x24; /* R24 = 0x24 */ + *psoft_stk-- = (INT8U)0x25; /* R25 = 0x25 */ + *psoft_stk-- = (INT8U)0x26; /* R26 = 0x26 */ + *psoft_stk-- = (INT8U)0x27; /* R27 = 0x27 */ + /* R28 R29:R28 is the software stack which gets ... */ + /* R29 ... stored in the task's OS_TCB. */ + *psoft_stk-- = (INT8U)0x30; /* R30 = 0x30 */ + *psoft_stk-- = (INT8U)0x31; /* R31 = 0x31 */ + *psoft_stk-- = (INT8U)0xAA; /* RAMPZ = 0xAA */ + *psoft_stk-- = (INT8U)0x80; /* SREG = Interrupts enabled */ + tmp = (INT16U)phard_stk; + *psoft_stk-- = (INT8U)(tmp >> 8); /* SPH */ + *psoft_stk = (INT8U) tmp; /* SPL */ + return ((OS_STK *)psoft_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/AVR/ATmega128/ICC/os_cpu_i.h b/Ports/AVR/ATmega128/ICC/os_cpu_i.h new file mode 100644 index 0000000..7c9d441 --- /dev/null +++ b/Ports/AVR/ATmega128/ICC/os_cpu_i.h @@ -0,0 +1,154 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega128 Specific code +; ICC AVR Compiler +; +; Filename : os_cpu_i.h +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; BIT DEFINITIONS +;******************************************************************************************************** + +BIT00 = 0x01 +BIT01 = 0x02 +BIT02 = 0x04 +BIT03 = 0x08 +BIT04 = 0x10 +BIT05 = 0x20 +BIT06 = 0x40 +BIT07 = 0x80 + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +SREG = 0x3F +SPH = 0x3E +SPL = 0x3D +RAMPZ = 0x3B + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + + .macro PUSH_ALL ; Save all registers + ST -Y,R0 + ST -Y,R1 + ST -Y,R2 + ST -Y,R3 + ST -Y,R4 + ST -Y,R5 + ST -Y,R6 + ST -Y,R7 + ST -Y,R8 + ST -Y,R9 + ST -Y,R10 + ST -Y,R11 + ST -Y,R12 + ST -Y,R13 + ST -Y,R14 + ST -Y,R15 + ST -Y,R16 + ST -Y,R17 + ST -Y,R18 + ST -Y,R19 + ST -Y,R20 + ST -Y,R21 + ST -Y,R22 + ST -Y,R23 + ST -Y,R24 + ST -Y,R25 + ST -Y,R26 + ST -Y,R27 + ST -Y,R30 + ST -Y,R31 + IN R16,RAMPZ + ST -Y,R16 + .endmacro + + .macro POP_ALL ; Restore all registers + LD R16,Y+ + OUT RAMPZ,R16 + LD R31,Y+ + LD R30,Y+ + LD R27,Y+ + LD R26,Y+ + LD R25,Y+ + LD R24,Y+ + LD R23,Y+ + LD R22,Y+ + LD R21,Y+ + LD R20,Y+ + LD R19,Y+ + LD R18,Y+ + LD R17,Y+ + LD R16,Y+ + LD R15,Y+ + LD R14,Y+ + LD R13,Y+ + LD R12,Y+ + LD R11,Y+ + LD R10,Y+ + LD R9,Y+ + LD R8,Y+ + LD R7,Y+ + LD R6,Y+ + LD R5,Y+ + LD R4,Y+ + LD R3,Y+ + LD R2,Y+ + LD R1,Y+ + LD R0,Y+ + .endmacro + + .macro PUSH_SP ; Save stack pointer + IN R16,SPH + ST -Y,R16 + IN R16,SPL + ST -Y,R16 + .endmacro + + .macro POP_SP ; Restore stack pointer + LD R16,Y+ + OUT SPL,R16 + LD R16,Y+ + OUT SPH,R16 + .endmacro + + .macro PUSH_SREG ; Save status register + IN R16,SREG + ST -Y,R16 + .endmacro + + .macro POP_SREG ; Restore status registers + LD R16,Y+ + OUT SREG,R16 + .endmacro + + .macro PUSH_SREG_INT ; Save status register + IN R16,SREG + SBR R16,BIT07 + ST -Y,R16 + .endmacro + + .macro POP_SREG_INT ; Restore status registers + LD R16,Y+ + CBR R16,BIT07 + OUT SREG,R16 + .endmacro diff --git a/Ports/AVR/ATmega128/ICC/os_dbg.c b/Ports/AVR/ATmega128/ICC/os_dbg.c new file mode 100644 index 0000000..1e21f4a --- /dev/null +++ b/Ports/AVR/ATmega128/ICC/os_dbg.c @@ -0,0 +1,291 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventEn = 0; +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; + +#if OS_TMR_EN > 0 +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); /* Size in Bytes of OSTmrTbl[] */ +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); /* Size in Bytes of OSTmrWheelTbl[] */ +#endif + +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if OS_TMR_EN > 0 + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR/ATmega256/IAR/os_cpu.h b/Ports/AVR/ATmega256/IAR/os_cpu.h new file mode 100644 index 0000000..075f303 --- /dev/null +++ b/Ports/AVR/ATmega256/IAR/os_cpu.h @@ -0,0 +1,135 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega256 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************** +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 8 bits) */ + +/* +********************************************************************************************************* +* Atmel AVR +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. The IAR compiler does not support inline assembly so I'm +* using the _OPC() intrinsic function. Here are the instructions: +* +* OS_ENTER_CRITICAL: +* ST -Y,R16 +* IN R16,SREG +* CLI +* PUSH R16 +* LD R16,Y+ +* +* OS_EXIT_CRITICAL: +* ST -Y,R16 +* POP R16 +* OUT SREG,R16 +* LD R16,Y+ +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() _CLI() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() _SEI() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() _OPC(0x930A);_OPC(0xB70F);_CLI();_OPC(0x930F);_OPC(0x9109) +#define OS_EXIT_CRITICAL() _OPC(0x930A);_OPC(0x910F),_OPC(0xBF0F);_OPC(0x9109) +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************** +* AVR Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************** +* GLOBAL VARIABLES +********************************************************************************************************** +*/ + +OS_CPU_EXT INT16U OSTaskStkSize; +OS_CPU_EXT INT16U OSTaskStkSizeHard; + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy(void); +void OSCtxSw(void); +void OSIntCtxSw(void); diff --git a/Ports/AVR/ATmega256/IAR/os_cpu_a.s90 b/Ports/AVR/ATmega256/IAR/os_cpu_a.s90 new file mode 100644 index 0000000..a2881d4 --- /dev/null +++ b/Ports/AVR/ATmega256/IAR/os_cpu_a.s90 @@ -0,0 +1,284 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega256 Specific code +; +; Filename : os_cpu_a.s90 +; Version : V2.93.00 +;******************************************************************************************************** + +#include + + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + MODULE OS_CPU_A + + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + + +;******************************************************************************************************** +; DISABLE/ENABLE INTERRUPTS USING OS_CRITICAL_METHOD #3 +; +; Description : These functions are used to disable and enable interrupts using OS_CRITICAL_METHOD #3. +; +; OS_CPU_SR OSCPUSaveSR (void) +; Get current value of SREG +; Disable interrupts +; Return original value of SREG +; +; void OSCPURestoreSR (OS_CPU_SR cpu_sr) +; Set SREG to cpu_sr +; Return +;******************************************************************************************************** + + RSEG FARCODE:CODE:NOROOT(1) + +OS_CPU_SR_Save: IN R16,SREG ; Get current state of interrupts disable flag + CLI ; Disable interrupts + RET ; Return original SREG value in R16 + + +OS_CPU_SR_Restore: OUT SREG,R16 ; Restore SREG + RET ; Return + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Note(s) : 1) The (data)stack frame is assumed to look as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; where the stack pointer points to the task start address. +; +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: CALL OSTaskSwHook ; Invoke user defined context switch hook + LDS R16,OSRunning ; Indicate that we are multitasking + INC R16 ; + STS OSRunning,R16 ; + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + LD R28,Z+ ; Load Y (R29:R28) pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + POP_SREG_INT ; Restore status register (DISABLE interrupts) + POP_ALL ; Restore all registers + RETI + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP+0 --> LSB of task code address +; +1 MSB of task code address (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +;******************************************************************************************************** + +OSCtxSw: PUSH_ALL ; Save current task's context + PUSH_SREG + PUSH_SP + + LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr + LDS R31,OSTCBCur+1 ; + ST Z+,R28 ; Save Y (R29:R28) pointer + ST Z+,R29 ; + + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +OSCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +;********************************************************************************************************* + +OSIntCtxSw: + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSIntCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +OSIntCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + END diff --git a/Ports/AVR/ATmega256/IAR/os_cpu_c.c b/Ports/AVR/ATmega256/IAR/os_cpu_c.c new file mode 100644 index 0000000..2d703d7 --- /dev/null +++ b/Ports/AVR/ATmega256/IAR/os_cpu_c.c @@ -0,0 +1,360 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega256 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* SREG to 0x00 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable interrupts. +* Failure to do this will make your system crash! +* +* The AVR return stack is placed OS_TASK_STK_SIZE_HARD bytes before the bottom of the task's +* stack. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *psoft_stk; + INT8U *phard_stk; /* Temp. variable used for setting up AVR hardware stack */ + INT32U tmp; + + + (void)opt; /* 'opt' is not used, prevent warning */ + psoft_stk = (INT8U *)ptos; + phard_stk = (INT8U *)ptos + - OSTaskStkSize /* Task stack size */ + + OSTaskStkSizeHard; /* AVR return stack ("hardware stack") */ + tmp = (INT32U)task; + *phard_stk-- = (INT8U)(tmp & 0xFF); /* Put task start address on top of "hardware stack" */ + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + + *psoft_stk-- = (INT8U)0x00; /* R0 = 0x00 */ + *psoft_stk-- = (INT8U)0x01; /* R1 = 0x01 */ + *psoft_stk-- = (INT8U)0x02; /* R2 = 0x02 */ + *psoft_stk-- = (INT8U)0x03; /* R3 = 0x03 */ + *psoft_stk-- = (INT8U)0x04; /* R4 = 0x04 */ + *psoft_stk-- = (INT8U)0x05; /* R5 = 0x05 */ + *psoft_stk-- = (INT8U)0x06; /* R6 = 0x06 */ + *psoft_stk-- = (INT8U)0x07; /* R7 = 0x07 */ + *psoft_stk-- = (INT8U)0x08; /* R8 = 0x08 */ + *psoft_stk-- = (INT8U)0x09; /* R9 = 0x09 */ + *psoft_stk-- = (INT8U)0x10; /* R10 = 0x10 */ + *psoft_stk-- = (INT8U)0x11; /* R11 = 0x11 */ + *psoft_stk-- = (INT8U)0x12; /* R12 = 0x12 */ + *psoft_stk-- = (INT8U)0x13; /* R13 = 0x13 */ + *psoft_stk-- = (INT8U)0x14; /* R14 = 0x14 */ + *psoft_stk-- = (INT8U)0x15; /* R15 = 0x15 */ + tmp = (INT16U)p_arg; + *psoft_stk-- = (INT8U)tmp; /* 'p_arg' passed in R17:R16 */ + *psoft_stk-- = (INT8U)(tmp >> 8); + *psoft_stk-- = (INT8U)0x18; /* R18 = 0x18 */ + *psoft_stk-- = (INT8U)0x19; /* R19 = 0x19 */ + *psoft_stk-- = (INT8U)0x20; /* R20 = 0x20 */ + *psoft_stk-- = (INT8U)0x21; /* R21 = 0x21 */ + *psoft_stk-- = (INT8U)0x22; /* R22 = 0x22 */ + *psoft_stk-- = (INT8U)0x23; /* R23 = 0x23 */ + *psoft_stk-- = (INT8U)0x24; /* R24 = 0x24 */ + *psoft_stk-- = (INT8U)0x25; /* R25 = 0x25 */ + *psoft_stk-- = (INT8U)0x26; /* R26 = 0x26 */ + *psoft_stk-- = (INT8U)0x27; /* R27 = 0x27 */ + /* R28 R29:R28 is the software stack which gets ... */ + /* R29 ... in the TCB. */ + *psoft_stk-- = (INT8U)0x30; /* R30 = 0x30 */ + *psoft_stk-- = (INT8U)0x31; /* R31 = 0x31 */ + *psoft_stk-- = (INT8U)0xAA; /* RAMPZ = 0xAA */ + *psoft_stk-- = (INT8U)0xE1; /* EIND = 0xE1 */ + *psoft_stk-- = (INT8U)0x80; /* SREG = Interrupts enabled */ + tmp = (INT16U)phard_stk; + *psoft_stk-- = (INT8U)(tmp >> 8); /* SPH */ + *psoft_stk = (INT8U) tmp; /* SPL */ + return ((OS_STK *)psoft_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/AVR/ATmega256/IAR/os_cpu_i.s90 b/Ports/AVR/ATmega256/IAR/os_cpu_i.s90 new file mode 100644 index 0000000..e679ed3 --- /dev/null +++ b/Ports/AVR/ATmega256/IAR/os_cpu_i.s90 @@ -0,0 +1,159 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega256 Specific code +; INCLUDE FILE +; +; Filename : os_cpu_i.s90 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; BIT DEFINITIONS +;******************************************************************************************************** + +BIT00 = 0x01 +BIT01 = 0x02 +BIT02 = 0x04 +BIT03 = 0x08 +BIT04 = 0x10 +BIT05 = 0x20 +BIT06 = 0x40 +BIT07 = 0x80 + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +SREG = 0x3F +SPH = 0x3E +SPL = 0x3D +RAMPZ = 0x3B +EIND = 0x3C + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + +PUSH_ALL MACRO ; Save all registers + ST -Y,R0 + ST -Y,R1 + ST -Y,R2 + ST -Y,R3 + ST -Y,R4 + ST -Y,R5 + ST -Y,R6 + ST -Y,R7 + ST -Y,R8 + ST -Y,R9 + ST -Y,R10 + ST -Y,R11 + ST -Y,R12 + ST -Y,R13 + ST -Y,R14 + ST -Y,R15 + ST -Y,R16 + ST -Y,R17 + ST -Y,R18 + ST -Y,R19 + ST -Y,R20 + ST -Y,R21 + ST -Y,R22 + ST -Y,R23 + ST -Y,R24 + ST -Y,R25 + ST -Y,R26 + ST -Y,R27 + ST -Y,R30 + ST -Y,R31 + IN R16,RAMPZ + ST -Y,R16 + IN R16,EIND + ST -Y,R16 + ENDM + +POP_ALL MACRO ; Restore all registers + LD R16,Y+ + OUT EIND,R16 + LD R16,Y+ + OUT RAMPZ,R16 + LD R31,Y+ + LD R30,Y+ + LD R27,Y+ + LD R26,Y+ + LD R25,Y+ + LD R24,Y+ + LD R23,Y+ + LD R22,Y+ + LD R21,Y+ + LD R20,Y+ + LD R19,Y+ + LD R18,Y+ + LD R17,Y+ + LD R16,Y+ + LD R15,Y+ + LD R14,Y+ + LD R13,Y+ + LD R12,Y+ + LD R11,Y+ + LD R10,Y+ + LD R9,Y+ + LD R8,Y+ + LD R7,Y+ + LD R6,Y+ + LD R5,Y+ + LD R4,Y+ + LD R3,Y+ + LD R2,Y+ + LD R1,Y+ + LD R0,Y+ + ENDM + +PUSH_SP MACRO ; Save stack pointer + IN R16,SPH + ST -Y,R16 + IN R16,SPL + ST -Y,R16 + ENDM + +POP_SP MACRO ; Restore stack pointer + LD R16,Y+ + OUT SPL,R16 + LD R16,Y+ + OUT SPH,R16 + ENDM + +PUSH_SREG MACRO ; Save status register + IN R16,SREG + ST -Y,R16 + ENDM + +POP_SREG MACRO ; Restore status registers + LD R16,Y+ + OUT SREG,R16 + ENDM + +PUSH_SREG_INT MACRO ; Save status register with interrupts ENABLED + IN R16,SREG + SBR R16,BIT07 + ST -Y,R16 + ENDM + +POP_SREG_INT MACRO ; Restore status registers but DISABLE interrupts + LD R16,Y+ + CBR R16,BIT07 + OUT SREG,R16 + ENDM diff --git a/Ports/AVR/ATmega256/IAR/os_dbg.c b/Ports/AVR/ATmega256/IAR/os_dbg.c new file mode 100644 index 0000000..48d6826 --- /dev/null +++ b/Ports/AVR/ATmega256/IAR/os_dbg.c @@ -0,0 +1,291 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventEn = 0; +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; + +#if OS_TMR_EN > 0 +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); /* Size in Bytes of OSTmrTbl[] */ +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); /* Size in Bytes of OSTmrWheelTbl[] */ +#endif + +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if OS_TMR_EN > 0 + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR/ATmega256/ICC/os_cpu.h b/Ports/AVR/ATmega256/ICC/os_cpu.h new file mode 100644 index 0000000..23f15ac --- /dev/null +++ b/Ports/AVR/ATmega256/ICC/os_cpu.h @@ -0,0 +1,126 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega256 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************** +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 8 bits) */ + +/* +********************************************************************************************************* +* Atmel AVR +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. The IAR compiler does not support inline assembly so I'm +* using the _OPC() intrinsic function. Here are the instructions: +* +* OS_ENTER_CRITICAL: +* ST -Y,R16 +* IN R16,SREG +* CLI +* PUSH R16 +* LD R16,Y+ +* +* OS_EXIT_CRITICAL: +* ST -Y,R16 +* POP R16 +* OUT SREG,R16 +* LD R16,Y+ +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************** +* AVR Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************** +* GLOBAL VARIABLES +********************************************************************************************************** +*/ + +OS_CPU_EXT INT16U OSTaskStkSize; /* Used to set the total stack size of a task */ +OS_CPU_EXT INT16U OSTaskStkSizeHard; /* Used to set the hardware stack size of a task */ + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy(void); +void OSCtxSw(void); +void OSIntCtxSw(void); diff --git a/Ports/AVR/ATmega256/ICC/os_cpu_a.s b/Ports/AVR/ATmega256/ICC/os_cpu_a.s new file mode 100644 index 0000000..847d08b --- /dev/null +++ b/Ports/AVR/ATmega256/ICC/os_cpu_a.s @@ -0,0 +1,238 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega256 Specific code +; ICC AVR Compiler +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + .include "os_cpu_i.h" + + +;******************************************************************************************************** +; DISABLE/ENABLE INTERRUPTS USING OS_CRITICAL_METHOD #3 +; +; Description : These functions are used to disable and enable interrupts using OS_CRITICAL_METHOD #3. +; +; OS_CPU_SR OSCPUSaveSR (void) +; Get current value of SREG +; Disable interrupts +; Return original value of SREG +; +; void OSCPURestoreSR (OS_CPU_SR cpu_sr) +; Set SREG to cpu_sr +; Return +;******************************************************************************************************** + + .area text(rel) + +_OS_CPU_SR_Save:: + IN R16,SREG ; Get current state of interrupts disable flag + CLI ; Disable interrupts + RET ; Return original SREG value in R16 + + +_OS_CPU_SR_Restore:: + OUT SREG,R16 ; Restore SREG + RET ; Return + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Note(s) : 1) The (data)stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +; +; where the stack pointer points to the task start address. +; +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +_OSStartHighRdy:: + CALL _OSTaskSwHook ; Invoke user defined context switch hook + + LDS R16,_OSRunning ; Indicate that we are multitasking + INC R16 ; + STS _OSRunning,R16 ; + + LDS R30,_OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,_OSTCBHighRdy+1 ; ready to run + LD R28,Z+ ; Load Y (R29:R28) pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + POP_SREG_INT ; Restore status register (Disable Interrupts) + POP_ALL ; Restore all registers + RETI ; Start task + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP+0 --> LSB of task code address +; +1 MSB of task code address (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +;******************************************************************************************************** + +_OSCtxSw:: + PUSH_ALL ; Save current task's context + PUSH_SREG + PUSH_SP + + LDS R30,_OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr + LDS R31,_OSTCBCur+1 ; + ST Z+,R28 ; Save Y (R29:R28) pointer + ST Z+,R29 ; + + CALL _OSTaskSwHook ; Call user defined task switch hook + + LDS R16,_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS _OSPrioCur,R16 + + LDS R30,_OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,_OSTCBHighRdy+1 ; ready to run + STS _OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS _OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction if interrupts DISABLED + RJMP _OSCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +_OSCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +;********************************************************************************************************* + +_OSIntCtxSw:: + CALL _OSTaskSwHook ; Call user defined task switch hook + + LDS R16,_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS _OSPrioCur,R16 ; + + LDS R30,_OSTCBHighRdy ; Z = OSTCBHighRdy->OSTCBStkPtr + LDS R31,_OSTCBHighRdy+1 ; + STS _OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS _OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction if interrupts DISABLED + RJMP _OSIntCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +_OSIntCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI diff --git a/Ports/AVR/ATmega256/ICC/os_cpu_c.c b/Ports/AVR/ATmega256/ICC/os_cpu_c.c new file mode 100644 index 0000000..2a87665 --- /dev/null +++ b/Ports/AVR/ATmega256/ICC/os_cpu_c.c @@ -0,0 +1,353 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega256 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* SREG to 0x00 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable interrupts. +* Failure to do this will make your system crash! +* +* The AVR return stack is placed OS_TASK_HARD_STK_SIZE bytes before the bottom of the task's +* stack. +* +* (1) IMPORTANT: The ICC compiler handles function pointers by actually passing the pointer +* to a location in Flash that actually contains the pointer to the function. +* +* (2) IMPORTANT: Currently, the ICC compiler handled function pointers as 16-bit addresses +* and thus, we 'force' 0x00 as the upper 8 bits of the task start address +* until ImageCraft fixes that issue. +* +* (3) IMPORTANT: You MUST set OSTaskStkSize and OSTaskStkSizeHard BEFORE calling OSInit() +* to initialize the Idle and statistic tasks stacks. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *psoft_stk; + INT8U *phard_stk; /* Temp. variable used for setting up AVR hardware stack */ + INT32U tmp; + + + (void)opt; /* 'opt' is not used, prevent warning */ + psoft_stk = (INT8U *)ptos; + phard_stk = (INT8U *)ptos + - OSTaskStkSize /* Task stack size */ + + OSTaskStkSizeHard; /* AVR return stack ("hardware stack") */ + + tmp = *(INT32U const *)task; /* ICC compiler handles function pointers indirectly! */ + + *phard_stk-- = (INT8U)(tmp & 0xFF); /* Put task start address on top of "hardware stack" */ + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + + *psoft_stk-- = (INT8U)0x00; /* R0 = 0x00 */ + *psoft_stk-- = (INT8U)0x01; /* R1 = 0x01 */ + *psoft_stk-- = (INT8U)0x02; /* R2 = 0x02 */ + *psoft_stk-- = (INT8U)0x03; /* R3 = 0x03 */ + *psoft_stk-- = (INT8U)0x04; /* R4 = 0x04 */ + *psoft_stk-- = (INT8U)0x05; /* R5 = 0x05 */ + *psoft_stk-- = (INT8U)0x06; /* R6 = 0x06 */ + *psoft_stk-- = (INT8U)0x07; /* R7 = 0x07 */ + *psoft_stk-- = (INT8U)0x08; /* R8 = 0x08 */ + *psoft_stk-- = (INT8U)0x09; /* R9 = 0x09 */ + *psoft_stk-- = (INT8U)0x10; /* R10 = 0x10 */ + *psoft_stk-- = (INT8U)0x11; /* R11 = 0x11 */ + *psoft_stk-- = (INT8U)0x12; /* R12 = 0x12 */ + *psoft_stk-- = (INT8U)0x13; /* R13 = 0x13 */ + *psoft_stk-- = (INT8U)0x14; /* R14 = 0x14 */ + *psoft_stk-- = (INT8U)0x15; /* R15 = 0x15 */ + tmp = (INT16U)p_arg; + *psoft_stk-- = (INT8U)tmp; /* 'p_arg' passed in R17:R16 */ + *psoft_stk-- = (INT8U)(tmp >> 8); + *psoft_stk-- = (INT8U)0x18; /* R18 = 0x18 */ + *psoft_stk-- = (INT8U)0x19; /* R19 = 0x19 */ + *psoft_stk-- = (INT8U)0x20; /* R20 = 0x20 */ + *psoft_stk-- = (INT8U)0x21; /* R21 = 0x21 */ + *psoft_stk-- = (INT8U)0x22; /* R22 = 0x22 */ + *psoft_stk-- = (INT8U)0x23; /* R23 = 0x23 */ + *psoft_stk-- = (INT8U)0x24; /* R24 = 0x24 */ + *psoft_stk-- = (INT8U)0x25; /* R25 = 0x25 */ + *psoft_stk-- = (INT8U)0x26; /* R26 = 0x26 */ + *psoft_stk-- = (INT8U)0x27; /* R27 = 0x27 */ + /* R28 R29:R28 is the software stack which gets ... */ + /* R29 ... stored in the task's OS_TCB. */ + *psoft_stk-- = (INT8U)0x30; /* R30 = 0x30 */ + *psoft_stk-- = (INT8U)0x31; /* R31 = 0x31 */ + + tmp = (INT32U)phard_stk; + tmp >>= 8; + *psoft_stk-- = (INT8U)(tmp >> 8); /* RAMPZ = Upper 8 bits of stack pointer */ + *psoft_stk-- = (INT8U)(tmp >> 8); /* EIND = Upper 8 bits of stack pointer */ + + *psoft_stk-- = (INT8U)0x80; /* SREG = Interrupts enabled */ + + tmp = (INT32U)phard_stk; + *psoft_stk-- = (INT8U)(tmp >> 8); /* SPH */ + *psoft_stk = (INT8U) tmp; /* SPL */ + return ((OS_STK *)psoft_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/AVR/ATmega256/ICC/os_cpu_i.h b/Ports/AVR/ATmega256/ICC/os_cpu_i.h new file mode 100644 index 0000000..3ddff99 --- /dev/null +++ b/Ports/AVR/ATmega256/ICC/os_cpu_i.h @@ -0,0 +1,159 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega256 Specific code +; INCLUDE FILE +; +; Filename : os_cpu_i.h +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; BIT DEFINITIONS +;******************************************************************************************************** + +BIT00 = 0x01 +BIT01 = 0x02 +BIT02 = 0x04 +BIT03 = 0x08 +BIT04 = 0x10 +BIT05 = 0x20 +BIT06 = 0x40 +BIT07 = 0x80 + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +SREG = 0x3F +SPH = 0x3E +SPL = 0x3D +RAMPZ = 0x3B +EIND = 0x3C + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + + .macro PUSH_ALL ; Save all registers + ST -Y,R0 + ST -Y,R1 + ST -Y,R2 + ST -Y,R3 + ST -Y,R4 + ST -Y,R5 + ST -Y,R6 + ST -Y,R7 + ST -Y,R8 + ST -Y,R9 + ST -Y,R10 + ST -Y,R11 + ST -Y,R12 + ST -Y,R13 + ST -Y,R14 + ST -Y,R15 + ST -Y,R16 + ST -Y,R17 + ST -Y,R18 + ST -Y,R19 + ST -Y,R20 + ST -Y,R21 + ST -Y,R22 + ST -Y,R23 + ST -Y,R24 + ST -Y,R25 + ST -Y,R26 + ST -Y,R27 + ST -Y,R30 + ST -Y,R31 + IN R16,RAMPZ + ST -Y,R16 + IN R16,EIND + ST -Y,R16 + .endmacro + + .macro POP_ALL ; Restore all registers + LD R16,Y+ + OUT EIND,R16 + LD R16,Y+ + OUT RAMPZ,R16 + LD R31,Y+ + LD R30,Y+ + LD R27,Y+ + LD R26,Y+ + LD R25,Y+ + LD R24,Y+ + LD R23,Y+ + LD R22,Y+ + LD R21,Y+ + LD R20,Y+ + LD R19,Y+ + LD R18,Y+ + LD R17,Y+ + LD R16,Y+ + LD R15,Y+ + LD R14,Y+ + LD R13,Y+ + LD R12,Y+ + LD R11,Y+ + LD R10,Y+ + LD R9,Y+ + LD R8,Y+ + LD R7,Y+ + LD R6,Y+ + LD R5,Y+ + LD R4,Y+ + LD R3,Y+ + LD R2,Y+ + LD R1,Y+ + LD R0,Y+ + .endmacro + + .macro PUSH_SP ; Save stack pointer + IN R16,SPH + ST -Y,R16 + IN R16,SPL + ST -Y,R16 + .endmacro + + .macro POP_SP ; Restore stack pointer + LD R16,Y+ + OUT SPL,R16 + LD R16,Y+ + OUT SPH,R16 + .endmacro + + .macro PUSH_SREG ; Save status register + IN R16,SREG + ST -Y,R16 + .endmacro + + .macro POP_SREG ; Restore status registers + LD R16,Y+ + OUT SREG,R16 + .endmacro + + .macro PUSH_SREG_INT ; Save status register + IN R16,SREG + SBR R16,BIT07 + ST -Y,R16 + .endmacro + + .macro POP_SREG_INT ; Restore status registers + LD R16,Y+ + CBR R16,BIT07 + OUT SREG,R16 + .endmacro diff --git a/Ports/AVR/ATmega256/ICC/os_dbg.c b/Ports/AVR/ATmega256/ICC/os_dbg.c new file mode 100644 index 0000000..1e21f4a --- /dev/null +++ b/Ports/AVR/ATmega256/ICC/os_dbg.c @@ -0,0 +1,291 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventEn = 0; +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; + +#if OS_TMR_EN > 0 +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); /* Size in Bytes of OSTmrTbl[] */ +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); /* Size in Bytes of OSTmrWheelTbl[] */ +#endif + +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if OS_TMR_EN > 0 + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR/ATxmega128/GNU/os_cpu.h b/Ports/AVR/ATxmega128/GNU/os_cpu.h new file mode 100644 index 0000000..87be1ac --- /dev/null +++ b/Ports/AVR/ATxmega128/GNU/os_cpu.h @@ -0,0 +1,126 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega128 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************** +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 8 bits) */ + +/* +********************************************************************************************************* +* Atmel AVR +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. The IAR compiler does not support inline assembly so I'm +* using the _OPC() intrinsic function. Here are the instructions: +* +* OS_ENTER_CRITICAL: +* ST -Y,R16 +* IN R16,SREG +* CLI +* PUSH R16 +* LD R16,Y+ +* +* OS_EXIT_CRITICAL: +* ST -Y,R16 +* POP R16 +* OUT SREG,R16 +* LD R16,Y+ +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************** +* AVR Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************** +* GLOBAL VARIABLES +********************************************************************************************************** +*/ + +OS_CPU_EXT INT16U OSTaskStkSize; /* Used to set the total stack size of a task */ +OS_CPU_EXT INT16U OSTaskStkSizeHard; /* Used to set the hardware stack size of a task */ + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy(void); +void OSCtxSw(void); +void OSIntCtxSw(void); diff --git a/Ports/AVR/ATxmega128/GNU/os_cpu_a.s b/Ports/AVR/ATxmega128/GNU/os_cpu_a.s new file mode 100644 index 0000000..8e18745 --- /dev/null +++ b/Ports/AVR/ATxmega128/GNU/os_cpu_a.s @@ -0,0 +1,251 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATXmega128A1 Specific code +; GNU AVR Compiler +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +#include + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSStartHighRdy + .global OSCtxSw + .global OSIntCtxSw + + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + .extern OSTaskSwHook + .extern OSRunning + .extern OSTCBHighRdy + .extern OSTCBCur + .extern OSPrioHighRdy + + + .text + + +;******************************************************************************************************** +; DISABLE/ENABLE INTERRUPTS USING OS_CRITICAL_METHOD #3 +; +; Description : These functions are used to disable and enable interrupts using OS_CRITICAL_METHOD #3. +; +; OS_CPU_SR OSCPUSaveSR (void) +; Get current value of SREG +; Disable interrupts +; Return original value of SREG +; +; void OSCPURestoreSR (OS_CPU_SR cpu_sr) +; Set SREG to cpu_sr +; Return +;******************************************************************************************************** + +OS_CPU_SR_Save: + IN R16,SREG ; Get current state of interrupts disable flag + CLI ; Disable interrupts + RET ; Return original SREG value in R16 + + +OS_CPU_SR_Restore: + OUT SREG,R16 ; Restore SREG + RET ; Return + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Note(s) : 1) The (data)stack frame is assumed to look as follows: +; +======+ +; OSTCBHighRdy->OSTCBStkPtr --> |RAMPZ | +; |RAMPY | +; |RAMPX | +; |RAMPD | +; |EIND | +; |R31 | +; |R30 | +; |R27 | +; |. | +; |SREG | +; |R0 | +; |PCH |-| +; |PCM | |--> PC address (3 bytes) +; |PCL |-| (High memory) +; +======+ +; where the stack pointer points to the task start address. +; +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: + CALL OSTaskSwHook ; Invoke user defined context switch hook + + LDS R16,OSRunning ; Indicate that we are multitasking + INC R16 ; + STS OSRunning,R16 ; + + LDS R26,OSTCBHighRdy ; Let X point to TCB of highest priority task + LDS R27,OSTCBHighRdy+1 ; ready to run + + RESTORE_SP ; SP = MEM[X]; + POP_ALL ; Restore all registers + RETI ; Start task + + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Note(s) : (1) (A) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; (B) The stack frame of the task to suspend looks as follows: +; +; SP+0 --> LSB of task code address +; +2 MSB of task code address (High memory) +; +; (C) The saved context of the task to resume looks as follows: +; +; +======+ +; OSTCBHighRdy->OSTCBStkPtr --> |SPL | ->stack pointer (Low memory) +; |SPH | +; |RAMPZ | +; |RAMPY | +; |RAMPX | +; |RAMPD | +; |EIND | +; |R31 | +; |R30 | +; |R27 | +; |. | +; |SREG | +; |R0 | +; |PCH |-| +; |PCM | |--> PC address (3 bytes) +; |PCL |-| (High memory) +; +======+ +; (2) The OSCtxSW() MUST: +; - Save all register in the current task task. +; - Make OSTCBCur->OSTCBStkPtr = SP. +; - Call user defined task swith hook. +; - OSPrioCur = OSPrioHighRdy +; - OSTCBCur = OSTCBHihgRdy +; - SP = OSTCBHighRdy->OSTCBStrkPtr +; - Pop all the register from the new stack +;******************************************************************************************************** + +OSCtxSw: + PUSH_ALL ; Save current task's context + + IN R26, SPL ; X = SP + IN R27, SPH ; + + LDS R28,OSTCBCur ; Y = OSTCBCur->OSTCBStkPtr + LDS R29,OSTCBCur+1 ; + ST Y+,R26 ; Y = SP + ST Y+,R27 ; + + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R26,OSTCBHighRdy ; Let X point to TCB of highest priority task + LDS R27,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R26 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R27 + + RESTORE_SP ; SP = MEM[X]; + POP_ALL + RET + + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 +; PCH +; PCL (High memory) +;********************************************************************************************************* + +OSIntCtxSw: + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 ; + + LDS R26,OSTCBHighRdy ; X = OSTCBHighRdy->OSTCBStkPtr + LDS R27,OSTCBHighRdy+1 ; + STS OSTCBCur,R26 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R27 ; + + RESTORE_SP ; SP = MEM[X]; + POP_ALL ; Restore all registers + RETI + diff --git a/Ports/AVR/ATxmega128/GNU/os_cpu_c.c b/Ports/AVR/ATxmega128/GNU/os_cpu_c.c new file mode 100644 index 0000000..6df203f --- /dev/null +++ b/Ports/AVR/ATxmega128/GNU/os_cpu_c.c @@ -0,0 +1,357 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATmega128 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* SREG to 0x00 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable interrupts. +* Failure to do this will make your system crash! +* +* The AVR return stack is placed OS_TASK_STK_SIZE_HARD bytes before the bottom of the task's +* stack. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U tmp; + + (void)opt; /* 'opt' is not used, prevent warning */ + tmp = (INT32U)task; + /* Put task start address on top of "hardware stack" */ + *ptos-- = (INT8U)(tmp & 0xFF); /* Save PC return address */ + tmp >>= 8; + *ptos-- = (INT8U)(tmp & 0xFF); + tmp >>= 8; + *ptos-- = (INT8U)(tmp & 0xFF); + + *ptos-- = (INT8U)0x00; /* R0 = 0x00 */ + *ptos-- = (INT8U)0x80; /* SREG = Interrupts enabled */ + + *ptos-- = (INT8U)0x00; /* R1 = 0x00 */ + *ptos-- = (INT8U)0x02; /* R2 = 0x02 */ + *ptos-- = (INT8U)0x03; /* R3 = 0x03 */ + *ptos-- = (INT8U)0x04; /* R4 = 0x04 */ + *ptos-- = (INT8U)0x05; /* R5 = 0x05 */ + *ptos-- = (INT8U)0x06; /* R6 = 0x06 */ + *ptos-- = (INT8U)0x07; /* R7 = 0x07 */ + *ptos-- = (INT8U)0x08; /* R8 = 0x08 */ + *ptos-- = (INT8U)0x09; /* R9 = 0x09 */ + *ptos-- = (INT8U)0x10; /* R10 = 0x10 */ + *ptos-- = (INT8U)0x11; /* R11 = 0x11 */ + *ptos-- = (INT8U)0x12; /* R12 = 0x12 */ + *ptos-- = (INT8U)0x13; /* R13 = 0x13 */ + *ptos-- = (INT8U)0x14; /* R14 = 0x14 */ + *ptos-- = (INT8U)0x15; /* R15 = 0x15 */ + *ptos-- = (INT8U)0x16; /* R16 = 0x16 */ + *ptos-- = (INT8U)0x17; /* R17 = 0x17 */ + *ptos-- = (INT8U)0x18; /* R18 = 0x18 */ + *ptos-- = (INT8U)0x19; /* R19 = 0x19 */ + *ptos-- = (INT8U)0x20; /* R20 = 0x20 */ + *ptos-- = (INT8U)0x21; /* R21 = 0x21 */ + *ptos-- = (INT8U)0x22; /* R22 = 0x22 */ + *ptos-- = (INT8U)0x23; /* R23 = 0x23 */ + tmp = (INT16U)p_arg; + *ptos-- = (INT8U)tmp; /* 'p_arg' passed in R24:R25 */ + *ptos-- = (INT8U)(tmp >> 8); + *ptos-- = (INT8U)0x26; /* R26 X = 0x26 */ + *ptos-- = (INT8U)0x27; /* R27 = 0x27 */ + *ptos-- = (INT8U)0x28; /* R28 Y = 0x28 */ + *ptos-- = (INT8U)0x29; /* R29 = 0x29 */ + *ptos-- = (INT8U)0x30; /* R30 Z = 0x30 */ + *ptos-- = (INT8U)0x31; /* R31 = 0x31 */ + *ptos-- = (INT8U)0x00; /* EIND = 0x00 */ + *ptos-- = (INT8U)0x00; /* RAMPD = 0x00 */ + *ptos-- = (INT8U)0x00; /* RAMPX = 0x00 */ + *ptos-- = (INT8U)0x00; /* RAMPY = 0x00 */ + *ptos-- = (INT8U)0x00; /* RAMPZ = 0x00 */ + + return ((OS_STK *)ptos); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/AVR/ATxmega128/GNU/os_cpu_i.h b/Ports/AVR/ATxmega128/GNU/os_cpu_i.h new file mode 100644 index 0000000..0fcaf3f --- /dev/null +++ b/Ports/AVR/ATxmega128/GNU/os_cpu_i.h @@ -0,0 +1,212 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATmega128 Specific code +; GNU AVR Compiler +; +; Filename : os_cpu_i.h +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; BIT DEFINITIONS +;******************************************************************************************************** + +BIT00 = 0x01 +BIT01 = 0x02 +BIT02 = 0x04 +BIT03 = 0x08 +BIT04 = 0x10 +BIT05 = 0x20 +BIT06 = 0x40 +BIT07 = 0x80 + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +SREG = 0x3F +SPH = 0x3E +SPL = 0x3D +EIND = 0x3C +RAMPZ = 0x3B +RAMPY = 0x3A +RAMPX = 0x39 +RAMPD = 0x38 + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + +;* +;********************************************************************************************************* +;* PUSH ALL THE REGISTER INTO THE STACK +;* +;* Description : Save all the register into the stack. +;* +-------+ +;* [RO..RAMPZ] ->| RO | +;* | SREG | +;* | R1 | +;* | R2 | +;* | . | +;* | . | +;* | RAMPZ | +;* +-------+ +;********************************************************************************************************* +;* + + .macro PUSH_ALL ; Save all registers + PUSH R0 + IN R0, SREG + PUSH R0 + PUSH R1 + CLR R1 + PUSH R2 + PUSH R3 + PUSH R4 + PUSH R5 + PUSH R6 + PUSH R7 + PUSH R8 + PUSH R9 + PUSH R10 + PUSH R11 + PUSH R12 + PUSH R13 + PUSH R14 + PUSH R15 + PUSH R16 + PUSH R17 + PUSH R18 + PUSH R19 + PUSH R20 + PUSH R21 + PUSH R22 + PUSH R23 + PUSH R24 + PUSH R25 + PUSH R26 + PUSH R27 + PUSH R28 + PUSH R29 + PUSH R30 + PUSH R31 + IN R16, EIND + PUSH R16 + IN R16, RAMPD + PUSH R16 + IN R16, RAMPX + PUSH R16 + IN R16, RAMPY + PUSH R16 + IN R16, RAMPZ + PUSH R16 + .endm +;* +;********************************************************************************************************* +;* POP ALL THE REGISTER OUT THE STACK +;* +;* Description : Restore all the register form the stack +;* +-------+ +;* | RO | ---> [RO..RAMPZ] +;* | SREG | +;* | R1 | +;* | R2 | +;* | . | +;* | . | +;* | RAMPZ | +;* +-------+ +;********************************************************************************************************* +;* + .macro POP_ALL ; Restore all registers + POP R16 + OUT RAMPZ, R16 + POP R16 + OUT RAMPY, R16 + POP R16 + OUT RAMPX, R16 + POP R16 + OUT RAMPD, R16 + POP R16 + OUT EIND, R16 + POP R31 + POP R30 + POP R29 + POP R28 + POP R27 + POP R26 + POP R25 + POP R24 + POP R23 + POP R22 + POP R21 + POP R20 + POP R19 + POP R18 + POP R17 + POP R16 + POP R15 + POP R14 + POP R13 + POP R12 + POP R11 + POP R10 + POP R9 + POP R8 + POP R7 + POP R6 + POP R5 + POP R4 + POP R3 + POP R2 + POP R1 + POP R0 + OUT SREG, R0 + POP R0 + .endm +;* +;********************************************************************************************************* +;* PUSH THE STACK POINTER INTO THE STACK +;* +;* Description : Save the stack pointer +;* +;* Note(s) : R28 and R29 are equal to the current stak pointer [R28-R29] = SP +;* after the macro exit. +;* +;********************************************************************************************************* +;* + + .macro SAVE_SP ; Save stack pointer + IN R26, SPL + IN R27, SPH + .endm + +;* +;********************************************************************************************************* +;* RESTORE THE STACK POINTER +;* +;* Description : Restore the Stack Pointer +;* +;* Note(s) : X register points to the memory location where the SP is contained. +;* +;********************************************************************************************************* +;* + .macro RESTORE_SP ; Restore stack pointer + LD R28,X+ + OUT SPL,R28 + LD R29,X+ + OUT SPH,R29 + .endm diff --git a/Ports/AVR/ATxmega128/GNU/os_dbg.c b/Ports/AVR/ATxmega128/GNU/os_dbg.c new file mode 100644 index 0000000..0f27c2d --- /dev/null +++ b/Ports/AVR/ATxmega128/GNU/os_dbg.c @@ -0,0 +1,293 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventEn = 0; +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; + +#if OS_TMR_EN > 0 +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); /* Size in Bytes of OSTmrTbl[] */ +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); /* Size in Bytes of OSTmrWheelTbl[] */ +#endif + +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if OS_TMR_EN > 0 + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + ptemp = (void *)&OSTmrCfgNameEn; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR/ATxmega128/IAR/os_cpu.h b/Ports/AVR/ATxmega128/IAR/os_cpu.h new file mode 100644 index 0000000..4c8b190 --- /dev/null +++ b/Ports/AVR/ATxmega128/IAR/os_cpu.h @@ -0,0 +1,93 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR Xmega Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() (OSCtxSw()) /* Perform task switch */ + +/* +********************************************************************************************************** +* GLOBAL VARIABLES +********************************************************************************************************** +*/ + +OS_CPU_EXT INT16U OSTaskStkSize; +OS_CPU_EXT INT16U OSTaskStkSizeHard; + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +void OSStartHighRdy(void); +void OSCtxSw(void); +void OSIntCtxSw(void); diff --git a/Ports/AVR/ATxmega128/IAR/os_cpu_a.s90 b/Ports/AVR/ATxmega128/IAR/os_cpu_a.s90 new file mode 100644 index 0000000..9c1e40e --- /dev/null +++ b/Ports/AVR/ATxmega128/IAR/os_cpu_a.s90 @@ -0,0 +1,283 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATMEL AVR Xmega Specific code +; +; Filename : os_cpu_a.s90 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; ASM HEADER +;******************************************************************************************************** + +#include + + MODULE OS_CPU_A + + RSEG FARCODE:CODE:NOROOT(1) + + + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Note(s) : 1) The (data)stack frame is assumed to look as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; RAMPX +; RAMPD +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; where the stack pointer points to the task start address. +; +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: + CALL OSTaskSwHook ; Invoke user defined context switch hook + LDS R16,OSRunning ; Indicate that we are multitasking + INC R16 ; + STS OSRunning,R16 ; + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + LD R28,Z+ ; Load Y (R29:R28) pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + POP_SREG_INT ; Restore status register (DISABLE interrupts) + POP_ALL ; Restore all registers + SEI ; Enable interrupts, since RETI does not on Xmega + RETI + + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP+0 --> LSB of task code address +; +1 MSB of task code address (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; RAMPX +; RAMPD +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +;******************************************************************************************************** + +OSCtxSw: + PUSH_ALL ; Save current task's context + PUSH_SREG + PUSH_SP + + LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr + LDS R31,OSTCBCur+1 ; + ST Z+,R28 ; Save Y (R29:R28) pointer + ST Z+,R29 ; + + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +OSCtxSw_1: + CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + SEI ; Enable interrupts, since RETI does not on Xmega + RET + + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; RAMPX +; RAMPD +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; RAMPX +; RAMPD +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +;********************************************************************************************************* + +OSIntCtxSw: + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSIntCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RETI + +OSIntCtxSw_1: + CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + SEI ; Enable interrupts, since RETI does not on Xmega + RETI + + + +;******************************************************************************************************** +; OS_CPU ASSEMBLY PORT FILE END +;******************************************************************************************************** + + END diff --git a/Ports/AVR/ATxmega128/IAR/os_cpu_c.c b/Ports/AVR/ATxmega128/IAR/os_cpu_c.c new file mode 100644 index 0000000..974a8a9 --- /dev/null +++ b/Ports/AVR/ATxmega128/IAR/os_cpu_c.c @@ -0,0 +1,366 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR Xmega Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL GLOBAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* SREG to 0x00 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable interrupts. +* Failure to do this will make your system crash! +* +* The AVR return stack is placed OS_TASK_STK_SIZE_HARD bytes before the bottom of the task's +* stack. +* +* Depending on "Register Utilization" settings, R4 to R15 may be locked to be used for global +* variables. Thus, their initial value is set to zero. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *psoft_stk; + OS_STK *phard_stk; /* Temp. variable used for setting up AVR hardware stack */ + INT32U tmp; + + + (void)opt; /* 'opt' is not used, prevent warning */ + psoft_stk = (INT8U *)ptos; + phard_stk = (INT8U *)ptos + - OSTaskStkSize /* Task stack size */ + + OSTaskStkSizeHard; /* AVR return stack ("hardware stack") */ + tmp = (INT32U)task; + *phard_stk-- = (INT8U)(tmp & 0xFF); /* Put task start address on top of "hardware stack" */ + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); + + *psoft_stk-- = (INT8U)0x00; /* R0 = 0x00 */ + *psoft_stk-- = (INT8U)0x01; /* R1 = 0x01 */ + *psoft_stk-- = (INT8U)0x02; /* R2 = 0x02 */ + *psoft_stk-- = (INT8U)0x03; /* R3 = 0x03 */ + *psoft_stk-- = (INT8U)0x00; /* R4 depending on "Register Utilization" settings, */ + *psoft_stk-- = (INT8U)0x00; /* R5 R4 to R15 may be locked to be used for global */ + *psoft_stk-- = (INT8U)0x00; /* R6 variables */ + *psoft_stk-- = (INT8U)0x00; /* R7 */ + *psoft_stk-- = (INT8U)0x00; /* R8 */ + *psoft_stk-- = (INT8U)0x00; /* R9 */ + *psoft_stk-- = (INT8U)0x00; /* R10 */ + *psoft_stk-- = (INT8U)0x00; /* R11 */ + *psoft_stk-- = (INT8U)0x00; /* R12 */ + *psoft_stk-- = (INT8U)0x00; /* R13 */ + *psoft_stk-- = (INT8U)0x00; /* R14 */ + *psoft_stk-- = (INT8U)0x00; /* R15 */ + tmp = (INT16U)p_arg; + *psoft_stk-- = (INT8U)tmp; /* 'p_arg' passed in R17:R16 */ + *psoft_stk-- = (INT8U)(tmp >> 8); + *psoft_stk-- = (INT8U)0x18; /* R18 = 0x18 */ + *psoft_stk-- = (INT8U)0x19; /* R19 = 0x19 */ + *psoft_stk-- = (INT8U)0x20; /* R20 = 0x20 */ + *psoft_stk-- = (INT8U)0x21; /* R21 = 0x21 */ + *psoft_stk-- = (INT8U)0x22; /* R22 = 0x22 */ + *psoft_stk-- = (INT8U)0x23; /* R23 = 0x23 */ + *psoft_stk-- = (INT8U)0x24; /* R24 = 0x24 */ + *psoft_stk-- = (INT8U)0x25; /* R25 = 0x25 */ + *psoft_stk-- = (INT8U)0x26; /* R26 = 0x26 */ + *psoft_stk-- = (INT8U)0x27; /* R27 = 0x27 */ + /* R28 R29:R28 is the software stack which gets ... */ + /* R29 ... in the TCB. */ + *psoft_stk-- = (INT8U)0x30; /* R30 = 0x30 */ + *psoft_stk-- = (INT8U)0x31; /* R31 = 0x31 */ + *psoft_stk-- = (INT8U)0x00; /* RAMPD = 0x00 */ + *psoft_stk-- = (INT8U)0x00; /* RAMPX = 0x00 */ + *psoft_stk-- = (INT8U)0x00; /* RAMPZ = 0x00 */ + *psoft_stk-- = (INT8U)0x00; /* EIND = 0x00 */ + *psoft_stk-- = (INT8U)0x80; /* SREG = Interrupts enabled */ + tmp = (INT16U)phard_stk; + *psoft_stk-- = (INT8U)(tmp >> 8); /* SPH */ + *psoft_stk = (INT8U) tmp; /* SPL */ + return ((OS_STK *)psoft_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_VERSION >= 281 && OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/AVR/ATxmega128/IAR/os_cpu_i.s90 b/Ports/AVR/ATxmega128/IAR/os_cpu_i.s90 new file mode 100644 index 0000000..d708446 --- /dev/null +++ b/Ports/AVR/ATxmega128/IAR/os_cpu_i.s90 @@ -0,0 +1,178 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATMEL AVR Xmega Include File +; +; Filename : os_cpu_i.s90 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; BIT DEFINITIONS +;******************************************************************************************************** + +BIT00 = 0x01 +BIT01 = 0x02 +BIT02 = 0x04 +BIT03 = 0x08 +BIT04 = 0x10 +BIT05 = 0x20 +BIT06 = 0x40 +BIT07 = 0x80 + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +SREG = 0x3F +SPH = 0x3E +SPL = 0x3D +EIND = 0x3C +RAMPZ = 0x3B +RAMPX = 0x39 +RAMPD = 0x38 + + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + +PUSH_ALL MACRO ; Save all registers + ST -Y,R0 + ST -Y,R1 + ST -Y,R2 + ST -Y,R3 + ST -Y,R4 + ST -Y,R5 + ST -Y,R6 + ST -Y,R7 + ST -Y,R8 + ST -Y,R9 + ST -Y,R10 + ST -Y,R11 + ST -Y,R12 + ST -Y,R13 + ST -Y,R14 + ST -Y,R15 + ST -Y,R16 + ST -Y,R17 + ST -Y,R18 + ST -Y,R19 + ST -Y,R20 + ST -Y,R21 + ST -Y,R22 + ST -Y,R23 + ST -Y,R24 + ST -Y,R25 + ST -Y,R26 + ST -Y,R27 + ST -Y,R30 + ST -Y,R31 + IN R16,RAMPD + ST -Y,R16 + IN R16,RAMPX + ST -Y,R16 + IN R16,RAMPZ + ST -Y,R16 + IN R16,EIND + ST -Y,R16 + ENDM + + + +POP_ALL MACRO ; Restore all registers + LD R16,Y+ + OUT EIND,R16 + LD R16,Y+ + OUT RAMPZ,R16 + LD R16,Y+ + OUT RAMPX,R16 + LD R16,Y+ + OUT RAMPD,R16 + LD R31,Y+ + LD R30,Y+ + LD R27,Y+ + LD R26,Y+ + LD R25,Y+ + LD R24,Y+ + LD R23,Y+ + LD R22,Y+ + LD R21,Y+ + LD R20,Y+ + LD R19,Y+ + LD R18,Y+ + LD R17,Y+ + LD R16,Y+ + LD R15,Y+ + LD R14,Y+ + LD R13,Y+ + LD R12,Y+ + LD R11,Y+ + LD R10,Y+ + LD R9,Y+ + LD R8,Y+ + LD R7,Y+ + LD R6,Y+ + LD R5,Y+ + LD R4,Y+ + LD R3,Y+ + LD R2,Y+ + LD R1,Y+ + LD R0,Y+ + ENDM + + + +PUSH_SP MACRO ; Save stack pointer + IN R16,SPH + ST -Y,R16 + IN R16,SPL + ST -Y,R16 + ENDM + + +POP_SP MACRO ; Restore stack pointer + LD R16,Y+ + OUT SPL,R16 + LD R16,Y+ + OUT SPH,R16 + ENDM + + +PUSH_SREG MACRO ; Save status register + IN R16,SREG + ST -Y,R16 + ENDM + + +POP_SREG MACRO ; Restore status registers + LD R16,Y+ + OUT SREG,R16 + ENDM + + +PUSH_SREG_INT MACRO ; Save status register with interrupts ENABLED + IN R16,SREG + SBR R16,BIT07 + ST -Y,R16 + ENDM + + +POP_SREG_INT MACRO ; Restore status registers but DISABLE interrupts + LD R16,Y+ + CBR R16,BIT07 + OUT SREG,R16 + ENDM diff --git a/Ports/AVR/ATxmega128/IAR/os_dbg.c b/Ports/AVR/ATxmega128/IAR/os_dbg.c new file mode 100644 index 0000000..c147eab --- /dev/null +++ b/Ports/AVR/ATxmega128/IAR/os_dbg.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR/Generic/IAR/os_cpu.h b/Ports/AVR/Generic/IAR/os_cpu.h new file mode 100644 index 0000000..093d341 --- /dev/null +++ b/Ports/AVR/Generic/IAR/os_cpu.h @@ -0,0 +1,135 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************** +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 8 bits) */ + +/* +********************************************************************************************************* +* Atmel AVR +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. The IAR compiler does not support inline assembly so I'm +* using the _OPC() intrinsic function. Here are the instructions: +* +* OS_ENTER_CRITICAL: +* ST -Y,R16 +* IN R16,SREG +* CLI +* PUSH R16 +* LD R16,Y+ +* +* OS_EXIT_CRITICAL: +* ST -Y,R16 +* POP R16 +* OUT SREG,R16 +* LD R16,Y+ +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() _CLI() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() _SEI() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() _OPC(0x930A);_OPC(0xB70F);_CLI();_OPC(0x930F);_OPC(0x9109) +#define OS_EXIT_CRITICAL() _OPC(0x930A);_OPC(0x910F),_OPC(0xBF0F);_OPC(0x9109) +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************** +* AVR Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************** +* GLOBAL VARIABLES +********************************************************************************************************** +*/ + +OS_CPU_EXT INT16U OSTaskStkSize; +OS_CPU_EXT INT16U OSTaskStkSizeHard; + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy(void); +void OSCtxSw(void); +void OSIntCtxSw(void); diff --git a/Ports/AVR/Generic/IAR/os_cpu_a.s90 b/Ports/AVR/Generic/IAR/os_cpu_a.s90 new file mode 100644 index 0000000..8e588f6 --- /dev/null +++ b/Ports/AVR/Generic/IAR/os_cpu_a.s90 @@ -0,0 +1,423 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ATMEL AVR Specific code +; +; Filename : os_cpu_a.s90 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +BIT00 = 0x01 +BIT01 = 0x02 +BIT02 = 0x04 +BIT03 = 0x08 +BIT04 = 0x10 +BIT05 = 0x20 +BIT06 = 0x40 +BIT07 = 0x80 + +SREG = 0x3F +SPH = 0x3E +SPL = 0x3D +RAMPZ = 0x3B +EIND = 0x3C + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + MODULE OS_CPU_A + + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + +;******************************************************************************************************** +; MACROS +;******************************************************************************************************** + +PUSH_ALL MACRO ; Save all registers + ST -Y,R0 + ST -Y,R1 + ST -Y,R2 + ST -Y,R3 + ST -Y,R4 + ST -Y,R5 + ST -Y,R6 + ST -Y,R7 + ST -Y,R8 + ST -Y,R9 + ST -Y,R10 + ST -Y,R11 + ST -Y,R12 + ST -Y,R13 + ST -Y,R14 + ST -Y,R15 + ST -Y,R16 + ST -Y,R17 + ST -Y,R18 + ST -Y,R19 + ST -Y,R20 + ST -Y,R21 + ST -Y,R22 + ST -Y,R23 + ST -Y,R24 + ST -Y,R25 + ST -Y,R26 + ST -Y,R27 + ST -Y,R30 + ST -Y,R31 + IN R16,RAMPZ + ST -Y,R16 + IN R16,EIND + ST -Y,R16 + ENDM + +POP_ALL MACRO ; Restore all registers + LD R16,Y+ + OUT EIND,R16 + LD R16,Y+ + OUT RAMPZ,R16 + LD R31,Y+ + LD R30,Y+ + LD R27,Y+ + LD R26,Y+ + LD R25,Y+ + LD R24,Y+ + LD R23,Y+ + LD R22,Y+ + LD R21,Y+ + LD R20,Y+ + LD R19,Y+ + LD R18,Y+ + LD R17,Y+ + LD R16,Y+ + LD R15,Y+ + LD R14,Y+ + LD R13,Y+ + LD R12,Y+ + LD R11,Y+ + LD R10,Y+ + LD R9,Y+ + LD R8,Y+ + LD R7,Y+ + LD R6,Y+ + LD R5,Y+ + LD R4,Y+ + LD R3,Y+ + LD R2,Y+ + LD R1,Y+ + LD R0,Y+ + ENDM + +PUSH_SP MACRO ; Save stack pointer + IN R16,SPH + ST -Y,R16 + IN R16,SPL + ST -Y,R16 + ENDM + +POP_SP MACRO ; Restore stack pointer + LD R16,Y+ + OUT SPL,R16 + LD R16,Y+ + OUT SPH,R16 + ENDM + +PUSH_SREG MACRO ; Save status register + IN R16,SREG + ST -Y,R16 + ENDM + +POP_SREG MACRO ; Restore status registers + LD R16,Y+ + OUT SREG,R16 + ENDM + +PUSH_SREG_INT MACRO ; Save status register with interrupts ENABLED + IN R16,SREG + SBR R16,BIT07 + ST -Y,R16 + ENDM + +POP_SREG_INT MACRO ; Restore status registers but DISABLE interrupts + LD R16,Y+ + CBR R16,BIT07 + OUT SREG,R16 + ENDM + + +;******************************************************************************************************** +; DISABLE/ENABLE INTERRUPTS USING OS_CRITICAL_METHOD #3 +; +; Description : These functions are used to disable and enable interrupts using OS_CRITICAL_METHOD #3. +; +; OS_CPU_SR OSCPUSaveSR (void) +; Get current value of SREG +; Disable interrupts +; Return original value of SREG +; +; void OSCPURestoreSR (OS_CPU_SR cpu_sr) +; Set SREG to cpu_sr +; Return +;******************************************************************************************************** + + RSEG FARCODE + +OS_CPU_SR_Save: IN R16,SREG ; Get current state of interrupts disable flag + CLI ; Disable interrupts + RET ; Return original SREG value in R16 + + +OS_CPU_SR_Restore: OUT SREG,R16 ; Restore SREG + RET ; Return + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Note(s) : 1) The (data)stack frame is assumed to look as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; where the stack pointer points to the task start address. +; +; 2) On SOME 'AVR' derivatives, the PC is only a 16 bit value and thus the hardware stack +; only contains 2 bytes per return address. +; +; 3) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: CALL OSTaskSwHook ; Invoke user defined context switch hook + LDS R16,OSRunning ; Indicate that we are multitasking + INC R16 ; + STS OSRunning,R16 ; + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + LD R28,Z+ ; Load Y (R29:R28) pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + POP_SREG_INT ; Restore status register (DISABLE interrupts) + POP_ALL ; Restore all registers + RETI + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP+0 --> LSB of task code address +; +1 MSB of task code address (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ----/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; 4) On SOME 'AVR' derivatives, the PC is only a 16 bit value and thus the hardware stack +; only contains 2 bytes per return address. +; +;******************************************************************************************************** + +OSCtxSw: PUSH_ALL ; Save current task's context + PUSH_SREG + PUSH_SP + + LDS R30,OSTCBCur ; Z = OSTCBCur->OSTCBStkPtr + LDS R31,OSTCBCur+1 ; + ST Z+,R28 ; Save Y (R29:R28) pointer + ST Z+,R29 ; + + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +OSCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + +;********************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBCur->OSTCBStkPtr ------> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; 3) The saved context of the task to resume looks as follows: +; +; Hardware Stack points to EMPTY +; <----------------------------\ +; PC (H) | +; PC (M) | +; PC (L) | +; | +; | +; OSTCBHighRdy->OSTCBStkPtr --> SPL of (return) stack pointer ---/ (Low memory) +; SPH of (return) stack pointer +; Flags to load in status register +; EIND +; RAMPZ +; R31 +; R30 +; R27 +; . +; . +; R0 (High memory) +; +; 4) On SOME 'AVR' derivatives, the PC is only a 16 bit value and thus the hardware stack +; only contains 2 bytes per return address. +;********************************************************************************************************* + +OSIntCtxSw: + CALL OSTaskSwHook ; Call user defined task switch hook + + LDS R16,OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + STS OSPrioCur,R16 + + LDS R30,OSTCBHighRdy ; Let Z point to TCB of highest priority task + LDS R31,OSTCBHighRdy+1 ; ready to run + STS OSTCBCur,R30 ; OSTCBCur = OSTCBHighRdy + STS OSTCBCur+1,R31 ; + + LD R28,Z+ ; Restore Y pointer + LD R29,Z+ ; + + POP_SP ; Restore stack pointer + LD R16,Y+ ; Restore status register + SBRC R16,7 ; Skip next instruction in interrupts DISABLED + RJMP OSIntCtxSw_1 + + OUT SREG,R16 ; Interrupts of task to return to are DISABLED + POP_ALL + RET + +OSIntCtxSw_1: CBR R16,BIT07 ; Interrupts of task to return to are ENABLED + OUT SREG,R16 + POP_ALL ; Restore all registers + RETI + + END diff --git a/Ports/AVR/Generic/IAR/os_cpu_c.c b/Ports/AVR/Generic/IAR/os_cpu_c.c new file mode 100644 index 0000000..ccf1f4e --- /dev/null +++ b/Ports/AVR/Generic/IAR/os_cpu_c.c @@ -0,0 +1,332 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : Interrupts are enabled when your task starts executing. You can change this by setting the +* SREG to 0x00 instead. In this case, interrupts would be disabled upon task startup. The +* application code would be responsible for enabling interrupts at the beginning of the task +* code. You will need to modify OSTaskIdle() and OSTaskStat() so that they enable interrupts. +* Failure to do this will make your system crash! +* +* The AVR return stack is placed OS_TASK_STK_SIZE_HARD bytes before the bottom of the task's +* stack. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *psoft_stk; + INT8U *phard_stk; /* Temp. variable used for setting up AVR hardware stack */ + INT32U tmp; + + + (void)opt; /* 'opt' is not used, prevent warning */ + psoft_stk = (INT8U *)ptos; + phard_stk = (INT8U *)ptos + - OSTaskStkSize /* Task stack size */ + + OSTaskStkSizeHard; /* AVR return stack ("hardware stack") */ + tmp = (INT32U)task; + /* Put task start address on top of "hardware stack" */ + *phard_stk-- = (INT8U)(tmp & 0xFF); /* Save lower 8 bits of address */ + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); +#if CPU_PC_N_BITS > 16 + tmp >>= 8; + *phard_stk-- = (INT8U)(tmp & 0xFF); /* Save upper 8 bits of 24-bit address */ +#endif + + *psoft_stk-- = (INT8U)0x00; /* R0 = 0x00 */ + *psoft_stk-- = (INT8U)0x01; /* R1 = 0x01 */ + *psoft_stk-- = (INT8U)0x02; /* R2 = 0x02 */ + *psoft_stk-- = (INT8U)0x03; /* R3 = 0x03 */ + *psoft_stk-- = (INT8U)0x04; /* R4 = 0x04 */ + *psoft_stk-- = (INT8U)0x05; /* R5 = 0x05 */ + *psoft_stk-- = (INT8U)0x06; /* R6 = 0x06 */ + *psoft_stk-- = (INT8U)0x07; /* R7 = 0x07 */ + *psoft_stk-- = (INT8U)0x08; /* R8 = 0x08 */ + *psoft_stk-- = (INT8U)0x09; /* R9 = 0x09 */ + *psoft_stk-- = (INT8U)0x10; /* R10 = 0x10 */ + *psoft_stk-- = (INT8U)0x11; /* R11 = 0x11 */ + *psoft_stk-- = (INT8U)0x12; /* R12 = 0x12 */ + *psoft_stk-- = (INT8U)0x13; /* R13 = 0x13 */ + *psoft_stk-- = (INT8U)0x14; /* R14 = 0x14 */ + *psoft_stk-- = (INT8U)0x15; /* R15 = 0x15 */ + tmp = (INT16U)p_arg; + *psoft_stk-- = (INT8U)tmp; /* 'p_arg' passed in R17:R16 */ + *psoft_stk-- = (INT8U)(tmp >> 8); + *psoft_stk-- = (INT8U)0x18; /* R18 = 0x18 */ + *psoft_stk-- = (INT8U)0x19; /* R19 = 0x19 */ + *psoft_stk-- = (INT8U)0x20; /* R20 = 0x20 */ + *psoft_stk-- = (INT8U)0x21; /* R21 = 0x21 */ + *psoft_stk-- = (INT8U)0x22; /* R22 = 0x22 */ + *psoft_stk-- = (INT8U)0x23; /* R23 = 0x23 */ + *psoft_stk-- = (INT8U)0x24; /* R24 = 0x24 */ + *psoft_stk-- = (INT8U)0x25; /* R25 = 0x25 */ + *psoft_stk-- = (INT8U)0x26; /* R26 = 0x26 */ + *psoft_stk-- = (INT8U)0x27; /* R27 = 0x27 */ + /* R28 R29:R28 is the software stack which gets ... */ + /* R29 ... in the TCB. */ + *psoft_stk-- = (INT8U)0x30; /* R30 = 0x30 */ + *psoft_stk-- = (INT8U)0x31; /* R31 = 0x31 */ + *psoft_stk-- = (INT8U)0xAA; /* RAMPZ = 0xAA */ + *psoft_stk-- = (INT8U)0xE1; /* EIND = 0xE1 */ + *psoft_stk-- = (INT8U)0x80; /* SREG = Interrupts enabled */ + tmp = (INT16U)phard_stk; + *psoft_stk-- = (INT8U)(tmp >> 8); /* SPH */ + *psoft_stk = (INT8U) tmp; /* SPL */ + return ((OS_STK *)psoft_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif +} +#endif diff --git a/Ports/AVR/Generic/IAR/os_dbg.c b/Ports/AVR/Generic/IAR/os_dbg.c new file mode 100644 index 0000000..ee8bd1d --- /dev/null +++ b/Ports/AVR/Generic/IAR/os_dbg.c @@ -0,0 +1,269 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventEn = 0; +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR32/AP7000/GNU/os_cpu.h b/Ports/AVR32/AP7000/GNU/os_cpu.h new file mode 100644 index 0000000..071113a --- /dev/null +++ b/Ports/AVR32/AP7000/GNU/os_cpu.h @@ -0,0 +1,94 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 AP7000 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#if __GNUC__ +#define OS_TASK_SW() __asm__ __volatile__ ("scall") /* Perform task switch by a supervisor call (exception) */ +#elif __ICCAVR32__ +#define OS_TASK_SW() (OSCtxSw()) /* Perform task switch by a supervisor call (exception) */ +#endif + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if __ICCAVR32__ +__scall extern void OSCtxSw(void); +#endif + + void OSIntCtxSw(void); + void OSStartHighRdy(void); + + void OSCtxRestore(INT32U *sp); + void OSIntCtxRestore(INT32U *sp); diff --git a/Ports/AVR32/AP7000/GNU/os_cpu_a.s b/Ports/AVR32/AP7000/GNU/os_cpu_a.s new file mode 100644 index 0000000..8b11b4c --- /dev/null +++ b/Ports/AVR32/AP7000/GNU/os_cpu_a.s @@ -0,0 +1,411 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* ATMEL AVR32 AP7000 Specific code +* GNU C Compiler +* +* Filename : os_cpu_a.s +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* ASM HEADER +********************************************************************************************************* +*/ + + .file "OS_CPU_A" + + .section .text, "ax" + + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + + .equ OS_CPU_SR_OFFSET, 0 /* Status Register offset in System Register */ + .equ OS_CPU_SR_GM_OFFSET, 16 /* Status Register, Global Interrupt Mask Offset */ + .equ OS_CPU_SR_MX_OFFSET, 22 /* Status Register, Execution Mode Mask offset */ + .equ OS_CPU_RSR_SUP_OFFSET, 20 /* Status Register, to return on Supervisor Context */ + .equ OS_CPU_RAR_SUP_OFFSET, 52 /* Address Register, to return on Supervisor Context */ + .equ OS_CPU_RSR_INT0_OFFSET, 24 /* Status Register, to return on INT0 Context */ + .equ OS_CPU_RAR_INT0_OFFSET, 56 /* Address Register, to return on INT0 Context */ + .equ OS_CPU_RSR_INT1_OFFSET, 28 /* Status Register, to return on INT1 Context */ + .equ OS_CPU_RAR_INT1_OFFSET, 60 /* Address Register, to return on INT1 Context */ + .equ OS_CPU_RSR_INT2_OFFSET, 32 /* Status Register, to return on INT2 Context */ + .equ OS_CPU_RAR_INT2_OFFSET, 64 /* Address Register, to return on INT2 Context */ + .equ OS_CPU_RSR_INT3_OFFSET, 36 /* Status Register, to return on INT3 Context */ + .equ OS_CPU_RAR_INT3_OFFSET, 68 /* Address Register, to return on INT3 Context */ + + +/* +********************************************************************************************************* +* PUBLIC DECLARATIONS +********************************************************************************************************* +*/ + + .global OSCtxSw + .global OSCtxRestore + .global OSIntCtxRestore + .global OSInt0ISRHandler + .global OSInt1ISRHandler + .global OSInt2ISRHandler + .global OSInt3ISRHandler + + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSTaskSwHook + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSIntNesting + .extern OSIntExit + .extern BSP_INTC_IntGetHandler + + + +/* +********************************************************************************************************* +* TASK LEVEL CONTEXT SWITCH +* +* Description: This function is called when a task makes a higher priority task ready-to-run. +* +* Arguments : none +* +* Note(s) : 1) Upon entry, +* OSTCBCur points to the OS_TCB of the task to suspend +* OSTCBHighRdy points to the OS_TCB of the task to resume +* +* 2) The saved context of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* SR ----/ (Low memory) +* PC +* R12 +* . +* . +* R0 +* LR ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 3) OSCtxSw() has to save all registers from the suspended task. PC and SR are retrieved from +* RAR_SUP and RSR_SUP. Only then the Stack Pointer of the task to suspend is saved on OSTCBCur. +* +* 4) OSCtxSw() MUST: +* a) Save processor registers then, +* b) Save current task`s stack pointer into the current task`s OS_TCB, +* c) Call OSTaskSwHook(), +* d) Set OSTCBCur = OSTCBHighRdy, +* e) Set OSPrioCur = OSPrioHighRdy, +* f) Switch to the highest priority task. +* +* pseudo-code: +* void OSCtxSw (void) +* { +* Save processor registers; +* +* OSTCBCur->OSTCBStkPtr = SP; +* +* OSTaskSwHook(); +* +* OSTCBCur = OSTCBHighRdy; +* OSPrioCur = OSPrioHighRdy; +* +* OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +* } +********************************************************************************************************* +*/ + +OSCtxSw: + STMTS --SP, LR /* Save LR into stack */ + STMTS --SP, R0-R12 /* Save R0-R12 into stack */ + + MFSR R9, OS_CPU_RSR_SUP_OFFSET /* Retrieve SR from previous Context */ + MFSR R8, OS_CPU_RAR_SUP_OFFSET /* Retrieve PC from previous Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R8, LO(OSTCBCur) + ORH R8, HI(OSTCBCur) /* OSTCBCur */ + LD.W R9, R8[0] /* *OSTCBCur */ + ST.W R9[0], SP /* OSTCBCur->OSTCBStkPtr = SP */ + + RCALL OSTaskSwHook + + MOV R12, LO(OSTCBHighRdy) + ORH R12, HI(OSTCBHighRdy) /* OSTCBHighRdy */ + LD.W R10, R12[0] /* *OSTCBHighRdy */ + MOV R8, LO(OSTCBCur) + ORH R8, HI(OSTCBCur) /* OSTCBCur */ + ST.W R8[0], R10 /* OSTCBCur = OSTCBHighRdy */ + + MOV R12, LO(OSPrioHighRdy) + ORH R12, HI(OSPrioHighRdy) + LD.UB R11, R12[0] /* *OSPrioHighRdy */ + MOV R12, LO(OSPrioCur) + ORH R12, HI(OSPrioCur) + ST.B R12[0], R11 /* OSPrioCur = OSPrioHighRdy */ + + LD.W R12, R10[0] /* Retrieve OSTCBHighRdy->OSTCBStkPtr */ + + LDM R12, R0-R1 /* Retrieve PC and SR from stack frame */ + MTSR OS_CPU_RSR_SUP_OFFSET, R1 /* Store SR to return from Supervisor Context */ + MTSR OS_CPU_RAR_SUP_OFFSET, R0 /* Store PC to return from Supervisor Context */ + SUB SP, R12, -2*4 /* Restore Stack Pointer */ + + LDMTS SP++, R0-R12 /* Restore R0-R12 */ + LDMTS SP++, LR /* Restore LR */ + RETS /* Restore PC and SR {restore task} */ + + + +/* +********************************************************************************************************* +* RESTORE CONTEXT FUNCTIONS +* +* Description: These functions are used to perform context switch. +* +* void OSCtxRestore (INT32U *sp) +* Restore Stack Pointer +* Restore SR and PC to Supervisor context +* Restore R0-R12, LR +* Return from Supervisor Call {context switch} +* +* void OSIntCtxRestore (INT32U *sp) +* Restore Stack Pointer +* Restore SR and PC to proper INTX context +* Restore R0-R12, LR +* Return from INT {context switch} +* +* Arguments : sp Stack address for the context to be restored +********************************************************************************************************* +*/ + +OSCtxRestore: + /* --- Context Restore Code */ + MOV SP, R12 /* Restore SP (Stack Pointer) */ + + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + MTSR OS_CPU_RSR_SUP_OFFSET, R1 /* Store SR to return from Supervisor Context */ + MTSR OS_CPU_RAR_SUP_OFFSET, R0 /* Store PC to return from Supervisor Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 */ + LDMTS SP++, LR /* Restore LR */ + RETS /* Restore PC and SR {restore task} */ + + +OSIntCtxRestore: + MOV SP, R12 /* Restore SP (Stack Pointer) */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + + MFSR R11, OS_CPU_SR_OFFSET /* Retrieve current SR */ + BFEXTU R11, R11, OS_CPU_SR_MX_OFFSET, 3 /* Retrieve current execution mode */ + + CP.W R11, 5 /* check execution mode */ + BREQ OSIntCtxRestore_INT3_Restore /* if (R11 == INT3) then goto INT3 */ + CP.W R11, 4 /* check execution mode */ + BREQ OSIntCtxRestore_INT2_Restore /* if (R11 == INT2) then goto INT2 */ + CP.W R11, 3 /* check execution mode */ + BREQ OSIntCtxRestore_INT1_Restore /* if (R11 == INT1) then goto INT1 */ + CP.W R11, 2 /* check execution mode */ + BREQ OSIntCtxRestore_INT0_Restore /* if (R11 == INT0) then goto INT0 */ + BRAL OSIntCtxRestore_Err__Restore /* goto Err if no INT context was detected */ + +OSIntCtxRestore_INT0_Restore: + MTSR OS_CPU_RSR_INT0_OFFSET, R1 /* Store SR to return from INT0 Context */ + MTSR OS_CPU_RAR_INT0_OFFSET, R0 /* Store PC to return from INT0 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ +OSIntCtxRestore_INT1_Restore: + MTSR OS_CPU_RSR_INT1_OFFSET, R1 /* Store SR to return from INT1 Context */ + MTSR OS_CPU_RAR_INT1_OFFSET, R0 /* Store PC to return from INT1 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ +OSIntCtxRestore_INT2_Restore: + MTSR OS_CPU_RSR_INT2_OFFSET, R1 /* Store SR to return from INT2 Context */ + MTSR OS_CPU_RAR_INT2_OFFSET, R0 /* Store PC to return from INT2 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ +OSIntCtxRestore_INT3_Restore: + MTSR OS_CPU_RSR_INT3_OFFSET, R1 /* Store SR to return from INT3 Context */ + MTSR OS_CPU_RAR_INT3_OFFSET, R0 /* Store PC to return from INT3 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + +OSIntCtxRestore_Err__Restore: /* Error detected (hold execution) */ + BREAKPOINT + + + +/* +********************************************************************************************************* +* OS INTERRUPT HANDLER +* +* Description: This function handles the OS specific steps to wrap an user-defined function to be called on an interrupt. +* +* prototype: void OSIntXISRHandler(CPU_FNCT_VOID ptrUserISR); +* +* Notes : 1) OSIntXISRHandler() MUST: +* a) disable interrupts, +* b) save registers (R0-R12,LR,PC,SR), +* c) increment OSIntNesting, +* d) if (OSIntNesting == 1) OSTCBCur->OSTCBStkPtr = SP, +* e) call user-defined function, +* f) call OSIntExit(), +* g) restore registers (R0-R12,LR,PC,SR), +* h) return from interrupt. +********************************************************************************************************* +*/ + +OSInt0ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT0_OFFSET /* Retrieve SR from INT0 Context */ + MFSR R8, OS_CPU_RAR_INT0_OFFSET /* Retrieve PC from INT0 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LO(OSIntNesting) + ORH R11, HI(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt0ISRHandler_1 + + MOV R11, LO(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HI(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt0ISRHandler_1: + ICALL R12 /* call user ISR function (address stored on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +OSInt1ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT1_OFFSET /* Retrieve SR from INT1 Context */ + MFSR R8, OS_CPU_RAR_INT1_OFFSET /* Retrieve PC from INT1 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LO(OSIntNesting) + ORH R11, HI(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt1ISRHandler_1 + + MOV R11, LO(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HI(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt1ISRHandler_1: + ICALL R12 /* call user ISR function (address stored on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +OSInt2ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT2_OFFSET /* Retrieve SR from INT2 Context */ + MFSR R8, OS_CPU_RAR_INT2_OFFSET /* Retrieve PC from INT2 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LO(OSIntNesting) + ORH R11, HI(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt2ISRHandler_1 + + MOV R11, LO(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HI(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt2ISRHandler_1: + ICALL R12 /* call user ISR function (address stored on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +OSInt3ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT3_OFFSET /* Retrieve SR from INT3 Context */ + MFSR R8, OS_CPU_RAR_INT3_OFFSET /* Retrieve PC from INT3 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LO(OSIntNesting) + ORH R11, HI(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt3ISRHandler_1 + + MOV R11, LO(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HI(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt3ISRHandler_1: + ICALL R12 /* call user ISR function (store on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +/* +********************************************************************************************************* +* CPU ASSEMBLY PORT FILE END +********************************************************************************************************* +*/ + diff --git a/Ports/AVR32/AP7000/GNU/os_cpu_c.c b/Ports/AVR32/AP7000/GNU/os_cpu_c.c new file mode 100644 index 0000000..cb108b6 --- /dev/null +++ b/Ports/AVR32/AP7000/GNU/os_cpu_c.c @@ -0,0 +1,392 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 AP7000 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +************************************************************************************************************** +* STATUS REGISTER MASKS +************************************************************************************************************** +*/ + +#define OS_CPU_SR_M0_MASK 0x00400000 /* Status Register, Supervisor Execution Mode Mask */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Avoid AVR32Studio warning "Target request failed: cannot access memory at address #" at debug mode. +* +* 2) Prevent AVR32Studio prematurely exiting from debug mode at OSCtxRestore due to invalid memory access. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + (void)opt; /* 'opt' is not used, prevent warning */ + + stk = ptos; + +#if __GNUC__ + *stk-- = (INT32U) 0x00000000; /* R14/LR (reset vector for GNU C) (note 1) */ +#else + *stk-- = (INT32U) 0x14141414; /* R14/LR */ +#endif + *stk-- = (INT32U) 0xFF0000FF; /* R0 */ + *stk-- = (INT32U) 0x01010101; /* R1 */ + *stk-- = (INT32U) 0x02020202; /* R2 */ + *stk-- = (INT32U) 0x03030303; /* R3 */ + *stk-- = (INT32U) 0x04040404; /* R4 */ + *stk-- = (INT32U) 0x05050505; /* R5 */ + *stk-- = (INT32U) 0x06060606; /* R6 */ +#if __GNUC__ + *stk-- = (INT32U) 0x00000000; /* R7 (note 2) */ +#else + *stk-- = (INT32U) 0x07070707; /* R7 */ +#endif + *stk-- = (INT32U) 0x08080808; /* R8 */ + *stk-- = (INT32U) 0x09090909; /* R9 */ + *stk-- = (INT32U) 0x10101010; /* R10 */ + *stk-- = (INT32U) 0x11111111; /* R11 */ + *stk-- = (INT32U) p_arg; /* R12 */ + + *stk-- = (INT32U) task; /* R15/PC */ + *stk = (INT32U) OS_CPU_SR_M0_MASK; /* SR: Supervisor mode */ + + return (stk); + } + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description: This function is called by OSIntExit() to perform a context switch from an ISR. +* +* Arguments : none +* +* Note(s) : 1) OSIntCtxSw() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSTCBCur = OSTCBHighRdy, +* c) Set OSPrioCur = OSPrioHighRdy, +* d) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSTaskSwHook(); + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; + + OSIntCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} + + +/* +********************************************************************************************************* +* START HIGHEST PRIORITY TASK READY-TO-RUN +* +* Description: This function is called by OSStart() to start the highest priority task that was created +* by your application before calling OSStart(). +* +* Arguments : none +* +* Note(s) : 1) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE, +* c) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSStartHighRdy (void) +{ + OSTaskSwHook(); + OSRunning = 1; + OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} diff --git a/Ports/AVR32/AP7000/GNU/os_dbg.c b/Ports/AVR32/AP7000/GNU/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/AVR32/AP7000/GNU/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR32/AP7000/IAR/os_cpu.h b/Ports/AVR32/AP7000/IAR/os_cpu.h new file mode 100644 index 0000000..fabac50 --- /dev/null +++ b/Ports/AVR32/AP7000/IAR/os_cpu.h @@ -0,0 +1,94 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 AP7000 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#ifdef __GNUC__ +#define OS_TASK_SW() __asm__ __volatile__ ("scall") /* Perform task switch by a supervisor call (exception) */ +#elif defined(__ICCAVR32__) +#define OS_TASK_SW() (OSCtxSw()) /* Perform task switch by a supervisor call (exception) */ +#endif + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +#if defined(__ICCAVR32__) +__scall extern void OSCtxSw(void); +#endif + + void OSIntCtxSw(void); + void OSStartHighRdy(void); + + void OSCtxRestore(INT32U *sp); + void OSIntCtxRestore(INT32U *sp); diff --git a/Ports/AVR32/AP7000/IAR/os_cpu_a.asm b/Ports/AVR32/AP7000/IAR/os_cpu_a.asm new file mode 100644 index 0000000..f8fa668 --- /dev/null +++ b/Ports/AVR32/AP7000/IAR/os_cpu_a.asm @@ -0,0 +1,412 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 AP7000 Specific code +* IAR C Compiler +* +* Filename : os_cpu_a.asm +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* ASM HEADER +********************************************************************************************************* +*/ + MODULE OS_CPU_A + + RSEG CODE32:CODE + + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +OS_CPU_SR_OFFSET EQU 0 /* Status Register offset in System Register */ +OS_CPU_SR_GM_OFFSET EQU 16 /* Status Register, Global Interrupt Mask Offset */ +OS_CPU_SR_MX_OFFSET EQU 22 /* Status Register, Execution Mode Mask offset */ +OS_CPU_RSR_SUP_OFFSET EQU 20 /* Status Register, to return on Supervisor Context */ +OS_CPU_RAR_SUP_OFFSET EQU 52 /* Address Register, to return on Supervisor Context */ +OS_CPU_RSR_INT0_OFFSET EQU 24 /* Status Register, to return on INT0 Context */ +OS_CPU_RAR_INT0_OFFSET EQU 56 /* Address Register, to return on INT0 Context */ +OS_CPU_RSR_INT1_OFFSET EQU 28 /* Status Register, to return on INT1 Context */ +OS_CPU_RAR_INT1_OFFSET EQU 60 /* Address Register, to return on INT1 Context */ +OS_CPU_RSR_INT2_OFFSET EQU 32 /* Status Register, to return on INT2 Context */ +OS_CPU_RAR_INT2_OFFSET EQU 64 /* Address Register, to return on INT2 Context */ +OS_CPU_RSR_INT3_OFFSET EQU 36 /* Status Register, to return on INT3 Context */ +OS_CPU_RAR_INT3_OFFSET EQU 68 /* Address Register, to return on INT3 Context */ + + +/* +********************************************************************************************************* +* PUBLIC DECLARATIONS +********************************************************************************************************* +*/ + + PUBLIC OSCtxSw + PUBLIC OSCtxRestore + PUBLIC OSIntCtxRestore + PUBLIC OSInt0ISRHandler + PUBLIC OSInt1ISRHandler + PUBLIC OSInt2ISRHandler + PUBLIC OSInt3ISRHandler + + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSTaskSwHook + EXTERN OSPrioHighRdy + EXTERN OSPrioCur + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN BSP_INTC_IntGetHandler + + + +/* +********************************************************************************************************* +* TASK LEVEL CONTEXT SWITCH +* +* Description: This function is called when a task makes a higher priority task ready-to-run. +* +* Arguments : none +* +* Note(s) : 1) Upon entry, +* OSTCBCur points to the OS_TCB of the task to suspend +* OSTCBHighRdy points to the OS_TCB of the task to resume +* +* 2) The saved context of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* SR ----/ (Low memory) +* PC +* R12 +* . +* . +* R0 +* LR ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 3) OSCtxSw() has to save all registers from the suspended task. PC and SR are retrieved from +* RAR_SUP and RSR_SUP. Only then the Stack Pointer of the task to suspend is saved on OSTCBCur. +* +* 4) OSCtxSw() MUST: +* a) Save processor registers then, +* b) Save current task`s stack pointer into the current task`s OS_TCB, +* c) Call OSTaskSwHook(), +* d) Set OSTCBCur = OSTCBHighRdy, +* e) Set OSPrioCur = OSPrioHighRdy, +* f) Switch to the highest priority task. +* +* pseudo-code: +* void OSCtxSw (void) +* { +* Save processor registers; +* +* OSTCBCur->OSTCBStkPtr = SP; +* +* OSTaskSwHook(); +* +* OSTCBCur = OSTCBHighRdy; +* OSPrioCur = OSPrioHighRdy; +* +* OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +* } +********************************************************************************************************* +*/ + +OSCtxSw: + STMTS --SP, LR /* Save LR into stack */ + STMTS --SP, R0-R12 /* Save R0-R12 into stack */ + + MFSR R9, OS_CPU_RSR_SUP_OFFSET /* Retrieve SR from previous Context */ + MFSR R8, OS_CPU_RAR_SUP_OFFSET /* Retrieve PC from previous Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R8, LWRD(OSTCBCur) + ORH R8, HWRD(OSTCBCur) /* OSTCBCur */ + LD.W R9, R8[0] /* *OSTCBCur */ + ST.W R9[0], SP /* OSTCBCur->OSTCBStkPtr = SP */ + + RCALL OSTaskSwHook + + MOV R12, LWRD(OSTCBHighRdy) + ORH R12, HWRD(OSTCBHighRdy) /* OSTCBHighRdy */ + LD.W R10, R12[0] /* *OSTCBHighRdy */ + MOV R8, LWRD(OSTCBCur) + ORH R8, HWRD(OSTCBCur) /* OSTCBCur */ + ST.W R8[0], R10 /* OSTCBCur = OSTCBHighRdy */ + + MOV R12, LWRD(OSPrioHighRdy) + ORH R12, HWRD(OSPrioHighRdy) + LD.UB R11, R12[0] /* *OSPrioHighRdy */ + MOV R12, LWRD(OSPrioCur) + ORH R12, HWRD(OSPrioCur) + ST.B R12[0], R11 /* OSPrioCur = OSPrioHighRdy */ + + LD.W R12, R10[0] /* Retrieve OSTCBHighRdy->OSTCBStkPtr */ + + LDM R12, R0-R1 /* Retrieve PC and SR from stack frame */ + MTSR OS_CPU_RSR_SUP_OFFSET, R1 /* Store SR to return from Supervisor Context */ + MTSR OS_CPU_RAR_SUP_OFFSET, R0 /* Store PC to return from Supervisor Context */ + SUB SP, R12, -2*4 /* Restore Stack Pointer */ + + LDMTS SP++, R0-R12 /* Restore R0-R12 */ + LDMTS SP++, LR /* Restore LR */ + RETS /* Restore PC and SR {restore task} */ + + + +/* +********************************************************************************************************* +* RESTORE CONTEXT FUNCTIONS +* +* Description: These functions are used to perform context switch. +* +* void OSCtxRestore (INT32U *sp) +* Restore Stack Pointer +* Restore SR and PC to Supervisor context +* Restore R0-R12, LR +* Return from Supervisor Call {context switch} +* +* void OSIntCtxRestore (INT32U *sp) +* Restore Stack Pointer +* Restore SR and PC to proper INTX context +* Restore R0-R12, LR +* Return from INT {context switch} +* +* Arguments : sp Stack address for the context to be restored +********************************************************************************************************* +*/ + +OSCtxRestore: + /* --- Context Restore Code */ + MOV SP, R12 /* Restore SP (Stack Pointer) */ + + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + MTSR OS_CPU_RSR_SUP_OFFSET, R1 /* Store SR to return from Supervisor Context */ + MTSR OS_CPU_RAR_SUP_OFFSET, R0 /* Store PC to return from Supervisor Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 */ + LDMTS SP++, LR /* Restore LR */ + RETS /* Restore PC and SR {restore task} */ + + +OSIntCtxRestore: + MOV SP, R12 /* Restore SP (Stack Pointer) */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + + MFSR R11, OS_CPU_SR_OFFSET /* Retrieve current SR */ + BFEXTU R11, R11, OS_CPU_SR_MX_OFFSET, 3 /* Retrieve current execution mode */ + + CP.W R11, 5 /* check execution mode */ + BREQ OSIntCtxRestore_INT3_Restore /* if (R11 == INT3) then goto INT3 */ + CP.W R11, 4 /* check execution mode */ + BREQ OSIntCtxRestore_INT2_Restore /* if (R11 == INT2) then goto INT2 */ + CP.W R11, 3 /* check execution mode */ + BREQ OSIntCtxRestore_INT1_Restore /* if (R11 == INT1) then goto INT1 */ + CP.W R11, 2 /* check execution mode */ + BREQ OSIntCtxRestore_INT0_Restore /* if (R11 == INT0) then goto INT0 */ + BRAL OSIntCtxRestore_Err__Restore /* goto Err if no INT context was detected */ + +OSIntCtxRestore_INT0_Restore: + MTSR OS_CPU_RSR_INT0_OFFSET, R1 /* Store SR to return from INT0 Context */ + MTSR OS_CPU_RAR_INT0_OFFSET, R0 /* Store PC to return from INT0 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ +OSIntCtxRestore_INT1_Restore: + MTSR OS_CPU_RSR_INT1_OFFSET, R1 /* Store SR to return from INT1 Context */ + MTSR OS_CPU_RAR_INT1_OFFSET, R0 /* Store PC to return from INT1 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ +OSIntCtxRestore_INT2_Restore: + MTSR OS_CPU_RSR_INT2_OFFSET, R1 /* Store SR to return from INT2 Context */ + MTSR OS_CPU_RAR_INT2_OFFSET, R0 /* Store PC to return from INT2 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ +OSIntCtxRestore_INT3_Restore: + MTSR OS_CPU_RSR_INT3_OFFSET, R1 /* Store SR to return from INT3 Context */ + MTSR OS_CPU_RAR_INT3_OFFSET, R0 /* Store PC to return from INT3 Context */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + +OSIntCtxRestore_Err__Restore: /* Error detected (hold execution) */ + BREAKPOINT + + + +/* +********************************************************************************************************* +* OS INTERRUPT HANDLER +* +* Description: This function handles the OS specific steps to wrap an user-defined function to be called on an interrupt. +* +* prototype: void OSIntXISRHandler(CPU_FNCT_VOID ptrUserISR); +* +* Notes : 1) OSIntXISRHandler() MUST: +* a) disable interrupts, +* b) save registers (R0-R12,LR,PC,SR), +* c) increment OSIntNesting, +* d) if (OSIntNesting == 1) OSTCBCur->OSTCBStkPtr = SP, +* e) call user-defined function, +* f) call OSIntExit(), +* g) restore registers (R0-R12,LR,PC,SR), +* h) return from interrupt. +********************************************************************************************************* +*/ + +OSInt0ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT0_OFFSET /* Retrieve SR from INT0 Context */ + MFSR R8, OS_CPU_RAR_INT0_OFFSET /* Retrieve PC from INT0 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LWRD(OSIntNesting) + ORH R11, HWRD(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt0ISRHandler_1 + + MOV R11, LWRD(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HWRD(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt0ISRHandler_1: + ICALL R12 /* call user ISR function (address stored on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +OSInt1ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT1_OFFSET /* Retrieve SR from INT1 Context */ + MFSR R8, OS_CPU_RAR_INT1_OFFSET /* Retrieve PC from INT1 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LWRD(OSIntNesting) + ORH R11, HWRD(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt1ISRHandler_1 + + MOV R11, LWRD(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HWRD(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt1ISRHandler_1: + ICALL R12 /* call user ISR function (address stored on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +OSInt2ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT2_OFFSET /* Retrieve SR from INT2 Context */ + MFSR R8, OS_CPU_RAR_INT2_OFFSET /* Retrieve PC from INT2 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LWRD(OSIntNesting) + ORH R11, HWRD(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt2ISRHandler_1 + + MOV R11, LWRD(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HWRD(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt2ISRHandler_1: + ICALL R12 /* call user ISR function (address stored on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +OSInt3ISRHandler: + /* --- Save stack frame */ + MFSR R9, OS_CPU_RSR_INT3_OFFSET /* Retrieve SR from INT3 Context */ + MFSR R8, OS_CPU_RAR_INT3_OFFSET /* Retrieve PC from INT3 Context */ + PUSHM R8-R9 /* Save PC, SR into stack */ + + MOV R11, LWRD(OSIntNesting) + ORH R11, HWRD(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSInt3ISRHandler_1 + + MOV R11, LWRD(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HWRD(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSInt3ISRHandler_1: + ICALL R12 /* call user ISR function (store on R12) */ + RCALL OSIntExit + /* --- Restore stack frame */ + LDM SP++, R0-R1 /* Retrieve PC and SR from stack frame */ + LDMTS SP++, R0-R12 /* Restore R0-R12 from stack */ + LDMTS SP++, LR /* Restore LR from stack */ + RETE /* Return from event handler */ + + + +/* +********************************************************************************************************* +* CPU ASSEMBLY PORT FILE END +********************************************************************************************************* +*/ + + END diff --git a/Ports/AVR32/AP7000/IAR/os_cpu_c.c b/Ports/AVR32/AP7000/IAR/os_cpu_c.c new file mode 100644 index 0000000..4d96a94 --- /dev/null +++ b/Ports/AVR32/AP7000/IAR/os_cpu_c.c @@ -0,0 +1,392 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 AP7000 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +************************************************************************************************************** +* STATUS REGISTER MASKS +************************************************************************************************************** +*/ + +#define OS_CPU_SR_M0_MASK 0x00400000 /* Status Register, Supervisor Execution Mode Mask */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Avoid AVR32Studio warning "Target request failed: cannot access memory at address #" at debug mode. +* +* 2) Prevent AVR32Studio prematurely exiting from debug mode at OSCtxRestore due to invalid memory access. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + (void)opt; /* 'opt' is not used, prevent warning */ + + stk = ptos; + +#ifdef __GNUC__ + *stk-- = (INT32U) 0x00000000; /* R14/LR (reset vector for GNU C) (note 1) */ +#else + *stk-- = (INT32U) 0x14141414; /* R14/LR */ +#endif + *stk-- = (INT32U) 0xFF0000FF; /* R0 */ + *stk-- = (INT32U) 0x01010101; /* R1 */ + *stk-- = (INT32U) 0x02020202; /* R2 */ + *stk-- = (INT32U) 0x03030303; /* R3 */ + *stk-- = (INT32U) 0x04040404; /* R4 */ + *stk-- = (INT32U) 0x05050505; /* R5 */ + *stk-- = (INT32U) 0x06060606; /* R6 */ +#ifdef __GNUC__ + *stk-- = (INT32U) 0x00000000; /* R7 (note 2) */ +#else + *stk-- = (INT32U) 0x07070707; /* R7 */ +#endif + *stk-- = (INT32U) 0x08080808; /* R8 */ + *stk-- = (INT32U) 0x09090909; /* R9 */ + *stk-- = (INT32U) 0x10101010; /* R10 */ + *stk-- = (INT32U) 0x11111111; /* R11 */ + *stk-- = (INT32U) p_arg; /* R12 */ + + *stk-- = (INT32U) task; /* R15/PC */ + *stk = (INT32U) OS_CPU_SR_M0_MASK; /* SR: Supervisor mode */ + + return (stk); + } + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description: This function is called by OSIntExit() to perform a context switch from an ISR. +* +* Arguments : none +* +* Note(s) : 1) OSIntCtxSw() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSTCBCur = OSTCBHighRdy, +* c) Set OSPrioCur = OSPrioHighRdy, +* d) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSTaskSwHook(); + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; + + OSIntCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} + + +/* +********************************************************************************************************* +* START HIGHEST PRIORITY TASK READY-TO-RUN +* +* Description: This function is called by OSStart() to start the highest priority task that was created +* by your application before calling OSStart(). +* +* Arguments : none +* +* Note(s) : 1) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE, +* c) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSStartHighRdy (void) +{ + OSTaskSwHook(); + OSRunning = 1; + OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} diff --git a/Ports/AVR32/AP7000/IAR/os_dbg.c b/Ports/AVR32/AP7000/IAR/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/AVR32/AP7000/IAR/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR32/UC3/GNU/os_cpu.h b/Ports/AVR32/UC3/GNU/os_cpu.h new file mode 100644 index 0000000..3446d32 --- /dev/null +++ b/Ports/AVR32/UC3/GNU/os_cpu.h @@ -0,0 +1,86 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 UC3 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() __asm__ __volatile__ ("scall") /* Perform task switch by a supervisor call (exception) */ + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +void OSCtxRestore(INT32U *sp); +void OSIntCtxRestore(INT32U *sp); diff --git a/Ports/AVR32/UC3/GNU/os_cpu_a.s b/Ports/AVR32/UC3/GNU/os_cpu_a.s new file mode 100644 index 0000000..873a8d1 --- /dev/null +++ b/Ports/AVR32/UC3/GNU/os_cpu_a.s @@ -0,0 +1,319 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 UC3 Specific code +* GNU C Compiler +* +* Filename : os_cpu_a.s +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* ASM HEADER +********************************************************************************************************* +*/ + + .file "OS_CPU_A" + + .section .text, "ax" + + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + + .equ OS_CPU_SR_GM_OFFSET, 16 /* Status Register, Global Interrupt Mask Offset */ + + +/* +********************************************************************************************************* +* PUBLIC DECLARATIONS +********************************************************************************************************* +*/ + + .global OSCtxSw + .global OSCtxRestore + .global OSIntCtxRestore + .global OSIntISRHandler + .global OSFastIntISRHandler + + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSTaskSwHook + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSIntNesting + .extern OSIntExit + .extern BSP_INTC_IntGetHandler + + + +/* +********************************************************************************************************* +* TASK LEVEL CONTEXT SWITCH +* +* Description: This function is called when a task makes a higher priority task ready-to-run. +* +* Arguments : none +* +* Note(s) : 1) Upon entry, +* OSTCBCur points to the OS_TCB of the task to suspend +* OSTCBHighRdy points to the OS_TCB of the task to resume +* +* 2) The stack frame of the task to suspend looks as follows: +* +* SP --> SR (Low Memory) +* PC (High memory) +* +* 3) The saved context of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* R7 ----/ (Low memory) +* . +* . +* R0 +* SR +* PC +* LR +* R12 +* . +* . +* R8 ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 4) OSCtxSw() has to save all registers from the suspended task. Since PC and SR are already +* on the stack, they need to be moved after R0-R7. Then, the remaining registers (R8-R12, +* LR) are pushed into the stack frame. Only then the Stack Pointer of the task to suspend +* is saved on OSTCBCur. +* +* 5) OSCtxSw() MUST: +* a) Save processor registers then, +* b) Save current task`s stack pointer into the current task`s OS_TCB, +* c) Call OSTaskSwHook(), +* d) Set OSTCBCur = OSTCBHighRdy, +* e) Set OSPrioCur = OSPrioHighRdy, +* f) Switch to the highest priority task. +* +* pseudo-code: +* void OSCtxSw (void) +* { +* Save processor registers; +* +* OSTCBCur->OSTCBStkPtr = SP; +* +* OSTaskSwHook(); +* +* OSTCBCur = OSTCBHighRdy; +* OSPrioCur = OSPrioHighRdy; +* +* OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +* } +********************************************************************************************************* +*/ + +OSCtxSw: + PUSHM R10-R12, LR /* Save R10-R12, LR into stack */ + LD.D R10, SP[4*4] /* Copy SR and PC from bottom of stack */ + PUSHM R10-R11 /* Save SR and PC into stack */ + ST.D SP[6*4], R8 /* Save R8 and R9 into stack */ + PUSHM R0-R7 /* Save R0-R7 into stack */ + + MOV R8, LO(OSTCBCur) + ORH R8, HI(OSTCBCur) /* OSTCBCur */ + LD.W R9, R8[0] /* *OSTCBCur */ + ST.W R9[0], SP /* OSTCBCur->OSTCBStkPtr = SP */ + + RCALL OSTaskSwHook + + MOV R12, LO(OSTCBHighRdy) + ORH R12, HI(OSTCBHighRdy) /* OSTCBHighRdy */ + LD.W R10, R12[0] /* *OSTCBHighRdy */ + MOV R8, LO(OSTCBCur) + ORH R8, HI(OSTCBCur) /* OSTCBCur */ + ST.W R8[0], R10 /* OSTCBCur = OSTCBHighRdy */ + + MOV R12, LO(OSPrioHighRdy) + ORH R12, HI(OSPrioHighRdy) + LD.UB R11, R12[0] /* *OSPrioHighRdy */ + MOV R12, LO(OSPrioCur) + ORH R12, HI(OSPrioCur) + ST.B R12[0], R11 /* OSPrioCur = OSPrioHighRdy */ + + LD.W R12, R10[0] /* Retrieve OSTCBHighRdy->OSTCBStkPtr */ + + LDM R12, R0-R7 /* Restore R0-R7 */ + LD.D R8, R12[14*4] /* Restore R8-R9 */ + LD.D R10, R12[ 8*4] /* Retrieve PC and SR from stack frame */ + ST.D R12[14*4], R10 /* Store PC and SR at bottom of stack frame */ + SUB R12, -10*4 /* Move Stack Pointer Reference to LR */ + SUB SP, R12, -4*4 /* Restore Stack Pointer */ + LDM R12, R10-R12, LR /* Restore R10-R12, LR */ + + RETS /* Restore PC and SR {restore task} */ + + + +/* +********************************************************************************************************* +* RESTORE CONTEXT FUNCTIONS +* +* Description: These functions are used to perform context switch. +* +* void OSCtxRestore (INT32U *sp) +* Restore R0-R9 +* Move SR and PC to bottom of Stack frame +* Restore Stack Pointer to point to SR and PC +* Restore R10-R12, LR +* Return from Supervisor Call {context switch} +* +* void OSIntCtxRestore (INT32U *sp) +* Restore Stack Pointer +* Restore R0-R7 +* Return from INT {context switch} +* +* Arguments : cpu_sp Stack address for the context to be restored +********************************************************************************************************* +*/ + +OSCtxRestore: + LDM R12, R0-R7 /* Restore R0-R7 */ + LD.D R8, R12[14*4] /* Restore R8-R9 */ + LD.D R10, R12[ 8*4] /* Retrieve PC and SR from stack frame */ + ST.D R12[14*4], R10 /* Store PC and SR at bottom of stack frame */ + SUB R12, -10*4 /* Move Stack Pointer Reference to LR */ + SUB SP, R12, -4*4 /* Restore Stack Pointer */ + LDM R12, R10-R12, LR /* Restore R10-R12, LR */ + RETS /* Restore PC and SR {restore task} */ + + +OSIntCtxRestore: + MOV SP, R12 /* Restore SP (Stack Pointer) */ + POPM R0-R7 /* Restore R0-R7 */ + RETE /* Restore R8-R12, LR, PC and SR {restore task} */ + + + +/* +********************************************************************************************************* +* OS INTERRUPT HANDLER +* +* Description: This function handles the OS specific steps to wrap an user-defined function to be called on an interrupt. +* +* prototype: void OSIntISRHandler(CPU_FNCT_PTR ptrUserISR); +* +* Notes : 1) OSIntISRHandler() MUST: +* a) save remaining registers (R0-R7), +* b) increment OSIntNesting, +* c) if (OSIntNesting == 1) OSTCBCur->OSTCBStkPtr = SP, +* d) re-enable interrupts, +* e) call user-defined function, +* f) call OSIntExit(), +* g) restore remaining registers (R0-R7), +* h) return from interrupt. +* +* 2) Interrupts MUST be disabled when this function is called. +********************************************************************************************************* +*/ + +OSIntISRHandler: + PUSHM R0-R7 /* Save R0-R7 into stack */ + + MOV R11, LO(OSIntNesting) + ORH R11, HI(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSIntISRHandler_1 + + MOV R11, LO(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HI(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSIntISRHandler_1: + CSRF OS_CPU_SR_GM_OFFSET /* Clear global interrupt mask (enable interrupts) */ + + ICALL R12 /* call user ISR function */ + RCALL OSIntExit + + POPM R0-R7 /* Restore R0-R7 from stack */ + RETE + + + +/* +********************************************************************************************************* +* OS FAST (non-OS) INTERRUPT HANDLER +* +* Description: This function handles OS specific steps to wrap an user-defined function to be called on a fast (non-OS) interrupt. +* +* prototype: void OSFastIntISRHandler(CPU_FNCT_PTR ptrUserISR); +* +* Notes : 1) OSFastIntISRHandler() MUST: +* a) increment OSIntNesting, +* b) re-enable interrupts, +* c) call user-defined function, +* d) disable interrupts, +* e) decrement OSIntNesting, +* f) return from interrupt. +* +* 2) Interrupts MUST be disabled when this function is called. +********************************************************************************************************* +*/ + +OSFastIntISRHandler: + MOV R11, LO(OSIntNesting) + ORH R11, HI(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CSRF OS_CPU_SR_GM_OFFSET /* Clear global interrupt mask (enable interrupts) */ + + ICALL R12 /* call user ISR function */ + + SSRF OS_CPU_SR_GM_OFFSET /* Set global interrupt mask (disable interrupts) */ + NOP + NOP + + MOV R11, LO(OSIntNesting) + ORH R11, HI(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, 1 + ST.B R11[0], R10 /* OSIntNesting-- */ + + RETE + + + +/* +********************************************************************************************************* +* CPU ASSEMBLY PORT FILE END +********************************************************************************************************* +*/ + diff --git a/Ports/AVR32/UC3/GNU/os_cpu_c.c b/Ports/AVR32/UC3/GNU/os_cpu_c.c new file mode 100644 index 0000000..76d6a42 --- /dev/null +++ b/Ports/AVR32/UC3/GNU/os_cpu_c.c @@ -0,0 +1,416 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 UC3 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +************************************************************************************************************** +* STATUS REGISTER MASKS +************************************************************************************************************** +*/ + +#define OS_CPU_SR_M0_MASK 0x00400000 /* Status Register, Supervisor Execution Mode Mask */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Avoid AVR32Studio warning "Target request failed: cannot access memory at address #" at debug mode. +* +* 2) Prevent AVR32Studio prematurely exiting from debug mode at OSCtxRestore due to invalid memory access. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + (void)opt; /* 'opt' is not used, prevent warning */ + + stk = ptos; + *stk-- = (INT32U) 0x08080808; /* R8 */ + *stk-- = (INT32U) 0x09090909; /* R9 */ + *stk-- = (INT32U) 0x10101010; /* R10 */ + *stk-- = (INT32U) 0x11111111; /* R11 */ + *stk-- = (INT32U) p_arg; /* R12 */ + *stk-- = (INT32U) 0x80000000; /* R14/LR (reset vector for GNU C) (note 1) */ + *stk-- = (INT32U) task; /* R15/PC */ + *stk-- = (INT32U) OS_CPU_SR_M0_MASK; /* SR: Supervisor mode */ + *stk-- = (INT32U) 0xFF0000FF; /* R0 */ + *stk-- = (INT32U) 0x01010101; /* R1 */ + *stk-- = (INT32U) 0x02020202; /* R2 */ + *stk-- = (INT32U) 0x03030303; /* R3 */ + *stk-- = (INT32U) 0x04040404; /* R4 */ + *stk-- = (INT32U) 0x05050505; /* R5 */ + *stk-- = (INT32U) 0x06060606; /* R6 */ + *stk = (INT32U) 0x00000000; /* R7 (note 2) */ + + return (stk); + } + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description: This function is called by OSIntExit() to perform a context switch from an ISR. +* +* Arguments : none +* +* Note(s) : 1) The stack frame is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* R7 ----/ (Low memory) +* . +* . +* R0 +* SR +* PC +* LR +* R12 +* . +* . +* R8 ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 2) OSIntCtxSw() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSTCBCur = OSTCBHighRdy, +* c) Set OSPrioCur = OSPrioHighRdy, +* d) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSTaskSwHook(); + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; + + OSIntCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} + + +/* +********************************************************************************************************* +* START HIGHEST PRIORITY TASK READY-TO-RUN +* +* Description: This function is called by OSStart() to start the highest priority task that was created +* by your application before calling OSStart(). +* +* Arguments : none +* +* Note(s) : 1) The stack frame is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* R7 ----/ (Low memory) +* . +* . +* R0 +* SR +* PC +* LR +* R12 +* . +* . +* R8 ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 2) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE, +* c) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSStartHighRdy (void) +{ + OSTaskSwHook(); + OSRunning = 1; + OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} diff --git a/Ports/AVR32/UC3/GNU/os_dbg.c b/Ports/AVR32/UC3/GNU/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/AVR32/UC3/GNU/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/AVR32/UC3/IAR/os_cpu.h b/Ports/AVR32/UC3/IAR/os_cpu.h new file mode 100644 index 0000000..d7e55b0 --- /dev/null +++ b/Ports/AVR32/UC3/IAR/os_cpu.h @@ -0,0 +1,88 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 UC3 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on AVR */ + +#define OS_TASK_SW() (OSCtxSw()) /* Perform task switch by a supervisor call (exception) */ + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +__scall extern void OSCtxSw(void); + + void OSIntCtxSw(void); + void OSStartHighRdy(void); + + void OSCtxRestore(INT32U *sp); + void OSIntCtxRestore(INT32U *sp); diff --git a/Ports/AVR32/UC3/IAR/os_cpu_a.asm b/Ports/AVR32/UC3/IAR/os_cpu_a.asm new file mode 100644 index 0000000..16037db --- /dev/null +++ b/Ports/AVR32/UC3/IAR/os_cpu_a.asm @@ -0,0 +1,319 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 UC3 Specific code +* IAR C Compiler +* +* Filename : os_cpu_a.asm +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* ASM HEADER +********************************************************************************************************* +*/ + MODULE OS_CPU_A + + RSEG CODE32:CODE + + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +OS_CPU_SR_GM_OFFSET EQU 16 /* Status Register, Global Interrupt Mask Offset */ + + +/* +********************************************************************************************************* +* PUBLIC DECLARATIONS +********************************************************************************************************* +*/ + + PUBLIC OSCtxSw + PUBLIC OSCtxRestore + PUBLIC OSIntCtxRestore + PUBLIC OSIntISRHandler + PUBLIC OSFastIntISRHandler + + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSTaskSwHook + EXTERN OSPrioHighRdy + EXTERN OSPrioCur + EXTERN OSIntNesting + EXTERN OSIntExit + EXTERN BSP_INTC_IntGetHandler + + + +/* +********************************************************************************************************* +* TASK LEVEL CONTEXT SWITCH +* +* Description: This function is called when a task makes a higher priority task ready-to-run. +* +* Arguments : none +* +* Note(s) : 1) Upon entry, +* OSTCBCur points to the OS_TCB of the task to suspend +* OSTCBHighRdy points to the OS_TCB of the task to resume +* +* 2) The stack frame of the task to suspend looks as follows: +* +* SP --> SR (Low Memory) +* PC (High memory) +* +* 3) The saved context of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* R7 ----/ (Low memory) +* . +* . +* R0 +* SR +* PC +* LR +* R12 +* . +* . +* R8 ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 4) OSCtxSw() has to save all registers from the suspended task. Since PC and SR are already +* on the stack, they need to be moved after R0-R7. Then, the remaining registers (R8-R12, +* LR) are pushed into the stack frame. Only then the Stack Pointer of the task to suspend +* is saved on OSTCBCur. +* +* 5) OSCtxSw() MUST: +* a) Save processor registers then, +* b) Save current task`s stack pointer into the current task`s OS_TCB, +* c) Call OSTaskSwHook(), +* d) Set OSTCBCur = OSTCBHighRdy, +* e) Set OSPrioCur = OSPrioHighRdy, +* f) Switch to the highest priority task. +* +* pseudo-code: +* void OSCtxSw (void) +* { +* Save processor registers; +* +* OSTCBCur->OSTCBStkPtr = SP; +* +* OSTaskSwHook(); +* +* OSTCBCur = OSTCBHighRdy; +* OSPrioCur = OSPrioHighRdy; +* +* OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +* } +********************************************************************************************************* +*/ + +OSCtxSw: + PUSHM R10-R12, LR /* Save R10-R12, LR into stack */ + LD.D R10, SP[4*4] /* Copy SR and PC from bottom of stack */ + PUSHM R10-R11 /* Save SR and PC into stack */ + ST.D SP[6*4], R8 /* Save R8 and R9 into stack */ + PUSHM R0-R7 /* Save R0-R7 into stack */ + + MOV R8, LWRD(OSTCBCur) + ORH R8, HWRD(OSTCBCur) /* OSTCBCur */ + LD.W R9, R8[0] /* *OSTCBCur */ + ST.W R9[0], SP /* OSTCBCur->OSTCBStkPtr = SP */ + + RCALL OSTaskSwHook + + MOV R12, LWRD(OSTCBHighRdy) + ORH R12, HWRD(OSTCBHighRdy) /* OSTCBHighRdy */ + LD.W R10, R12[0] /* *OSTCBHighRdy */ + MOV R8, LWRD(OSTCBCur) + ORH R8, HWRD(OSTCBCur) /* OSTCBCur */ + ST.W R8[0], R10 /* OSTCBCur = OSTCBHighRdy */ + + MOV R12, LWRD(OSPrioHighRdy) + ORH R12, HWRD(OSPrioHighRdy) + LD.UB R11, R12[0] /* *OSPrioHighRdy */ + MOV R12, LWRD(OSPrioCur) + ORH R12, HWRD(OSPrioCur) + ST.B R12[0], R11 /* OSPrioCur = OSPrioHighRdy */ + + LD.W R12, R10[0] /* Retrieve OSTCBHighRdy->OSTCBStkPtr */ + + LDM R12, R0-R7 /* Restore R0-R7 */ + LD.D R8, R12[14*4] /* Restore R8-R9 */ + LD.D R10, R12[ 8*4] /* Retrieve PC and SR from stack frame */ + ST.D R12[14*4], R10 /* Store PC and SR at bottom of stack frame */ + SUB R12, -10*4 /* Move Stack Pointer Reference to LR */ + SUB SP, R12, -4*4 /* Restore Stack Pointer */ + LDM R12, R10-R12, LR /* Restore R10-R12, LR */ + + RETS /* Restore PC and SR {restore task} */ + + + +/* +********************************************************************************************************* +* RESTORE CONTEXT FUNCTIONS +* +* Description: These functions are used to perform context switch. +* +* void OSCtxRestore (INT32U *sp) +* Restore R0-R9 +* Move SR and PC to bottom of Stack frame +* Restore Stack Pointer to point to SR and PC +* Restore R10-R12, LR +* Return from Supervisor Call {context switch} +* +* void OSIntCtxRestore (INT32U *sp) +* Restore Stack Pointer +* Restore R0-R7 +* Return from INT {context switch} +* +* Arguments : cpu_sp Stack address for the context to be restored +********************************************************************************************************* +*/ + +OSCtxRestore: + LDM R12, R0-R7 /* Restore R0-R7 */ + LD.D R8, R12[14*4] /* Restore R8-R9 */ + LD.D R10, R12[ 8*4] /* Retrieve PC and SR from stack frame */ + ST.D R12[14*4], R10 /* Store PC and SR at bottom of stack frame */ + SUB R12, -10*4 /* Move Stack Pointer Reference to LR */ + SUB SP, R12, -4*4 /* Restore Stack Pointer */ + LDM R12, R10-R12, LR /* Restore R10-R12, LR */ + RETS /* Restore PC and SR {restore task} */ + + +OSIntCtxRestore: + MOV SP, R12 /* Restore SP (Stack Pointer) */ + POPM R0-R7 /* Restore R0-R7 */ + RETE /* Restore R8-R12, LR, PC and SR {restore task} */ + + + +/* +********************************************************************************************************* +* OS INTERRUPT HANDLER +* +* Description: This function handles the OS specific steps to wrap an user-defined function to be called on an interrupt. +* +* prototype: void OSIntISRHandler(CPU_FNCT_PTR ptrUserISR); +* +* Notes : 1) OSIntISRHandler() MUST: +* a) save remaining registers (R0-R7), +* b) increment OSIntNesting, +* c) if (OSIntNesting == 1) OSTCBCur->OSTCBStkPtr = SP, +* d) re-enable interrupts, +* e) call user-defined function, +* f) call OSIntExit(), +* g) restore remaining registers (R0-R7), +* h) return from interrupt. +* +* 2) Interrupts MUST be disabled when this function is called. +********************************************************************************************************* +*/ + +OSIntISRHandler: + PUSHM R0-R7 /* Save R0-R7 into stack */ + + MOV R11, LWRD(OSIntNesting) + ORH R11, HWRD(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CP.W R10, 1 /* Test OSIntNesting */ + BRNE OSIntISRHandler_1 + + MOV R11, LWRD(OSTCBCur) /* if (OSIntNesting == 1) { */ + ORH R11, HWRD(OSTCBCur) + LD.W R10, R11[0] + ST.W R10[0], SP /* OSTCBCur->OSTCBStkPtr = SP; */ + /* } */ +OSIntISRHandler_1: + CSRF OS_CPU_SR_GM_OFFSET /* Clear global interrupt mask (enable interrupts) */ + + ICALL R12 /* call user ISR function */ + RCALL OSIntExit + + POPM R0-R7 /* Restore R0-R7 from stack */ + RETE + + + +/* +********************************************************************************************************* +* OS FAST (non-OS) INTERRUPT HANDLER +* +* Description: This function handles OS specific steps to wrap an user-defined function to be called on a fast (non-OS) interrupt. +* +* prototype: void OSFastIntISRHandler(CPU_FNCT_PTR ptrUserISR); +* +* Notes : 1) OSFastIntISRHandler() MUST: +* a) increment OSIntNesting, +* b) re-enable interrupts, +* c) call user-defined function, +* d) disable interrupts, +* e) decrement OSIntNesting, +* f) return from interrupt. +* +* 2) Interrupts MUST be disabled when this function is called. +********************************************************************************************************* +*/ + +OSFastIntISRHandler: + MOV R11, LWRD(OSIntNesting) + ORH R11, HWRD(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, -1 + ST.B R11[0], R10 /* OSIntNesting++ */ + + CSRF OS_CPU_SR_GM_OFFSET /* Clear global interrupt mask (enable interrupts) */ + + ICALL R12 /* call user ISR function */ + + SSRF OS_CPU_SR_GM_OFFSET /* Set global interrupt mask (disable interrupts) */ + NOP + NOP + + MOV R11, LWRD(OSIntNesting) + ORH R11, HWRD(OSIntNesting) + LD.UB R10, R11[0] + SUB R10, 1 + ST.B R11[0], R10 /* OSIntNesting-- */ + + RETE + + + +/* +********************************************************************************************************* +* CPU ASSEMBLY PORT FILE END +********************************************************************************************************* +*/ + + END diff --git a/Ports/AVR32/UC3/IAR/os_cpu_c.c b/Ports/AVR32/UC3/IAR/os_cpu_c.c new file mode 100644 index 0000000..6585c96 --- /dev/null +++ b/Ports/AVR32/UC3/IAR/os_cpu_c.c @@ -0,0 +1,412 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ATMEL AVR32 UC3 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +/* +************************************************************************************************************** +* STATUS REGISTER MASKS +************************************************************************************************************** +*/ + +#define OS_CPU_SR_M0_MASK 0x00400000 /* Status Register, Supervisor Execution Mode Mask */ + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + (void)opt; /* 'opt' is not used, prevent warning */ + + stk = ptos; + *stk-- = (INT32U) 0x08080808; /* R8 */ + *stk-- = (INT32U) 0x09090909; /* R9 */ + *stk-- = (INT32U) 0x10101010; /* R10 */ + *stk-- = (INT32U) 0x11111111; /* R11 */ + *stk-- = (INT32U) p_arg; /* R12 */ + *stk-- = (INT32U) 0x14141414; /* R14/LR */ + *stk-- = (INT32U) task; /* R15/PC */ + *stk-- = (INT32U) OS_CPU_SR_M0_MASK; /* SR: Supervisor mode */ + *stk-- = (INT32U) 0xFF0000FF; /* R0 */ + *stk-- = (INT32U) 0x01010101; /* R1 */ + *stk-- = (INT32U) 0x02020202; /* R2 */ + *stk-- = (INT32U) 0x03030303; /* R3 */ + *stk-- = (INT32U) 0x04040404; /* R4 */ + *stk-- = (INT32U) 0x05050505; /* R5 */ + *stk-- = (INT32U) 0x06060606; /* R6 */ + *stk = (INT32U) 0x07070707; /* R7 */ + + return (stk); + } + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description: This function is called by OSIntExit() to perform a context switch from an ISR. +* +* Arguments : none +* +* Note(s) : 1) The stack frame is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* R7 ----/ (Low memory) +* . +* . +* R0 +* SR +* PC +* LR +* R12 +* . +* . +* R8 ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 2) OSIntCtxSw() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSTCBCur = OSTCBHighRdy, +* c) Set OSPrioCur = OSPrioHighRdy, +* d) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSTaskSwHook(); + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; + + OSIntCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} + + +/* +********************************************************************************************************* +* START HIGHEST PRIORITY TASK READY-TO-RUN +* +* Description: This function is called by OSStart() to start the highest priority task that was created +* by your application before calling OSStart(). +* +* Arguments : none +* +* Note(s) : 1) The stack frame is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr --> SP --> +* R7 ----/ (Low memory) +* . +* . +* R0 +* SR +* PC +* LR +* R12 +* . +* . +* R8 ----\ (High memory) +* +* where the stack pointer points to the task start address. +* +* 2) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE, +* c) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSStartHighRdy (void) +{ + OSTaskSwHook(); + OSRunning = 1; + OSCtxRestore(OSTCBHighRdy->OSTCBStkPtr); +} diff --git a/Ports/AVR32/UC3/IAR/os_dbg.c b/Ports/AVR32/UC3/IAR/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/AVR32/UC3/IAR/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/Blackfin/VDSP++/os_cpu.h b/Ports/Blackfin/VDSP++/os_cpu.h new file mode 100644 index 0000000..c4f1c90 --- /dev/null +++ b/Ports/Blackfin/VDSP++/os_cpu.h @@ -0,0 +1,148 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* uCOS-II port for Analog Device's Blackfin 533 +* Visual DSP++ 5.0 +* +* This port was made with a large contribution from the Analog Devices Inc development team +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#if !defined(OS_CPU_H) +#define OS_CPU_H + + +/* +********************************************************************************************************* +* GLOBAL DEFINES +********************************************************************************************************* +*/ +#if ( defined(_LANGUAGE_ASM) || defined(_LANGUAGE_C)) + /* NESTED & NOT_NESTED Defines for interrupts routines */ +#define NESTED 1 +#define NOT_NESTED 0 + +#endif + +#if defined(_LANGUAGE_C) + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on Blackfin */ +#define OS_CRITICAL_METHOD 3 + +#define IVG0 0 /* 16 Interrupts vector number ( 0 to 15) */ +#define IVG1 1 +#define IVG2 2 +#define IVG3 3 +#define IVG4 4 +#define IVG5 5 +#define IVG6 6 +#define IVG7 7 +#define IVG8 8 +#define IVG9 9 +#define IVG10 10 +#define IVG11 11 +#define IVG12 12 +#define IVG13 13 +#define IVG14 14 +#define IVG15 15 + + +/* +********************************************************************************************************* +* GLOBAL MACROS +********************************************************************************************************* +*/ + + +#define OS_TASK_SW() asm("raise 14;"); /* Raise Interrupt 14 (trap) */ + + +/* +********************************************************************************************************* +* CRITICAL SECTIONS MANAGEMENT +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + + +typedef unsigned int BOOLEAN; /* Unsigned 8 bit quantity */ +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register */ + +typedef void (*FNCT_PTR)(void); /* Pointer to a function which returns void and has no argument */ + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +extern void OSStartHighRdy(void); /* See OS_CPU_A.S */ +extern void OSIntCtxSw(void); /* See OS_CPU_A.S */ + +OS_CPU_SR OS_CPU_SR_Save(void); /* See OS_CPU_A.S */ +void OS_CPU_SR_Restore(OS_CPU_SR sr); /* See OS_CPU_A.S */ +void OS_CPU_RegisterHandler(INT8U ivg, FNCT_PTR fn, BOOLEAN nesting); /* See OS_CPU_C.C */ + +#endif /* _LANGUAGE_C */ + +#endif /* OS_CPU_H */ + diff --git a/Ports/Blackfin/VDSP++/os_cpu_a.asm b/Ports/Blackfin/VDSP++/os_cpu_a.asm new file mode 100644 index 0000000..e190704 --- /dev/null +++ b/Ports/Blackfin/VDSP++/os_cpu_a.asm @@ -0,0 +1,945 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* uCOS-II port for Analog Device's Blackfin 533 +* Visual DSP++ 5.0 +* +* This port was made with a large contribution from the Analog Devices Inc development team +* +* Filename : os_cpu_a.asm +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include +#include + + +/* +********************************************************************************************************* +* LOCAL MACROS +********************************************************************************************************* +*/ + +#define UPPER_( x ) (((x) >> 16) & 0x0000FFFF) +#define LOWER_( x ) ((x) & 0x0000FFFF) +#define LOAD(x, y) x##.h = UPPER_(y); x##.l = LOWER_(y) +#define LOADA(x, y) x##.h = y; x##.l = y + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + +.global _OS_CPU_EnableIntEntry; +.global _OS_CPU_DisableIntEntry; +.global _OS_CPU_SR_Save; +.global _OS_CPU_SR_Restore; +.global _OS_CPU_NESTING_ISR; +.global _OS_CPU_NON_NESTING_ISR; +.global _OS_CPU_ISR_Entry; +.global _OS_CPU_ISR_Exit; +.global _OSStartHighRdy; +.global _OSCtxSw; +.global _OSIntCtxSw; +.global _OS_CPU_Invalid_Task_Return; + + +/* +********************************************************************************************************* +* Blackfin C Run-Time stack/frame Macros +********************************************************************************************************* +*/ + +#define INIT_C_RUNTIME_STACK(frame_size) \ + LINK frame_size; \ + SP += -12; /* make space for outgoing arguments */ + /* when calling C-functions */ + +#define DEL_C_RUNTIME_STACK() \ + UNLINK; + +/* +********************************************************************************************************* +* WORKAROUND for Anomaly 05-00-0283 Macro +********************************************************************************************************* +*/ + +#define WORKAROUND_05000283() \ + CC = R0 == R0; /* always true */ \ + P0.L = 0x14; /* MMR space - CHIPID */ \ + P0.H = 0xffc0; \ + IF CC JUMP 4; \ + R0 = [ P0 ]; /* bogus MMR read that is speculatively */ + /* read and killed - never executed */ + +/* +********************************************************************************************************* +* EXTERNAL FUNCTIONS +********************************************************************************************************* +*/ + +.extern _OS_CPU_IntHandler; +.extern _OSTaskSwHook; +.extern _OSIntEnter; +.extern _OSIntExit; + +/* +********************************************************************************************************* +* EXTERNAL VARIABLES +********************************************************************************************************* +*/ + +.extern _OSIntNesting; +.extern _OSPrioCur; +.extern _OSPrioHighRdy; +.extern _OSRunning; +.extern _OSTCBCur; +.extern _OSTCBHighRdy; + + +.section program; + +/* +********************************************************************************************************* +* OS_CPU_EnableIntEntry(); +* +* Description : Enables an interrupt entry. Interrupt vector to enable is represented by the argument +* passed to this function. +* +* +* +* Arguments : Interrupt vector number (0 to 15) passed into R0 register +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_EnableIntEntry: + + R1 = 1; + R1 <<= R0; + CLI R0; + R1 = R1 | R0; + STI R1; + +_OS_CPU_EnableIntEntry.end: + RTS; + +/* +********************************************************************************************************* +* OS_CPU_DisableIntEntry(); +* +* Description : Disables an interrupt entry. Interrupt vector to disable is represented by the argument +* passed to this function. +* +* +* +* Arguments : Interrupt vector number (0 to 15) passed into R0 register +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_DisableIntEntry: + + R1 = 1; + R1 <<= R0; + R1 = ~R1; + CLI R0; + R1 = R1 & R0; + STI R1; + +_OS_CPU_DisableIntEntry.end: + RTS; + +/* +********************************************************************************************************* +* OS_CPU_SR_Save() +* +* Description : Disables interrupts and save IMASK register into R0. +* +* +* Arguments : None +* +* Returns : Current IMASK contents in R0 +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_SR_Save: + + CLI R0; + +_OS_CPU_SR_Save.end: + RTS; + +/* +********************************************************************************************************* +* OS_CPU_SR_Restore() +* +* +* Description : Enables interrupts and load IMASK register with the value passed as an argument to +* this routine. +* +* +* Arguments : Value to load into IMASK register. R0 holds this new value. +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_SR_Restore: + + STI R0; + +_OS_CPU_SR_Restore.end: + RTS; + +/* +********************************************************************************************************* +* NESTING INTERRUPTS HANDLER +* OS_CPU_NESTING_ISR(); +* +* Description : This routine is intented to the target of the interrupt processing functionality with +* nesting support. +* +* It saves the current Task context (see _OS_CPU_ISR_Entry), +* and calls the application interrupt handler OS_CPU_IntHandler (see os_cpu_c.c) +* +* +* Arguments : None +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_NESTING_ISR: + + [ -- SP ] = R0; + [ -- SP ] = P1; + [ -- SP ] = RETS; + R0 = NESTED; /* To indicate that this ISR supports nesting */ + + CALL.X _OS_CPU_ISR_Entry; + + WORKAROUND_05000283() + INIT_C_RUNTIME_STACK(0x0) + + CALL.X _OS_CPU_IntHandler; /* See os_cpu_c.c */ + SP += -4; /* Disable interrupts by this artificial pop */ + RETI = [ SP++ ]; /* of RETI register. Restore context need to */ + CALL.X _OSIntExit; /* be done while interrupts are disabled */ + + DEL_C_RUNTIME_STACK() + JUMP.X _OS_CPU_ISR_Exit; + +_OS_CPU_NESTING_ISR.end: + NOP; + +/* +********************************************************************************************************* +* NON NESTING INTERRUPTS HANDLER +* OS_CPU_NON_NESTING_ISR(); +* +* Description : This routine is intented to the target of the interrupt processing functionality without +* nesting support. +* +* It saves the current Task context (see _OS_CPU_ISR_Entry), +* and calls the application interrupt handler OS_CPU_IntHandler (see os_cpu_c.c) +* +* +* Arguments : None +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_NON_NESTING_ISR: + + [ -- SP ] = R0; + [ -- SP ] = P1; + [ -- SP ] = RETS; + R0 = NOT_NESTED; /* This ISR doesn't support nesting */ + + CALL.X _OS_CPU_ISR_Entry; + + WORKAROUND_05000283() + INIT_C_RUNTIME_STACK(0x0) + + CALL.X _OS_CPU_IntHandler; /* See os_cpu_c.c */ + CALL.X _OSIntExit; + + DEL_C_RUNTIME_STACK() + JUMP.X _OS_CPU_ISR_Exit; + +_OS_CPU_NON_NESTING_ISR.end: + NOP; + +/* +********************************************************************************************************* +* OS_CPU_ISR_Entry() +* +* Description : This routine serves as the interrupt entry function for ISRs. +* +* +* __OS_CPU_ISR_Entry consists of +* +* 1.'uCOS Interrupt Entry management' - incremements OSIntNesting and saves SP in the TCB if +* OSIntNesting == 1. +* 2.'CPU context save' - After OSIntNesting is incremented, it is safe to re-enable interrupts. +* Then the rest of the processor's context is saved. +* +* Refer to VisualDSP++ C/C++ Compiler and Library Manual for Blackfin Processors +* and ADSP-BF53x/BF56x Blackfin(R) Processor Programming Reference Manual. +* +* The convention for the task frame (after context save is complete) is as follows: +* (stack represented from high to low memory as per convention) +* (*** High memory ***) R0 +* P1 +* RETS (function return address of thread) +* R1 +* R2 +* P0 +* P2 +* ASTAT +* RETI (interrupt return address: $PC of thread) +* R7:3 (R7 is lower than R3) +* P5:3 (P5 is lower than P3) +* FP (frame pointer) +* I3:0 (I3 is lower than I0) +* B3:0 (B3 is lower than B0) +* L3:0 (L3 is lower than L0) +* M3:0 (M3 is lower than M0) +* A0.x +* A0.w +* A1.x +* A1.w +* LC1:0 (LC1 is lower than LC0) +* LT1:0 (LT1 is lower than LT0) +* OSTCBHighRdy--> OSTCBStkPtr --> (*** Low memory ***)LB1:0 (LB1 is lower than LB0) +* +* Arguments : RO is set to NESTED or NOT_NESTED constant. +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_ISR_Entry: +ucos_ii_interrupt_entry_mgmt: + + [ -- SP ] = R1; + [ -- SP ] = R2; + [ -- SP ] = P0; + [ -- SP ] = P2; + [ -- SP ] = ASTAT; + + LOADA(P0 , _OSRunning); + R2 = B [ P0 ] ( Z ); + CC = R2 == 1; /* Is OSRunning set */ + IF ! CC JUMP ucos_ii_interrupt_entry_mgmt.end; + LOADA(P0, _OSIntNesting); + R2 = B [ P0 ] ( Z ); + R1 = 255 ( X ); + CC = R2 < R1; /* Nesting < 255 */ + IF ! CC JUMP ucos_ii_interrupt_entry_mgmt.end; + R2 = R2.B (X); + R2 += 1; /* Increment OsIntNesting */ + B [ P0 ] = R2; + CC = R2 == 1; /* Save SP if OSIntNesting == 1 */ + IF ! CC JUMP ucos_ii_interrupt_entry_mgmt.end; + LOADA(P2, _OSTCBCur); + P0 = [ P2 ]; + R2 = SP; + R1 = 144; + R2 = R2 - R1; + [ P0 ] = R2; + +ucos_ii_interrupt_entry_mgmt.end: + NOP; + +interrupt_cpu_save_context: + + CC = R0 == NESTED; + IF !CC JUMP non_reetrant_isr; + +reetrant_isr: + [ -- SP ] = RETI; /* If ISR is REENTRANT, then simply push RETI onto stack */ + /* IPEND[4] is currently set, globally disabling interrupts */ + /* IPEND[4] will be cleared when RETI is pushed onto stack */ + JUMP save_remaining_context; + +non_reetrant_isr: + R1 = RETI; /* If ISR is NON-REENTRANT, then save RETI through R1 */ + [ -- SP ] = R1; /* IPEND[4] is currently set, globally disabling interrupts */ + /* IPEND[4] will stay set when RETI is saved through R1 */ + + +save_remaining_context: + [ -- SP ] = (R7:3, P5:3); + [ -- SP ] = FP; + [ -- SP ] = I0; + [ -- SP ] = I1; + [ -- SP ] = I2; + [ -- SP ] = I3; + [ -- SP ] = B0; + [ -- SP ] = B1; + [ -- SP ] = B2; + [ -- SP ] = B3; + [ -- SP ] = L0; + [ -- SP ] = L1; + [ -- SP ] = L2; + [ -- SP ] = L3; + [ -- SP ] = M0; + [ -- SP ] = M1; + [ -- SP ] = M2; + [ -- SP ] = M3; + R1.L = A0.x; + [ -- SP ] = R1; + R1 = A0.w; + [ -- SP ] = R1; + R1.L = A1.x; + [ -- SP ] = R1; + R1 = A1.w; + [ -- SP ] = R1; + [ -- SP ] = LC0; + R3 = 0; + LC0 = R3; + [ -- SP ] = LC1; + R3 = 0; + LC1 = R3; + [ -- SP ] = LT0; + [ -- SP ] = LT1; + [ -- SP ] = LB0; + [ -- SP ] = LB1; + L0 = 0 ( X ); + L1 = 0 ( X ); + L2 = 0 ( X ); + L3 = 0 ( X ); + +interrupt_cpu_save_context.end: +_OS_CPU_ISR_Entry.end: + RTS; + + +/* +********************************************************************************************************* +* OS_CPU_ISR_Exit () +* +* +* Description : ThIS routine serves as the interrupt exit function for all ISRs (whether reentrant +* (nested) or non-reentrant (non-nested)). RETI is populated by a stack pop for both nested +* as well non-nested interrupts. +* +* This is a straigtforward implementation restoring the processor's context as per the +* following task stack frame convention, returns from the interrupt with the RTI instruction. +* +* Refer to VisualDSP++ C/C++ Compiler and Library Manual for Blackfin Processors +* and ADSP-BF53x/BF56x Blackfin(R) Processor Programming Reference Manual. +* +* The convention for the task frame (after context save is complete) is as follows: +* (stack represented from high to low memory as per convention) +* (*** High memory ***) R0 +* P1 +* RETS (function return address of thread) +* R1 +* R2 +* P0 +* P2 +* ASTAT +* RETI (interrupt return address: $PC of thread) +* R7:3 (R7 is lower than R3) +* P5:3 (P5 is lower than P3) +* FP (frame pointer) +* I3:0 (I3 is lower than I0) +* B3:0 (B3 is lower than B0) +* L3:0 (L3 is lower than L0) +* M3:0 (M3 is lower than M0) +* A0.x +* A0.w +* A1.x +* A1.w +* LC1:0 (LC1 is lower than LC0) +* LT1:0 (LT1 is lower than LT0) +* OSTCBHighRdy--> OSTCBStkPtr --> (*** Low memory ***)LB1:0 (LB1 is lower than LB0) +* +* Arguments : None +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_ISR_Exit: +interrupt_cpu_restore_context: + + LB1 = [ SP ++ ]; + LB0 = [ SP ++ ]; + LT1 = [ SP ++ ]; + LT0 = [ SP ++ ]; + LC1 = [ SP ++ ]; + LC0 = [ SP ++ ]; + R0 = [ SP ++ ]; + A1 = R0; + R0 = [ SP ++ ]; + A1.x = R0.L; + R0 = [ SP ++ ]; + A0 = R0; + R0 = [ SP ++ ]; + A0.x = R0.L; + M3 = [ SP ++ ]; + M2 = [ SP ++ ]; + M1 = [ SP ++ ]; + M0 = [ SP ++ ]; + L3 = [ SP ++ ]; + L2 = [ SP ++ ]; + L1 = [ SP ++ ]; + L0 = [ SP ++ ]; + B3 = [ SP ++ ]; + B2 = [ SP ++ ]; + B1 = [ SP ++ ]; + B0 = [ SP ++ ]; + I3 = [ SP ++ ]; + I2 = [ SP ++ ]; + I1 = [ SP ++ ]; + I0 = [ SP ++ ]; + FP = [ SP ++ ]; + (R7:3, P5:3) = [ SP ++ ]; + RETI = [ SP ++ ]; /* IPEND[4] will stay set when RETI popped from stack */ + ASTAT = [ SP ++ ]; + P2 = [ SP ++ ]; + P0 = [ SP ++ ]; + R2 = [ SP ++ ]; + R1 = [ SP ++ ]; + RETS = [ SP ++ ]; + P1 = [ SP ++ ]; + +interrupt_cpu_restore_context.end: + + R0 = [ SP ++ ]; + RTI; /* Reenable interrupts via IPEND[4] bit after RTI executes. */ + NOP; /* Return to task */ + NOP; + +_OS_CPU_ISR_Exit.end: + NOP; + + +/* +********************************************************************************************************* +* START MULTITASKING +* OSStartHighRdy() +* +* Description: Starts the highest priority task that is available to run.OSStartHighRdy() MUST: +* +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE, +* c) Switch to the highest priority task. +* +* Refer to VisualDSP++ C/C++ Compiler and Library Manual for Blackfin Processors +* and ADSP-BF53x/BF56x Blackfin(R) Processor Programming Reference Manual. +* +* The convention for the task frame (after context save is complete) is as follows: +* (stack represented from high to low memory as per convention) +* +* (*** High memory ***) R0 +* P1 +* RETS (function return address of thread) +* R1 +* R2 +* P0 +* P2 +* ASTAT +* RETI (interrupt return address: $PC of thread) +* R7:3 (R7 is lower than R3) +* P5:3 (P5 is lower than P3) +* FP (frame pointer) +* I3:0 (I3 is lower than I0) +* B3:0 (B3 is lower than B0) +* L3:0 (L3 is lower than L0) +* M3:0 (M3 is lower than M0) +* A0.x +* A0.w +* A1.x +* A1.w +* LC1:0 (LC1 is lower than LC0) +* LT1:0 (LT1 is lower than LT0) +* OSTCBHighRdy--> OSTCBStkPtr --> (*** Low memory ***)LB1:0 (LB1 is lower than LB0) +* +* Arguments : None +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OSStartHighRdy: + + +#if (OS_TASK_SW_HOOK_EN == 1) /* Do the task switch hook function - don't need to save */ + /* RETS since _OSStartHighRdy never returns */ + + INIT_C_RUNTIME_STACK(0x0) /* Setup C-runtime stack - call OSTaskSwHook() */ + + CALL.X _OSTaskSwHook; + + DEL_C_RUNTIME_STACK() /* Tear down C run-time stack - restores SP */ +#endif + + + LOADA(P1, _OSTCBHighRdy); /* Get the SP for the highest ready task */ + P2 = [ P1 ]; + SP = [ P2 ]; + LOADA(P1, _OSRunning); /* Set OSRunning to true */ + R1 = 1; + [ P1 ] = R1; + /* Restore CPU context without popping off RETI */ + P1 = 140; /* Skipping over LB1:0, LT1:0, LC1:0, A1:0, M3:0, */ + SP = SP + P1; /* L3:0, B3:0, I3:0, FP, P5:3, R7:3 */ + RETS = [ SP ++ ]; /* Pop off RETI value into RETS */ + SP += 12; /* Skipping over ASAT, P2, P0 */ + + R1 = 0; /* Zap loop counters to zero, to make sure */ + LC0 = R1; LC1 = R1; /* that hw loops are disabled */ + L0 = R1; L1 = R1; /* Clear the DAG Length regs too, so that it's safe */ + L2 = R1; L3 = R1; /* to use I-regs without them wrapping around. */ + + R2 = [ SP ++ ]; /* Loading the 3rd argument of the C function - R2 */ + R1 = [ SP ++ ]; /* Loading the 2nd argument of the C function - R1 */ + SP += 8; /* Skipping over RETS, P1 */ + R0 = [ SP ++ ]; /* Loading the 1st argument of the C function - R0 */ + + /* Return to high ready task */ +_OSStartHighRdy.end: + RTS; + + +/* +********************************************************************************************************* +* O/S CPU Context Switch +* OSCtxSw() +* +* Description : This function is called to switch the context of the current running task +* This function is registered as the IVG14 handler and will be called to handle both +* interrupt and task level context switches. +* +* Refer to VisualDSP++ C/C++ Compiler and Library Manual for Blackfin Processors +* and ADSP-BF53x/BF56x Blackfin(R) Processor Programming Reference Manual. +* +* The convention for the task frame (after context save is complete) is as follows: +* (stack represented from high to low memory as per convention) +* (*** High memory ***) R0 +* P1 +* RETS (function return address of thread) +* R1 +* R2 +* P0 +* P2 +* ASTAT +* RETI (interrupt return address: $PC of thread) +* R7:3 (R7 is lower than R3) +* P5:3 (P5 is lower than P3) +* FP (frame pointer) +* I3:0 (I3 is lower than I0) +* B3:0 (B3 is lower than B0) +* L3:0 (L3 is lower than L0) +* M3:0 (M3 is lower than M0) +* A0.x +* A0.w +* A1.x +* A1.w +* LC1:0 (LC1 is lower than LC0) +* LT1:0 (LT1 is lower than LT0) +* OSTCBHighRdy--> OSTCBStkPtr --> (*** Low memory ***)LB1:0 (LB1 is lower than LB0) +* +* Arguments : None +* +* Returns : None +* +* Note(s) : Note 1 +* +* If new priority == current priority, don't do anything. +* This condition is triggered by the following sequence of events: +* +* 1. OS_Sched() is called at a task level and interrupts are disabled. +* 2. A HW interrupt happens during the protected section of the task level call to OS_Sched(). +* 3. OS_Sched() decides to perform a context switch, updates both OSPrioHighRdy and +* OSTCBHighRdy, and issues a trap 14. +* 4. OS_Sched() re-enabled interrupts. +* 5. The higher priority HW interrupt fires and results in an event that makes the +* original task switched out by #3 ready to run again. This results in OSPrioHighRdy +* begin set back to OSPrioCur. +* 6. The scheduling logic in OSIntExit() decides to do nothing because OSPrioHighRdy +* equals OSPrioCur. This means OSTCBHighRdy is now invalid and cannot be used because +* it points to the context of the task scheduled in #3. +* 7. The trap 14 interrupt fires +* 8. If OSPrioHighRdy == OSPrioCur ignore the invalid OSTCBHighRdy and continue running the +* task that was originally running upon entering #1. +* +********************************************************************************************************* +*/ + +_OSCtxSw: + /* Save context, interrupts disabled by IPEND[4] bit */ + [ -- SP ] = R0; + [ -- SP ] = P1; + [ -- SP ] = RETS; + [ -- SP ] = R1; + [ -- SP ] = R2; + [ -- SP ] = P0; + [ -- SP ] = P2; + [ -- SP ] = ASTAT; + R1 = RETI; /* IPEND[4] is currently set, globally disabling interrupts */ + /* IPEND[4] will stay set when RETI is saved through R1 */ + + [ -- SP ] = R1; + [ -- SP ] = (R7:3, P5:3); + [ -- SP ] = FP; + [ -- SP ] = I0; + [ -- SP ] = I1; + [ -- SP ] = I2; + [ -- SP ] = I3; + [ -- SP ] = B0; + [ -- SP ] = B1; + [ -- SP ] = B2; + [ -- SP ] = B3; + [ -- SP ] = L0; + [ -- SP ] = L1; + [ -- SP ] = L2; + [ -- SP ] = L3; + [ -- SP ] = M0; + [ -- SP ] = M1; + [ -- SP ] = M2; + [ -- SP ] = M3; + R1.L = A0.x; + [ -- SP ] = R1; + R1 = A0.w; + [ -- SP ] = R1; + R1.L = A1.x; + [ -- SP ] = R1; + R1 = A1.w; + [ -- SP ] = R1; + [ -- SP ] = LC0; + R3 = 0; + LC0 = R3; + [ -- SP ] = LC1; + R3 = 0; + LC1 = R3; + [ -- SP ] = LT0; + [ -- SP ] = LT1; + [ -- SP ] = LB0; + [ -- SP ] = LB1; + L0 = 0 ( X ); + L1 = 0 ( X ); + L2 = 0 ( X ); + L3 = 0 ( X ); + + /* Note: OSCtxSw uses call-preserved registers (R4:7, P3:5) */ + /* unlike OSIntCtxSw to allow calling _OSTaskSwHook. */ + LOADA(P3, _OSPrioHighRdy); /* Get a high ready task priority */ + R4 = B[ P3 ](Z); + LOADA(P3, _OSPrioCur); /* Get a current task priority */ + R5 = B[ P3 ](Z); + CC = R4 == R5; /* If new priority == current priority, don't do anything. */ + IF CC JUMP _AbortOSCtxSw; /* See Note 1 */ + LOADA(P4, _OSTCBCur); /* Get a pointer to the current task's TCB */ + P5 = [ P4 ]; + [ P5 ] = SP; /* Context save done so save SP in the TCB */ + +#if (OS_TASK_SW_HOOK_EN == 1) + + INIT_C_RUNTIME_STACK(0x0) /* Setup C-runtime stack - call OSTaskSwHook() */ + CALL.X _OSTaskSwHook; + DEL_C_RUNTIME_STACK() /* Tear down C run-time stack - restores SP */ + +#endif + + B[ P3 ] = R4; /* OSPrioCur = OSPrioHighRdy */ + LOADA(P3, _OSTCBHighRdy); /* Get a pointer to the high ready task's TCB */ + P5 = [ P3 ]; + [ P4 ] = P5; /* OSTCBCur = OSTCBHighRdy */ + +_OSCtxSw_modify_SP: + + SP = [ P5 ]; /* Make it the current task by switching the stack pointer */ + +_AbortOSCtxSw: +_CtxSwRestoreCtx: +_OSCtxSw.end: + /* Restoring CPU context and return to task */ + LB1 = [ SP ++ ]; + LB0 = [ SP ++ ]; + LT1 = [ SP ++ ]; + LT0 = [ SP ++ ]; + LC1 = [ SP ++ ]; + LC0 = [ SP ++ ]; + R0 = [ SP ++ ]; + A1 = R0; + R0 = [ SP ++ ]; + A1.x = R0.L; + R0 = [ SP ++ ]; + A0 = R0; + R0 = [ SP ++ ]; + A0.x = R0.L; + M3 = [ SP ++ ]; + M2 = [ SP ++ ]; + M1 = [ SP ++ ]; + M0 = [ SP ++ ]; + L3 = [ SP ++ ]; + L2 = [ SP ++ ]; + L1 = [ SP ++ ]; + L0 = [ SP ++ ]; + B3 = [ SP ++ ]; + B2 = [ SP ++ ]; + B1 = [ SP ++ ]; + B0 = [ SP ++ ]; + I3 = [ SP ++ ]; + I2 = [ SP ++ ]; + I1 = [ SP ++ ]; + I0 = [ SP ++ ]; + FP = [ SP ++ ]; + (R7:3, P5:3) = [ SP ++ ]; + RETI = [ SP ++ ]; /* IPEND[4] will stay set when RETI popped from stack */ + ASTAT = [ SP ++ ]; + P2 = [ SP ++ ]; + P0 = [ SP ++ ]; + R2 = [ SP ++ ]; + R1 = [ SP ++ ]; + RETS = [ SP ++ ]; + P1 = [ SP ++ ]; + R0 = [ SP ++ ]; + RTI; /* Reenable interrupts via IPEND[4] bit after RTI executes. */ + /* Return to task */ + +/* +********************************************************************************************************* +* OSIntCtxSw() +* +* Description : Performs the Context Switch from an ISR. +* +* OSIntCtxSw() must implement the following pseudo-code: +* +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* +* +* +* Arguments : None +* +* Returns : None +* +* Note(s) : OSIntCtxSw uses scratch registers (R0:3, P0:2, ASTAT) +* unlike OSCtxSw because it is called from OSIntExit and will +* return back to OSIntExit through an RTS. +********************************************************************************************************* +*/ + +_OSIntCtxSw: + +#if (OS_TASK_SW_HOOK_EN == 1) + + INIT_C_RUNTIME_STACK(0x0) /* Setup C-runtime stack - call OSTaskSwHook() */ + CALL.X _OSTaskSwHook; + DEL_C_RUNTIME_STACK() /* Tear down C run-time stack - restores SP */ + +#endif + + LOADA(P0, _OSPrioCur); /* Get a current task priority */ + LOADA(P1, _OSPrioHighRdy); /* Get a high ready task priority */ + R0 = B[ P1 ](Z); + B[ P0 ] = R0; /* OSPrioCur = OSPrioHighRdy */ + LOADA(P0, _OSTCBCur); /* Get a pointer to the current task's TCB */ + LOADA(P1, _OSTCBHighRdy); /* Get a pointer to the high ready task's TCB */ + P2 = [ P1 ]; + [ P0 ] = P2; /* OSTCBCur = OSTCBHighRdy */ + +_OSIntCtxSw_modify_SP: + /* Load stack pointer into P0 from task TCB. Do not modify SP because we return to */ + /* OSIntExit, which modifies SP through the the UNLINK instruction. Instead, we */ + /* modify the FP of the ISR frame. This essentially 'moves the frame of the ISR */ + /* 'above' the frame the of the new task. Thus, when the UNLINK instruction that */ + /* unlinks the frame of the ISR, the SP of the new task is loaded. Thus, the new */ + /* context is restored. */ + + + R0 = [ P2 ]; /* Get stack pointer to the high ready task */ + R0 += -8; /* Subtract 2 stack items for FP, RETS (LINK instruction */ + /* pushes FP, RETS onto stack) */ + [ FP ] = R0; /* Modify the FP of ISR with the task's SP. */ + + + SP += -4; /* Interrupts are re-enabled when OSIntCtxSw() returns */ + RETI = [ SP++ ]; /* to OSIntExit() (where OS_EXIT_CRITICAL() restores */ + /* original IMASK value). */ + /* However, the context restore process must be */ + /* uninterruptible - we accomplish this by an artificial'*/ + /* stack pop into the RETI register, thus setting the */ + /* global interrupts disable bit (IPEND[4]) */ + /* Before the stack pop, adjust the stack pointer. */ + +_OSIntCtxSw.end: + RTS; + + +/* +********************************************************************************************************* +* _OS_Invalid_Task_Return () +* +* Description : All tasks (threads) within uCOS-II are while(1) loops - once done with it's operations, +* task can supsend, delete itself etc. to yield the processor. Under NO circumstances can +* a task return with a RTS. However, in case of a return, the following function serves +* as a placeholder for debugging purposes. +* +* Arguments : None +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +_OS_CPU_Invalid_Task_Return: + +_OS_CPU_Invalid_Task_Return.end: /* Stay here */ + JUMP 0; diff --git a/Ports/Blackfin/VDSP++/os_cpu_c.c b/Ports/Blackfin/VDSP++/os_cpu_c.c new file mode 100644 index 0000000..3b866b6 --- /dev/null +++ b/Ports/Blackfin/VDSP++/os_cpu_c.c @@ -0,0 +1,522 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* uCOS-II port for Analog Device's Blackfin 533 +* Visual DSP++ 5.0 +* +* This port was made with a large contribution from the Analog Devices Inc development team +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + +#define EVENT_VECTOR_TABLE_ADDR 0xFFE02000 /* Event vector table start address */ +#define IPEND 0xFFE02108 /* Interrupt Pending Register */ +#define IPEND_BIT_4_MASK 0xFFFFFFEF /* IPEND Register bit 4 mask */ +#define IVG_NUM 16 /* Interrupt vector number */ +#define pIPEND ((volatile unsigned long *)IPEND) /* Pointer to IPEND Register */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +static FNCT_PTR OS_CPU_IntHanlderTab[IVG_NUM] = {(void *)0}; + +/* +********************************************************************************************************* +* LOCAL FUNCTIONS +********************************************************************************************************* +*/ + +void OSTaskCreateHook (OS_TCB *ptcb); +void OSTaskDelHook (OS_TCB *ptcb); +void OSTaskSwHook (void); +void OSTCBInitHook (OS_TCB *ptcb); +void OSInitHookBegin (void); +void OSInitHookEnd (void); +void OSTaskStatHook (void); +void OSTimeTickHook (void); +void OSTaskIdleHook (void); +void OS_CPU_IntHandler (void); +void OS_CPU_RegisterHandler (INT8U ivg, FNCT_PTR fn, BOOLEAN nesting); +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt); + +/* +********************************************************************************************************* +* EXTERNAL FUNCTIONS +********************************************************************************************************* +*/ + +extern void OSCtxSw (void); /* See OS_CPU_A.S */ +extern void OS_CPU_NESTING_ISR (void); /* See OS_CPU_A.S */ +extern void OS_CPU_NON_NESTING_ISR (void); /* See OS_CPU_A.S */ +extern void OS_CPU_EnableIntEntry (INT8U mask); /* See OS_CPU_A.S */ +extern void OS_CPU_DisableIntEntry (INT8U mask); /* See OS_CPU_A.S */ +extern void OS_CPU_Invalid_Task_Return (void); /* See OS_CPU_A.S */ + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* void OSTaskCreateHook(OS_TCB *ptcb) +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Returns : None +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif + +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* void OSTaskDelHook(OS_TCB *ptcb) +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Returns : None +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* void OSTaskSwHook (void) +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : None +* +* Returns : None +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Returns : None +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* void OSInitHookBegin (void) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : None +* +* Returns : None +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK (END) +* void OSInitHookEnd (void) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : None +* +* Returns : None +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ + + INT32U *pEventVectorTable; + + pEventVectorTable = ((INT32U*)EVENT_VECTOR_TABLE_ADDR); /* Pointer to Event Vector Table */ + pEventVectorTable[IVG14] = (INT32U)&OSCtxSw; /* Register the context switch */ + /* handler for IVG14 */ + OS_CPU_EnableIntEntry(IVG14); /* Enable Interrupt for IVG14 */ + +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* void OSTaskStatHook (void) +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : None +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* void OSTimeTickHook (void) +* +* Description: This function is called every tick. +* +* Arguments : None +* +* Returns : None +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif +} +#endif + + + +/* +********************************************************************************************************* +* IDLE HOOK +* void OSTaskIdleHook (void) +* +* Description: This function is called by uC/OS-ii IDLE Task. +* +* Arguments : None +* +* Returns : None +* +* Note(s) : 1) This hook function is called when the IDLE task executes - place code here that +* needs to be done when the processor is 'idle' i.e. no tasks are being executed. +* +* 2) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* ISR HANDLER REGISTRATION +* void OS_CPU_RegisterHandler(INT8U ivg, FNCT_PTR fn, BOOLEAN nesting) +* +* Description : Registers Interrupts handler routine within the event table OS_CPU_IntrHanlderTab. +* Chooses OS_CPU_NESTING_ISR or OS_CPU_NON_NESTING_ISR as ISR Handler depending on the value +* of nesting argument. +* Enables Interrupt for a given IVG (first argument) +* +* Arguments : INT8U ivg : interrupt vector groupe number (IVG0 to IVG15) +* FNCT_PTR fn : function pointer to the handler routine for a given IVG +* BOOLEAN nesting : to choose Nested ISR or not +* +* Returns : None +* +* Note(s) : 1) IVG14 is reserved for task-level context switching +* 2) IVG6 is used for Core Timer to drive the OS ticks +********************************************************************************************************* +*/ + +void OS_CPU_RegisterHandler (INT8U ivg, FNCT_PTR fn, BOOLEAN nesting) +{ + INT32U *pEventVectorTable; + + + if (ivg > IVG15) { /* The Blackfin 533 supports only 16 vectors */ + return; + } + + if (ivg == IVG14) { /* IVG14 is reserved for task-level context */ + return; /* switching */ + } + + if (ivg == IVG4) { /* Reserved vector */ + return; + } + + pEventVectorTable = (INT32U*)EVENT_VECTOR_TABLE_ADDR; /* pEventVectorTable points to the start */ + /* address of Event vector table */ + if (nesting == NESTED) { + pEventVectorTable[ivg] = (INT32U)&OS_CPU_NESTING_ISR; /* Select Nested ISR if nesting is required */ + /* for the given ivg */ + } else { + pEventVectorTable[ivg] = (INT32U)&OS_CPU_NON_NESTING_ISR; /* Select Non Nested ISR if nesting is not */ + /* required for the given ivg */ + } + + OS_CPU_IntHanlderTab[ivg] = fn; /* Register Handler routine for the given ivg */ + OS_CPU_EnableIntEntry(ivg); + +} + +/* +********************************************************************************************************* +* ISR HANDLER GLOBAL ROUTINE +* void OS_CPU_IntHandler(void) +* +* Description : This routine is called by OS_CPU_NON_NESTING_ISR or OS_CPU_NESTING_ISR when an +* interrupt occurs. It determines the high priority pending interrupt request +* depending on the value of IPEND register, and then selects the Handler routine for that +* IRQ using OS_CPU_IntrHanlderTab table. +* +* Arguments : None +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +void OS_CPU_IntHandler (void) +{ + INT32U status; + INT32U mask; + INT8U i; + + + mask = 1; + status = *pIPEND & IPEND_BIT_4_MASK; /* Use IPEND_BIT_4_MASK to avoid testing */ + /* IPEND[4] :disable interrupts */ + for (i =0; i < IVG_NUM; i++) { + + if ((1 << i) == (status & mask)) { + + if (OS_CPU_IntHanlderTab[i] != (void *)0) { /* Be sure that Handler routine was */ + /* registered */ + OS_CPU_IntHanlderTab[i](); /* Branch to the Handler routine */ + + } + break; + + } + mask <<=1; + } +} + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : This function does the following (refer to Porting chapter (Chapter 13 of uCOS-II book) +* (1) Simulate a function call to the task with an argument +* (2) Simulate ISR vector +* (3) Setup stack frame to contain desired initial values of all registers +* (4) Return top of stack pointer to the caller +* +* Refer to VisualDSP++ C/C++ Compiler and Library Manual for Blackfin Processors +* and ADSP-BF53x/BF56x Blackfin(R) Processor Programming Reference Manual. +* +* The convention for the task frame (after context save is complete) is as follows: +* (stack represented from high to low memory as per convention) +* (*** High memory ***) R0 +* P1 +* RETS (function return address of thread) +* R1 +* R2 +* P0 +* P2 +* ASTAT +* RETI (interrupt return address: $PC of thread) +* R7:3 (R7 is lower than R3) +* P5:3 (P5 is lower than P3) +* FP (frame pointer) +* I3:0 (I3 is lower than I0) +* B3:0 (B3 is lower than B0) +* L3:0 (L3 is lower than L0) +* M3:0 (M3 is lower than M0) +* A0.x +* A0.w +* A1.x +* A1.w +* LC1:0 (LC1 is lower than LC0) +* LT1:0 (LT1 is lower than LT0) +* OSTCBHighRdy--> OSTCBStkPtr --> (*** Low memory ***)LB1:0 (LB1 is lower than LB0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + INT8U i; + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = ptos; /* Load stack pointer */ + + /* Simulate a function call to the task with an argument */ + stk -= 3; /* 3 words assigned for incoming args (R0, R1, R2) */ + + /* Now simulating vectoring to an ISR */ + *--stk = (OS_STK) pdata; /* R0 value - caller's incoming argument #1 */ + *--stk = (OS_STK) 0; /* P1 value - value irrelevant */ + + *--stk = (OS_STK)OS_CPU_Invalid_Task_Return; /* RETS value - NO task should return with RTS. */ + /* however OS_CPU_Invalid_Task_Return is a safety */ + /* catch-allfor tasks that return with an RTS */ + + *--stk = (OS_STK) pdata; /* R1 value - caller's incoming argument #2 */ + /* (not relevant in current test example) */ + *--stk = (OS_STK) pdata; /* R2 value - caller's incoming argument #3 */ + /* (not relevant in current test example) */ + *--stk = (OS_STK) 0; /* P0 value - value irrelevant */ + *--stk = (OS_STK) 0; /* P2 value - value irrelevant */ + *--stk = (OS_STK) 0; /* ASTAT value - caller's ASTAT value - value */ + /* irrelevant */ + + *--stk = (OS_STK) task; /* RETI value- pushing the start address of the task */ + + for (i = 35; i>0; i--) { /* remaining reg values - R7:3, P5:3, */ + /* 4 words of A1:0(.W,.X), LT0, LT1, */ + *--stk = (OS_STK)0; /* LC0, LC1, LB0, LB1,I3:0, M3:0, L3:0, B3:0, */ + } /* All values irrelevant */ + + return ((OS_STK *)stk); /* Return top-of-stack */ +} diff --git a/Ports/C28x/Generic/CCS/os_cpu.h b/Ports/C28x/Generic/CCS/os_cpu.h new file mode 100644 index 0000000..665c449 --- /dev/null +++ b/Ports/C28x/Generic/CCS/os_cpu.h @@ -0,0 +1,195 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI C28x Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : TI C28x +* Mode : C28 Object mode +* Toolchain : TI C/C++ Compiler +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* OS TICK INTERRUPT PRIORITY CONFIGURATION +* +* Note(s) : (1) For systems that don't need any high, real-time priority interrupts; the tick interrupt +* should be configured as the highest priority interrupt but won't adversely affect system +* operations. +* +* (2) For systems that need one or more high, real-time interrupts; these should be configured +* higher than the tick interrupt which MAY delay execution of the tick interrupt. +* +* (a) If the higher priority interrupts do NOT continually consume CPU cycles but only +* occasionally delay tick interrupts, then the real-time interrupts can successfully +* handle their intermittent/periodic events with the system not losing tick interrupts +* but only increasing the jitter. +* +* (b) If the higher priority interrupts consume enough CPU cycles to continually delay the +* tick interrupt, then the CPU/system is most likely over-burdened & can't be expected +* to handle all its interrupts/tasks. The system time reference gets compromised as a +* result of losing tick interrupts. +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef long double FP64; /* Double precision floating point */ + +typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register (INTM = 1 bit) */ + + +/* +********************************************************************************************************* +* C28x +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + + +/* +********************************************************************************************************* +* C28x Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 0u /* Stack grows from LOW to HIGH memory on C28x */ + + +/* +********************************************************************************************************* +* OS_TASK_SW +* +* Note(s): OS_TASK_SW() invokes the task level context switch. +* +* (1) On some processors, this corresponds to a call to OSCtxSw() which is an assembly language +* function that performs the context switch. +* +* (2) On some processors, you need to simulate an interrupt using a 'software interrupt' or a +* TRAP instruction. Some compilers allow you to add in-line assembly language as shown. +********************************************************************************************************* +*/ + +#define OS_TASK_SW() asm(" TRAP #16") + + +/* +********************************************************************************************************* +* OSIntCtxSw +* +* Note(s): OSIntCtxSw() invokes the interrupt level context switch. +* +* (1) On some processors, this corresponds to a call to OSIntCtxSw() which is an assembly language +* function that performs the context switch. +* +* (2) On some processors, you need to simulate an interrupt using a 'software interrupt' or a +* TRAP instruction. Some compilers allow you to add in-line assembly language as shown. +********************************************************************************************************* +*/ + +#define OSIntCtxSw() asm(" TRAP #16") + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + /* Wrapper functions to get ST0 and ST1 registers. */ +INT16U OS_CPU_GetST0 (void); +INT16U OS_CPU_GetST1 (void); + /* OS-II Port Implementation. See OS_CPU_A.ASM */ +#if (OS_CRITICAL_METHOD == 3u) +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy (void); + +void OS_CPU_INT_Handler (void); + +void OS_CPU_RTOSINT_Handler(void); + +#endif + diff --git a/Ports/C28x/Generic/CCS/os_cpu_a.asm b/Ports/C28x/Generic/CCS/os_cpu_a.asm new file mode 100644 index 0000000..f7aba43 --- /dev/null +++ b/Ports/C28x/Generic/CCS/os_cpu_a.asm @@ -0,0 +1,282 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; TI C28x Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : TI C28x +; Mode : C28 Object mode +; Toolchain : TI C/C++ Compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; INCLUDE FILES +;******************************************************************************************************** + + .include "os_cpu_i.asm" + + +;******************************************************************************************************** +; EXTERNAL GLOBAL VARIABLES +;******************************************************************************************************** + ; External references + .ref _OSRunning + .ref _OSPrioCur + .ref _OSPrioHighRdy + .ref _OSTCBCur + .ref _OSTCBHighRdy + .ref _OSIntExit + .ref _OSTaskSwHook + .ref _OS_CPU_IntHandler + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + ; Functions declared in this file + .def _OS_CPU_GetST0 + .def _OS_CPU_GetST1 + .def _OS_CPU_SR_Save + .def _OS_CPU_SR_Restore + .def _OSStartHighRdy + .def _OS_CPU_RTOSINT_Handler + .def _OS_CPU_INT_Handler + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + ; Set text section and reset local labels. + .text + .newblock + + +;******************************************************************************************************** +; GET ST0 and ST1 +; +; Description : Wrapper function to get ST0 and ST1 registers from a C function. +; +; Prototypes : INT16U OS_CPU_GetST0(void); +; INT16U OS_CPU_GetST1(void); +;******************************************************************************************************** + + .asmfunc +_OS_CPU_GetST0: + PUSH ST0 + POP AL + LRETR + .endasmfunc + + .asmfunc +_OS_CPU_GetST1: + PUSH ST1 + POP AL + LRETR + .endasmfunc + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + + .asmfunc +_OS_CPU_SR_Save: + PUSH ST1 + DINT + POP @AL + AND AL, #1 + LRETR + .endasmfunc + + .asmfunc +_OS_CPU_SR_Restore: + PUSH ST1 + POP AR0 + AND AR0, #0xFFFE + OR AL, AR0 + PUSH AL + POP ST1 + LRETR + .endasmfunc + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; Note(s) : 1) This function triggers a PendSV exception (essentially, causes a context switch) to cause +; the first task to start. +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook(). +; b) Set OSRunning to TRUE; +; c) Restore context for OSTCBCurPtr. +; d) IRET into highest ready task. +;******************************************************************************************************** + .asmfunc +_OSStartHighRdy: + ; Call OSTaskSwHook() + LCR #_OSTaskSwHook + ; Set OSRunning to TRUE. + MOVL XAR0, #_OSRunning + MOV *AR0, #1 + ; Restore context. + MOVL XAR0, #_OSTCBCur ; Get the process's SP. + MOVL XAR1, *XAR0 + MOV AL , *AR1 + MOV @SP , AL + ; Restore registers. + OS_CTX_RESTORE + ; IRET into task. + IRET + .endasmfunc + ; Catch start high failure. +OSStartHang: + SB OSStartHang, UNC + + +;******************************************************************************************************** +; GENERIC INTERRUPT HANDLER +; void OS_CPU_INT_Handler(void) +; +; Note(s) : 1) Assembly wrapper for ISRs. +; +; 2) Saves task context before servicing the interrupt and maintains the value of IER across +; interrupts. +;******************************************************************************************************** + + .asmfunc +_OS_CPU_INT_Handler: + + OS_CTX_SAVE + + ASP + + LCR #_OS_CPU_IntHandler + + NASP + + OS_CTX_RESTORE + + IRET + .endasmfunc + + +;******************************************************************************************************** +; HANDLE RTOSINT INTERRUPT +; void OS_CPU_RTOSINT_Handler(void) +; +; Note(s) : 1) The RTOSINT interrupt is used to perform a context switch. The C28x core saves the +; ST0, T, ACC, P, AR0, AR1, ST1, DP, IER, DBGSTAT (shadow) registers and the Return +; Address. +; The remaining registers AR1H, AR0H, XAR2..XAR7, XT and RPC are saved by the handler. +; +; 2) The context switching RTOSINT handler pseudo-code is: +; a) Save remaining registers on the process stack; +; b) Save the process SP in its TCB, OSTCBCurPtr->OSTCBStkPtr = SP; +; c) Call OSTaskSwHook(); +; d) Get current high priority, OSPrioCur = OSPrioHighRdy; +; e) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +; f) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore AR1H, AR0H, XAR2..XAR7, XT and RPC registers from the new process stack; +; h) Overwrite the previously saved (at context switch out) IER register with current IER. +; i) Perform exception return which will restore remaining context. +; +; 3) On entry into RTOSINT handler: +; a) The following have been saved on the process stack (by processor): +; ST0, T, ACC, P, AR0, AR1, ST1, DP, IER, DBGSTAT (shadow) registers and the Return +; Address. +; b) OSTCBCurPtr points to the OS_TCB of the task to suspend +; OSTCBHighRdyPtr points to the OS_TCB of the task to resume +; +; 4) This function MUST be placed in entry 16 (for RTOSINT) of the C28x interrupt table. +;******************************************************************************************************** + + .asmfunc +_OS_CPU_RTOSINT_Handler: + ; Save registers. + OS_CTX_SAVE + ; Save SP to current process. + MOVL XAR0, #_OSTCBCur ; Get the process's SP. + MOVL XAR1, *XAR0 + MOV AL , @SP + MOV *AR1, AL + + ASP ; Align the stack pointer. + ; Call OSTaskSwHook. + LCR #_OSTaskSwHook + NASP ; Restore alignement of the stack pointer. + + ; OSPrioCur = OSPrioHighRdy + MOVL XAR0, #_OSPrioHighRdy + MOVL XAR1, #_OSPrioCur + MOV ACC, *XAR0 + MOV *XAR1, ACC + ; OSTCBCur = OSTCBHighRdy + MOVL XAR0, #_OSTCBHighRdy + MOVL XAR1, #_OSTCBCur + MOVL ACC, *XAR0 + MOVL *XAR1, ACC + ; Get SP from new process. + MOVL XAR0, *XAR1 + MOV AL , *AR0 + MOV @SP , AL + + OS_CTX_RESTORE + ; Return from interrupt to restore remaining registers. + IRET + .endasmfunc + + +;******************************************************************************************************** +; OS-II ASSEMBLY PORT FILE END +;******************************************************************************************************** + + .end diff --git a/Ports/C28x/Generic/CCS/os_cpu_c.c b/Ports/C28x/Generic/CCS/os_cpu_c.c new file mode 100644 index 0000000..d2838c1 --- /dev/null +++ b/Ports/C28x/Generic/CCS/os_cpu_c.c @@ -0,0 +1,372 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI C28x Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : TI C28x +* Mode : C28 Object mode +* Toolchain : TI C/C++ Compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include +#include + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ + +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)&ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)&ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when task starts executing. +* +* 2) See inline comments for stack frame format. +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + INT32U *p_stk32; + + /* Prevent compiler warnings. */ + (void)&opt; + + /* Load and pre-align stack pointer. */ + p_stk = ptos; + if ((INT32U)(void *)p_stk % 2u == 0u) { + p_stk++; + } + p_stk32 = (INT32U *)p_stk; + /* Save registers as if auto-saved. */ + /* Follow stacking method in "9) Perform automatic ... */ + /* ..context save" of section 3.4 in "SPRU430E" */ + *p_stk32++ = (0x11110000) | OS_CPU_GetST0(); /* T:ST0 */ + *p_stk32++ = 0x33332222; /* AH:AL */ + *p_stk32++ = 0x55554444; /* PH:PL */ + *p_stk32++ = 0x77776666; /* AR1:AR0 */ + *p_stk32++ = (0x00000000) | OS_CPU_GetST1(); /* DP:ST1 */ + *p_stk32++ = 0x00000000; /* DBGSTAT:IER */ + *p_stk32++ = (INT32U)task; /* Save Return Address [PC+1]. */ + + /* Save remaining registers. */ + *p_stk32++ = 0x77776666; /* AR1H:AR0H */ + *p_stk32++ = 0x99999999; /* XAR2 */ + *p_stk32++ = 0xAAAAAAAA; /* XAR3 */ + *p_stk32++ = (INT32U)p_arg; /* XAR4: void * parameter. */ + *p_stk32++ = 0xCCCCCCCC; /* XAR5 */ + *p_stk32++ = 0xDDDDDDDD; /* XAR6 */ + *p_stk32++ = 0xEEEEEEEE; /* XAR7 */ + *p_stk32++ = 0xFFFFFFFF; /* XT */ + *p_stk32++ = (INT32U)&OS_TaskReturn; /* RPC */ + +#if __TMS320C28XX_FPU32__ == 1 /* Save FPU registers, if enabled. */ + *p_stk32++ = 0x00000000; /* R0H */ + *p_stk32++ = 0x11111111; /* R1H */ + *p_stk32++ = 0x22222222; /* R2H */ + *p_stk32++ = 0x33333333; /* R3H */ + *p_stk32++ = 0x44444444; /* R4H */ + *p_stk32++ = 0x55555555; /* R5H */ + *p_stk32++ = 0x66666666; /* R6H */ + *p_stk32++ = 0x77777777; /* R7H */ + *p_stk32++ = 0x00000000; /* STF */ + *p_stk32++ = 0x00000000; /* RB */ +#endif + /* Return pointer to next free location. */ + return ((OS_STK *)p_stk32); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)&ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + diff --git a/Ports/C28x/Generic/CCS/os_cpu_i.asm b/Ports/C28x/Generic/CCS/os_cpu_i.asm new file mode 100644 index 0000000..ae1ba07 --- /dev/null +++ b/Ports/C28x/Generic/CCS/os_cpu_i.asm @@ -0,0 +1,109 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; TI C28x Port +; ASSEMBLY LANGUAGE MACROS +; +; Filename : os_cpu_i.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : TI C28x +; Mode : C28 Object mode +; Toolchain : TI C/C++ Compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; OS_CTX_SAVE +; +; Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +; the same order as they were saved in OSTaskStkInit(). +;******************************************************************************************************** + +OS_CTX_SAVE .macro + ; Save remaining registers. + PUSH AR1H:AR0H ; AR1H:AR0H + PUSH XAR2 ; XAR2 + PUSH XAR3 ; XAR3 + PUSH XAR4 ; XAR4 + PUSH XAR5 ; XAR5 + PUSH XAR6 ; XAR6 + PUSH XAR7 ; XAR7 + PUSH XT ; XT + PUSH RPC ; RPC + + .if .TMS320C2800_FPU32 = 1 ; Save FPU registers, if enabled. + MOVZ AR1 , @SP ; Can't use SP for indirect addressing. + MOV32 *XAR1++, R0H ; R0H + MOV32 *XAR1++, R1H ; R1H + MOV32 *XAR1++, R2H ; R2H + MOV32 *XAR1++, R3H ; R3H + MOV32 *XAR1++, R4H ; R4H + MOV32 *XAR1++, R5H ; R5H + MOV32 *XAR1++, R6H ; R6H + MOV32 *XAR1++, R7H ; R7H + MOV32 *XAR1++, STF ; STF + MOV AL , AR1 ; Can't use indirect addressing with RB. + MOV @SP , AL ; Restore SP. + PUSH RB ; RB + .endif + .endm + + +;******************************************************************************************************** +; OS_CTX_RESTORE +; +; Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +; reverse order of OS_CTX_SAVE (see above) +;******************************************************************************************************** + +OS_CTX_RESTORE .macro + .if .TMS320C2800_FPU32 = 1 ; Restore FPU registers, if enabled. + POP RB ; RB + MOVZ AR1, @SP ; Can't use SP for indirect addressing. + MOV32 STF, *--XAR1 ; STF + MOV32 R7H, *--XAR1 ; R7H + MOV32 R6H, *--XAR1 ; R6H + MOV32 R5H, *--XAR1 ; R5H + MOV32 R4H, *--XAR1 ; R4H + MOV32 R3H, *--XAR1 ; R3H + MOV32 R2H, *--XAR1 ; R2H + MOV32 R1H, *--XAR1 ; R1H + MOV32 R0H, *--XAR1 ; R0H + MOV AL , AR1 ; Restore SP. + MOV @SP , AL + .endif + ; Restore CPU registers part 1. + POP RPC ; RPC + POP XT ; XT + POP XAR7 ; XAR7 + POP XAR6 ; XAR6 + POP XAR5 ; XAR5 + POP XAR4 ; XAR4 + POP XAR3 ; XAR3 + POP XAR2 ; XAR2 + + ; Overwrite saved IER in stack frame. + MOVZ AR0 , @SP ; Get SP. + SUBB XAR0, #6 ; Point to old IER. + MOVL ACC , *XAR0 ; Get old DBGSTAT:IER. + AND ACC, #0xFFFF << 16 + MOV AL, IER ; Get current IER. + MOVL *XAR0, ACC ; Overwrite IER. + + ; Restore registers part 2. + POP AR1H:AR0H ; AR1H:AR0H + .endm + diff --git a/Ports/C28x/Generic/CCS/os_dbg.c b/Ports/C28x/Generic/CCS/os_dbg.c new file mode 100644 index 0000000..246ea29 --- /dev/null +++ b/Ports/C28x/Generic/CCS/os_dbg.c @@ -0,0 +1,320 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT volatile + + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +OS_COMPILER_OPT INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu.h b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..1a1416b --- /dev/null +++ b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu.h @@ -0,0 +1,112 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ColdFire with EMAC Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_TASK_SW() asm(TRAP #14;) /* Use Trap #14 to perform a Task Level Context Switch */ + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* ColdFire Specifics +********************************************************************************************************* +*/ + +#define OS_INITIAL_SR 0x2000 /* Supervisor mode, interrupts enabled */ + +#define OS_TRAP_NBR 14 /* OSCtxSw() invoked through TRAP #14 */ + + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +void OSStartHighRdy(void); +void OSIntCtxSw (void); +void OSCtxSw (void); + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif /* End of CPU cfg module inclusion. */ + diff --git a/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_a.asm b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_a.asm new file mode 100644 index 0000000..851f50e --- /dev/null +++ b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_a.asm @@ -0,0 +1,286 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; +; ColdFire with EMAC +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; Note(s) : 1) This port uses the MOVEM.L (A7),D0-D7/A0-A6, LEA 60(A7)A7 construct instead of +; the traditional 68xxx MOVEM.L (A7)+,D0-D7/A0-A6. +; +; 2) The LEA instruction is required because the ColdFire cannot push multiple +; registers directly to the stack. +;******************************************************************************************************** +*/ + +#include + +/* +;************************************************************************************************* +; PUBLIC DECLARATIONS +;************************************************************************************************* +*/ + + .global _OSCtxSw + .global _OSIntCtxSw + .global _OSStartHighRdy + + .global _OS_My_ISR + +/* +;************************************************************************************************** +; EXTERNAL DECLARATIONS +;************************************************************************************************** +*/ + + .extern _OSRunning + .extern _OSIntExit + .extern _OSIntNesting + .extern _OSLockNesting + .extern _OSPrioCur + .extern _OSPrioHighRdy + .extern _OSRdyGrp + .extern _OSRdyTbl + .extern _OSTaskSwHook + .extern _OSTCBCur + .extern _OSTCBHighRdy + .extern _OSIntEnter + + .text + .align 4 + + +/* +;******************************************************************************************* +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description: This function is called by OSStart() to start the highest priority task that +; was created by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ACC0 Low Memory +; + 4 ACC1 +; + 8 ACC2 +; + 12 ACC3 +; + 16 ACCEXT01 +; + 20 ACCEXT23 +; + 24 MASK +; + 28 MACSR +; + 32 D0 +; + 36 D1 +; + 40 D2 +; + 44 D3 +; + 48 D4 +; + 52 D5 +; + 56 D6 +; + 60 D7 +; + 64 A0 +; + 68 A1 +; + 72 A2 +; + 76 A3 +; + 80 A4 +; + 84 A5 +; + 88 A6 +; + 92 Format, Vector, OS_INITIAL_SR +; + 96 task +; + 100 task +; + 104 p_arg High Memory +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************* +*/ + +_OSStartHighRdy: + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVEQ.L #1, D4 /* OSRunning = TRUE; */ + MOVE.B D4,_OSRunning /* Indicates that we are multitasking */ + + MOVE.L (_OSTCBHighRdy),A1 /* Point to TCB of highest prio task ready to run*/ + MOVE.L (A1),A7 /* Get the stack pointer of the task to resume */ + + OS_EMAC_RESTORE /* Restore the EMAC registers */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Store all the regs */ + LEA 60(A7),A7 /* Advance the stack pointer */ + + RTE /* Return to task */ + + +/* +;******************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher prio task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows (the registers +; for task to suspend need to be saved): +; +; SP + 0 ----> Format, Vector, SR Low Memory +; + 4 PC of task High Memory +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ACC0 Low Memory +; + 4 ACC1 +; + 8 ACC2 +; + 12 ACC3 +; + 16 ACCEXT01 +; + 20 ACCEXT23 +; + 24 MASK +; + 28 MACSR +; + 32 D0 +; + 36 D1 +; + 40 D2 +; + 44 D3 +; + 48 D4 +; + 52 D5 +; + 56 D6 +; + 60 D7 +; + 64 A0 +; + 68 A1 +; + 72 A2 +; + 76 A3 +; + 80 A4 +; + 84 A5 +; + 88 A6 +; + 92 SR of task +; + 96 PC of task High Memory +;******************************************************************************************* +*/ + +_OSCtxSw: + LEA -60(A7),A7 + MOVEM.L D0-D7/A0-A6,(A7) /* Save the registers of the current task */ + + OS_EMAC_SAVE /* Save the EMAC registers */ + + MOVE.L (_OSTCBCur),A1 /* Save stack pointer in the suspended task TCB */ + MOVE.L A7,(A1) + + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.L (_OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(_OSTCBCur) + MOVE.L (A1),A7 /* Get the stack pointer of the task to resume */ + + MOVE.B (_OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(_OSPrioCur) + + OS_EMAC_RESTORE /* Restore the EMAC registers */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore the CPU registers */ + LEA 60(A7),A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; +; Description : This function is provided for backward compatibility and to +; satisfy OSIntExit() +; in OS_CORE.C. +; +; Arguments : none +;******************************************************************************************* +*/ + +_OSIntCtxSw: + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.B (_OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(_OSPrioCur) + + MOVE.L (_OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(_OSTCBCur) + MOVE.L (A1),A7 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + OS_EMAC_RESTORE /* Restore the EMAC registers */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore ALL CPU registers from new task stack */ + LEA 60(A7),A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; GENERIC ISR +; +; Description : This function shows how to write ISRs +; +; Arguments : none +; +; Notes : 1) You MUST save ALL the CPU registers as shown below +; 2) You MUST increment 'OSIntNesting' and NOT call OSIntEnter() +; 3) You MUST use OSIntExit() to exit an ISR. +;******************************************************************************************* +*/ + +_OS_My_ISR: + MOVE.W #0x2700,SR /* Disable interrupts */ + + LEA -60(A7),A7 /* Save processor registers onto stack */ + MOVEM.L D0-D7/A0-A6,(A7) + + OS_EMAC_SAVE /* Save the EMAC registers */ + + MOVEQ.L #0,D0 /* OSIntNesting++ */ + MOVE.B (_OSIntNesting),D0 + ADDQ.L #1,D0 + MOVE.B D0,(_OSIntNesting) + + CMPI.L #1, D0 /* if (OSIntNesting == 1) */ + BNE _OS_My_ISR_1 + MOVE.L (_OSTCBCur), A1 /* OSTCBCur- + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The initial value of the Status Register (SR) is OS_INITIAL_SR sets the MCF5275 processor +* to run in SUPERVISOR mode. It is assumed that all uC/OS-II tasks run in supervisor +* mode. +* 2) You can pass the above options in the 'opt' argument. You MUST only use the upper +* 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make changes +* to the code below, you will need to ensure that it doesn't affect the behaviour of +* OS_TaskIdle() and OS_TaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + + + opt = opt; /* 'opt' is not used, prevent compiler warning */ + + switch ((INT32U)ptos & 0x00000003) { /* Align the stack on a longword boundary */ + case 0: + pstk32 = (OS_STK *)((INT32U)ptos + 0); + break; + + case 1: + pstk32 = (OS_STK *)((INT32U)ptos - 1); + break; + + case 2: + pstk32 = (OS_STK *)((INT32U)ptos - 2); + break; + + case 3: + pstk32 = (OS_STK *)((INT32U)ptos - 3); + break; + } + + *pstk32 = 0; /* -- SIMULATE CALL TO FUNCTION WITH ARGUMENT -- */ + *--pstk32 = (INT32U)p_arg; /* p_arg */ + *--pstk32 = (INT32U)task; /* Task return address */ + + /* ------ SIMULATE INTERRUPT STACK FRAME ------- */ + *--pstk32 = (INT32U)task; /* Task return address */ + *--pstk32 = (INT32U)(0x40000000 | OS_INITIAL_SR); /* format and status register */ + + /* ------- SAVE ALL PROCESSOR REGISTERS -------- */ + *--pstk32 = (INT32U)0x00A600A6L; /* Register A6 */ + *--pstk32 = (INT32U)0x00A500A5L; /* Register A5 */ + *--pstk32 = (INT32U)0x00A400A4L; /* Register A4 */ + *--pstk32 = (INT32U)0x00A300A3L; /* Register A3 */ + *--pstk32 = (INT32U)0x00A200A2L; /* Register A2 */ + *--pstk32 = (INT32U)0x00A100A1L; /* Register A1 */ + *--pstk32 = (INT32U)p_arg; /* Register A0 */ + *--pstk32 = (INT32U)0x00D700D7L; /* Register D7 */ + *--pstk32 = (INT32U)0x00D600D6L; /* Register D6 */ + *--pstk32 = (INT32U)0x00D500D5L; /* Register D5 */ + *--pstk32 = (INT32U)0x00D400D4L; /* Register D4 */ + *--pstk32 = (INT32U)0x00D300D3L; /* Register D3 */ + *--pstk32 = (INT32U)0x00D200D2L; /* Register D2 */ + *--pstk32 = (INT32U)0x00D100D1L; /* Register D1 */ + *--pstk32 = (INT32U)p_arg; /* Register D0 */ + + /* ------- SAVE ALL EMAC REGISTERS ------------- */ + *--pstk32 = (INT32U)0x00000000L; /* Register MACSR */ + *--pstk32 = (INT32U)0x00000000L; /* Register MASK */ + *--pstk32 = (INT32U)0x000ACE23L; /* Register ACCEXT23 */ + *--pstk32 = (INT32U)0x000ACE01L; /* Register ACCEXT01 */ + *--pstk32 = (INT32U)0x0000ACC3L; /* Register ACC3 */ + *--pstk32 = (INT32U)0x0000ACC2L; /* Register ACC2 */ + *--pstk32 = (INT32U)0x0000ACC1L; /* Register ACC1 */ + *--pstk32 = (INT32U)0x0000ACC0L; /* Register ACC0 */ + + return ((OS_STK *)pstk32); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif + diff --git a/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_i.asm b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_i.asm new file mode 100644 index 0000000..c127690 --- /dev/null +++ b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_cpu_i.asm @@ -0,0 +1,63 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; Filename : os_cpu_i.asm +; Version : V2.93.00 +;******************************************************************************************************** +*/ + +/* +;************************************************************************************************** +; MACROS +;************************************************************************************************** +*/ + + .macro OS_EMAC_SAVE + /* CODE BELOW TO SAVE EMAC REGISTERS */ + MOVE.L MACSR,D7 /* Save the MACSR */ + CLR.L D0 /* Disable rounding in the MACSR */ + MOVE.L D0,MACSR /* Save the accumulators */ + MOVE.L ACC0,D0 + MOVE.L ACC1,D1 + MOVE.L ACC2,D2 + MOVE.L ACC3,D3 + MOVE.L ACCEXT01,D4 /* Save the accumulator extensions */ + MOVE.L ACCEXT23,D5 + MOVE.L MASK,D6 /* Save the address mask */ + LEA -32(A7),A7 /* Move the EMAC state to the task's stack */ + MOVEM.L D0-D7,(A7) + + .endm + + + + .macro OS_EMAC_RESTORE + /* CODE BELOW TO RESTORE EMAC REGISTERS */ + MOVEM.L (A7),D0-D7 /* Restore the EMAC state */ + MOVE.L #0,MACSR /* Disable rounding in the MACSR */ + MOVE.L D0,ACC0 /* Restore the accumulators */ + MOVE.L D1,ACC1 + MOVE.L D2,ACC2 + MOVE.L D3,ACC3 + MOVE.L D4,ACCEXT01 + MOVE.L D5,ACCEXT23 + MOVE.L D6,MASK + MOVE.L D7,MACSR + LEA 32(A7),A7 + + .endm diff --git a/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_dbg.c b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/ColdFire-EMAC/Generic/CodeWarrior/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ColdFire/5272/GNU/os_cpu.h b/Ports/ColdFire/5272/GNU/os_cpu.h new file mode 100644 index 0000000..e9c31e5 --- /dev/null +++ b/Ports/ColdFire/5272/GNU/os_cpu.h @@ -0,0 +1,140 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MCF5272 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register, 32 bits on ColdFire */ + + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola ColdFire MCF5272 Inline Assembly +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 2 + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() __asm__("MOVE.L %D0,-(%A7);" \ + "MOVE %SR, %D0;" \ + "ORI.L #0x0700,%D0;" \ + "MOVE %D0, %SR;" \ + "MOVE.L (%A7)+,%D0;" ) + +#define OS_EXIT_CRITICAL() __asm__("MOVE.L %D0,-(%A7);" \ + "MOVE %SR, %D0;" \ + "ANDI.L #0xF0FF,%D0;" \ + "MOVE %D0, %SR;" \ + "MOVE.L (%A7)+, %D0;") +#endif + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + + + +#define OS_TASK_SW() __asm__("TRAP #15;") /* Use Trap #15 to perform a Task Level Context Switch */ + + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* ColdFire Specifics +********************************************************************************************************* +*/ + +#define OS_INITIAL_SR 0x2000 /* Supervisor mode, interrupts enabled */ + +#define OS_TRAP_NBR 15 /* OSCtxSw() invoked through TRAP #15 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSInitVBR(void); +void OSVectSet(INT8U vect, void (*addr)(void)); +void *OSVectGet(INT8U vect); + +#endif diff --git a/Ports/ColdFire/5272/GNU/os_cpu_a.s b/Ports/ColdFire/5272/GNU/os_cpu_a.s new file mode 100644 index 0000000..dae65f3 --- /dev/null +++ b/Ports/ColdFire/5272/GNU/os_cpu_a.s @@ -0,0 +1,393 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; Note(s) : 1) This port uses the MOVEM.L (A7),D0-D7/A0-A6, LEA 60(A7)A7 construct instead of +; the traditional 68xxx MOVEM.L (A7)+,D0-D7/A0-A6. It is perfectly in order to +; push/pop individual registers using MOVEM.L (A7)+,D2, etc. but it's a bit slower +; (and more verbose). +; +; 2) The LEA instruction is required because the ColdFire cannot push multiple +; registers directly to the stack. +; +; 3) Changed OSIntCtxSw for new uC/OS-II version 2.51 features. OSTickISR was also +; changed to deal with the Stack Pointer in a different way than in the V2.04. +; See the uC/OS-II release notes for details on how this is accomplished. +;******************************************************************************************************** +*/ + +.equ IMMADDR, 0x10000000 +.equ sTER0, (IMMADDR+0x210) +.equ REF_EVENT, 0x02 + + +/* +;************************************************************************************************* +; PUBLIC DECLARATIONS +;************************************************************************************************* +*/ + + .global OSCtxSw + .global OSIntCtxSw + .global OSIntExitCF + .global OSStartHighRdy + .global OSTickISR + .global OSInitVBR + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + +/* +;************************************************************************************************** +; EXTERNAL DECLARATIONS +;************************************************************************************************** +*/ + + .extern OSCtxSwCtr + .extern OSIntExit + .extern OSIntNesting + .extern OSLockNesting + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSRdyGrp + .extern OSRdyTbl + .extern OSRunning + .extern OSTaskSwHook + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSTCBPrioTbl + .extern OSTimeTick + .extern OSUnMapTbl + + .extern OSIntEnter + +/* +;******************************************************************************************************** +; OS_CPU_SR_Save() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the D0 register as expected by the +; compiler. +;******************************************************************************************************** +*/ + .text + +OS_CPU_SR_Save: + MOVE %SR,%D0 /* Copy SR into D0 */ + MOVE.L %D0,-(%A7) /* Save D0 */ + ORI.L #0x0700,%D0 /* Disable interrupts */ + MOVE %D0,%SR + MOVE.L (%A7)+,%D0 /* Restore original state of SR */ + RTS + +/* +;******************************************************************************************************** +; OS_CPU_SR_Restore() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the SR to restore. It is assumed that this 'argument' is +; passed in the D0 register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** +*/ + +OS_CPU_SR_Restore: + MOVE %D0,%SR + RTS + +/* +;************************************************************************************************* +; VECTOR BASE REGISTER INITIALIZATION +; +; This is to set the Vector Base Register to 0x00000000, in case the startup bootloader moved it +; somewhere else. +;************************************************************************************************* +*/ + +OSInitVBR: + MOVE.L #0x00000000, %D0 + MOVEC %D0, %VBR + RTS + +/* +;************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description: This function is called by OSStart() to start the highest priority task that was +; created by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 Format, Vector, OS_INITIAL_SR +; + 64 task +; + 68 task +; + 72 p_arg High Memory +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;************************************************************************************************* +*/ + +OSStartHighRdy: + JSR OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVEQ.L #1, %D4 /* OSRunning = TRUE; */ + MOVE.B %D4,OSRunning /* Indicates that we are multitasking */ + + MOVE.L (OSTCBHighRdy),%A1 /* Point to TCB of highest priority task ready to run */ + MOVE.L (%A1),%A7 /* Get the stack pointer of the task to resume */ + + MOVEM.L (%A7),%D0-%D7/%A0-%A6 /* Store all the regs */ + LEA 60(%A7),%A7 /* Advance the stack pointer */ + + RTE /* Return to task */ + + +/* +;************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows (the registers for +; task to suspend need to be saved): +; +; SP + 0 ----> Format, Vector, SR Low Memory +; + 4 PC of task High Memory +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 SR of task +; + 64 PC of task High Memory +; +;************************************************************************************************* +*/ + +OSCtxSw: + LEA -60(%A7),%A7 + MOVEM.L %D0-%D7/%A0-%A6,(%A7) /* Save the registers of the current task */ + + MOVE.L (OSTCBCur),%A1 /* Save the stack pointer in the suspended task TCB */ + MOVE.L %A7,(%A1) + + JSR OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.L (OSTCBHighRdy),%A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L %A1,(OSTCBCur) + MOVE.L (%A1),%A7 /* Get the stack pointer of the task to resume */ + + MOVE.B (OSPrioHighRdy),%D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B %D0,(OSPrioCur) + + MOVEM.L (%A7),%D0-%D7/%A0-%A6 /* Restore the CPU registers */ + LEA 60(%A7),%A7 + + RTE /* Run task */ + +/* +;************************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; +; Description : This function is provided for backward compatibility and to satisfy OSIntExit() +; in OS_CORE.C. +; +; Arguments : none +;************************************************************************************************* +*/ + +OSIntCtxSw: + JSR OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.L (OSTCBHighRdy),%A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L %A1,(OSTCBCur) + MOVE.L (%A1),%A7 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + MOVE.B (OSPrioHighRdy),%D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B %D0,(OSPrioCur) + + MOVEM.L (%A7),%D0-%D7/%A0-%A6 /* Restore ALL CPU registers from new task's stack */ + LEA 60(%A7),%A7 + + RTE /* Run task */ + +/* +;******************************************************************************************************* +; ISR EXIT +; +; Note(s) : 1) This function MUST be JUMPed to instead of calling OSIntExit() at the end of an ISR. +;******************************************************************************************************* +*/ + +OSIntExitCF: + MOVE %SR,%D0 /* Disable interrupts */ + ORI.L #0x0700,%D0 + MOVE %D0,%SR + + MOVE.B (OSIntNesting),%D0 /* OSIntNesting-- */ + ANDI.L #0x00FF,%D0 + SUBQ.L #1,%D0 + MOVE.B %D0,(OSIntNesting) + + MOVE.L (60,%A7),%D0 /* if (LAST nested ISR) { */ + ANDI.L #0x0700,%D0 + BNE OSIntExitCF_Exit + + TST.B OSLockNesting /* if (OSLockNesting == 0) */ + BNE OSIntExitCF_Exit + + MOVEQ.L #0,%D0 /* y = OSUnMapTbl[OSRdyGrp]; */ + MOVE.B OSRdyGrp,%D0 + LEA OSUnMapTbl,%A0 + MOVE.B (%A0,%D0.L),%D3 /* y is in D3 */ + + MOVEQ.L #0,%D0 + MOVE.B %D3,%D0 /* copy y into D0 */ + LEA OSRdyTbl,%A0 + MOVEQ.L #0,%D1 + MOVE.B (%A0,%D0.L),%D1 /* D1 = OSRdyTbl[y] */ + LEA OSUnMapTbl,%A0 /* OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]) */ + MOVE.B %D3,%D0 + LSL.L #3,%D0 /* D0 = (y << 3) */ + MOVE.B (%A0,%D1.L),%D1 /* D1 = OSUnMapTbl[OSRdyTbl[y]] */ + ADD.L %D1,%D0 + MOVE.B %D0,OSPrioHighRdy + + MOVE.B OSPrioHighRdy,%D0 + MOVE.B OSPrioCur,%D1 + ANDI.L #0xFF,%D1 + ANDI.L #0xFF,%D0 + CMP.L %D1,%D0 /* if (OSPrioHighRdy != OSPrioCur) { */ + BEQ OSIntExitCF_Exit + + MOVEQ.L #0,%D0 /* OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; */ + MOVE.B OSPrioHighRdy,%D0 + LEA OSTCBPrioTbl,%A0 + MOVEA.L (%A0,%D0.L*4),%A0 + MOVE.L %A0,OSTCBHighRdy + + ADDQ.L #1,OSCtxSwCtr /* OSCtxSwCtr++; */ + + /* PERFORM INTERRUPT LEVEL CONTEXT SWITCH: */ + JSR OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.L (OSTCBHighRdy),%A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L %A1,(OSTCBCur) + MOVE.L (%A1),%A7 /* CPU stack pointer = OSTCBHighRdy->OSTCBStkPtr */ + + MOVE.B (OSPrioHighRdy),%D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B %D0,(OSPrioCur) + +OSIntExitCF_Exit: + MOVEM.L (%A7),%D0-%D7/%A0-%A6 /* Restore processor registers from stack */ + LEA 60(%A7),%A7 + RTE /* Return to task or nested ISR */ + + +/* +;******************************************************************************************************* +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. +; +; This function is installed as the timer tick ISR and called each time TIMER0 on the +; MCF5272 reaches it's reference value. +; +; Arguments : none +; +; Notes : 1) You MUST save ALL the CPU registers as shown below +; 2) You MUST increment 'OSIntNesting' and NOT call OSIntEnter() +; 3) You MUST JUMP to OSIntExitCF() instead of call the function. +; 4) You MUST NOT use OSIntExit() to exit an ISR with the MCF5272. +;******************************************************************************************************* +*/ + +OSTickISR: + LEA -60(%A7),%A7 /* Save processor registers onto stack */ + MOVEM.L %D0-%D7/%A0-%A6,(%A7) + + MOVE %SR, %D0 /* Disable interrupts */ + ORI.L #0x0700,%D0 + MOVE %D0, %SR + + MOVEQ.L #0,%D0 /* OSIntNesting++ */ + MOVE.B (OSIntNesting),%D0 + ADDQ.L #1,%D0 + MOVE.B %D0,(OSIntNesting) + + CMPI.L #1, %D0 /* if (OSIntNesting == 1) */ + BNE OSTickISR_1 + MOVE.L (OSTCBCur), %A1 /* OSTCBCur- + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The initial value of the Status Register (SR) is OS_INITIAL_SR sets the MCF5272 processor +* to run in SUPERVISOR mode. It is assumed that all uC/OS-II tasks run in supervisor +* mode. +* 2) You can pass the above options in the 'opt' argument. You MUST only use the upper +* 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make changes +* to the code below, you will need to ensure that it doesn't affect the behaviour of +* OS_TaskIdle() and OS_TaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + + + opt = opt; /* 'opt' is not used, prevent compiler warning */ + + switch ((INT32U)ptos & 0x00000003) { /* Align the stack on a longword boundary */ + case 0: + pstk32 = (OS_STK *)((INT32U)ptos + 0); + break; + + case 1: + pstk32 = (OS_STK *)((INT32U)ptos - 1); + break; + + case 2: + pstk32 = (OS_STK *)((INT32U)ptos - 2); + break; + + case 3: + pstk32 = (OS_STK *)((INT32U)ptos - 3); + break; + } + + *pstk32 = 0; /* -- SIMULATE CALL TO FUNCTION WITH ARGUMENT -- */ + *--pstk32 = (INT32U)p_arg; /* p_arg */ + *--pstk32 = (INT32U)task; /* Task return address */ + + /* ------ SIMULATE INTERRUPT STACK FRAME ------- */ + *--pstk32 = (INT32U)task; /* Task return address */ + *--pstk32 = (INT32U)(0x40000000 | OS_INITIAL_SR); /* format and status register */ + + /* ------- SAVE ALL PROCESSOR REGISTERS -------- */ + *--pstk32 = (INT32U)0x00A600A6L; /* Register A6 */ + *--pstk32 = (INT32U)0x00A500A5L; /* Register A5 */ + *--pstk32 = (INT32U)0x00A400A4L; /* Register A4 */ + *--pstk32 = (INT32U)0x00A300A3L; /* Register A3 */ + *--pstk32 = (INT32U)0x00A200A2L; /* Register A2 */ + *--pstk32 = (INT32U)0x00A100A1L; /* Register A1 */ + *--pstk32 = (INT32U)0x00A000A0L; /* Register A0 */ + *--pstk32 = (INT32U)0x00D700D7L; /* Register D7 */ + *--pstk32 = (INT32U)0x00D600D6L; /* Register D6 */ + *--pstk32 = (INT32U)0x00D500D5L; /* Register D5 */ + *--pstk32 = (INT32U)0x00D400D4L; /* Register D4 */ + *--pstk32 = (INT32U)0x00D300D3L; /* Register D3 */ + *--pstk32 = (INT32U)0x00D200D2L; /* Register D2 */ + *--pstk32 = (INT32U)0x00D100D1L; /* Register D1 */ + *--pstk32 = (INT32U)0x00D000D0L; /* Register D0 */ + return ((OS_STK *)pstk32); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* GET ISR VECTOR +* +* Description: This function is called to get the address of the exception handler specified by 'vect'. +* It is assumed that the VBR (Vector Base Register) is set to 0x00000000. +* +* Arguments : vect is the vector number +* +* Note(s) : 1) Interrupts are disabled during this call +* 2) It is assumed that the VBR (Vector Base Register) is set to 0x00000000. +********************************************************************************************************* +*/ +void *OSVectGet (INT8U vect) +{ + void *addr; + + + OS_ENTER_CRITICAL(); + addr = (void *)(*(INT32U *)((INT16U)vect * 4)); + OS_EXIT_CRITICAL(); + return (addr); +} + +/* +********************************************************************************************************* +* SET ISR VECTOR +* +* Description: This function is called to set the contents of an exception vector. The function assumes +* that the VBR (Vector Base Register) is set to 0x00000000. +* +* Arguments : vect is the vector number +* addr is the address of the ISR handler +* +* Note(s) : 1) Interrupts are disabled during this call +********************************************************************************************************* +*/ +void OSVectSet (INT8U vect, void (*addr)(void)) +{ + INT32U *pvect; + + + pvect = (INT32U *)((INT16U)vect * 4); + OS_ENTER_CRITICAL(); + *pvect = (INT32U)addr; + OS_EXIT_CRITICAL(); +} diff --git a/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu.h b/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu.h new file mode 100644 index 0000000..8beab00 --- /dev/null +++ b/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu.h @@ -0,0 +1,125 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ColdFire Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register, 16 bits on ColdFire */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola ColdFire MCF5275 Inline Assembly +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ + +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ + +#endif + +#define OS_TASK_SW() asm(TRAP #14;) /* Use Trap #14 to perform a Task Level Context Switch */ + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* ColdFire Specifics +********************************************************************************************************* +*/ + +#define OS_INITIAL_SR 0x2000 /* Supervisor mode, interrupts enabled */ + +#define OS_TRAP_NBR 14 /* OSCtxSw() invoked through TRAP #14 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSStartHighRdy(void); +void OSIntCtxSw(void); +void OSCtxSw(void); +void OSInitVBR(void); + +#endif + diff --git a/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu_a.asm b/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu_a.asm new file mode 100644 index 0000000..faed770 --- /dev/null +++ b/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_cpu_a.asm @@ -0,0 +1,308 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; Note(s) : 1) This port uses the MOVEM.L (A7),D0-D7/A0-A6, LEA 60(A7)A7 construct instead of +; the traditional 68xxx MOVEM.L (A7)+,D0-D7/A0-A6. It is perfectly in order to +; push/pop individual registers using MOVEM.L (A7)+,D2, etc. but it's a bit slower +; (and more verbose). +; +; 2) The LEA instruction is required because the ColdFire cannot push multiple +; registers directly to the stack. +; +; 3) Changed OSIntCtxSw for new uC/OS-II version 2.51 features. +;******************************************************************************************************** +*/ + +/* +;************************************************************************************************* +; PUBLIC DECLARATIONS +;************************************************************************************************* +*/ + + .global _OS_CPU_SR_Save + .global _OS_CPU_SR_Restore + .global _OSCtxSw + .global _OSIntCtxSw + .global _OSStartHighRdy + + .global _OS_My_ISR + +/* +;************************************************************************************************** +; EXTERNAL DECLARATIONS +;************************************************************************************************** +*/ + + .extern _OSRunning + .extern _OSIntExit + .extern _OSIntNesting + .extern _OSLockNesting + .extern _OSPrioCur + .extern _OSPrioHighRdy + .extern _OSRdyGrp + .extern _OSRdyTbl + .extern _OSTaskSwHook + .extern _OSTCBCur + .extern _OSTCBHighRdy + .extern _OSIntEnter + + .text + .align 4 + +/* +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the D0 register as expected by the +; compiler. +;******************************************************************************************************** +*/ + +_OS_CPU_SR_Save: + MOVE.W SR,D0 ; Copy SR into D0 + MOVE.L D0,-(A7) ; Save D0 + ORI.L #0x0700,D0 ; Disable interrupts + MOVE D0,SR + MOVE.L (A7)+,D0 ; Restore D0 + RTS + +/* +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the SR to restore. It is assumed that this 'argument' is +; passed on the stack as follows: +; +; A7 + 0 -> D0 +; + 4 return address +; + 8 return address +; + 4 D0 +; A7 + 0 -> +; +; Returns : None +;******************************************************************************************************** +*/ + +_OS_CPU_SR_Restore: + MOVE.L D0,-(A7) ; Save D0 + MOVE.W 10(A7),D0 + MOVE.W D0,SR + MOVE.L (A7)+,D0 ; Restore D0 + RTS + +/* +;******************************************************************************************* +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description: This function is called by OSStart() to start the highest priority task that +; was created by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 Format, Vector, OS_INITIAL_SR +; + 64 task +; + 68 task +; + 72 p_arg High Memory +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************* +*/ + +_OSStartHighRdy: + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVEQ.L #1, D4 /* OSRunning = TRUE; */ + MOVE.B D4,_OSRunning /* Indicates that we are multitasking */ + + MOVE.L (_OSTCBHighRdy),A1 /* Point to TCB of highest prio task ready to run*/ + MOVE.L (A1),A7 /* Get the stack pointer of the task to resume */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Store all the regs */ + LEA 60(A7),A7 /* Advance the stack pointer */ + + RTE /* Return to task */ + + +/* +;******************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher prio task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows (the registers +; for task to suspend need to be saved): +; +; SP + 0 ----> Format, Vector, SR Low Memory +; + 4 PC of task High Memory +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 SR of task +; + 64 PC of task High Memory +; +;******************************************************************************************* +*/ + +_OSCtxSw: + LEA -60(A7),A7 + MOVEM.L D0-D7/A0-A6,(A7) /* Save the registers of the current task */ + + MOVE.L (_OSTCBCur),A1 /* Save stack pointer in the suspended task TCB */ + MOVE.L A7,(A1) + + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.L (_OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(_OSTCBCur) + MOVE.L (A1),A7 /* Get the stack pointer of the task to resume */ + + MOVE.B (_OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(_OSPrioCur) + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore the CPU registers */ + LEA 60(A7),A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; +; Description : This function is provided for backward compatibility and to +; satisfy OSIntExit() +; in OS_CORE.C. +; +; Arguments : none +;******************************************************************************************* +*/ + +_OSIntCtxSw: + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.B (_OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(_OSPrioCur) + + MOVE.L (_OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(_OSTCBCur) + MOVE.L (A1),A7 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore ALL CPU registers from new task stack */ + LEA 60(A7),A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; GENERIC ISR +; +; Description : This function shows how to write ISRs +; +; Arguments : none +; +; Notes : 1) You MUST save ALL the CPU registers as shown below +; 2) You MUST increment 'OSIntNesting' and NOT call OSIntEnter() +; 3) You MUST JUMP to OSIntExitCF() instead of call the function. +; 4) You MUST NOT use OSIntExit() to exit an ISR with the MCF5275. +;******************************************************************************************* +*/ + +_OS_My_ISR: + MOVE.W #0x2700,SR /* Disable interrupts */ + + LEA -60(A7),A7 /* Save processor registers onto stack */ + MOVEM.L D0-D7/A0-A6,(A7) + + MOVEQ.L #0,D0 /* OSIntNesting++ */ + MOVE.L (_OSIntNesting),D0 + ADDQ.L #1,D0 + MOVE.L D0,(_OSIntNesting) + + CMPI.L #1, D0 /* if (OSIntNesting == 1) */ + BNE _OS_My_ISR_1 + MOVE.L (_OSTCBCur), A1 /* OSTCBCur- + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +extern const INT32U far _START_SBSS[]; /* Defined in the linker file, far forces abs. addressing */ + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The initial value of the Status Register (SR) is OS_INITIAL_SR sets the MCF5275 processor +* to run in SUPERVISOR mode. It is assumed that all uC/OS-II tasks run in supervisor +* mode. +* 2) You can pass the above options in the 'opt' argument. You MUST only use the upper +* 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make changes +* to the code below, you will need to ensure that it doesn't affect the behaviour of +* OS_TaskIdle() and OS_TaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + + + (void)opt; /* 'opt' is not used, prevent compiler warning */ + + switch ((INT32U)ptos & 0x00000003) { /* Align the stack on a longword boundary */ + case 0: + pstk32 = (OS_STK *)((INT32U)ptos + 0); + break; + + case 1: + pstk32 = (OS_STK *)((INT32U)ptos - 1); + break; + + case 2: + pstk32 = (OS_STK *)((INT32U)ptos - 2); + break; + + case 3: + pstk32 = (OS_STK *)((INT32U)ptos - 3); + break; + } + + *pstk32 = 0; /* ------- SIMULATE CALL TO FUNCTION WITH ARGUMENT -------- */ + *--pstk32 = (INT32U)p_arg; /* p_arg */ + *--pstk32 = (INT32U)task; /* Task return address */ + + /* ------- SIMULATE INTERRUPT STACK FRAME ----------------- */ + *--pstk32 = (INT32U)task; /* Task return address */ + *--pstk32 = (INT32U)(0x40000000 | OS_INITIAL_SR); /* format and status register */ + + /* ------- SAVE ALL PROCESSOR REGISTERS ------------------- */ + *--pstk32 = (INT32U)0x00A600A6L; /* Register A6 */ + *--pstk32 = (INT32U)_START_SBSS; /* Register A5, Global mem ptr, linker initialized symbol */ + *--pstk32 = (INT32U)0x00A400A4L; /* Register A4 */ + *--pstk32 = (INT32U)0x00A300A3L; /* Register A3 */ + *--pstk32 = (INT32U)0x00A200A2L; /* Register A2 */ + *--pstk32 = (INT32U)0x00A100A1L; /* Register A1 */ + *--pstk32 = (INT32U)p_arg; /* Register A0 */ + *--pstk32 = (INT32U)0x00D700D7L; /* Register D7 */ + *--pstk32 = (INT32U)0x00D600D6L; /* Register D6 */ + *--pstk32 = (INT32U)0x00D500D5L; /* Register D5 */ + *--pstk32 = (INT32U)0x00D400D4L; /* Register D4 */ + *--pstk32 = (INT32U)0x00D300D3L; /* Register D3 */ + *--pstk32 = (INT32U)0x00D200D2L; /* Register D2 */ + *--pstk32 = (INT32U)0x00D100D1L; /* Register D1 */ + *--pstk32 = (INT32U)p_arg; /* Register D0 */ + return ((OS_STK *)pstk32); /* Return pointer to new top-of-stack */ +} + + + + + diff --git a/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_dbg.c b/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/ColdFire/Generic/CW_For_Microcontrollers/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ColdFire/Generic/CodeWarrior/os_cpu.h b/Ports/ColdFire/Generic/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..6dd7c8e --- /dev/null +++ b/Ports/ColdFire/Generic/CodeWarrior/os_cpu.h @@ -0,0 +1,112 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ColdFire Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_TASK_SW() asm(TRAP #14;) /* Use Trap #14 to perform a Task Level Context Switch */ + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* ColdFire Specifics +********************************************************************************************************* +*/ + +#define OS_INITIAL_SR 0x2000 /* Supervisor mode, interrupts enabled */ + +#define OS_TRAP_NBR 14 /* OSCtxSw() invoked through TRAP #14 */ + + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +void OSStartHighRdy(void); +void OSIntCtxSw (void); +void OSCtxSw (void); + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif /* End of CPU cfg module inclusion. */ + diff --git a/Ports/ColdFire/Generic/CodeWarrior/os_cpu_a.asm b/Ports/ColdFire/Generic/CodeWarrior/os_cpu_a.asm new file mode 100644 index 0000000..fa67ad6 --- /dev/null +++ b/Ports/ColdFire/Generic/CodeWarrior/os_cpu_a.asm @@ -0,0 +1,264 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; Note(s) : 1) This port uses the MOVEM.L (A7),D0-D7/A0-A6, LEA 60(A7)A7 construct instead of +; the traditional 68xxx MOVEM.L (A7)+,D0-D7/A0-A6. It is perfectly in order to +; push/pop individual registers using MOVEM.L (A7)+,D2, etc. but it's a bit slower +; (and more verbose). +; +; 2) The LEA instruction is required because the ColdFire cannot push multiple +; registers directly to the stack. +; +; 3) Changed OSIntCtxSw for new uC/OS-II version 2.51 features. +;******************************************************************************************************** +*/ + +#include + +/* +;************************************************************************************************* +; PUBLIC DECLARATIONS +;************************************************************************************************* +*/ + + .global _OSCtxSw + .global _OSIntCtxSw + .global _OSStartHighRdy + + .global _OS_My_ISR + +/* +;************************************************************************************************** +; EXTERNAL DECLARATIONS +;************************************************************************************************** +*/ + + .extern _OSRunning + .extern _OSIntExit + .extern _OSIntNesting + .extern _OSLockNesting + .extern _OSPrioCur + .extern _OSPrioHighRdy + .extern _OSRdyGrp + .extern _OSRdyTbl + .extern _OSTaskSwHook + .extern _OSTCBCur + .extern _OSTCBHighRdy + .extern _OSIntEnter + + .text + .align 4 + + +/* +;******************************************************************************************* +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description: This function is called by OSStart() to start the highest priority task that +; was created by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 Format, Vector, OS_INITIAL_SR +; + 64 task +; + 68 task +; + 72 p_arg High Memory +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************* +*/ + +_OSStartHighRdy: + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVEQ.L #1, D4 /* OSRunning = TRUE; */ + MOVE.B D4,_OSRunning /* Indicates that we are multitasking */ + + MOVE.L (_OSTCBHighRdy),A1 /* Point to TCB of highest prio task ready to run*/ + MOVE.L (A1),A7 /* Get the stack pointer of the task to resume */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Store all the regs */ + LEA 60(A7),A7 /* Advance the stack pointer */ + + RTE /* Return to task */ + + +/* +;******************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher prio task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows (the registers +; for task to suspend need to be saved): +; +; SP + 0 ----> Format, Vector, SR Low Memory +; + 4 PC of task High Memory +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 SR of task +; + 64 PC of task High Memory +; +;******************************************************************************************* +*/ + +_OSCtxSw: + LEA -60(A7),A7 + MOVEM.L D0-D7/A0-A6,(A7) /* Save the registers of the current task */ + + MOVE.L (_OSTCBCur),A1 /* Save stack pointer in the suspended task TCB */ + MOVE.L A7,(A1) + + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.L (_OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(_OSTCBCur) + MOVE.L (A1),A7 /* Get the stack pointer of the task to resume */ + + MOVE.B (_OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(_OSPrioCur) + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore the CPU registers */ + LEA 60(A7),A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; +; Description : This function is provided for backward compatibility and to +; satisfy OSIntExit() +; in OS_CORE.C. +; +; Arguments : none +;******************************************************************************************* +*/ + +_OSIntCtxSw: + JSR _OSTaskSwHook /* Invoke user defined context switch hook */ + + MOVE.B (_OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(_OSPrioCur) + + MOVE.L (_OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(_OSTCBCur) + MOVE.L (A1),A7 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore ALL CPU registers from new task stack */ + LEA 60(A7),A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; GENERIC ISR +; +; Description : This function shows how to write ISRs +; +; Arguments : none +; +; Notes : 1) You MUST save ALL the CPU registers as shown below +; 2) You MUST increment 'OSIntNesting' and NOT call OSIntEnter() +; 3) You MUST use OSIntExit() to exit an ISR. +;******************************************************************************************* +*/ + +_OS_My_ISR: + MOVE.W #0x2700,SR /* Disable interrupts */ + + LEA -60(A7),A7 /* Save processor registers onto stack */ + MOVEM.L D0-D7/A0-A6,(A7) + + OS_EMAC_SAVE /* Save the EMAC registers */ + + MOVEQ.L #0,D0 /* OSIntNesting++ */ + MOVE.B (_OSIntNesting),D0 + ADDQ.L #1,D0 + MOVE.B D0,(_OSIntNesting) + + CMPI.L #1, D0 /* if (OSIntNesting == 1) */ + BNE _OS_My_ISR_1 + MOVE.L (_OSTCBCur), A1 /* OSTCBCur- + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The initial value of the Status Register (SR) is OS_INITIAL_SR sets the MCF5275 processor +* to run in SUPERVISOR mode. It is assumed that all uC/OS-II tasks run in supervisor +* mode. +* 2) You can pass the above options in the 'opt' argument. You MUST only use the upper +* 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make changes +* to the code below, you will need to ensure that it doesn't affect the behaviour of +* OS_TaskIdle() and OS_TaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + + + opt = opt; /* 'opt' is not used, prevent compiler warning */ + + switch ((INT32U)ptos & 0x00000003) { /* Align the stack on a longword boundary */ + case 0: + pstk32 = (OS_STK *)((INT32U)ptos + 0); + break; + + case 1: + pstk32 = (OS_STK *)((INT32U)ptos - 1); + break; + + case 2: + pstk32 = (OS_STK *)((INT32U)ptos - 2); + break; + + case 3: + pstk32 = (OS_STK *)((INT32U)ptos - 3); + break; + } + + *pstk32 = 0; /* -- SIMULATE CALL TO FUNCTION WITH ARGUMENT -- */ + *--pstk32 = (INT32U)p_arg; /* p_arg */ + *--pstk32 = (INT32U)task; /* Task return address */ + + /* ------ SIMULATE INTERRUPT STACK FRAME ------- */ + *--pstk32 = (INT32U)task; /* Task return address */ + *--pstk32 = (INT32U)(0x40000000 | OS_INITIAL_SR); /* format and status register */ + + /* ------- SAVE ALL PROCESSOR REGISTERS -------- */ + *--pstk32 = (INT32U)0x00A600A6L; /* Register A6 */ + *--pstk32 = (INT32U)0x00A500A5L; /* Register A5 */ + *--pstk32 = (INT32U)0x00A400A4L; /* Register A4 */ + *--pstk32 = (INT32U)0x00A300A3L; /* Register A3 */ + *--pstk32 = (INT32U)0x00A200A2L; /* Register A2 */ + *--pstk32 = (INT32U)0x00A100A1L; /* Register A1 */ + *--pstk32 = (INT32U)p_arg; /* Register A0 */ + *--pstk32 = (INT32U)0x00D700D7L; /* Register D7 */ + *--pstk32 = (INT32U)0x00D600D6L; /* Register D6 */ + *--pstk32 = (INT32U)0x00D500D5L; /* Register D5 */ + *--pstk32 = (INT32U)0x00D400D4L; /* Register D4 */ + *--pstk32 = (INT32U)0x00D300D3L; /* Register D3 */ + *--pstk32 = (INT32U)0x00D200D2L; /* Register D2 */ + *--pstk32 = (INT32U)0x00D100D1L; /* Register D1 */ + *--pstk32 = (INT32U)p_arg; /* Register D0 */ + return ((OS_STK *)pstk32); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif + diff --git a/Ports/ColdFire/Generic/CodeWarrior/os_cpu_i.asm b/Ports/ColdFire/Generic/CodeWarrior/os_cpu_i.asm new file mode 100644 index 0000000..efa7d79 --- /dev/null +++ b/Ports/ColdFire/Generic/CodeWarrior/os_cpu_i.asm @@ -0,0 +1,40 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; Filename : os_cpu_i.asm +; Version : V2.93.00 +;******************************************************************************************************** +*/ + +/* +;************************************************************************************************** +; MACROS +;************************************************************************************************** +*/ + + .macro OS_EMAC_SAVE + /* non-EMAC port does not save any EMAC registers */ + + .endm + + + + .macro OS_EMAC_RESTORE + /* non-EMAC port does not save any EMAC registers */ + + .endm diff --git a/Ports/ColdFire/Generic/CodeWarrior/os_dbg.c b/Ports/ColdFire/Generic/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/ColdFire/Generic/CodeWarrior/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/ColdFire/Generic/IAR/os_cpu.h b/Ports/ColdFire/Generic/IAR/os_cpu.h new file mode 100644 index 0000000..0a040b7 --- /dev/null +++ b/Ports/ColdFire/Generic/IAR/os_cpu.h @@ -0,0 +1,112 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* ColdFire Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_TASK_SW() __asm("TRAP #14") /* Use Trap #14 to perform a Task Level Context Switch */ + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* ColdFire Specifics +********************************************************************************************************* +*/ + +#define OS_INITIAL_SR 0x2000 /* Supervisor mode, interrupts enabled */ + +#define OS_TRAP_NBR 14 /* OSCtxSw() invoked through TRAP #14 */ + + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +void OSStartHighRdy(void); +void OSIntCtxSw (void); +void OSCtxSw (void); + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif /* End of CPU cfg module inclusion. */ + diff --git a/Ports/ColdFire/Generic/IAR/os_cpu_a.asm b/Ports/ColdFire/Generic/IAR/os_cpu_a.asm new file mode 100644 index 0000000..a5d4f27 --- /dev/null +++ b/Ports/ColdFire/Generic/IAR/os_cpu_a.asm @@ -0,0 +1,263 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; Note(s) : 1) This port uses the MOVEM.L (A7),D0-D7/A0-A6, LEA 60(A7)A7 construct instead of +; the traditional 68xxx MOVEM.L (A7)+,D0-D7/A0-A6. It is perfectly in order to +; push/pop individual registers using MOVEM.L (A7)+,D2, etc. but it's a bit slower +; (and more verbose). +; +; 2) The LEA instruction is required because the ColdFire cannot push multiple +; registers directly to the stack. +; +; 3) Changed OSIntCtxSw for new uC/OS-II version 2.51 features. +;******************************************************************************************************** +*/ + +#include + +/* +;************************************************************************************************* +; PUBLIC DECLARATIONS +;************************************************************************************************* +*/ + + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSStartHighRdy + + PUBLIC OS_My_ISR + +/* +;************************************************************************************************** +; EXTERNAL DECLARATIONS +;************************************************************************************************** +*/ + + EXTERN OSRunning + EXTERN OSIntExit + EXTERN OSIntNesting + EXTERN OSLockNesting + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRdyGrp + EXTERN OSRdyTbl + EXTERN OSTaskSwHook + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSIntEnter + + RSEG CODE:CODE:NOROOT(2) /* Align to power 2, 4 bytes. */ + + +/* +;******************************************************************************************* +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description: This function is called by OSStart() to start the highest priority task that +; was created by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 Format, Vector, OS_INITIAL_SR +; + 64 task +; + 68 task +; + 72 p_arg High Memory +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************* +*/ + +OSStartHighRdy: + JSR (OSTaskSwHook) /* Invoke user defined context switch hook */ + + MOVEQ.L #1, D4 /* OSRunning = TRUE; */ + MOVE.B D4, (OSRunning) /* Indicates that we are multitasking */ + + MOVEA.L (OSTCBHighRdy),A1 /* Point to TCB of highest prio task ready to run*/ + MOVEA.L (A1), A7 /* Get the stack pointer of the task to resume */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Store all the regs */ + LEA (60, A7), A7 /* Advance the stack pointer */ + + RTE /* Return to task */ + + +/* +;******************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher prio task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows (the registers +; for task to suspend need to be saved): +; +; SP + 0 ----> Format, Vector, SR Low Memory +; + 4 PC of task High Memory +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 Low Memory +; + 4 D1 +; + 8 D2 +; + 12 D3 +; + 16 D4 +; + 20 D5 +; + 24 D6 +; + 28 D7 +; + 32 A0 +; + 36 A1 +; + 40 A2 +; + 44 A3 +; + 48 A4 +; + 52 A5 +; + 56 A6 +; + 60 SR of task +; + 64 PC of task High Memory +; +;******************************************************************************************* +*/ + +OSCtxSw: + LEA (-60, A7), A7 + MOVEM.L D0-D7/A0-A6,(A7) /* Save the registers of the current task */ + + MOVEA.L (OSTCBCur),A1 /* Save stack pointer in the suspended task TCB */ + MOVE.L A7,(A1) + + JSR (OSTaskSwHook) /* Invoke user defined context switch hook */ + + MOVEA.L (OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(OSTCBCur) + MOVEA.L (A1),A7 /* Get the stack pointer of the task to resume */ + + MOVE.B (OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(OSPrioCur) + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore the CPU registers */ + LEA (60, A7), A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; INTERRUPT LEVEL CONTEXT SWITCH +; +; +; Description : This function is provided for backward compatibility and to +; satisfy OSIntExit() +; in OS_CORE.C. +; +; Arguments : none +;******************************************************************************************* +*/ + +OSIntCtxSw: + JSR (OSTaskSwHook) /* Invoke user defined context switch hook */ + + MOVE.B (OSPrioHighRdy),D0 /* OSPrioCur = OSPrioHighRdy */ + MOVE.B D0,(OSPrioCur) + + MOVEA.L (OSTCBHighRdy),A1 /* OSTCBCur = OSTCBHighRdy */ + MOVE.L A1,(OSTCBCur) + MOVEA.L (A1),A7 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + MOVEM.L (A7),D0-D7/A0-A6 /* Restore ALL CPU registers from new task stack */ + LEA (60, A7), A7 + + RTE /* Run task */ + +/* +;******************************************************************************************* +; GENERIC ISR +; +; Description : This function shows how to write ISRs +; +; Arguments : none +; +; Notes : 1) You MUST save ALL the CPU registers as shown below +; 2) You MUST increment 'OSIntNesting' and NOT call OSIntEnter() +; 3) You MUST use OSIntExit() to exit an ISR. +;******************************************************************************************* +*/ + +OS_My_ISR: + MOVE.W #0x2700,SR /* Disable interrupts */ + + LEA (-60, A7), A7 /* Save processor registers onto stack */ + MOVEM.L D0-D7/A0-A6,(A7) + + OS_EMAC_SAVE /* Save the EMAC registers */ + + MOVEQ.L #0,D0 /* OSIntNesting++ */ + MOVE.B (OSIntNesting),D0 + ADDQ.L #1,D0 + MOVE.B D0,(OSIntNesting) + + CMPI.L #1, D0 /* if (OSIntNesting == 1) */ + BNE.W (OS_My_ISR_1) + MOVEA.L (OSTCBCur), A1 /* OSTCBCur- + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The initial value of the Status Register (SR) is OS_INITIAL_SR sets the MCF5275 processor +* to run in SUPERVISOR mode. It is assumed that all uC/OS-II tasks run in supervisor +* mode. +* 2) You can pass the above options in the 'opt' argument. You MUST only use the upper +* 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make changes +* to the code below, you will need to ensure that it doesn't affect the behaviour of +* OS_TaskIdle() and OS_TaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + + + opt = opt; /* 'opt' is not used, prevent compiler warning */ + + switch ((INT32U)ptos & 0x00000003) { /* Align the stack on a longword boundary */ + case 0: + pstk32 = (OS_STK *)((INT32U)ptos + 0); + break; + + case 1: + pstk32 = (OS_STK *)((INT32U)ptos - 1); + break; + + case 2: + pstk32 = (OS_STK *)((INT32U)ptos - 2); + break; + + case 3: + pstk32 = (OS_STK *)((INT32U)ptos - 3); + break; + } + + *pstk32 = 0; /* -- SIMULATE CALL TO FUNCTION WITH ARGUMENT -- */ + *--pstk32 = (INT32U)p_arg; /* p_arg */ + *--pstk32 = (INT32U)task; /* Task return address */ + + /* ------ SIMULATE INTERRUPT STACK FRAME ------- */ + *--pstk32 = (INT32U)task; /* Task return address */ + *--pstk32 = (INT32U)(0x40000000 | OS_INITIAL_SR); /* format and status register */ + + /* ------- SAVE ALL PROCESSOR REGISTERS -------- */ + *--pstk32 = (INT32U)0x00A600A6L; /* Register A6 */ + *--pstk32 = (INT32U)0x00A500A5L; /* Register A5 */ + *--pstk32 = (INT32U)0x00A400A4L; /* Register A4 */ + *--pstk32 = (INT32U)0x00A300A3L; /* Register A3 */ + *--pstk32 = (INT32U)0x00A200A2L; /* Register A2 */ + *--pstk32 = (INT32U)0x00A100A1L; /* Register A1 */ + *--pstk32 = (INT32U)p_arg; /* Register A0 */ + *--pstk32 = (INT32U)0x00D700D7L; /* Register D7 */ + *--pstk32 = (INT32U)0x00D600D6L; /* Register D6 */ + *--pstk32 = (INT32U)0x00D500D5L; /* Register D5 */ + *--pstk32 = (INT32U)0x00D400D4L; /* Register D4 */ + *--pstk32 = (INT32U)0x00D300D3L; /* Register D3 */ + *--pstk32 = (INT32U)0x00D200D2L; /* Register D2 */ + *--pstk32 = (INT32U)0x00D100D1L; /* Register D1 */ + *--pstk32 = (INT32U)p_arg; /* Register D0 */ + return ((OS_STK *)pstk32); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif + diff --git a/Ports/ColdFire/Generic/IAR/os_cpu_i.asm b/Ports/ColdFire/Generic/IAR/os_cpu_i.asm new file mode 100644 index 0000000..44dbd33 --- /dev/null +++ b/Ports/ColdFire/Generic/IAR/os_cpu_i.asm @@ -0,0 +1,40 @@ +/* +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** +*/ + +/* +;******************************************************************************************************** +; Filename : os_cpu_i.asm +; Version : V2.93.00 +;******************************************************************************************************** +*/ + +/* +;************************************************************************************************** +; MACROS +;************************************************************************************************** +*/ + +OS_EMAC_SAVE MACRO + /* non-EMAC port does not save any EMAC registers */ + + ENDM + + + +OS_EMAC_RESTORE MACRO + /* non-EMAC port does not save any EMAC registers */ + + ENDM diff --git a/Ports/ColdFire/Generic/IAR/os_dbg.c b/Ports/ColdFire/Generic/IAR/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/ColdFire/Generic/IAR/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.ASM b/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.ASM new file mode 100644 index 0000000..916c940 --- /dev/null +++ b/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.ASM @@ -0,0 +1,371 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Freescale DSP568xx Specific code +; Metrowerks CodeWarrior for Freescale Embedded DSP568xx +; +; Filename : os_cpu.asm +; Version : V2.93.00 +;******************************************************************************************************** + + SECTION rtlib + + include "os_portasm.h" + + GLOBAL FOSTaskStkInit + GLOBAL FOSStartHighRdy + GLOBAL FOSCtxSw + GLOBAL FOSIntCtxSw + GLOBAL FOSTickISR + GLOBAL FtimerTick + GLOBAL FOS_DISABLE_INTERRUPTS + GLOBAL FOS_ENABLE_INTERRUPTS + + XREF FOSIntExit + XREF FOSTimeTick + XREF FOSTaskSwHook + + XREF FOSIntNesting + XREF FOSTickDOSCtr + XREF FValueOSPrioHighRdy + XREF FSetOSPrioCur + XREF FSetOSRunning + XREF FOSTCBCur + XREF FOSTCBHighRdy + + XREF FTickSetSP + + XREF FPE_state + + +; +; After executing the SWI through the SDK Dispatcher and calling the uC/OS ISR, +; the stack frame looks like this: +; +; PC (Low memory) +; SR +; Optional alignment word +; SP +; Y +; R0 +; A2 +; B2 +; X0 +; N3 +; M01 +; OMR +; C2 +; D2 +; A10 +; B10 +; N +; R1 +; R2 +; R3 +; LA +; LA2 +; LC2 +; LC +; HWS +; HWS +; PC of DispatchRestore +; OSTCBCur->OSTCBStkPtr --> SR of DispatchRestore (High memory) +; +; OSCtwSw and OSIntCtwSw add the CW Floating Point state on the stack, as follows; +; +; OSTCBCur->OSTCBStkPtr --> C10 (Low memory) +; D10 +; R5 +; FPE_State (High memory) +; +; OSTaskStkInit creates the above stack contents in preparation for +; starting a uC/OS task as if it had been suspended thru OSCtwSw. +; +; WARNING: OSTaskStkInit must be kept in sync with registers saved by Dispatcher. +; + +;/* +;********************************************************************************************************* +;* INITIALIZE A TASK'S STACK +;* +;* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +;* stack frame of the task being created. This function is highly processor specific. +;* +;* Arguments : task is a pointer to the task code +;* +;* pdata is a pointer to a user supplied data area that will be passed to the task +;* when the task first executes. +;* +;* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +;* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +;* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +;* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +;* of the stack. +;* +;* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +;* (see uCOS_II.H for OS_TASK_OPT_???). +;* +;* Returns : Always returns the location of the new top-of-stack' once the processor registers have +;* been placed on the stack in the proper order. +;* +;* Note(s) : Interrupts are enabled when your task starts executing. +;* +;********************************************************************************************************* +;*/ + +;asm OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +;{ +; /* +; Input Parameters: +; +; Y0 => opt +; R2 => pd +; R3 => pdata +; R4 => ptos +; +; Register Usage During Execution: +; +; R2 => pd +; R3 => pdata +; R4 => ptos +; Y => temp +; X0 => temp +; A => temp +; +; */ + +FDispatchRestore: + + move.l x:(SP)-,R4 + + ; restore hardware stack + move.w hws,A ; clear HWS to ensure reload + move.w hws,A + move.l x:(SP)-,hws + move.l x:(SP)-,hws + + ; restore all saved registers + move.l x:(SP)-,lc + move.l x:(SP)-,lc2 + move.l x:(SP)-,la2 + move.l x:(SP)-,la + + move.l x:(SP)-,R3 + move.l x:(SP)-,R2 + move.l x:(SP)-,R1 + move.l x:(SP)-,N + move.l x:(SP)-,B + move.l x:(SP)-,A + + move.l x:(SP)-,D2 + move.l x:(SP)-,C2 + move.l x:(SP)-,OMR + move.l x:(SP)-,M01 + move.l x:(SP)-,N3 + move.l x:(SP)-,X0 + move.l x:(SP)-,B2 + move.l x:(SP)-,A2 + move.l x:(SP)-,R0 + move.l x:(SP)-,Y + move.l x:(SP)-,SP + nop + nop + + rti + + + +FOSTaskStkInit: + + adda #1,R4 ; Align SP + + move.l R4,A + bfclr #$0001,A0 + move.l A10,R4 + + move.w R2,X:(R4)+ ; PC portion of return address + + move.l R2,A ; Isolate SR portion of return address + andc #$001F,A1 + move.w #10,Y0 + asll.w A1,Y0,X0 + move.w X0,x:(R4) ; Create new SR with interrupts enabled + + move.l R4,A ; Store SP to simulate AlignSP + adda #1,R4 + nop + move.l A10,x:(R4)+ + + move.l #$0000,Y + rep #6 + move.l Y,x:(R4)+ ; Clear following 6 registers + ; Y, R0, A2, B2, X0, N3 + + move.w #0,A + move.w M01,A0 + move.l A10,x:(R4)+ + move.w OMR,A0 + move.l A10,x:(R4)+ + + rep #6 + move.l Y,x:(R4)+ ; Clear following 6 registers + ; C2, D2, A10, B10, N, R1 + + move.l R3,x:(R4)+ ; Save pdata as R2 (task parameter) + + rep #8 + move.l Y,x:(R4)+ ; Clear following 8 registers + ; R3, LA, LA2, LC2, LC, HWS, HWS, R4 + + move.l #>>FDispatchRestore,A ; Create jsr return to DispatchRestore + move.w A0,x:(R4)+ ; PC portion of DispatchRestore address + andc #$001F,A1 + move.w #10,Y0 + asll.w A1,Y0,X0 + move.w X0,x:(R4)+ + + move.l #$0000,Y + rep #3 + move.l Y,x:(R4)+ ; Clear following 3 registers + ; C10, D10, R5 + + move.w Y1,x:(R4)+ ; Save FPE_state as long (0) + move.w Y1,x:(R4) ; Note that SP (R4) is now odd + + tfra R4,R2 ; return ((OS_STK *)stk); + + rts +;} + + PAGE +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +FOSStartHighRdy: + + + jsr FOSTaskSwHook ; Call user defined task switch hook +; + LoadRx X:FOSTCBHighRdy,R2 ; R2 = OSTCBHighRdy + LoadRx X:(R2),R2 + tfra R2,SP ; SP = OSTCBHighRdy->OSTCBStkPtr + nop + nop +; + jsr FSetOSRunning ; Indicate that multitasking has started +; + bra RestartTask ; Run task + + + PAGE +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) +; void OSCtxSw(void) +; +; Note(s): 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +;********************************************************************************************************* + +FOSIntCtxSw: +FOSCtxSw: +; + adda #2,SP + move.l C10,x:(SP)+ + move.l D10,x:(SP)+ + move.l R5,x:(SP)+ + + ; + ; Save FP Emulation State + ; + move.w x:FPE_state,A + move.l A10,x:(SP) + + ; + ; uC/OS logic + ; + jsr FOSTaskSwHook ; Call user defined task switch hook + + LoadRx x:FOSTCBCur,R2 ; Pre-load OSTCBCur for uC/OS logic + +; StoreRx SP,X:(R2) ; Save stack top for current task + + tfra SP,R5 + StoreRx R5,X:(R2) + + LoadRx x:FOSTCBHighRdy,R2 ; OSTCBCur = OSTCBHighRdy (Step 1) + +; LoadRx x:(R2),SP ; SP = OSTCBHighRdy->OSTCBStkPtr + LoadRx x:(R2),R5 + tfra R5,SP + + StoreRx R2,x:FOSTCBCur ; OSTCBCur = OSTCBHighRdy (Step 2) + + jsr FValueOSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + jsr FSetOSPrioCur ; Finish OSPrioCur = OSPrioHighRdy + +RestartTask: ; Return to new task + + move.l x:(SP)-,y1 ; Restore Floating Point emulation state + move.w y1,x:FPE_state + move.l x:(SP)-,R5 ; Restore R5 + move.l x:(SP)-,D ; Restore D10 + move.l x:(SP)-,C ; Restore C10 + + rts ; Return to Caller (DispatchRestore or uC/OS) + + +;/* +;********************************************************************************************************* +;* +;* asm void OS_DISABLE_INTERRUPTS (OS_CPU_SR * cpu_sr); +;* +;********************************************************************************************************* +;*/ + +FOS_DISABLE_INTERRUPTS: + + move.w SR,x:(R2) + bfset #$0300,SR + rts + +;/* +;********************************************************************************************************* +;* +;* asm void OS_ENABLE_INTERRUPTS (OS_CPU_SR cpu_sr); +;* +;********************************************************************************************************* +;*/ +FOS_ENABLE_INTERRUPTS: + + moveu.w Y0,SR + rts + + + + ENDSEC + + END + diff --git a/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.C b/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.C new file mode 100644 index 0000000..b1208e9 --- /dev/null +++ b/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.C @@ -0,0 +1,343 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale DSP568xx Specific code +* Metrowerks CodeWarrior for Freescale Embedded DSP568xx +* +* Filename : os_cpu.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include "includes.h" +#include "AroPrintf.h" +#include "AS1.h" +#include "memoire.h" +#include "IO.h" +#include "AroCan.h" +#include "MesureBus.h" +#include "Superviseur.h" +#include "Resultat.h" +#include "EntreesSorties.h" +#include "Mesures.h" +#include "Apprentissage.h" +#include "Controleur_Intensite.h" +#include "Defauts.h" + +#include "Diagnostique.h" +#include "CalculateurConsNormal.h" +#include "Regulateur.h" +#include "GenerateurAA.h" +#include "Shell.h" +OS_CPU_SR cpu_sr; + +#ifdef TRACE_CPU + UINT8 OSIdleCtrRunMax; +#endif + +#ifdef DEBUG_REGU + INT16 g_wRegDebugEm; + UINT16 g_uwRegDebugT_Soudage; + UINT16 g_wRegDebugCommande; + UINT16 g_uwRegDebugConsigne; + UINT16 g_uwRegDebugGS; +#endif + +#ifdef TRACE_TENSION_BUS +extern UINT16 g_uwDebugCBTension_Maxi; +#endif + + +#if OS_CPU_HOOKS_EN +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_VERSION > 203 +void OSInitHookBegin (void) +{ + +#ifdef TRACE_CPU + OSIdleCtrRunMax=0; +#endif + +#ifdef TRACE_TENSION_BUS + g_uwDebugCBTension_Maxi=0; +#endif + +#ifdef DEBUG_REGU + g_wRegDebugCommande=30000; +#endif + +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Returns : none +* +********************************************************************************************************* +*/ + +#if OS_VERSION > 203 +void OSInitHookEnd (void) +{ + Shell_vInit(); +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) I decided to change the options on the statistic task to allow for floating-point in +* case you decide to do math. in OSTaskStatHook(). +********************************************************************************************************* +*/ +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb=ptcb; + +} + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb=ptcb; +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +void OSTaskSwHook (void) +{ + + +} + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +void OSTaskStatHook (void) +{ + AS1_TComData ucTouche; + switch(AS1_RecvChar(&ucTouche)) + { + case ERR_OK : Shell_vExecute(ucTouche); + + break; + + case ERR_SPEED : Aro_uwPrintf("ERR_SPEED\r"); + break; + + + case ERR_BREAK : Aro_uwPrintf("ERR_BREAK\r"); + break; + + case ERR_COMMON : Aro_uwPrintf("ERR_COMMON\r"); + break; + + case ERR_RXEMPTY : + break; + + default : Aro_uwPrintf("AUTRE\r"); + } + + if(OSCPUUsage>OSIdleCtrRunMax) + { + OSIdleCtrRunMax=OSCPUUsage; + } +} + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OSTCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb=ptcb; +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +void OSTimeTickHook (void) +{ + +} + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_VERSION >= 205 +void OSTaskIdleHook (void) +{ + +} + +#endif + + +/* +********************************************************************************************************* +* Helper routines to interface C to ASM +********************************************************************************************************* +*/ +int ValueOSPrioHighRdy (void); +void SetOSRunning (void); +void SetOSPrioCur (int Priority); + + +int ValueOSPrioHighRdy (void) +{ + return (int)OSPrioHighRdy; +} + +void SetOSRunning (void) +{ + OSRunning = TRUE; +} + +void SetOSPrioCur (int Priority) +{ + OSPrioCur = Priority; +} + + +/* +;********************************************************************************************************* +; HANDLE TICK ISR +; +; Description: This function is called by the timer ISR periodically (every tick). +; The exact amount of time for each tick depends on how the timer was configured. +; +; Arguments : none +; +; Returns : none +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; if (!OSRunning) Return; +; +; OSIntNesting++; +; +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; +; OSIntExit(); Notify uC/OS-II about end of ISR +; +; Return +;********************************************************************************************************* +*/ + +void OSTickISR (void) +{ + + if (OSRunning) + { + OSIntNesting++; /* Increment interrupt nesting */ + + OSTimeTick(); /* Process system tick */ + OSIntExit(); /* Notify uC/OS-II of end of ISR */ + } +} + + +#endif diff --git a/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.H b/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.H new file mode 100644 index 0000000..aa5e15b --- /dev/null +++ b/Ports/DSP56F8xxx/CodeWarrior/OS_CPU.H @@ -0,0 +1,159 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale DSP568xx Specific code +* Metrowerks CodeWarrior for Freescale Embedded DSP568xx +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx. Not actually needed for ... */ +#define WORD INT16S /* ... uC/OS-II. */ +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +OS_CPU_EXT OS_CPU_SR cpu_sr; + +/* +********************************************************************************************************* +* Freescale DSP568xx +* +* Method #1: Not implemented. +* +* Method #2: Not implemented. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#if 0 + + /* These routines emphasize speed at the expense of space */ + + inline void OS_DISABLE_INTERRUPTS (register volatile OS_CPU_SR * cpu_sr) + { + asm(move.w SR,x:(cpu_sr)); + asm(bfset #$0300,SR); + asm(nop); + asm(nop); + asm(nop); + asm(nop); + asm(nop); + } + + inline void OS_ENABLE_INTERRUPTS (register OS_CPU_SR cpu_sr) + { + asm(moveu.w cpu_sr,SR); + asm(nop); + asm(nop); + asm(nop); + asm(nop); + asm(nop); + } + +#else + + /* These routines emphasize space at the expense of speed */ + + asm void OS_DISABLE_INTERRUPTS (OS_CPU_SR * cpu_sr); + + asm void OS_ENABLE_INTERRUPTS (OS_CPU_SR cpu_sr); + +#endif + + +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 +#error "OS_CRITICAL_METHOD #1 - Not Implemented" +#endif + +#if OS_CRITICAL_METHOD == 2 +#error "OS_CRITICAL_METHOD #2 - Not Implemented" +#endif + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() OS_DISABLE_INTERRUPTS (&cpu_sr) + +#define OS_EXIT_CRITICAL() OS_ENABLE_INTERRUPTS (cpu_sr) +#endif + +/* +********************************************************************************************************* +* Freescale DSP568xx Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 0 /* Stack grows from LOW to HIGH memory on DPS568xx */ + +#define OS_TASK_SW() asm(swi) + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/DSP56F8xxx/CodeWarrior/os_portasm.h b/Ports/DSP56F8xxx/CodeWarrior/os_portasm.h new file mode 100644 index 0000000..39df000 --- /dev/null +++ b/Ports/DSP56F8xxx/CodeWarrior/os_portasm.h @@ -0,0 +1,61 @@ +; File: os_portasm.h + + include "asmdef.h" + +;/******************************************************* +;* Conditional assembly +;*******************************************************/ + +;/* Change the following define to '0' to eliminate asserts */ + define ASSERT_ON_INVALID_PARAMETER '1' + +;/* For V1 compatibility */ + define debug 'debughlt' + +;/* +; These defines permit the same ASM source code to be +; used for Large and Small Memory Models +;*/ + define PORT_LARGE_MEMORY_MODEL '1' + + define CODEWARRIOR_WORKAROUND '0' + + IF @DEF(F__CW_M56800E_LMM) + +; Large Memory Model defines + + define LoadRx 'move.l' + define StoreRx 'move.l' + define TestRx 'tst.l' + + define PTR_SIZE '2' + + else + +; Small Memory Model defines + + define LoadRx 'moveu.w' + define StoreRx 'move.w' + define TestRx 'tst.w' + + define PTR_SIZE '1' + + endif + +;/******************************************************* +;* Constants +;*******************************************************/ + +;/* Function Result Values */ +PASS equ 0 +FAIL equ -1 + +true equ 1 +false equ 0 + +;/******************************************************* +;* Implementation Limits +;*******************************************************/ + +PORT_MAX_VECTOR_LEN equ 65535 + diff --git a/Ports/FR/Softune/os_cpu.h b/Ports/FR/Softune/os_cpu.h new file mode 100644 index 0000000..8e06ee8 --- /dev/null +++ b/Ports/FR/Softune/os_cpu.h @@ -0,0 +1,120 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Fujitsu FR Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT +********************************************************************************************************* +*/ + +#define OS_CPU_INT_DIS_MEAS_EN 0 + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (PS = 32 bits) */ + +/* +********************************************************************************************************* +* FR SPECIFIC +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + +/* +********************************************************************************************************* +* FR Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ + + /* Interrupt vector # used task level context switch */ +#define OS_TASK_SW() __asm(" INT #0x40"); + +#define CPU_ILM 0x1F /* Initial task's ILM */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); /* See OS_CPU_A.ASM */ +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); diff --git a/Ports/FR/Softune/os_cpu_a.asm b/Ports/FR/Softune/os_cpu_a.asm new file mode 100644 index 0000000..393cb2b --- /dev/null +++ b/Ports/FR/Softune/os_cpu_a.asm @@ -0,0 +1,203 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Fujitsu FR Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** + + +;********************************************************************************************************* +; GLOCAL REFERENCES +;********************************************************************************************************* + + .PROGRAM OS_CPU_A + + .EXPORT _OS_CPU_SR_Save + .EXPORT _OS_CPU_SR_Restore + + .EXPORT _OSStartHighRdy + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + + .IMPORT _OSTaskSwHook + .IMPORT _OSPrioHighRdy + .IMPORT _OSPrioCur + .IMPORT _OSRunning + .IMPORT _OSTCBCur + .IMPORT _OSTCBHighRdy + +;********************************************************************************************************* +; INCLUDES +;********************************************************************************************************* + +#include "os_cpu_i.asm" + + .section CODE, code, align=4 + + +;********************************************************************************************************* +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +;********************************************************************************************************* + + +_OS_CPU_SR_Save: + MOV PS, R4 ; Save state of PS + ANDCCR #0xEF ; Disable interrupts + RET + +_OS_CPU_SR_Restore: + MOV R4, PS ; Restore state of PS + RET + +;********************************************************************************************************* +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy: + + CALL _OSTaskSwHook ; Call user defined task switch hook + + LDI #1, R1 ; OSRunning = TRUE + LDI #_OSRunning, R0 + STB R1, @R0 + + LDI #_OSTCBHighRdy, R12 ; Resume stack pointer + LD @R12, R13 + LD @R13, R15 + + POP_ALL ; Restore context of resisters + + RETI ; Run task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is actually an Software Interrupt handler +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack +; h) Return to new task's code +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +;********************************************************************************************************* + +_OSCtxSw: + PUSH_ALL ; Save context of interrupted task + + LDI #_OSTCBCur, R0 ; OSTCBCur->OSTCBStkPtr = SSP + LD @R0, R1 + ST R15, @R1 + + CALL _OSTaskSwHook ; Call user defined task switch hook + + LDI #_OSPrioHighRdy, R0 ; OSPrioCur = OSPrioHighRdy + LDUB @R0, R3 + LDI #_OSPrioCur, R1 + STB R3, @R1 + + LDI #_OSTCBHighRdy, R0 ; OSTCBCur = OSTCBHighRdy + LD @R0, R2 + LDI #_OSTCBCur, R1 + ST R2, @R1 + LD @R2, R15 ; SSP = OSTCBHighRdy->OSTCBStkPtr + + POP_ALL ; Restore context of interrupted task + + RETI + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SYS mode with BOTH FIQ and IRQ interrupts DISABLED +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack +; f) Return to new task's code +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +;********************************************************************************************************* + +_OSIntCtxSw: + CALL _OSTaskSwHook ; Call user defined task switch hook + + LDI #_OSPrioHighRdy, R0 ; OSPrioCur = OSPrioHighRdy + LDUB @R0, R3 + LDI #_OSPrioCur, R1 + STB R3, @R1 + + LDI #_OSTCBHighRdy, R0 ; OSTCBCur = OSTCBHighRdy + LD @R0, R2 + LDI #_OSTCBCur, R1 + ST R2, @R1 + LD @R2, R15 ; SSP = OSTCBHighRdy->OSTCBStkPtr + + POP_ALL ; Restore context of interrupted task + + RETI + + .END diff --git a/Ports/FR/Softune/os_cpu_c.c b/Ports/FR/Softune/os_cpu_c.c new file mode 100644 index 0000000..7e91040 --- /dev/null +++ b/Ports/FR/Softune/os_cpu_c.c @@ -0,0 +1,291 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Fujitsu FR Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in SUPERVISOR mode. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + + + (void)opt; /* 'opt' is not used, prevent warning */ + pstk = (INT32U *)ptos; /* Load stack pointer */ + + *pstk-- = (INT32U)(CPU_ILM << 16) + 0x00000010; /* PS = Enable interrupts */ + *pstk-- = (INT32U)task; /* PC */ + *pstk-- = (INT32U)task; /* RP */ + *pstk-- = (INT32U)0x14141414; /* R14 */ + *pstk-- = (INT32U)0x13131313; /* R13 */ + *pstk-- = (INT32U)0x12121212; /* R12 */ + *pstk-- = (INT32U)0x11111111; /* R11 */ + *pstk-- = (INT32U)0x10101010; /* R10 */ + *pstk-- = (INT32U)0x09090909; /* R9 */ + *pstk-- = (INT32U)0x08080808; /* R8 */ + *pstk-- = (INT32U)0x07070707; /* R7 */ + *pstk-- = (INT32U)0x06060606; /* R6 */ + *pstk-- = (INT32U)0x05050505; /* R5 */ + *pstk-- = (INT32U)p_arg; /* Simulate call to function with argument */ + *pstk-- = (INT32U)0x03030303; /* R3 */ + *pstk-- = (INT32U)0x02020202; /* R2 */ + *pstk-- = (INT32U)0x01010101; /* R1 */ + *pstk-- = (INT32U)0x00000000; /* R0 */ + *pstk-- = (INT32U)0xD1D1D1D1; /* MDH */ + *pstk = (INT32U)0xD0D0D0D0; /* MDL */ + + return ((OS_STK *)pstk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/FR/Softune/os_cpu_i.asm b/Ports/FR/Softune/os_cpu_i.asm new file mode 100644 index 0000000..19068e8 --- /dev/null +++ b/Ports/FR/Softune/os_cpu_i.asm @@ -0,0 +1,42 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Fujitsu FR Port +; +; Filename : os_cpu_i.asm +; Version : V2.93.00 +;******************************************************************************************************** + +;********************************************************************************************************* +; MACROS +;********************************************************************************************************* + +#macro PUSH_ALL + ST RP, @-R15 + STM1 (R8,R9,R10,R11,R12,R13,R14) + STM0 (R0,R1,R2,R3,R4,R5,R6,R7) + ST MDH, @-R15 + ST MDL, @-R15 +#endm + + +#macro POP_ALL + LD @R15+, MDL + LD @R15+, MDH + LDM0 (R7,R6,R5,R4,R3,R2,R1,R0) + LDM1 (R14,R13,R12,R11,R10,R9,R8) + LD @R15+, RP +#endm diff --git a/Ports/FR/Softune/os_dbg.c b/Ports/FR/Softune/os_dbg.c new file mode 100644 index 0000000..ba530ba --- /dev/null +++ b/Ports/FR/Softune/os_dbg.c @@ -0,0 +1,269 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* Fujitsu FR Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_core.c b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_core.c new file mode 100644 index 0000000..1e778b3 --- /dev/null +++ b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_core.c @@ -0,0 +1,969 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* CORE FUNCTIONS +* +* Filename : os_core.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_MASTER_FILE +#define OS_GLOBALS +#include +#endif + +/* +********************************************************************************************************* +* MAPPING TABLE TO MAP BIT POSITION TO BIT MASK +* +* Note: Index into table is desired bit position, 0..7 +* Indexed value corresponds to bit mask +********************************************************************************************************* +*/ + +INT8U const OSMapTbl[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; + +/* +********************************************************************************************************* +* PRIORITY RESOLUTION TABLE +* +* Note: Index into table is bit pattern to resolve highest priority +* Indexed value corresponds to highest priority bit position (i.e. 0..7) +********************************************************************************************************* +*/ + +INT8U const OSUnMapTbl[256] = { + 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F */ + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F */ + 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF */ + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF */ + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */ + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0xF0 to 0xFF */ +}; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ +static void OS_InitMisc(void); +static void OS_InitRdyList(void); +static void OS_InitTaskIdle(void); +#if OS_TASK_STAT_EN > 0 +static void OS_InitTaskStat(void); +#endif +static void OS_InitTCBList(void); + + +/* +********************************************************************************************************* +* INITIALIZATION +* +* Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to +* creating any uC/OS-II object and, prior to calling OSStart(). +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +void OSInit (void) +{ +#if OS_VERSION >= 204 + OSInitHookBegin(); /* Call port specific initialization code */ +#endif + + OS_InitMisc(); /* Initialize miscellaneous variables */ + + OS_InitRdyList(); /* Initialize the Ready List */ + + OS_InitTCBList(); /* Initialize the free list of OS_TCBs */ + + OS_InitTaskIdle(); /* Create the Idle Task */ + +#if OS_TASK_STAT_EN > 0 + OS_InitTaskStat(); /* Create the Statistic Task */ +#endif + +#if OS_VERSION >= 204 + OSInitHookEnd(); /* Call port specific init. code */ +#endif +} + +/* +********************************************************************************************************* +* ENTER ISR +* +* Description: This function is used to notify uC/OS-II that you are about to service an interrupt +* service routine (ISR). This allows uC/OS-II to keep track of interrupt nesting and thus +* only perform rescheduling at the last nested ISR. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function should be called ith interrupts already disabled +* 2) Your ISR can directly increment OSIntNesting without calling this function because +* OSIntNesting has been declared 'global'. +* 3) You MUST still call OSIntExit() even though you increment OSIntNesting directly. +* 4) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call +* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the +* end of the ISR. +* 5) You are allowed to nest interrupts up to 255 levels deep. +* 6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because +* OSIntEnter() is always called with interrupts disabled. +********************************************************************************************************* +*/ + +void OSIntEnter (void) +{ + if (OSRunning == TRUE) { + if (OSIntNesting < 255u) { + OSIntNesting++; /* Increment ISR nesting level */ + } + } +} + +/* +********************************************************************************************************* +* EXIT ISR +* +* Description: This function is used to notify uC/OS-II that you have completed serviving an ISR. When +* the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether +* a new, high-priority task, is ready to run. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call +* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the +* end of the ISR. +* 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock()) +********************************************************************************************************* +*/ + +void OSIntExit (void) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + + + if (OSRunning == TRUE) { + OS_ENTER_CRITICAL(); + if (OSIntNesting > 0) { /* Prevent OSIntNesting from wrapping */ + OSIntNesting--; + } + if (OSIntNesting == 0) { /* Reschedule only if all ISRs complete ... */ + if (OSLockNesting == 0) { /* ... and not locked. */ + OSIntExitY = OSUnMapTbl[OSRdyGrp]; + OSPrioHighRdy = (INT8U)((OSIntExitY << 3) + OSUnMapTbl[OSRdyTbl[OSIntExitY]]); + if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; +#if OS_TASK_PROFILE_EN > 0 + OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ +#endif + OSCtxSwCtr++; /* Keep track of the number of ctx switches */ + OSIntCtxSw(); /* Perform interrupt level ctx switch */ + } + } + } + OS_EXIT_CRITICAL(); + } +} + +/* +********************************************************************************************************* +* START MULTITASKING +* +* Description: This function is used to start the multitasking process which lets uC/OS-II manages the +* task that you have created. Before you can call OSStart(), you MUST have called OSInit() +* and you MUST have created at least one task. +* +* Arguments : none +* +* Returns : none +* +* Note : OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE. +* c) Load the context of the task pointed to by OSTCBHighRdy. +* d_ Execute the task. +********************************************************************************************************* +*/ + +void OSStart (void) +{ + INT8U y; + INT8U x; + + + if (OSRunning == FALSE) { + y = OSUnMapTbl[OSRdyGrp]; /* Find highest priority's task priority number */ + x = OSUnMapTbl[OSRdyTbl[y]]; + OSPrioHighRdy = (INT8U)((y << 3) + x); + OSPrioCur = OSPrioHighRdy; + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */ + OSTCBCur = OSTCBHighRdy; + OSStartHighRdy(); /* Execute target specific code to start task */ + } +} + +/* +********************************************************************************************************* +* STATISTICS INITIALIZATION +* +* Description: This function is called by your application to establish CPU usage by first determining +* how high a 32-bit counter would count to in 1 second if no other tasks were to execute +* during that time. CPU usage is then determined by a low priority task which keeps track +* of this 32-bit counter every second but this time, with other tasks running. CPU usage is +* determined by: +* +* OSIdleCtr +* CPU Usage (%) = 100 * (1 - ------------) +* OSIdleCtrMax +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0 +void OSStatInit (void) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + + + OSTimeDly(2); /* Synchronize with clock tick */ + OS_ENTER_CRITICAL(); + OSIdleCtr = 0L; /* Clear idle counter */ + OS_EXIT_CRITICAL(); + OSTimeDly(OS_TICKS_PER_SEC / 10); /* Determine MAX. idle counter value for 1/10 second */ + OS_ENTER_CRITICAL(); + OSIdleCtrMax = OSIdleCtr; /* Store maximum idle counter count in 1/10 second */ + OSStatRdy = TRUE; + OS_EXIT_CRITICAL(); +} +#endif + +/* +********************************************************************************************************* +* PROCESS SYSTEM TICK +* +* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known +* as a 'clock tick'). This function should be called by the ticker ISR but, can also be +* called by a high priority task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +void OSTimeTick (void) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + OS_TCB *ptcb; + BOOLEAN step; + + +#if OS_TIME_TICK_HOOK_EN > 0 + OSTimeTickHook(); /* Call user definable hook */ +#endif +#if OS_TIME_GET_SET_EN > 0 + OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter */ + OSTime++; + OS_EXIT_CRITICAL(); +#endif + if (OSRunning == TRUE) { + ptcb = OSTCBList; /* Point at first TCB in TCB list */ + while (ptcb->OSTCBPrio != OS_IDLE_PRIO) { /* Go through all TCBs in TCB list */ + OS_ENTER_CRITICAL(); + if (ptcb->OSTCBDly != 0) { /* Delayed or waiting for event with TO */ + if (--ptcb->OSTCBDly == 0) { /* Decrement nbr of ticks to end of delay */ + if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */ + OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make task R-to-R (timed out)*/ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + } else { /* Yes, Leave 1 tick to prevent loosing the ... */ + ptcb->OSTCBDly = 1; /* ... task when the suspension is removed. */ + } + } + } + ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */ + OS_EXIT_CRITICAL(); + } + } +} + +/* +********************************************************************************************************* +* DUMMY FUNCTION +* +* Description: This function doesn't do anything. It is called by OSTaskDel(). +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0 +void OS_Dummy (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE MISCELLANEOUS VARIABLES +* +* Description: This function is called by OSInit() to initialize miscellaneous variables. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitMisc (void) +{ +#if OS_TIME_GET_SET_EN > 0 + OSTime = 0L; /* Clear the 32-bit system clock */ +#endif + + OSTaskCtr = 0; /* Clear the number of tasks */ + + OSRunning = FALSE; /* Indicate that multitasking not started */ + + OSCtxSwCtr = 0; /* Clear the context switch counter */ + OSIdleCtr = 0L; /* Clear the 32-bit idle counter */ + +#if OS_TASK_STAT_EN > 0 + OSIdleCtrRun = 0L; + OSIdleCtrMax = 0L; + OSStatRdy = FALSE; /* Statistic task is not ready */ +#endif +} + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE READY LIST +* +* Description: This function is called by OSInit() to initialize the Ready List. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitRdyList (void) +{ + INT16U i; + INT8U *prdytbl; + + + OSRdyGrp = 0x00; /* Clear the ready list */ + prdytbl = &OSRdyTbl[0]; + for (i = 0; i < OS_RDY_TBL_SIZE; i++) { + *prdytbl++ = 0x00; + } + + OSPrioCur = 0; + OSPrioHighRdy = 0; + + OSTCBHighRdy = (OS_TCB *)0; + OSTCBCur = (OS_TCB *)0; +} + + +/* +********************************************************************************************************* +* INITIALIZATION +* CREATING THE IDLE TASK +* +* Description: This function creates the Idle Task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitTaskIdle (void) +{ +#if OS_TASK_CREATE_EXT_EN > 0 + #if OS_STK_GROWTH == 1 + (void)OSTaskCreateExt(OS_TaskIdle, + (void *)0, /* No arguments passed to OS_TaskIdle() */ + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Top-Of-Stack */ + OS_IDLE_PRIO, /* Lowest priority level */ + OS_TASK_IDLE_ID, + &OSTaskIdleStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_IDLE_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ + #else + (void)OSTaskCreateExt(OS_TaskIdle, + (void *)0, /* No arguments passed to OS_TaskIdle() */ + &OSTaskIdleStk[0], /* Set Top-Of-Stack */ + OS_IDLE_PRIO, /* Lowest priority level */ + OS_TASK_IDLE_ID, + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack */ + OS_TASK_IDLE_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ + #endif +#else + #if OS_STK_GROWTH == 1 + (void)OSTaskCreate(OS_TaskIdle, + (void *)0, + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], + OS_IDLE_PRIO); + #else + (void)OSTaskCreate(OS_TaskIdle, + (void *)0, + &OSTaskIdleStk[0], + OS_IDLE_PRIO); + #endif +#endif +} + +/* +********************************************************************************************************* +* INITIALIZATION +* CREATING THE STATISTIC TASK +* +* Description: This function creates the Statistic Task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0 +static void OS_InitTaskStat (void) +{ +#if OS_TASK_CREATE_EXT_EN > 0 + #if OS_STK_GROWTH == 1 + (void)OSTaskCreateExt(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Top-Of-Stack */ + OS_STAT_PRIO, /* One higher than the idle task */ + OS_TASK_STAT_ID, + &OSTaskStatStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_STAT_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ + #else + (void)OSTaskCreateExt(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[0], /* Set Top-Of-Stack */ + OS_STAT_PRIO, /* One higher than the idle task */ + OS_TASK_STAT_ID, + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Bottom-Of-Stack */ + OS_TASK_STAT_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ + #endif +#else + #if OS_STK_GROWTH == 1 + (void)OSTaskCreate(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1], /* Set Top-Of-Stack */ + OS_STAT_PRIO); /* One higher than the idle task */ + #else + (void)OSTaskCreate(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[0], /* Set Top-Of-Stack */ + OS_STAT_PRIO); /* One higher than the idle task */ + #endif +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS +* +* Description: This function is called by OSInit() to initialize the free list of OS_TCBs. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitTCBList (void) +{ + INT8U i; + OS_TCB *ptcb1; + OS_TCB *ptcb2; + + + OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); /* Clear all the TCBs */ + OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */ + ptcb1 = &OSTCBTbl[0]; + ptcb2 = &OSTCBTbl[1]; + for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) { /* Init. list of free TCBs */ + ptcb1->OSTCBNext = ptcb2; +#if OS_TASK_NAME_SIZE > 1 + ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */ + ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL; +#endif + ptcb1++; + ptcb2++; + } + ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */ +#if OS_TASK_NAME_SIZE > 1 + ptcb1->OSTCBTaskName[0] = '?'; /* Unknown name */ + ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL; +#endif + OSTCBList = (OS_TCB *)0; /* TCB lists initializations */ + OSTCBFreeList = &OSTCBTbl[0]; +} + +/* +********************************************************************************************************* +* CLEAR A SECTION OF MEMORY +* +* Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM. +* +* Arguments : pdest is the start of the RAM to clear (i.e. write 0x00 to) +* +* size is the number of bytes to clear. +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Note that we can only clear up to 64K bytes of RAM. This is not an issue because none +* of the uses of this function gets close to this limit. +* 3) The clear is done one byte at a time since this will work on any processor irrespective +* of the alignment of the destination. +********************************************************************************************************* +*/ + +void OS_MemClr (INT8U *pdest, INT16U size) +{ + while (size > 0) { + *pdest++ = (INT8U)0; + size--; + } +} + +/* +********************************************************************************************************* +* COPY A BLOCK OF MEMORY +* +* Description: This function is called by other uC/OS-II services to copy a block of memory from one +* location to another. +* +* Arguments : pdest is a pointer to the 'destination' memory block +* +* psrc is a pointer to the 'source' memory block +* +* size is the number of bytes to copy. +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. There is +* no provision to handle overlapping memory copy. However, that's not a problem since this +* is not a situation that will happen. +* 2) Note that we can only copy up to 64K bytes of RAM +* 3) The copy is done one byte at a time since this will work on any processor irrespective +* of the alignment of the source and destination. +********************************************************************************************************* +*/ + +void OS_MemCopy (INT8U *pdest, INT8U *psrc, INT16U size) +{ + while (size > 0) { + *pdest++ = *psrc++; + size--; + } +} + +/* +********************************************************************************************************* +* SCHEDULER +* +* Description: This function is called by other uC/OS-II services to determine whether a new, high +* priority task has been made ready to run. This function is invoked by TASK level code +* and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling). +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock()) +********************************************************************************************************* +*/ + +void OS_Sched (void) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + INT8U y; + + + OS_ENTER_CRITICAL(); + if (OSIntNesting == 0) { /* Schedule only if all ISRs done and ... */ + if (OSLockNesting == 0) { /* ... scheduler is not locked */ + y = OSUnMapTbl[OSRdyGrp]; /* Get pointer to HPT ready to run */ + OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); + if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; +#if OS_TASK_PROFILE_EN > 0 + OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ +#endif + OSCtxSwCtr++; /* Increment context switch counter */ + OS_TASK_SW(); /* Perform a context switch */ + } + } + } + OS_EXIT_CRITICAL(); +} + +/* +********************************************************************************************************* +* COPY AN ASCII STRING +* +* Description: This function is called by other uC/OS-II services to copy an ASCII string from a 'source' +* string to a 'destination' string. +* +* Arguments : pdest is a pointer to the string that will be receiving the copy. Note that there MUST +* be sufficient space in the destination storage area to receive this string. +* +* psrc is a pointer to the source string. The source string MUST NOT be greater than +* 254 characters. +* +* Returns : The size of the string (excluding the NUL terminating character) +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +#if (OS_EVENT_NAME_SIZE > 1) || (OS_FLAG_NAME_SIZE > 1) || (OS_MEM_NAME_SIZE > 1) || (OS_TASK_NAME_SIZE > 1) +INT8U OS_StrCopy (char *pdest, char *psrc) +{ + INT8U len; + + + len = 0; + while (*psrc != OS_ASCII_NUL) { + *pdest++ = *psrc++; + len++; + } + *pdest = OS_ASCII_NUL; + return (len); +} +#endif + +/* +********************************************************************************************************* +* DETERMINE THE LENGTH OF AN ASCII STRING +* +* Description: This function is called by other uC/OS-II services to determine the size of an ASCII string +* (excluding the NUL character). +* +* Arguments : psrc is a pointer to the string for which we need to know the size. +* +* Returns : The size of the string (excluding the NUL terminating character) +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) The string to check must be less than 255 characters long. +********************************************************************************************************* +*/ + +#if (OS_EVENT_NAME_SIZE > 1) || (OS_FLAG_NAME_SIZE > 1) || (OS_MEM_NAME_SIZE > 1) || (OS_TASK_NAME_SIZE > 1) +INT8U OS_StrLen (char *psrc) +{ + INT8U len; + + + len = 0; + while (*psrc != OS_ASCII_NUL) { + psrc++; + len++; + } + return (len); +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK +* +* Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks +* executes because they are ALL waiting for event(s) to occur. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be +* enabled for at least a few instructions. On some processors (ex. Philips XA), enabling +* and then disabling interrupts didn't allow the processor enough time to have interrupts +* enabled before they were disabled again. uC/OS-II would thus never recognize +* interrupts. +* 2) This hook has been added to allow you to do such things as STOP the CPU to conserve +* power. +********************************************************************************************************* +*/ + +void OS_TaskIdle (void *parg) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + + + parg = parg; /* Prevent compiler warning for not using 'parg' */ + for (;;) { + OS_ENTER_CRITICAL(); + OSIdleCtr++; + OS_EXIT_CRITICAL(); + OSTaskIdleHook(); /* Call user definable HOOK */ + } +} + +/* +********************************************************************************************************* +* STATISTICS TASK +* +* Description: This task is internal to uC/OS-II and is used to compute some statistics about the +* multitasking environment. Specifically, OS_TaskStat() computes the CPU usage. +* CPU usage is determined by: +* +* OSIdleCtr +* OSCPUUsage = 100 * (1 - ------------) (units are in %) +* OSIdleCtrMax +* +* Arguments : parg this pointer is not used at this time. +* +* Returns : none +* +* Notes : 1) This task runs at a priority level higher than the idle task. In fact, it runs at the +* next higher priority, OS_IDLE_PRIO-1. +* 2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0. +* 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the +* maximum value for the idle counter. +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0 +void OS_TaskStat (void *parg) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + INT32U run; + INT32U max; + INT8S usage; + + + parg = parg; /* Prevent compiler warning for not using 'parg' */ + while (OSStatRdy == FALSE) { + OSTimeDly(2 * OS_TICKS_PER_SEC / 10); /* Wait until statistic task is ready */ + } + max = OSIdleCtrMax / 100L; + for (;;) { + OS_ENTER_CRITICAL(); + OSIdleCtrRun = OSIdleCtr; /* Obtain the of the idle counter for the past second */ + run = OSIdleCtr; + OSIdleCtr = 0L; /* Reset the idle counter for the next second */ + OS_EXIT_CRITICAL(); + if (max > 0L) { + usage = (INT8S)(100L - run / max); + if (usage >= 0) { /* Make sure we don't have a negative percentage */ + OSCPUUsage = usage; + } else { + OSCPUUsage = 0; + } + } else { + OSCPUUsage = 0; + max = OSIdleCtrMax / 100L; + } + OSTaskStatHook(); /* Invoke user definable hook */ +#if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0) + OS_TaskStatStkChk(); /* Check the stacks for each task */ +#endif + OSTimeDly(OS_TICKS_PER_SEC / 10); /* Accumulate OSIdleCtr for the next 1/10 second */ + } +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE TCB +* +* Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when +* a task is created (see OSTaskCreate() and OSTaskCreateExt()). +* +* Arguments : prio is the priority of the task being created +* +* ptos is a pointer to the task's top-of-stack assuming that the CPU registers +* have been placed on the stack. Note that the top-of-stack corresponds to a +* 'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory +* location if OS_STK_GROWTH is set to 0. Note that stack growth is CPU +* specific. +* +* pbos is a pointer to the bottom of stack. A NULL pointer is passed if called by +* 'OSTaskCreate()'. +* +* id is the task's ID (0..65535) +* +* stk_size is the size of the stack (in 'stack units'). If the stack units are INT8Us +* then, 'stk_size' contains the number of bytes for the stack. If the stack +* units are INT32Us then, the stack contains '4 * stk_size' bytes. The stack +* units are established by the #define constant OS_STK which is CPU +* specific. 'stk_size' is 0 if called by 'OSTaskCreate()'. +* +* pext is a pointer to a user supplied memory area that is used to extend the task +* control block. This allows you to store the contents of floating-point +* registers, MMU registers or anything else you could find useful during a +* context switch. You can even assign a name to each task and store this name +* in this TCB extension. A NULL pointer is passed if called by OSTaskCreate(). +* +* opt options as passed to 'OSTaskCreateExt()' or, +* 0 if called from 'OSTaskCreate()'. +* +* Returns : OS_NO_ERR if the call was successful +* OS_NO_MORE_TCB if there are no more free TCBs to be allocated and thus, the task cannot +* be created. +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + OS_TCB *ptcb; + + + OS_ENTER_CRITICAL(); + ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */ + if (ptcb != (OS_TCB *)0) { + OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */ + OS_EXIT_CRITICAL(); + ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */ + ptcb->OSTCBPrio = prio; /* Load task priority into TCB */ + ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */ + ptcb->OSTCBDly = 0; /* Task is not delayed */ + +#if OS_TASK_CREATE_EXT_EN > 0 + ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */ + ptcb->OSTCBStkSize = stk_size; /* Store stack size */ + ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */ + ptcb->OSTCBOpt = opt; /* Store task options */ + ptcb->OSTCBId = id; /* Store task ID */ +#else + pext = pext; /* Prevent compiler warning if not used */ + stk_size = stk_size; + pbos = pbos; + opt = opt; + id = id; +#endif + +#if OS_TASK_DEL_EN > 0 + ptcb->OSTCBDelReq = OS_NO_ERR; +#endif + + ptcb->OSTCBY = (INT8U)(prio >> 3); /* Pre-compute X, Y, BitX and BitY */ + ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY]; + ptcb->OSTCBX = (INT8U)(prio & 0x07); + ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX]; + +#if OS_EVENT_EN > 0 + ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */ +#endif + +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) && (OS_TASK_DEL_EN > 0) + ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */ +#endif + +#if (OS_MBOX_EN > 0) || ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) + ptcb->OSTCBMsg = (void *)0; /* No message received */ +#endif + +#if OS_TASK_PROFILE_EN > 0 + ptcb->OSTCBCtxSwCtr = 0L; /* Initialize profiling variables */ + ptcb->OSTCBCyclesStart = 0L; + ptcb->OSTCBCyclesTot = 0L; + ptcb->OSTCBStkBase = (OS_STK *)0; + ptcb->OSTCBStkUsed = 0L; +#endif + +#if OS_TASK_NAME_SIZE > 1 + ptcb->OSTCBTaskName[0] = '?'; /* Unknown name at task creation */ + ptcb->OSTCBTaskName[1] = OS_ASCII_NUL; +#endif + +#if OS_VERSION >= 204 + OSTCBInitHook(ptcb); +#endif + + OSTaskCreateHook(ptcb); /* Call user defined hook */ + + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = ptcb; + ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ + ptcb->OSTCBPrev = (OS_TCB *)0; + if (OSTCBList != (OS_TCB *)0) { + OSTCBList->OSTCBPrev = ptcb; + } + OSTCBList = ptcb; + OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OS_EXIT_CRITICAL(); + return (OS_NO_ERR); + } + OS_EXIT_CRITICAL(); + return (OS_NO_MORE_TCB); +} diff --git a/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_task.c b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_task.c new file mode 100644 index 0000000..3977543 --- /dev/null +++ b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_task.c @@ -0,0 +1,110 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TASK MANAGEMENT +* +* Filename : os_task.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_MASTER_FILE +#include +#endif + +/* +********************************************************************************************************* +* CREATE A TASK +* +* Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either +* be created prior to the start of multitasking or by a running task. A task cannot be +* created by an ISR. +* +* Arguments : task is a pointer to the task's code +* +* p_arg is a pointer to an optional data area which can be used to pass parameters to +* the task when the task first executes. Where the task is concerned it thinks +* it was invoked and passed the argument 'p_arg' as follows: +* +* void Task (void *p_arg) +* { +* for (;;) { +* Task code; +* } +* } +* +* ptos is a pointer to the task's top of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'pstk' will thus point to the highest (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'pstk' will point to the +* lowest memory location of the stack and the stack will grow with increasing +* memory locations. +* +* prio is the task's priority. A unique priority MUST be assigned to each task and the +* lower the number, the higher the priority. +* +* Returns : OS_NO_ERR if the function was successful. +* OS_PRIO_EXIT if the task priority already exist +* (each task MUST have a unique priority). +* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EN > 0 +INT8U OSTaskCreate (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + OS_STK *psp; + INT8U err; + + +#if OS_ARG_CHK_EN > 0 + if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ + return (OS_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ + OSTCBPrioTbl[prio] = (OS_TCB *)1; /* Reserve the priority to prevent others from doing ... */ + /* ... the same thing until task is created. */ + OS_EXIT_CRITICAL(); + psp = (OS_STK *)OSTaskStkInit(task, p_arg, ptos, 0); /* Initialize the task's stack */ + err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0); + if (err == OS_NO_ERR) { + OS_ENTER_CRITICAL(); + OSTaskCtr++; /* Increment the #tasks counter */ + OS_EXIT_CRITICAL(); + if (OSRunning == TRUE) { /* Find highest priority task if multitasking has started */ + OS_Sched(); + } + } else { + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */ + OS_EXIT_CRITICAL(); + } + return (err); + } + OS_EXIT_CRITICAL(); + return (OS_PRIO_EXIST); +} +#endif diff --git a/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_time.c b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_time.c new file mode 100644 index 0000000..949be5d --- /dev/null +++ b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/os_time.c @@ -0,0 +1,67 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TIME MANAGEMENT +* +* Filename : os_time.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_MASTER_FILE +#include +#endif + +/* +********************************************************************************************************* +* DELAY TASK 'n' TICKS (n from 0 to 65535) +* +* Description: This function is called to delay execution of the currently running task until the +* specified number of system ticks expires. This, of course, directly equates to delaying +* the current task for some time to expire. No delay will result If the specified delay is +* 0. If the specified delay is greater than 0 then, a context switch will result. +* +* Arguments : ticks is the time delay that the task will be suspended in number of clock 'ticks'. +* Note that by specifying 0, the task will not be delayed. +* +* Returns : none +********************************************************************************************************* +*/ + +void OSTimeDly (INT16U ticks) +{ +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + INT8U y; + + + if (ticks > 0) { /* 0 means no delay! */ + OS_ENTER_CRITICAL(); + y = OSTCBCur->OSTCBY; /* Delay current task */ + OSRdyTbl[y] &= ~OSTCBCur->OSTCBBitX; + if (OSRdyTbl[y] == 0) { + OSRdyGrp &= ~OSTCBCur->OSTCBBitY; + } + OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */ + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next task to run! */ + } +} diff --git a/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/ucos_ii.h b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/ucos_ii.h new file mode 100644 index 0000000..7265e78 --- /dev/null +++ b/Ports/H8-300L/H8-38024/EDK38024/uCOS-II/ucos_ii.h @@ -0,0 +1,1297 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : ucos_ii.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_uCOS_II_H +#define OS_uCOS_II_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_VERSION 270u /* Version of uC/OS-II (Vx.yy mult. by 100) */ + +#ifdef OS_GLOBALS +#define OS_EXT +#else +#define OS_EXT extern +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define OS_ASCII_NUL (char)0 + +#define OS_PRIO_SELF 0xFF /* Indicate SELF priority */ + +#if OS_TASK_STAT_EN > 0 +#define OS_N_SYS_TASKS 2 /* Number of system tasks */ +#else +#define OS_N_SYS_TASKS 1 +#endif + +#define OS_STAT_PRIO (OS_LOWEST_PRIO - 1) /* Statistic task priority */ +#define OS_IDLE_PRIO (OS_LOWEST_PRIO) /* IDLE task priority */ + +#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 8 + 1) /* Size of event table */ +#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 8 + 1) /* Size of ready table */ + +#define OS_TASK_IDLE_ID 65535u /* I.D. numbers for Idle and Stat tasks */ +#define OS_TASK_STAT_ID 65534u + +#define OS_EVENT_EN (((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) || (OS_SEM_EN > 0) || (OS_MUTEX_EN > 0)) + + +/* +********************************************************************************************************* +* TASK STATUS (Bit definition for OSTCBStat) +********************************************************************************************************* +*/ +#define OS_STAT_RDY 0x00 /* Ready to run */ +#define OS_STAT_SEM 0x01 /* Pending on semaphore */ +#define OS_STAT_MBOX 0x02 /* Pending on mailbox */ +#define OS_STAT_Q 0x04 /* Pending on queue */ +#define OS_STAT_SUSPEND 0x08 /* Task is suspended */ +#define OS_STAT_MUTEX 0x10 /* Pending on mutual exclusion semaphore */ +#define OS_STAT_FLAG 0x20 /* Pending on event flag group */ + +/* +********************************************************************************************************* +* OS_EVENT types +********************************************************************************************************* +*/ +#define OS_EVENT_TYPE_UNUSED 0 +#define OS_EVENT_TYPE_MBOX 1 +#define OS_EVENT_TYPE_Q 2 +#define OS_EVENT_TYPE_SEM 3 +#define OS_EVENT_TYPE_MUTEX 4 +#define OS_EVENT_TYPE_FLAG 5 + +/* +********************************************************************************************************* +* EVENT FLAGS +********************************************************************************************************* +*/ +#define OS_FLAG_WAIT_CLR_ALL 0 /* Wait for ALL the bits specified to be CLR (i.e. 0) */ +#define OS_FLAG_WAIT_CLR_AND 0 + +#define OS_FLAG_WAIT_CLR_ANY 1 /* Wait for ANY of the bits specified to be CLR (i.e. 0) */ +#define OS_FLAG_WAIT_CLR_OR 1 + +#define OS_FLAG_WAIT_SET_ALL 2 /* Wait for ALL the bits specified to be SET (i.e. 1) */ +#define OS_FLAG_WAIT_SET_AND 2 + +#define OS_FLAG_WAIT_SET_ANY 3 /* Wait for ANY of the bits specified to be SET (i.e. 1) */ +#define OS_FLAG_WAIT_SET_OR 3 + + +#define OS_FLAG_CONSUME 0x80 /* Consume the flags if condition(s) satisfied */ + + +#define OS_FLAG_CLR 0 +#define OS_FLAG_SET 1 + +/* +********************************************************************************************************* +* Values for OSTickStepState +* +* Note(s): This feature is used by uC/OS-View. +********************************************************************************************************* +*/ + +#if OS_TICK_STEP_EN > 0 +#define OS_TICK_STEP_DIS 0 /* Stepping is disabled, tick runs as mormal */ +#define OS_TICK_STEP_WAIT 1 /* Waiting for uC/OS-View to set OSTickStepState to _ONCE */ +#define OS_TICK_STEP_ONCE 2 /* Process tick once and wait for next cmd from uC/OS-View */ +#endif + +/* +********************************************************************************************************* +* Possible values for 'opt' argument of OSSemDel(), OSMboxDel(), OSQDel() and OSMutexDel() +********************************************************************************************************* +*/ +#define OS_DEL_NO_PEND 0 +#define OS_DEL_ALWAYS 1 + +/* +********************************************************************************************************* +* OS???PostOpt() OPTIONS +* +* These #defines are used to establish the options for OSMboxPostOpt() and OSQPostOpt(). +********************************************************************************************************* +*/ +#define OS_POST_OPT_NONE 0x00 /* Post to highest priority task waiting */ +#define OS_POST_OPT_BROADCAST 0x01 /* Broadcast message to ALL tasks waiting */ +#define OS_POST_OPT_FRONT 0x02 /* Post to highest priority task waiting */ + +/* +********************************************************************************************************* +* TASK OPTIONS (see OSTaskCreateExt()) +********************************************************************************************************* +*/ +#define OS_TASK_OPT_STK_CHK 0x0001 /* Enable stack checking for the task */ +#define OS_TASK_OPT_STK_CLR 0x0002 /* Clear the stack when the task is create */ +#define OS_TASK_OPT_SAVE_FP 0x0004 /* Save the contents of any floating-point registers */ + +/* +********************************************************************************************************* +* ERROR CODES +********************************************************************************************************* +*/ +#define OS_NO_ERR 0 + +#define OS_ERR_EVENT_TYPE 1u +#define OS_ERR_PEND_ISR 2u +#define OS_ERR_POST_NULL_PTR 3u +#define OS_ERR_PEVENT_NULL 4u +#define OS_ERR_POST_ISR 5u +#define OS_ERR_QUERY_ISR 6u +#define OS_ERR_INVALID_OPT 7u +#define OS_ERR_TASK_WAITING 8u + +#define OS_TIMEOUT 10u +#define OS_TASK_NOT_EXIST 11u +#define OS_ERR_EVENT_NAME_TOO_LONG 12u +#define OS_ERR_FLAG_NAME_TOO_LONG 13u +#define OS_ERR_TASK_NAME_TOO_LONG 14u +#define OS_ERR_PNAME_NULL 15u + +#define OS_MBOX_FULL 20u + +#define OS_Q_FULL 30u +#define OS_Q_EMPTY 31u + +#define OS_PRIO_EXIST 40u +#define OS_PRIO_ERR 41u +#define OS_PRIO_INVALID 42u + +#define OS_SEM_OVF 50u + +#define OS_TASK_DEL_ERR 60u +#define OS_TASK_DEL_IDLE 61u +#define OS_TASK_DEL_REQ 62u +#define OS_TASK_DEL_ISR 63u + +#define OS_NO_MORE_TCB 70u + +#define OS_TIME_NOT_DLY 80u +#define OS_TIME_INVALID_MINUTES 81u +#define OS_TIME_INVALID_SECONDS 82u +#define OS_TIME_INVALID_MILLI 83u +#define OS_TIME_ZERO_DLY 84u + +#define OS_TASK_SUSPEND_PRIO 90u +#define OS_TASK_SUSPEND_IDLE 91u + +#define OS_TASK_RESUME_PRIO 100u +#define OS_TASK_NOT_SUSPENDED 101u + +#define OS_MEM_INVALID_PART 110u +#define OS_MEM_INVALID_BLKS 111u +#define OS_MEM_INVALID_SIZE 112u +#define OS_MEM_NO_FREE_BLKS 113u +#define OS_MEM_FULL 114u +#define OS_MEM_INVALID_PBLK 115u +#define OS_MEM_INVALID_PMEM 116u +#define OS_MEM_INVALID_PDATA 117u +#define OS_MEM_INVALID_ADDR 118u +#define OS_MEM_NAME_TOO_LONG 119u + +#define OS_ERR_NOT_MUTEX_OWNER 120u + +#define OS_TASK_OPT_ERR 130u + +#define OS_ERR_DEL_ISR 140u +#define OS_ERR_CREATE_ISR 141u + +#define OS_FLAG_INVALID_PGRP 150u +#define OS_FLAG_ERR_WAIT_TYPE 151u +#define OS_FLAG_ERR_NOT_RDY 152u +#define OS_FLAG_INVALID_OPT 153u +#define OS_FLAG_GRP_DEPLETED 154u + + +/* +********************************************************************************************************* +* EVENT CONTROL BLOCK +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +typedef struct os_event { + INT8U OSEventType; /* Type of event control block (see OS_EVENT_TYPE_???) */ + INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ + INT16U OSEventCnt; /* Semaphore Count (not used if other EVENT type) */ + void *OSEventPtr; /* Pointer to message or queue structure */ + INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ +#if OS_EVENT_NAME_SIZE > 1 + char OSEventName[OS_EVENT_NAME_SIZE]; +#endif +} OS_EVENT; +#endif + + +/* +********************************************************************************************************* +* EVENT FLAGS CONTROL BLOCK +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +typedef struct os_flag_grp { /* Event Flag Group */ + INT8U OSFlagType; /* Should be set to OS_EVENT_TYPE_FLAG */ + void *OSFlagWaitList; /* Pointer to first NODE of task waiting on event flag */ + OS_FLAGS OSFlagFlags; /* 8, 16 or 32 bit flags */ +#if OS_FLAG_NAME_SIZE > 1 + char OSFlagName[OS_FLAG_NAME_SIZE]; +#endif +} OS_FLAG_GRP; + + + +typedef struct os_flag_node { /* Event Flag Wait List Node */ + void *OSFlagNodeNext; /* Pointer to next NODE in wait list */ + void *OSFlagNodePrev; /* Pointer to previous NODE in wait list */ + void *OSFlagNodeTCB; /* Pointer to TCB of waiting task */ + void *OSFlagNodeFlagGrp; /* Pointer to Event Flag Group */ + OS_FLAGS OSFlagNodeFlags; /* Event flag to wait on */ + INT8U OSFlagNodeWaitType; /* Type of wait: */ + /* OS_FLAG_WAIT_AND */ + /* OS_FLAG_WAIT_ALL */ + /* OS_FLAG_WAIT_OR */ + /* OS_FLAG_WAIT_ANY */ +} OS_FLAG_NODE; +#endif + + +/* +********************************************************************************************************* +* MESSAGE MAILBOX DATA +********************************************************************************************************* +*/ + +#if OS_MBOX_EN > 0 +typedef struct os_mbox_data { + void *OSMsg; /* Pointer to message in mailbox */ + INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_MBOX_DATA; +#endif + +/* +********************************************************************************************************* +* MEMORY PARTITION DATA STRUCTURES +********************************************************************************************************* +*/ + +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +typedef struct os_mem { /* MEMORY CONTROL BLOCK */ + void *OSMemAddr; /* Pointer to beginning of memory partition */ + void *OSMemFreeList; /* Pointer to list of free memory blocks */ + INT32U OSMemBlkSize; /* Size (in bytes) of each block of memory */ + INT32U OSMemNBlks; /* Total number of blocks in this partition */ + INT32U OSMemNFree; /* Number of memory blocks remaining in this partition */ +#if OS_MEM_NAME_SIZE > 1 + char OSMemName[OS_MEM_NAME_SIZE]; /* Memory partition name */ +#endif +} OS_MEM; + + +typedef struct os_mem_data { + void *OSAddr; /* Pointer to the beginning address of the memory partition */ + void *OSFreeList; /* Pointer to the beginning of the free list of memory blocks */ + INT32U OSBlkSize; /* Size (in bytes) of each memory block */ + INT32U OSNBlks; /* Total number of blocks in the partition */ + INT32U OSNFree; /* Number of memory blocks free */ + INT32U OSNUsed; /* Number of memory blocks used */ +} OS_MEM_DATA; +#endif + + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORE DATA +********************************************************************************************************* +*/ + +#if OS_MUTEX_EN > 0 +typedef struct os_mutex_data { + INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ + INT8U OSValue; /* Mutex value (0 = used, 1 = available) */ + INT8U OSOwnerPrio; /* Mutex owner's task priority or 0xFF if no owner */ + INT8U OSMutexPIP; /* Priority Inheritance Priority or 0xFF if no owner */ +} OS_MUTEX_DATA; +#endif + +/* +********************************************************************************************************* +* MESSAGE QUEUE DATA +********************************************************************************************************* +*/ + +#if OS_Q_EN > 0 +typedef struct os_q { /* QUEUE CONTROL BLOCK */ + struct os_q *OSQPtr; /* Link to next queue control block in list of free blocks */ + void **OSQStart; /* Pointer to start of queue data */ + void **OSQEnd; /* Pointer to end of queue data */ + void **OSQIn; /* Pointer to where next message will be inserted in the Q */ + void **OSQOut; /* Pointer to where next message will be extracted from the Q */ + INT16U OSQSize; /* Size of queue (maximum number of entries) */ + INT16U OSQEntries; /* Current number of entries in the queue */ +} OS_Q; + + +typedef struct os_q_data { + void *OSMsg; /* Pointer to next message to be extracted from queue */ + INT16U OSNMsgs; /* Number of messages in message queue */ + INT16U OSQSize; /* Size of message queue */ + INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_Q_DATA; +#endif + +/* +********************************************************************************************************* +* SEMAPHORE DATA +********************************************************************************************************* +*/ + +#if OS_SEM_EN > 0 +typedef struct os_sem_data { + INT16U OSCnt; /* Semaphore count */ + INT8U OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + INT8U OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_SEM_DATA; +#endif + +/* +********************************************************************************************************* +* TASK STACK DATA +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EXT_EN > 0 +typedef struct os_stk_data { + INT32U OSFree; /* Number of free bytes on the stack */ + INT32U OSUsed; /* Number of bytes used on the stack */ +} OS_STK_DATA; +#endif + + +/* +********************************************************************************************************* +* TASK CONTROL BLOCK +********************************************************************************************************* +*/ + +typedef struct os_tcb { + OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */ + +#if OS_TASK_CREATE_EXT_EN > 0 + void *OSTCBExtPtr; /* Pointer to user definable data for TCB extension */ + OS_STK *OSTCBStkBottom; /* Pointer to bottom of stack */ + INT32U OSTCBStkSize; /* Size of task stack (in number of stack elements) */ + INT16U OSTCBOpt; /* Task options as passed by OSTaskCreateExt() */ + INT16U OSTCBId; /* Task ID (0..65535) */ +#endif + + struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */ + struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */ + +#if OS_EVENT_EN > 0 + OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */ +#endif + +#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0) + void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */ +#endif + +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +#if OS_TASK_DEL_EN > 0 + OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */ +#endif + OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run */ +#endif + + INT16U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event */ + INT8U OSTCBStat; /* Task status */ + INT8U OSTCBPrio; /* Task priority (0 == highest, 63 == lowest) */ + + INT8U OSTCBX; /* Bit position in group corresponding to task priority (0..7) */ + INT8U OSTCBY; /* Index into ready table corresponding to task priority */ + INT8U OSTCBBitX; /* Bit mask to access bit position in ready table */ + INT8U OSTCBBitY; /* Bit mask to access bit position in ready group */ + +#if OS_TASK_DEL_EN > 0 + BOOLEAN OSTCBDelReq; /* Indicates whether a task needs to delete itself */ +#endif + +#if OS_TASK_PROFILE_EN > 0 + INT32U OSTCBCtxSwCtr; /* Number of time the task was switched in */ + INT32U OSTCBCyclesTot; /* Total number of clock cycles the task has been running */ + INT32U OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption */ + OS_STK *OSTCBStkBase; /* Pointer to the beginning of the task stack */ + INT32U OSTCBStkUsed; /* Number of bytes used from the stack */ +#endif + +#if OS_TASK_NAME_SIZE > 1 + char OSTCBTaskName[OS_TASK_NAME_SIZE]; +#endif +} OS_TCB; + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_EXT INT32U OSCtxSwCtr; /* Counter of number of context switches */ + +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_EXT OS_EVENT *OSEventFreeList; /* Pointer to list of free EVENT control blocks */ +OS_EXT OS_EVENT OSEventTbl[OS_MAX_EVENTS];/* Table of EVENT control blocks */ +#endif + +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_EXT OS_FLAG_GRP OSFlagTbl[OS_MAX_FLAGS]; /* Table containing event flag groups */ +OS_EXT OS_FLAG_GRP *OSFlagFreeList; /* Pointer to free list of event flag groups */ +#endif + +#if OS_TASK_STAT_EN > 0 +OS_EXT INT8S OSCPUUsage; /* Percentage of CPU used */ +OS_EXT INT32U OSIdleCtrMax; /* Max. value that idle ctr can take in 1 sec. */ +OS_EXT INT32U OSIdleCtrRun; /* Val. reached by idle ctr at run time in 1 sec. */ +OS_EXT BOOLEAN OSStatRdy; /* Flag indicating that the statistic task is rdy */ +OS_EXT OS_STK OSTaskStatStk[OS_TASK_STAT_STK_SIZE]; /* Statistics task stack */ +#endif + +OS_EXT INT8U OSIntNesting; /* Interrupt nesting level */ +OS_EXT INT8U OSIntExitY; + +OS_EXT INT8U OSLockNesting; /* Multitasking lock nesting level */ + +OS_EXT INT8U OSPrioCur; /* Priority of current task */ +OS_EXT INT8U OSPrioHighRdy; /* Priority of highest priority task */ + +OS_EXT INT8U OSRdyGrp; /* Ready list group */ +OS_EXT INT8U OSRdyTbl[OS_RDY_TBL_SIZE]; /* Table of tasks which are ready to run */ + +OS_EXT BOOLEAN OSRunning; /* Flag indicating that kernel is running */ + +OS_EXT INT8U OSTaskCtr; /* Number of tasks created */ + +OS_EXT volatile INT32U OSIdleCtr; /* Idle counter */ + +OS_EXT OS_STK OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE]; /* Idle task stack */ + + +OS_EXT OS_TCB *OSTCBCur; /* Pointer to currently running TCB */ +OS_EXT OS_TCB *OSTCBFreeList; /* Pointer to list of free TCBs */ +OS_EXT OS_TCB *OSTCBHighRdy; /* Pointer to highest priority TCB R-to-R */ +OS_EXT OS_TCB *OSTCBList; /* Pointer to doubly linked list of TCBs */ +OS_EXT OS_TCB *OSTCBPrioTbl[OS_LOWEST_PRIO + 1];/* Table of pointers to created TCBs */ +OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS]; /* Table of TCBs */ + +#if OS_TICK_STEP_EN > 0 +OS_EXT INT8U OSTickStepState; /* Indicates the state of the tick step feature */ +#endif + +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_EXT OS_MEM *OSMemFreeList; /* Pointer to free list of memory partitions */ +OS_EXT OS_MEM OSMemTbl[OS_MAX_MEM_PART];/* Storage for memory partition manager */ +#endif + +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_EXT OS_Q *OSQFreeList; /* Pointer to list of free QUEUE control blocks */ +OS_EXT OS_Q OSQTbl[OS_MAX_QS]; /* Table of QUEUE control blocks */ +#endif + +#if OS_TIME_GET_SET_EN > 0 +OS_EXT volatile INT32U OSTime; /* Current value of system time (in ticks) */ +#endif + + +extern INT8U const OSMapTbl[8]; /* Priority->Bit Mask lookup table */ +extern INT8U const OSUnMapTbl[256]; /* Priority->Index lookup table */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Target Independent Functions) +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN > 0) && (OS_EVENT_NAME_SIZE > 1) +INT8U OSEventNameGet(OS_EVENT *pevent, char *pname, INT8U *err); +void OSEventNameSet(OS_EVENT *pevent, char *pname, INT8U *err); +#endif + +/* +********************************************************************************************************* +* EVENT FLAGS MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + +#if OS_FLAG_ACCEPT_EN > 0 +OS_FLAGS OSFlagAccept(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT8U *err); +#endif + +OS_FLAG_GRP *OSFlagCreate(OS_FLAGS flags, INT8U *err); + +#if OS_FLAG_DEL_EN > 0 +OS_FLAG_GRP *OSFlagDel(OS_FLAG_GRP *pgrp, INT8U opt, INT8U *err); +#endif + +#if (OS_FLAG_EN > 0) && (OS_FLAG_NAME_SIZE > 1) +INT8U OSFlagNameGet(OS_FLAG_GRP *pgrp, char *pname, INT8U *err); +void OSFlagNameSet(OS_FLAG_GRP *pgrp, char *pname, INT8U *err); +#endif + +OS_FLAGS OSFlagPend(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U wait_type, INT16U timeout, INT8U *err); +OS_FLAGS OSFlagPendGetFlagsRdy(void); +OS_FLAGS OSFlagPost(OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U operation, INT8U *err); + +#if OS_FLAG_QUERY_EN > 0 +OS_FLAGS OSFlagQuery(OS_FLAG_GRP *pgrp, INT8U *err); +#endif +#endif + +/* +********************************************************************************************************* +* MESSAGE MAILBOX MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_MBOX_EN > 0 + +#if OS_MBOX_ACCEPT_EN > 0 +void *OSMboxAccept(OS_EVENT *pevent); +#endif + +OS_EVENT *OSMboxCreate(void *msg); + +#if OS_MBOX_DEL_EN > 0 +OS_EVENT *OSMboxDel(OS_EVENT *pevent, INT8U opt, INT8U *err); +#endif + +void *OSMboxPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); + +#if OS_MBOX_POST_EN > 0 +INT8U OSMboxPost(OS_EVENT *pevent, void *msg); +#endif + +#if OS_MBOX_POST_OPT_EN > 0 +INT8U OSMboxPostOpt(OS_EVENT *pevent, void *msg, INT8U opt); +#endif + +#if OS_MBOX_QUERY_EN > 0 +INT8U OSMboxQuery(OS_EVENT *pevent, OS_MBOX_DATA *p_mbox_data); +#endif +#endif + +/* +********************************************************************************************************* +* MEMORY MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + +OS_MEM *OSMemCreate(void *addr, INT32U nblks, INT32U blksize, INT8U *err); +void *OSMemGet(OS_MEM *pmem, INT8U *err); +#if OS_MEM_NAME_SIZE > 1 +INT8U OSMemNameGet(OS_MEM *pmem, char *pname, INT8U *err); +void OSMemNameSet(OS_MEM *pmem, char *pname, INT8U *err); +#endif +INT8U OSMemPut(OS_MEM *pmem, void *pblk); + +#if OS_MEM_QUERY_EN > 0 +INT8U OSMemQuery(OS_MEM *pmem, OS_MEM_DATA *p_mem_data); +#endif + +#endif + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORE MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_MUTEX_EN > 0 + +#if OS_MUTEX_ACCEPT_EN > 0 +INT8U OSMutexAccept(OS_EVENT *pevent, INT8U *err); +#endif + +OS_EVENT *OSMutexCreate(INT8U prio, INT8U *err); + +#if OS_MUTEX_DEL_EN > 0 +OS_EVENT *OSMutexDel(OS_EVENT *pevent, INT8U opt, INT8U *err); +#endif + +void OSMutexPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); +INT8U OSMutexPost(OS_EVENT *pevent); + +#if OS_MUTEX_QUERY_EN > 0 +INT8U OSMutexQuery(OS_EVENT *pevent, OS_MUTEX_DATA *p_mutex_data); +#endif + +#endif + + +/* +********************************************************************************************************* +* MESSAGE QUEUE MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + +#if OS_Q_ACCEPT_EN > 0 +void *OSQAccept(OS_EVENT *pevent, INT8U *err); +#endif + +OS_EVENT *OSQCreate(void **start, INT16U size); + +#if OS_Q_DEL_EN > 0 +OS_EVENT *OSQDel(OS_EVENT *pevent, INT8U opt, INT8U *err); +#endif + +#if OS_Q_FLUSH_EN > 0 +INT8U OSQFlush(OS_EVENT *pevent); +#endif + +void *OSQPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); + +#if OS_Q_POST_EN > 0 +INT8U OSQPost(OS_EVENT *pevent, void *msg); +#endif + +#if OS_Q_POST_FRONT_EN > 0 +INT8U OSQPostFront(OS_EVENT *pevent, void *msg); +#endif + +#if OS_Q_POST_OPT_EN > 0 +INT8U OSQPostOpt(OS_EVENT *pevent, void *msg, INT8U opt); +#endif + +#if OS_Q_QUERY_EN > 0 +INT8U OSQQuery(OS_EVENT *pevent, OS_Q_DATA *p_q_data); +#endif + +#endif + + +/* +********************************************************************************************************* +* SEMAPHORE MANAGEMENT +********************************************************************************************************* +*/ +#if OS_SEM_EN > 0 + +#if OS_SEM_ACCEPT_EN > 0 +INT16U OSSemAccept(OS_EVENT *pevent); +#endif + +OS_EVENT *OSSemCreate(INT16U cnt); + +#if OS_SEM_DEL_EN > 0 +OS_EVENT *OSSemDel(OS_EVENT *pevent, INT8U opt, INT8U *err); +#endif + +void OSSemPend(OS_EVENT *pevent, INT16U timeout, INT8U *err); +INT8U OSSemPost(OS_EVENT *pevent); + +#if OS_SEM_QUERY_EN > 0 +INT8U OSSemQuery(OS_EVENT *pevent, OS_SEM_DATA *p_sem_data); +#endif + +#endif + + +/* +********************************************************************************************************* +* TASK MANAGEMENT +********************************************************************************************************* +*/ +#if OS_TASK_CHANGE_PRIO_EN > 0 +INT8U OSTaskChangePrio(INT8U oldprio, INT8U newprio); +#endif + +#if OS_TASK_CREATE_EN > 0 +INT8U OSTaskCreate(void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio); +#endif + +#if OS_TASK_CREATE_EXT_EN > 0 +INT8U OSTaskCreateExt(void (*task)(void *pd), + void *p_arg, + OS_STK *ptos, + INT8U prio, + INT16U id, + OS_STK *pbos, + INT32U stk_size, + void *pext, + INT16U opt); +#endif + +#if OS_TASK_DEL_EN > 0 +INT8U OSTaskDel(INT8U prio); +INT8U OSTaskDelReq(INT8U prio); +#endif + +#if OS_TASK_NAME_SIZE > 1 +INT8U OSTaskNameGet(INT8U prio, char *pname, INT8U *err); +void OSTaskNameSet(INT8U prio, char *pname, INT8U *err); +#endif + +#if OS_TASK_SUSPEND_EN > 0 +INT8U OSTaskResume(INT8U prio); +INT8U OSTaskSuspend(INT8U prio); +#endif + +#if OS_TASK_CREATE_EXT_EN > 0 +INT8U OSTaskStkChk(INT8U prio, OS_STK_DATA *p_stk_data); +#endif + +#if OS_TASK_QUERY_EN > 0 +INT8U OSTaskQuery(INT8U prio, OS_TCB *p_task_data); +#endif + + +/* +********************************************************************************************************* +* TIME MANAGEMENT +********************************************************************************************************* +*/ + +void OSTimeDly(INT16U ticks); + +#if OS_TIME_DLY_HMSM_EN > 0 +INT8U OSTimeDlyHMSM(INT8U hours, INT8U minutes, INT8U seconds, INT16U milli); +#endif + +#if OS_TIME_DLY_RESUME_EN > 0 +INT8U OSTimeDlyResume(INT8U prio); +#endif + +#if OS_TIME_GET_SET_EN > 0 +INT32U OSTimeGet(void); +void OSTimeSet(INT32U ticks); +#endif + +void OSTimeTick(void); + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +void OSInit(void); + +void OSIntEnter(void); +void OSIntExit(void); + +#if OS_SCHED_LOCK_EN > 0 +void OSSchedLock(void); +void OSSchedUnlock(void); +#endif + +void OSStart(void); + +void OSStatInit(void); + +INT16U OSVersion(void); + + +/* +********************************************************************************************************* +* INTERNAL FUNCTION PROTOTYPES +* (Your application MUST NOT call these functions) +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0 +void OS_Dummy(void); +#endif + +#if OS_EVENT_EN > 0 +INT8U OS_EventTaskRdy(OS_EVENT *pevent, void *msg, INT8U msk); +void OS_EventTaskWait(OS_EVENT *pevent); +void OS_EventTO(OS_EVENT *pevent); +void OS_EventWaitListInit(OS_EVENT *pevent); +#endif + +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +void OS_FlagInit(void); +void OS_FlagUnlink(OS_FLAG_NODE *pnode); +#endif + +void OS_MemClr(INT8U *pdest, INT16U size); +void OS_MemCopy(INT8U *pdest, INT8U *psrc, INT16U size); + +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +void OS_MemInit(void); +#endif + +#if OS_Q_EN > 0 +void OS_QInit(void); +#endif + +void OS_Sched(void); + +#if (OS_EVENT_NAME_SIZE > 1) || (OS_FLAG_NAME_SIZE > 1) || (OS_MEM_NAME_SIZE > 1) || (OS_TASK_NAME_SIZE > 1) +INT8U OS_StrCopy(char *pdest, char *psrc); +INT8U OS_StrLen(char *psrc); +#endif + +void OS_TaskIdle(void *p_arg); + +#if OS_TASK_STAT_EN > 0 +void OS_TaskStat(void *p_arg); +#endif + +#if OS_TASK_CREATE_EXT_EN > 0 +void OS_TaskStkClr(OS_STK *ptos, INT32U size, INT16U opt); +#endif + +#if (OS_TASK_STAT_STK_CHK_EN > 0) && (OS_TASK_CREATE_EXT_EN > 0) +void OS_TaskStatStkChk(void); +#endif + +INT8U OS_TCBInit(INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt); + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Target Specific Functions) +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit(void); +#endif + +#if OS_VERSION >= 204 +void OSInitHookBegin(void); +void OSInitHookEnd(void); +#endif + +void OSIntCtxSw(void); + +void OSStartHighRdy(void); + +void OSTaskCreateHook(OS_TCB *ptcb); +void OSTaskDelHook(OS_TCB *ptcb); + +#if OS_VERSION >= 251 +void OSTaskIdleHook(void); +#endif + +void OSTaskStatHook(void); +OS_STK *OSTaskStkInit(void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt); + +#if OS_TASK_SW_HOOK_EN > 0 +void OSTaskSwHook(void); +#endif + +#if OS_VERSION >= 204 +void OSTCBInitHook(OS_TCB *ptcb); +#endif + +#if OS_TIME_TICK_HOOK_EN > 0 +void OSTimeTickHook(void); +#endif + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Compiler Specific ISR prototypes) +********************************************************************************************************* +*/ + +#ifndef OS_ISR_PROTO_EXT +void OSCtxSw(void); +void OSTickISR(void); +#endif + + +/* +********************************************************************************************************* +* LOOK FOR MISSING #define CONSTANTS +* +* This section is used to generate ERROR messages at compile time if certain #define constants are +* MISSING in OS_CFG.H. This allows you to quickly determine the source of the error. +* +* You SHOULD NOT change this section UNLESS you would like to add more comments as to the source of the +* compile time error. +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* EVENT FLAGS +********************************************************************************************************* +*/ + +#ifndef OS_FLAG_EN +#error "OS_CFG.H, Missing OS_FLAG_EN: Enable (1) or Disable (0) code generation for Event Flags" +#else + #ifndef OS_MAX_FLAGS + #error "OS_CFG.H, Missing OS_MAX_FLAGS: Max. number of Event Flag Groups in your application" + #else + #if OS_MAX_FLAGS > 255 + #error "OS_CFG.H, OS_MAX_FLAGS must be <= 255" + #endif + #endif + + #ifndef OS_FLAG_WAIT_CLR_EN + #error "OS_CFG.H, Missing OS_FLAG_WAIT_CLR_EN: Include code for Wait on Clear EVENT FLAGS" + #endif + + #ifndef OS_FLAG_ACCEPT_EN + #error "OS_CFG.H, Missing OS_FLAG_ACCEPT_EN: Include code for OSFlagAccept()" + #endif + + #ifndef OS_FLAG_DEL_EN + #error "OS_CFG.H, Missing OS_FLAG_DEL_EN: Include code for OSFlagDel()" + #endif + + #ifndef OS_FLAG_NAME_SIZE + #error "OS_CFG.H, Missing OS_FLAG_NAME_SIZE: Determines the size of flag group names" + #endif + + #ifndef OS_FLAG_QUERY_EN + #error "OS_CFG.H, Missing OS_FLAG_QUERY_EN: Include code for OSFlagQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MESSAGE MAILBOXES +********************************************************************************************************* +*/ + +#ifndef OS_MBOX_EN +#error "OS_CFG.H, Missing OS_MBOX_EN: Enable (1) or Disable (0) code generation for MAILBOXES" +#else + #ifndef OS_MBOX_ACCEPT_EN + #error "OS_CFG.H, Missing OS_MBOX_ACCEPT_EN: Include code for OSMboxAccept()" + #endif + + #ifndef OS_MBOX_DEL_EN + #error "OS_CFG.H, Missing OS_MBOX_DEL_EN: Include code for OSMboxDel()" + #endif + + #ifndef OS_MBOX_POST_EN + #error "OS_CFG.H, Missing OS_MBOX_POST_EN: Include code for OSMboxPost()" + #endif + + #ifndef OS_MBOX_POST_OPT_EN + #error "OS_CFG.H, Missing OS_MBOX_POST_OPT_EN: Include code for OSMboxPostOpt()" + #endif + + #ifndef OS_MBOX_QUERY_EN + #error "OS_CFG.H, Missing OS_MBOX_QUERY_EN: Include code for OSMboxQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MEMORY MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_MEM_EN +#error "OS_CFG.H, Missing OS_MEM_EN: Enable (1) or Disable (0) code generation for MEMORY MANAGER" +#else + #ifndef OS_MAX_MEM_PART + #error "OS_CFG.H, Missing OS_MAX_MEM_PART: Max. number of memory partitions" + #else + #if OS_MAX_MEM_PART > 255 + #error "OS_CFG.H, OS_MAX_MEM_PART must be <= 255" + #endif + #endif + + #ifndef OS_MEM_NAME_SIZE + #error "OS_CFG.H, Missing OS_MEM_NAME_SIZE: Determines the size of memory partition names" + #endif + + #ifndef OS_MEM_QUERY_EN + #error "OS_CFG.H, Missing OS_MEM_QUERY_EN: Include code for OSMemQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORES +********************************************************************************************************* +*/ + +#ifndef OS_MUTEX_EN +#error "OS_CFG.H, Missing OS_MUTEX_EN: Enable (1) or Disable (0) code generation for MUTEX" +#else + #ifndef OS_MUTEX_ACCEPT_EN + #error "OS_CFG.H, Missing OS_MUTEX_ACCEPT_EN: Include code for OSMutexAccept()" + #endif + + #ifndef OS_MUTEX_DEL_EN + #error "OS_CFG.H, Missing OS_MUTEX_DEL_EN: Include code for OSMutexDel()" + #endif + + #ifndef OS_MUTEX_QUERY_EN + #error "OS_CFG.H, Missing OS_MUTEX_QUERY_EN: Include code for OSMutexQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MESSAGE QUEUES +********************************************************************************************************* +*/ + +#ifndef OS_Q_EN +#error "OS_CFG.H, Missing OS_Q_EN: Enable (1) or Disable (0) code generation for QUEUES" +#else + #ifndef OS_MAX_QS + #error "OS_CFG.H, Missing OS_MAX_QS: Max. number of queue control blocks" + #else + #if OS_MAX_QS > 255 + #error "OS_CFG.H, OS_MAX_QS must be <= 255" + #endif + #endif + + #ifndef OS_Q_ACCEPT_EN + #error "OS_CFG.H, Missing OS_Q_ACCEPT_EN: Include code for OSQAccept()" + #endif + + #ifndef OS_Q_DEL_EN + #error "OS_CFG.H, Missing OS_Q_DEL_EN: Include code for OSQDel()" + #endif + + #ifndef OS_Q_FLUSH_EN + #error "OS_CFG.H, Missing OS_Q_FLUSH_EN: Include code for OSQFlush()" + #endif + + #ifndef OS_Q_POST_EN + #error "OS_CFG.H, Missing OS_Q_POST_EN: Include code for OSQPost()" + #endif + + #ifndef OS_Q_POST_FRONT_EN + #error "OS_CFG.H, Missing OS_Q_POST_FRONT_EN: Include code for OSQPostFront()" + #endif + + #ifndef OS_Q_POST_OPT_EN + #error "OS_CFG.H, Missing OS_Q_POST_OPT_EN: Include code for OSQPostOpt()" + #endif + + #ifndef OS_Q_QUERY_EN + #error "OS_CFG.H, Missing OS_Q_QUERY_EN: Include code for OSQQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* SEMAPHORES +********************************************************************************************************* +*/ + +#ifndef OS_SEM_EN +#error "OS_CFG.H, Missing OS_SEM_EN: Enable (1) or Disable (0) code generation for SEMAPHORES" +#else + #ifndef OS_SEM_ACCEPT_EN + #error "OS_CFG.H, Missing OS_SEM_ACCEPT_EN: Include code for OSSemAccept()" + #endif + + #ifndef OS_SEM_DEL_EN + #error "OS_CFG.H, Missing OS_SEM_DEL_EN: Include code for OSSemDel()" + #endif + + #ifndef OS_SEM_QUERY_EN + #error "OS_CFG.H, Missing OS_SEM_QUERY_EN: Include code for OSSemQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* TASK MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_MAX_TASKS +#error "OS_CFG.H, Missing OS_MAX_TASKS: Max. number of tasks in your application" +#else + #if OS_MAX_TASKS < 2 + #error "OS_CFG.H, OS_MAX_TASKS must be >= 2" + #endif + #if OS_MAX_TASKS > 63 + #error "OS_CFG.H, OS_MAX_TASKS must be <= 63" + #endif +#endif + +#ifndef OS_TASK_IDLE_STK_SIZE +#error "OS_CFG.H, Missing OS_TASK_IDLE_STK_SIZE: Idle task stack size" +#endif + +#ifndef OS_TASK_STAT_EN +#error "OS_CFG.H, Missing OS_TASK_STAT_EN: Enable (1) or Disable(0) the statistics task" +#endif + +#ifndef OS_TASK_STAT_STK_SIZE +#error "OS_CFG.H, Missing OS_TASK_STAT_STK_SIZE: Statistics task stack size" +#endif + +#ifndef OS_TASK_STAT_STK_CHK_EN +#error "OS_CFG.H, Missing OS_TASK_STAT_STK_CHK_EN: Check task stacks from statistics task" +#endif + +#ifndef OS_TASK_CHANGE_PRIO_EN +#error "OS_CFG.H, Missing OS_TASK_CHANGE_PRIO_EN: Include code for OSTaskChangePrio()" +#endif + +#ifndef OS_TASK_CREATE_EN +#error "OS_CFG.H, Missing OS_TASK_CREATE_EN: Include code for OSTaskCreate()" +#endif + +#ifndef OS_TASK_CREATE_EXT_EN +#error "OS_CFG.H, Missing OS_TASK_CREATE_EXT_EN: Include code for OSTaskCreateExt()" +#endif + +#ifndef OS_TASK_DEL_EN +#error "OS_CFG.H, Missing OS_TASK_DEL_EN: Include code for OSTaskDel()" +#endif + +#ifndef OS_TASK_NAME_SIZE +#error "OS_CFG.H, Missing OS_TASK_NAME_SIZE: Determine the size of task names" +#endif + +#ifndef OS_TASK_SUSPEND_EN +#error "OS_CFG.H, Missing OS_TASK_SUSPEND_EN: Include code for OSTaskSuspend() and OSTaskResume()" +#endif + +#ifndef OS_TASK_QUERY_EN +#error "OS_CFG.H, Missing OS_TASK_QUERY_EN: Include code for OSTaskQuery()" +#endif + +/* +********************************************************************************************************* +* TIME MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_TICKS_PER_SEC +#error "OS_CFG.H, Missing OS_TICKS_PER_SEC: Sets the number of ticks in one second" +#endif + +#ifndef OS_TIME_DLY_HMSM_EN +#error "OS_CFG.H, Missing OS_TIME_DLY_HMSM_EN: Include code for OSTimeDlyHMSM()" +#endif + +#ifndef OS_TIME_DLY_RESUME_EN +#error "OS_CFG.H, Missing OS_TIME_DLY_RESUME_EN: Include code for OSTimeDlyResume()" +#endif + +#ifndef OS_TIME_GET_SET_EN +#error "OS_CFG.H, Missing OS_TIME_GET_SET_EN: Include code for OSTimeGet() and OSTimeSet()" +#endif + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#ifndef OS_ARG_CHK_EN +#error "OS_CFG.H, Missing OS_ARG_CHK_EN: Enable (1) or Disable (0) argument checking" +#endif + +#ifndef OS_CPU_HOOKS_EN +#error "OS_CFG.H, Missing OS_CPU_HOOKS_EN: uC/OS-II hooks are found in the processor port files when 1" +#endif + +#ifndef OS_LOWEST_PRIO +#error "OS_CFG.H, Missing OS_LOWEST_PRIO: Defines the lowest priority that can be assigned" +#endif + +#ifndef OS_MAX_EVENTS +#error "OS_CFG.H, Missing OS_MAX_EVENTS: Max. number of event control blocks in your application" +#else + #if OS_MAX_EVENTS > 255 + #error "OS_CFG.H, OS_MAX_EVENTS must be <= 255" + #endif +#endif + +#ifndef OS_SCHED_LOCK_EN +#error "OS_CFG.H, Missing OS_SCHED_LOCK_EN: Include code for OSSchedLock() and OSSchedUnlock()" +#endif + +#ifndef OS_TASK_PROFILE_EN +#error "OS_CFG.H, Missing OS_TASK_PROFILE_EN: Include data structure for run-time task profiling" +#endif + +#ifndef OS_TASK_SW_HOOK_EN +#error "OS_CFG.H, Missing OS_TASK_SW_HOOK_EN: Allows you to include the code for OSTaskSwHook() or not" +#endif + +#ifndef OS_TICK_STEP_EN +#error "OS_CFG.H, Missing OS_TICK_STEP_EN: Allows to 'step' one tick at a time with uC/OS-View" +#endif + +#ifndef OS_TIME_TICK_HOOK_EN +#error "OS_CFG.H, Missing OS_TIME_TICK_HOOK_EN: Allows you to include the code for OSTimeTickHook() or not" +#endif + +#ifndef OS_DEBUG_EN +#error "OS_CFG.H, Missing OS_DEBUG_EN: Allows you to include variables for debugging or not" +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Ports/H8-300L/Normal/HEW/os_cpu.h b/Ports/H8-300L/Normal/HEW/os_cpu.h new file mode 100644 index 0000000..c5d1715 --- /dev/null +++ b/Ports/H8-300L/Normal/HEW/os_cpu.h @@ -0,0 +1,135 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8/300 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* CPU Status Register */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Hitachi H8S +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 + +#define OS_ENTER_CRITICAL() set_imask_ccr(1) + +#define OS_EXIT_CRITICAL() set_imask_ccr(0) +#endif + + +#if OS_CRITICAL_METHOD == 2 + +#define OS_ENTER_CRITICAL() cpu_sr = get_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() set_ccr(cpu_sr); +#endif + + +#if OS_CRITICAL_METHOD == 3 + +#define OS_ENTER_CRITICAL() cpu_sr = get_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() set_ccr(cpu_sr); +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/H8-300L/Normal/HEW/os_cpu_a.src b/Ports/H8-300L/Normal/HEW/os_cpu_a.src new file mode 100644 index 0000000..f4f9413 --- /dev/null +++ b/Ports/H8-300L/Normal/HEW/os_cpu_a.src @@ -0,0 +1,289 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8/300 Specific code +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** +;;; caseon ; Make identifier's case significant + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + .EXPORT _OSStartHighRdy ; Public functions + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + .EXPORT _OSTickISR + + .IMPORT _OSIntEnter ; External functions + .IMPORT _OSIntExit + .IMPORT _OSTimeTick + .IMPORT _OSTaskSwHook + + .IMPORT _OSTCBCur ; External variables (uC/OS-II) + .IMPORT _OSTCBHighRdy + .IMPORT _OSPrioCur + .IMPORT _OSPrioHighRdy + .IMPORT _OSIntNesting + .IMPORT _OSRunning + + .IMPORT _Tmr_ISRClr ; Function to clear the timer interrupt + +;******************************************************************************************************** +; Equates +;******************************************************************************************************** + + + +;******************************************************************************************************** +; MACROS +; +; Note(s): 1) Save 16-bit registers in case they were used in the application code. +;******************************************************************************************************** +; + .MACRO PUSHALL + PUSH R0 + PUSH R1 + PUSH R2 + PUSH R3 + PUSH R4 + PUSH R5 + PUSH R6 + .ENDM + + .MACRO POPALL + POP R6 + POP R5 + POP R4 + POP R3 + POP R2 + POP R1 + POP R0 + .ENDM + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> R6 LOW MEMORY +; + 2 R5 +; + 4 R4 +; + 6 R3 +; + 8 R2 +; + 10 R1 +; + 12 R0 +; + 14 CCR (Initial value of 0x0000) +; + 16 task (address of 'task') +; + 18 task (address of 'task') +; + 20 p_arg (contents of 'p_arg') +; HIGH MEMORY +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy: + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @_OSRunning +; + MOV.W @_OSTCBHighRdy, R0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.W R0, @_OSTCBCur + MOV.W @R0, SP +; + POPALL ; Restore task registers +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> PC of task (Lower 16-bits only) +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> R6 +; + 2 R5 +; + 4 R4 +; + 6 R3 +; + 8 R2 +; + 10 R1 +; + 12 R0 +; + 14 CCR +; + 16 PC of task +; HIGH MEMORY +; +; 4) OSCtxSw() is invoked by a JSR instead of a TRAP. Because of this, the CCR is NOT +; placed onto the stack immediately following the return address. The CCR is placed +; on the stack 'manually' by first pushing R0 (to reserve the memory for the CCR) and +; then, moving the CCR to the reserved memory location 'after' pushing all the other +; registers. +;********************************************************************************************************* + +_OSCtxSw: + PUSH R0 ; Reserve space to store CCR (see below) + PUSHALL ; Save processor registers R0 to R6 +; + STC CCR,R0L ; Save CCR onto stack ... + MOV.B R0L,R0H + MOV.W R0,@(14,SP) ; ... into reserved location +; + MOV.W @_OSTCBCur, R6 ; Save current task's SP into its TCB + MOV.W SP, @R6 +; + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B @_OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @_OSPrioCur +; + MOV.W @_OSTCBHighRdy, R6 ; Get new task's SP from its TCB + MOV.W R6, @_OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.W @R6, SP ; SP = OSTCBHighRdy->OSTCBStkPtr +; + POPALL ; Restore processor registers R0 to R6 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; SP + 0 ----> R6 +; + 2 R5 +; + 4 R4 +; + 8 R3 +; + 10 R2 +; + 12 R1 +; + 14 R0 +; + 16 CCR +; + 18 PC of task +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> R6 +; + 2 R5 +; + 4 R4 +; + 8 R3 +; + 10 R2 +; + 12 R1 +; + 14 R0 +; + 16 CCR +; + 18 PC of task +; HIGH MEMORY +;********************************************************************************************************* + +_OSIntCtxSw: + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.W @_OSTCBHighRdy, R6 ; OSTCBCur = OSTCBHighRdy + MOV.W R6, @_OSTCBCur + + MOV.B @_OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @_OSPrioCur +; + MOV.W @R6, SP ; SP = OSTCBCur->OSTCBStkPtr +; + POPALL +; + RTE + + +;********************************************************************************************************* +; TICK ISR +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; Clear the interrupt; Not needed for the timer we used. +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* + +_OSTickISR: + PUSHALL ; Save registers of interrupted task +; + MOV.B @_OSIntNesting, R6L ; OSIntNesting++; + INC.B R6L + MOV.B R6L, @_OSIntNesting +; + CMP.B #1,R6L ; if (OSIntNesting == 1) { + BNE _OSTickISR_1 + + MOV.W @_OSTCBCur, R6 ; Save current task's SP into its TCB + MOV.W SP, @R6 ; +; ; } +; +_OSTickISR_1: +; Clear interrupt! ... Not needed for the Timer we used. +; + JSR @_OSTimeTick ; Tick occurred, call kernel functions +; + JSR @_OSIntExit + +_OSTickISR_2: + POPALL +; + RTE + + .END diff --git a/Ports/H8-300L/Normal/HEW/os_cpu_c.c b/Ports/H8-300L/Normal/HEW/os_cpu_c.c new file mode 100644 index 0000000..81c6d17 --- /dev/null +++ b/Ports/H8-300L/Normal/HEW/os_cpu_c.c @@ -0,0 +1,255 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8/300 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The following simulates the stack for a function called by an exception. The pointer +* to the function argument 'p_arg' is placed in R6 because the HEW compiler passes the +* first argument of a function in this register. If your compiler passes the first +* argument on the stack, load it on the stack like in the original uC/OS-II. +* 2) An INT16U pointer is used because the stack is 16-bit wide stack. +* 3) The H8-300 is a BIG Endian processor +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT16U *)ptos; /* Load stack pointer */ + + /* Simulate call to your task */ + *--pstk = (INT16U)p_arg; /* If 'p_arg' passed on stack */ + *--pstk = (INT16U)task; /* Return address */ + /* Simulate interrupt stacking */ + *--pstk = (INT16U)task; /* PC = Return address to Task */ + *--pstk = (INT16U)0x0000; /* CCR = 0x0000 (Upper and Lower duplicated) */ + *--pstk = (INT16U)p_arg; /* R0 = p_arg */ + *--pstk = (INT16U)0x1111; /* R1 = 0x1111 */ + *--pstk = (INT16U)0x2222; /* R2 = 0x2222 */ + *--pstk = (INT16U)0x3333; /* R3 = 0x3333 */ + *--pstk = (INT16U)0x4444; /* R4 = 0x4444 */ + *--pstk = (INT16U)0x5555; /* R5 = 0x5555 */ + *--pstk = (INT16U)0x6666; /* R6 = 0x6666 */ + /* 'pstk' now points at R6 on stack */ + return ((OS_STK *)pstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/H8-300L/Normal/HEW/os_dbg.c b/Ports/H8-300L/Normal/HEW/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/H8-300L/Normal/HEW/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/H8-300L/Normal/IAR/os_cpu.h b/Ports/H8-300L/Normal/IAR/os_cpu.h new file mode 100644 index 0000000..b349794 --- /dev/null +++ b/Ports/H8-300L/Normal/IAR/os_cpu.h @@ -0,0 +1,137 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8-300 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include /* IAR intrinsic function prototypes */ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* CPU Status Register */ + + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Hitachi H8 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. You MUST +* change the constant in OS_CPU_A.ASM, function OSIntCtxSw() from 10 to 8. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. You MUST change the constant in OS_CPU_A.ASM, function +* OSIntCtxSw() from 8 to 10. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 + +#define OS_ENTER_CRITICAL() __set_imask_ccr(1) + +#define OS_EXIT_CRITICAL() __set_imask_ccr(0) +#endif + + +#if OS_CRITICAL_METHOD == 2 + +#define OS_ENTER_CRITICAL() cpu_sr = __read_ccr(); __or_ccr(0x80) + +#define OS_EXIT_CRITICAL() __write_ccr(cpu_sr); +#endif + + +#if OS_CRITICAL_METHOD == 3 + +#define OS_ENTER_CRITICAL() cpu_sr = __read_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() __write_ccr(cpu_sr); +#endif + + +#define OS_TASK_SW() OSCtxSw() + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/H8-300L/Normal/IAR/os_cpu_a.s37 b/Ports/H8-300L/Normal/IAR/os_cpu_a.s37 new file mode 100644 index 0000000..fd832f6 --- /dev/null +++ b/Ports/H8-300L/Normal/IAR/os_cpu_a.s37 @@ -0,0 +1,288 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8-300 +; +; Filename : os_cpu_a.s37 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + PUBLIC OSStartHighRdy ; Public functions + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + + EXTERN OSIntEnter ; External functions + EXTERN OSIntExit + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + EXTERN OSTCBCur ; External variables (uC/OS-II) + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntNesting + EXTERN OSRunning + + EXTERN Tmr_ISRClr ; Function to clear the timer interrupt + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> R6 LOW MEMORY +; + 2 R5 +; + 4 R4 +; + 6 R3 +; + 8 R2 +; + 10 R1 +; + 12 R0 +; + 14 CCR (Initial value of 0x0000) +; + 16 task (address of 'task') +; + 18 task (address of 'task') +; + 20 p_arg (contents of 'p_arg') +; HIGH MEMORY +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + RSEG CODE(1) + +OSStartHighRdy: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @OSRunning +; + MOV.W @OSTCBHighRdy, R0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.W R0, @OSTCBCur + MOV.W @R0, SP +; + POP R6 + POP R5 + POP R4 + POP R3 + POP R2 + POP R1 + POP R0 +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> PC of task (Lower 16-bits only) +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> R6 +; + 2 R5 +; + 4 R4 +; + 6 R3 +; + 8 R2 +; + 10 R1 +; + 12 R0 +; + 14 CCR +; + 16 PC of task +; HIGH MEMORY +; +; 4) OSCtxSw() is invoked by a JSR instead of a TRAP. Because of this, the CCR is NOT +; placed onto the stack immediately following the return address. The CCR is placed +; on the stack 'manually' by first pushing R0 (to reserve the memory for the CCR) and +; then, moving the CCR to the reserved memory location 'after' pushing all the other +; registers. +;********************************************************************************************************* + +OSCtxSw: + PUSH R0 ; Reserve space for the CCR (see below) + + PUSH R0 + PUSH R1 + PUSH R2 + PUSH R3 + PUSH R4 + PUSH R5 + PUSH R6 +; + STC CCR, R0L ; Save CCR onto stack + MOV.B R0L, R0H + MOV.W R0, @(14,SP) ; into the reserved location + + MOV.W @OSTCBCur, R6 ; Save current task's SP into its TCB + MOV.W ER7, @R6 +; + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.W @OSTCBHighRdy, R6 ; Get new task's SP from its TCB + MOV.W R6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.W @R6, ER7 +; + POP R6 + POP R5 + POP R4 + POP R3 + POP R2 + POP R1 + POP R0 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; SP + 0 ----> R6 +; + 2 R5 +; + 4 R4 +; + 8 R3 +; + 10 R2 +; + 12 R1 +; + 14 R0 +; + 16 CCR +; + 18 PC of task +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> R6 +; + 2 R5 +; + 4 R4 +; + 8 R3 +; + 10 R2 +; + 12 R1 +; + 14 R0 +; + 16 CCR +; + 18 PC of task +; HIGH MEMORY +;********************************************************************************************************* + +OSIntCtxSw: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.W @OSTCBHighRdy, R6 ; Get new task's SP from its TCB + MOV.W R6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy +; + MOV.W @R6, SP +; + POP R6 + POP R5 + POP R4 + POP R3 + POP R2 + POP R1 + POP R0 +; + RTE + + +;********************************************************************************************************* +;* TICK ISR +;* +;* OSTickISR: +;* Push ALL registers onto current task's stack +;* OSIntNesting++; +;* if (OSIntNesting == 1) { +;* OSTCBCur->OSTCBStkPtr = SP; +;* } +;* /* Code to clear interrupt source */ +;* OSTimeTick(); +;* OSIntExit(); +;* Pop ALL registers from current stack; +;* Return from interrupt; +;********************************************************************************************************* + +OSTickISR: + PUSH R0 + PUSH R1 + PUSH R2 + PUSH R3 + PUSH R4 + PUSH R5 + PUSH R6 + + MOV.B @OSIntNesting, R6L ; tell uC/OS-II we're in an ISR + INC.B R6L + MOV.B R6L, @OSIntNesting + + CMP.B #1,R6L ; if (OSNesting == 1) + BNE OSTickISR1 + MOV.W @OSTCBCur, R6 ; Save current task's SP into its TCB + MOV.W SP, @R6 +OSTickISR1: + +; ADD YOUR code HERE to clear the interrupt source! + + JSR @OSTimeTick ; Notify uC/OS-II about Tick + + JSR @OSIntExit ; Notify uC/OS-II about end of ISR + + POP R6 + POP R5 + POP R4 + POP R3 + POP R2 + POP R1 + POP R0 + + RTE + + END diff --git a/Ports/H8-300L/Normal/IAR/os_cpu_c.c b/Ports/H8-300L/Normal/IAR/os_cpu_c.c new file mode 100644 index 0000000..63e6ea9 --- /dev/null +++ b/Ports/H8-300L/Normal/IAR/os_cpu_c.c @@ -0,0 +1,255 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The following simulates the stack for a function called by an exception. The pointer +* to the function argument 'p_arg' is placed in R6 because the IAR compiler passes the +* first argument of a function in this register. If your compiler passes the first +* argument on the stack, load it on the stack like in the original uC/OS. +* 2) An INT16U pointer is used because the SMALL model assumes a 16-bit wide stack. +* 3) The H8 is a BIG Endian processor +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT16U *)ptos; /* Load stack pointer */ + + /* Simulate call to your task */ + *--pstk = (INT16U)p_arg; /* If 'p_arg' passed on stack */ + *--pstk = (INT16U)task; /* Return address */ + /* Simulate interrupt stacking */ + *--pstk = (INT16U)task; /* PC = Return address to Task */ + *--pstk = (INT16U)0x0000; /* CCR = 0x0000 (Upper and Lower duplicated) */ + *--pstk = (INT16U)p_arg; /* R0 = p_arg */ + *--pstk = (INT16U)0x1111; /* R1 = 0x1111 */ + *--pstk = (INT16U)0x2222; /* R2 = 0x2222 */ + *--pstk = (INT16U)0x3333; /* R3 = 0x3333 */ + *--pstk = (INT16U)0x4444; /* R4 = 0x4444 */ + *--pstk = (INT16U)0x5555; /* R5 = 0x5555 */ + *--pstk = (INT16U)0x6666; /* R6 = 0x6666 */ + /* 'pstk' now points at R6 on stack */ + return ((OS_STK *)pstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/H8-300L/Normal/IAR/os_dbg.c b/Ports/H8-300L/Normal/IAR/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/H8-300L/Normal/IAR/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/H8S/Adv/HEW/os_cpu.h b/Ports/H8S/Adv/HEW/os_cpu.h new file mode 100644 index 0000000..d3e9b27 --- /dev/null +++ b/Ports/H8S/Adv/HEW/os_cpu.h @@ -0,0 +1,121 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* 32-bit floating point */ +typedef double FP64; /* 64-bit floating point */ + +typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* CPU Status Register */ + +/* +********************************************************************************************************* +* Hitachi H8S +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 + +#define OS_ENTER_CRITICAL() set_imask_ccr(1) + +#define OS_EXIT_CRITICAL() set_imask_ccr(0) +#endif + + +#if OS_CRITICAL_METHOD == 2 + +#define OS_ENTER_CRITICAL() cpu_sr = get_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() set_ccr(cpu_sr); +#endif + + +#if OS_CRITICAL_METHOD == 3 + +#define OS_ENTER_CRITICAL() cpu_sr = get_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() set_ccr(cpu_sr); +#endif + + +#define OS_TASK_SW() trapa(0) + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/H8S/Adv/HEW/os_cpu_a.src b/Ports/H8S/Adv/HEW/os_cpu_a.src new file mode 100644 index 0000000..ddd3ab9 --- /dev/null +++ b/Ports/H8S/Adv/HEW/os_cpu_a.src @@ -0,0 +1,281 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8S Specific code +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + .EXPORT _OSStartHighRdy ; Public functions + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + .EXPORT _OSTickISR + + .IMPORT _OSIntEnter ; External functions + .IMPORT _OSIntExit + .IMPORT _OSTimeTick + .IMPORT _OSTaskSwHook + + .IMPORT _OSTCBCur ; External variables (uC/OS-II) + .IMPORT _OSTCBHighRdy + .IMPORT _OSPrioCur + .IMPORT _OSPrioHighRdy + .IMPORT _OSIntNesting + .IMPORT _OSRunning + + .IMPORT _TickClr ; Function to clear the timer interrupt + +;******************************************************************************************************** +; Equates +;******************************************************************************************************** + + + +;******************************************************************************************************** +; MACROS +; +; Note(s): 1) Save 32-bit registers in case they were used in the application code. +;******************************************************************************************************** +; + .MACRO PUSHALL + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 + .ENDM + + .MACRO POPALL + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 + .ENDM + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 LOW MEMORY +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 CCR +; + 29 task (24-bit address of 'task') +; + 32 p_arg (contents of 'p_arg') +; HIGH MEMORY +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy: + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @_OSRunning +; + MOV.L @_OSTCBHighRdy, ER0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L #_OSTCBCur, ER1 + MOV.L ER0, @ER1 + MOV.L @ER0, ER7 +; + POPALL ; Restore task registers +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> 8 bit CCR +; + 1 ----> PC of task +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 CCR +; + 29 PC of task (24-bit) +; HIGH MEMORY +; +;********************************************************************************************************* + +_OSCtxSw: + PUSHALL ; Save processor registers R0 to R6 +; + MOV.L @_OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +; + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B @_OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @_OSPrioCur +; + MOV.L @_OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @_OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 ; SP = OSTCBHighRdy->OSTCBStkPtr +; + POPALL ; Restore processor registers R0 to R6 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; SP + 0 Return address of OSIntCtxSw() +; + 4 ER3 saved upon entry by OSIntExit +; + 8 ER2 saved upon entry by OSIntExit +; + 12 Return address of OSIntExit() +; + 16 ER6 +; + 20 ER5 +; + 24 ER4 +; + 28 ER3 +; + 32 ER2 +; + 36 ER1 +; + 40 ER0 +; + 44 CCR +; + 45 PC of task (24-bit) +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 CCR +; + 29 PC of task (24-bit) +; HIGH MEMORY +;********************************************************************************************************* + +_OSIntCtxSw: + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B @_OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @_OSPrioCur +; + MOV.L @_OSTCBHighRdy, ER6 ; OSTCBCur = OSTCBHighRdy + MOV.L ER6, @_OSTCBCur + MOV.L @ER6, ER7 ; SP = OSTCBCur->OSTCBStkPtr +; + POPALL +; + RTE + + +;********************************************************************************************************* +; TICK ISR +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; Clear the interrupt; Not needed for the timer we used. +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* + +_OSTickISR: + PUSHALL ; Save registers of interrupted task +; + MOV.B @_OSIntNesting, R6L ; OSIntNesting++; + INC.B R6L + MOV.B R6L, @_OSIntNesting +; + CMP.B #1,R6L ; if (OSIntNesting == 1) { + BNE _OSTickISR_1 + + MOV.L @_OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 ; +; ; } +; +_OSTickISR_1: + JSR @_TickClr +; + JSR @_OSTimeTick ; Tick occurred, call kernel functions +; + JSR @_OSIntExit + + POPALL +; + RTE + + .END diff --git a/Ports/H8S/Adv/HEW/os_cpu_c.c b/Ports/H8S/Adv/HEW/os_cpu_c.c new file mode 100644 index 0000000..f330622 --- /dev/null +++ b/Ports/H8S/Adv/HEW/os_cpu_c.c @@ -0,0 +1,308 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT32U *)ptos; /* Load stack pointer */ + + /* Simulate call to your task */ + *--stk = (INT32U)pdata; /* If 'p_arg' passed on stack */ + *--stk = (INT32U)task; /* Return address */ + /* Simulate interrupt stacking */ + *--stk = (INT32U)task; /* PC = Return address to Task, CCR is upper 8 bits */ + *--stk = (INT32U)pdata; /* ER0 = p_arg */ + *--stk = (INT32U)0x11111111; /* ER1 = 0x11111111 */ + *--stk = (INT32U)0x22222222; /* ER2 = 0x22222222 */ + *--stk = (INT32U)0x33333333; /* ER3 = 0x33333333 */ + *--stk = (INT32U)0x44444444; /* ER4 = 0x44444444 */ + *--stk = (INT32U)0x55555555; /* ER5 = 0x55555555 */ + *--stk = (INT32U)0x66666666; /* ER6 = 0x66666666 */ + /* 'pstk' now points at R6 on stack */ + return ((OS_STK *)stk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/H8S/Adv/HEW/os_dbg.c b/Ports/H8S/Adv/HEW/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/H8S/Adv/HEW/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/H8S/Adv/IAR/os_cpu.h b/Ports/H8S/Adv/IAR/os_cpu.h new file mode 100644 index 0000000..6b68de6 --- /dev/null +++ b/Ports/H8S/Adv/IAR/os_cpu.h @@ -0,0 +1,125 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR H8 Compiler +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include /* IAR intrinsic function prototypes */ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* CPU Status Register */ + +/* +********************************************************************************************************* +* Hitachi H8S +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. You MUST +* change the constant in OS_CPU_A.ASM, function OSIntCtxSw() from 10 to 8. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. You MUST change the constant in OS_CPU_A.ASM, function +* OSIntCtxSw() from 8 to 10. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 + +#define OS_ENTER_CRITICAL() __set_imask_ccr(1) + +#define OS_EXIT_CRITICAL() __set_imask_ccr(0) +#endif + + +#if OS_CRITICAL_METHOD == 2 + +#define OS_ENTER_CRITICAL() cpu_sr = __read_ccr(); __or_ccr(0x80) + +#define OS_EXIT_CRITICAL() __write_ccr(cpu_sr); +#endif + + +#if OS_CRITICAL_METHOD == 3 + +#define OS_ENTER_CRITICAL() cpu_sr = __read_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() __write_ccr(cpu_sr); +#endif + + +#define OS_TASK_SW() __TRAPA(0) + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/H8S/Adv/IAR/os_cpu_a.asm b/Ports/H8S/Adv/IAR/os_cpu_a.asm new file mode 100644 index 0000000..203a07c --- /dev/null +++ b/Ports/H8S/Adv/IAR/os_cpu_a.asm @@ -0,0 +1,301 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8S +; (Advanced Mode) +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; Compiler : IAR H8 Compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + PUBLIC OSStartHighRdy ; Public functions + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + + EXTERN OSIntEnter ; External functions + EXTERN OSIntExit + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + EXTERN OSTCBCur ; External variables (uC/OS-II) + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntNesting + EXTERN OSRunning + +;******************************************************************************************************** +; Define vector table +;******************************************************************************************************** + + COMMON INTVEC(2) + + ORG 0020H ; Task switching TRAPA0 vector + DC.L OSCtxSw ; (32-bit pointer in ADVANCED mode) + + ORG 0080H ; Timer 0 GRA (Vector 0x0080 on H8S/2623) + DC.L OSTickISR ; (32-bit pointer in ADVANCED mode) + + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 (H) +; + 2 ER6 (L) (Contains 'p_arg') +; + 4 ER5 (H) +; + 6 ER5 (L) +; + 8 ER4 (H) +; + 10 ER4 (L) +; + 12 ER3 (H) +; + 14 ER3 (L) +; + 16 ER2 (H) +; + 18 ER2 (L) +; + 20 ER1 (H) +; + 22 ER1 (L) +; + 24 ER0 (H) +; + 26 ER0 (L) +; + 28 CCR (Initial value of 0x0000) +; + 30 task (16-bit address of 'task') +; + 32 task (16-bit address of 'task') +; + 34 p_arg (16-bit contents of 'p_arg') +; HIGH MEMORY +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + RSEG CODE(1) + +OSStartHighRdy: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @OSRunning +; + MOV.L @OSTCBHighRdy, ER0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L ER0, @OSTCBCur + MOV.L @ER0, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> 8-bit CCR +; + 1 24-bit PC of task +; + 4 +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSCtxSw: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 +; + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +; + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; + 0 Return address of OSIntCtxSw() +; + 4 ER3 saved upon entry by OSIntExit +; + 8 ER2 saved upon entry by OSIntExit +; + 12 Return address of OSIntExit() +; OSTCBCur->OSTCBStkPtr -----> + 16 ER6 +; + 20 ER5 +; + 24 ER4 +; + 28 ER3 +; + 32 ER2 +; + 36 ER1 +; + 40 ER0 +; + 44 8-bit CCR & 24-bit PC of task +; + 48 HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr -> + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSIntCtxSw: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +;* TICK ISR +;* +;* OSTickISR: +;* Push ALL registers onto current task's stack +;* OSIntNesting++; +;* if (OSIntNesting == 1) { +;* OSTCBCur->OSTCBStkPtr = SP; +;* } +;* /* Code to clear interrupt source */ +;* OSTimeTick(); +;* OSIntExit(); +;* Pop ALL registers from current stack; +;* Return from interrupt; +;********************************************************************************************************* + +OSTickISR: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 + + MOV.B @OSIntNesting, R6L ; tell uC/OS-II we're in an ISR + INC.B R6L + MOV.B R6L, @OSIntNesting + + CMP.B #1,R6L ; if (OSNesting == 1) + BNE OSTickISR1 + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +OSTickISR1: + +; ADD YOUR code HERE to clear the interrupt source! + + JSR @OSTimeTick ; Notify uC/OS-II about Tick + + JSR @OSIntExit ; Notify uC/OS-II about end of ISR + + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 + + RTE + + END diff --git a/Ports/H8S/Adv/IAR/os_cpu_a.s37 b/Ports/H8S/Adv/IAR/os_cpu_a.s37 new file mode 100644 index 0000000..da7bc0b --- /dev/null +++ b/Ports/H8S/Adv/IAR/os_cpu_a.s37 @@ -0,0 +1,301 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8S +; (Advanced Mode) +; +; Filename : os_cpu_a.s37 +; Version : V2.93.00 +;******************************************************************************************************** +; Compiler : IAR H8 Compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + PUBLIC OSStartHighRdy ; Public functions + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + + EXTERN OSIntEnter ; External functions + EXTERN OSIntExit + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + EXTERN OSTCBCur ; External variables (uC/OS-II) + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntNesting + EXTERN OSRunning + +;******************************************************************************************************** +; Define vector table +;******************************************************************************************************** + + COMMON INTVEC(2) + + ORG 0020H ; Task switching TRAPA0 vector + DC.L OSCtxSw ; (32-bit pointer in ADVANCED mode) + + ORG 0080H ; Timer 0 GRA (Vector 0x0080 on H8S/2623) + DC.L OSTickISR ; (32-bit pointer in ADVANCED mode) + + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 (H) +; + 2 ER6 (L) (Contains 'p_arg') +; + 4 ER5 (H) +; + 6 ER5 (L) +; + 8 ER4 (H) +; + 10 ER4 (L) +; + 12 ER3 (H) +; + 14 ER3 (L) +; + 16 ER2 (H) +; + 18 ER2 (L) +; + 20 ER1 (H) +; + 22 ER1 (L) +; + 24 ER0 (H) +; + 26 ER0 (L) +; + 28 CCR (Initial value of 0x0000) +; + 30 task (16-bit address of 'task') +; + 32 task (16-bit address of 'task') +; + 34 p_arg (16-bit contents of 'p_arg') +; HIGH MEMORY +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + RSEG CODE(1) + +OSStartHighRdy: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @OSRunning +; + MOV.L @OSTCBHighRdy, ER0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L ER0, @OSTCBCur + MOV.L @ER0, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> 8-bit CCR +; + 1 24-bit PC of task +; + 4 +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSCtxSw: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 +; + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +; + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; + 0 Return address of OSIntCtxSw() +; + 4 ER3 saved upon entry by OSIntExit +; + 8 ER2 saved upon entry by OSIntExit +; + 12 Return address of OSIntExit() +; OSTCBCur->OSTCBStkPtr -----> + 16 ER6 +; + 20 ER5 +; + 24 ER4 +; + 28 ER3 +; + 32 ER2 +; + 36 ER1 +; + 40 ER0 +; + 44 8-bit CCR & 24-bit PC of task +; + 48 HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr -> + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSIntCtxSw: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +;* TICK ISR +;* +;* OSTickISR: +;* Push ALL registers onto current task's stack +;* OSIntNesting++; +;* if (OSIntNesting == 1) { +;* OSTCBCur->OSTCBStkPtr = SP; +;* } +;* /* Code to clear interrupt source */ +;* OSTimeTick(); +;* OSIntExit(); +;* Pop ALL registers from current stack; +;* Return from interrupt; +;********************************************************************************************************* + +OSTickISR: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 + + MOV.B @OSIntNesting, R6L ; tell uC/OS-II we're in an ISR + INC.B R6L + MOV.B R6L, @OSIntNesting + + CMP.B #1,R6L ; if (OSNesting == 1) + BNE OSTickISR1 + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +OSTickISR1: + +; ADD YOUR code HERE to clear the interrupt source! + + JSR @OSTimeTick ; Notify uC/OS-II about Tick + + JSR @OSIntExit ; Notify uC/OS-II about end of ISR + + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 + + RTE + + END diff --git a/Ports/H8S/Adv/IAR/os_cpu_c.c b/Ports/H8S/Adv/IAR/os_cpu_c.c new file mode 100644 index 0000000..f1e57c5 --- /dev/null +++ b/Ports/H8S/Adv/IAR/os_cpu_c.c @@ -0,0 +1,258 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR H8 Compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The following simulates the stack for a function called by an exception. The pointer +* to the function argument 'p_arg' is placed in R6 because the IAR compiler passes the +* first argument of a function in this register. If your compiler passes the first +* argument on the stack, load it on the stack like in the original uC/OS. +* 2) An INT16U pointer is used because the SMALL model assumes a 16-bit wide stack. +* 3) The H8 is a BIG Endian processor +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT32U *)ptos; /* Load stack pointer */ + + /* Simulate call to your task */ + *--pstk = (INT32U)p_arg; /* If 'p_arg' passed on stack */ + *--pstk = (INT32U)task; /* Return address */ + /* Simulate interrupt stacking */ + *--pstk = (INT32U)task; /* Advanced Mode: 32-Bit program counter */ + /* Simulate ISR Entry saving all registers */ + *--pstk = (INT32U)0x00000000; /* ER0 = 0x00000000 */ + *--pstk = (INT32U)0x11111111; /* ER1 = 0x11111111 */ + *--pstk = (INT32U)0x22222222; /* ER2 = 0x22222222 */ + *--pstk = (INT32U)0x33333333; /* ER3 = 0x33333333 */ + *--pstk = (INT32U)0x44444444; /* ER4 = 0x44444444 */ + *--pstk = (INT32U)0x55555555; /* ER5 = 0x55555555 */ + *--pstk = (INT32U)0x66666666; /* ER6 = 0x66666666 */ + /* 'pstk' now points at R6 on stack */ + return ((OS_STK *)pstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/H8S/Adv/IAR/os_dbg.c b/Ports/H8S/Adv/IAR/os_dbg.c new file mode 100644 index 0000000..adbc2c4 --- /dev/null +++ b/Ports/H8S/Adv/IAR/os_dbg.c @@ -0,0 +1,271 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR H8 Compiler +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #ff 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu.h b/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu.h new file mode 100644 index 0000000..9cd78c0 --- /dev/null +++ b/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu.h @@ -0,0 +1,115 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR H8 Compiler +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include /* IAR intrinsic function prototypes */ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* CPU Status Register */ + +/* +********************************************************************************************************* +* Hitachi H8S +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. You MUST +* change the constant in OS_CPU_A.ASM, function OSIntCtxSw() from 10 to 8. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. You MUST change the constant in OS_CPU_A.ASM, function +* OSIntCtxSw() from 8 to 10. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() \ + set_imask_ccr(1); + + +#define OS_EXIT_CRITICAL() \ + set_imask_ccr(0); +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() \ + cpu_sr = get_ccr(); \ + or_ccr(0x80); + + +#define OS_EXIT_CRITICAL() \ + set_ccr(cpu_sr); +#endif + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() \ + cpu_sr = get_ccr(); \ + or_ccr(0x80); + + +#define OS_EXIT_CRITICAL() \ + set_ccr(cpu_sr); +#endif + + +#define OS_TASK_SW() trapa(0) + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ diff --git a/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_a.s37 b/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_a.s37 new file mode 100644 index 0000000..da7f28f --- /dev/null +++ b/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_a.s37 @@ -0,0 +1,337 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8S +; (Advanced Mode) +; +; Filename : os_cpu_a.s37 +; Version : V2.93.00 +;******************************************************************************************************** +; Compiler : IAR H8 Compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + PUBLIC OSStartHighRdy ; Public functions + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + PUBLIC OSCPUSaveSR + PUBLIC OSCPURestoreSR + + EXTERN OSIntEnter ; External functions + EXTERN OSIntExit + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + EXTERN OSTCBCur ; External variables (uC/OS-II) + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntNesting + EXTERN OSRunning + +;******************************************************************************************************** +; Define vector table +;******************************************************************************************************** + + COMMON INTVEC(2) + + ORG 0020H ; Task switching TRAPA0 vector + DC.L OSCtxSw ; (32-bit pointer in ADVANCED mode) + + ORG 0080H ; Timer 0 GRA (Vector 0x0080 on H8S/2623) + DC.L OSTickISR ; (32-bit pointer in ADVANCED mode) + + + +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the R0L register as expected by the +; compiler. +;******************************************************************************************************** + +OSCPUSaveSR: + STC CCR, R0L ; Save CCR in R0L + ORC #H'80, CCR ; Disable interrupts + RTS + +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the CCR to restore. It is assumed that this 'argument' is +; passed in the R0L register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** + +OSCPURestoreSR: + LDC R0L, CCR + RTS + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 (H) +; + 2 ER6 (L) (Contains 'p_arg') +; + 4 ER5 (H) +; + 6 ER5 (L) +; + 8 ER4 (H) +; + 10 ER4 (L) +; + 12 ER3 (H) +; + 14 ER3 (L) +; + 16 ER2 (H) +; + 18 ER2 (L) +; + 20 ER1 (H) +; + 22 ER1 (L) +; + 24 ER0 (H) +; + 26 ER0 (L) +; + 28 CCR (Initial value of 0x0000) +; + 30 task (16-bit address of 'task') +; + 32 task (16-bit address of 'task') +; + 34 p_arg (16-bit contents of 'p_arg') +; HIGH MEMORY +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + RSEG CODE(1) + +OSStartHighRdy: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @OSRunning +; + MOV.L @OSTCBHighRdy, ER0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L ER0, @OSTCBCur + MOV.L @ER0, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> 8-bit CCR +; + 1 24-bit PC of task +; + 4 +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSCtxSw: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 +; + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +; + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; + 0 Return address of OSIntCtxSw() +; + 4 ER3 saved upon entry by OSIntExit +; + 8 ER2 saved upon entry by OSIntExit +; + 12 Return address of OSIntExit() +; OSTCBCur->OSTCBStkPtr -----> + 16 ER6 +; + 20 ER5 +; + 24 ER4 +; + 28 ER3 +; + 32 ER2 +; + 36 ER1 +; + 40 ER0 +; + 44 8-bit CCR & 24-bit PC of task +; + 48 HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr -> + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSIntCtxSw: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +;* TICK ISR +;* +;* OSTickISR: +;* Push ALL registers onto current task's stack +;* OSIntNesting++; +;* if (OSIntNesting == 1) { +;* OSTCBCur->OSTCBStkPtr = SP; +;* } +;* /* Code to clear interrupt source */ +;* OSTimeTick(); +;* OSIntExit(); +;* Pop ALL registers from current stack; +;* Return from interrupt; +;********************************************************************************************************* + +OSTickISR: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 + + MOV.B @OSIntNesting, R6L ; tell uC/OS-II we're in an ISR + INC.B R6L + MOV.B R6L, @OSIntNesting + + CMP.B #1,R6L ; if (OSNesting == 1) + BNE OSTickISR1 + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +OSTickISR1: + +; ADD YOUR code HERE to clear the interrupt source! + + JSR @OSTimeTick ; Notify uC/OS-II about Tick + + JSR @OSIntExit ; Notify uC/OS-II about end of ISR + + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 + + RTE + + END diff --git a/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_c.c b/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_c.c new file mode 100644 index 0000000..f1e57c5 --- /dev/null +++ b/Ports/H8S/H8S-26xx/Adv/IAR/os_cpu_c.c @@ -0,0 +1,258 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR H8 Compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The following simulates the stack for a function called by an exception. The pointer +* to the function argument 'p_arg' is placed in R6 because the IAR compiler passes the +* first argument of a function in this register. If your compiler passes the first +* argument on the stack, load it on the stack like in the original uC/OS. +* 2) An INT16U pointer is used because the SMALL model assumes a 16-bit wide stack. +* 3) The H8 is a BIG Endian processor +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT32U *)ptos; /* Load stack pointer */ + + /* Simulate call to your task */ + *--pstk = (INT32U)p_arg; /* If 'p_arg' passed on stack */ + *--pstk = (INT32U)task; /* Return address */ + /* Simulate interrupt stacking */ + *--pstk = (INT32U)task; /* Advanced Mode: 32-Bit program counter */ + /* Simulate ISR Entry saving all registers */ + *--pstk = (INT32U)0x00000000; /* ER0 = 0x00000000 */ + *--pstk = (INT32U)0x11111111; /* ER1 = 0x11111111 */ + *--pstk = (INT32U)0x22222222; /* ER2 = 0x22222222 */ + *--pstk = (INT32U)0x33333333; /* ER3 = 0x33333333 */ + *--pstk = (INT32U)0x44444444; /* ER4 = 0x44444444 */ + *--pstk = (INT32U)0x55555555; /* ER5 = 0x55555555 */ + *--pstk = (INT32U)0x66666666; /* ER6 = 0x66666666 */ + /* 'pstk' now points at R6 on stack */ + return ((OS_STK *)pstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/H8S/H8S-26xx/Adv/IAR/os_dbg.c b/Ports/H8S/H8S-26xx/Adv/IAR/os_dbg.c new file mode 100644 index 0000000..adbc2c4 --- /dev/null +++ b/Ports/H8S/H8S-26xx/Adv/IAR/os_dbg.c @@ -0,0 +1,271 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR H8 Compiler +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #ff 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/H8SX/Adv/HEW/os_cpu.h b/Ports/H8SX/Adv/HEW/os_cpu.h new file mode 100644 index 0000000..22a3554 --- /dev/null +++ b/Ports/H8SX/Adv/HEW/os_cpu.h @@ -0,0 +1,121 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8SX Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* 32-bit floating point */ +typedef double FP64; /* 64-bit floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 24-bit wide (32-bit) */ +typedef unsigned char OS_CPU_SR; /* CPU Status Register */ + +/* +********************************************************************************************************* +* Hitachi H8SX +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 + +#define OS_ENTER_CRITICAL() set_imask_ccr(1) + +#define OS_EXIT_CRITICAL() set_imask_ccr(0) +#endif + + +#if OS_CRITICAL_METHOD == 2 + +#define OS_ENTER_CRITICAL() cpu_sr = get_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() set_ccr(cpu_sr); +#endif + + +#if OS_CRITICAL_METHOD == 3 + +#define OS_ENTER_CRITICAL() cpu_sr = get_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() set_ccr(cpu_sr); +#endif + + +#define OS_TASK_SW() trapa(0) + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/H8SX/Adv/HEW/os_cpu_a.src b/Ports/H8SX/Adv/HEW/os_cpu_a.src new file mode 100644 index 0000000..46af036 --- /dev/null +++ b/Ports/H8SX/Adv/HEW/os_cpu_a.src @@ -0,0 +1,281 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8SX Specific code +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + .EXPORT _OSStartHighRdy ; Public functions + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + .EXPORT _OSTickISR + + .IMPORT _OSIntEnter ; External functions + .IMPORT _OSIntExit + .IMPORT _OSTimeTick + .IMPORT _OSTaskSwHook + + .IMPORT _OSTCBCur ; External variables (uC/OS-II) + .IMPORT _OSTCBHighRdy + .IMPORT _OSPrioCur + .IMPORT _OSPrioHighRdy + .IMPORT _OSIntNesting + .IMPORT _OSRunning + + .IMPORT _TickClr ; Function to clear the timer interrupt + +;******************************************************************************************************** +; Equates +;******************************************************************************************************** + + + +;******************************************************************************************************** +; MACROS +; +; Note(s): 1) Save 32-bit registers in case they were used in the application code. +;******************************************************************************************************** +; + .MACRO PUSHALL + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 + .ENDM + + .MACRO POPALL + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 + .ENDM + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 LOW MEMORY +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 CCR +; + 29 task (24-bit address of 'task') +; + 32 p_arg (contents of 'p_arg') +; HIGH MEMORY +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy: + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @_OSRunning +; + MOV.L @_OSTCBHighRdy, ER0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L #_OSTCBCur, ER1 + MOV.L ER0, @ER1 + MOV.L @ER0, ER7 +; + POPALL ; Restore task registers +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> 8 bit CCR +; + 1 ----> PC of task +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 CCR +; + 29 PC of task (24-bit) +; HIGH MEMORY +; +;********************************************************************************************************* + +_OSCtxSw: + PUSHALL ; Save processor registers R0 to R6 +; + MOV.L @_OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +; + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B @_OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @_OSPrioCur +; + MOV.L @_OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @_OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 ; SP = OSTCBHighRdy->OSTCBStkPtr +; + POPALL ; Restore processor registers R0 to R6 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; SP + 0 Return address of OSIntCtxSw() +; + 4 ER3 saved upon entry by OSIntExit +; + 8 ER2 saved upon entry by OSIntExit +; + 12 Return address of OSIntExit() +; + 16 ER6 +; + 20 ER5 +; + 24 ER4 +; + 28 ER3 +; + 32 ER2 +; + 36 ER1 +; + 40 ER0 +; + 44 CCR +; + 45 PC of task (24-bit) +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 CCR +; + 29 PC of task (24-bit) +; HIGH MEMORY +;********************************************************************************************************* + +_OSIntCtxSw: + JSR @_OSTaskSwHook ; Execute task switch hook +; + MOV.B @_OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @_OSPrioCur +; + MOV.L @_OSTCBHighRdy, ER6 ; OSTCBCur = OSTCBHighRdy + MOV.L ER6, @_OSTCBCur + MOV.L @ER6, ER7 ; SP = OSTCBCur->OSTCBStkPtr +; + POPALL +; + RTE + + +;********************************************************************************************************* +; TICK ISR +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; Save all registers on the current task's stack; +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; Clear the interrupt; Not needed for the timer we used. +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; OSIntExit(); Notify uC/OS-II about end of ISR +; Restore all registers that were save on the current task's stack; +; Return from Interrupt; +;********************************************************************************************************* + +_OSTickISR: + PUSHALL ; Save registers of interrupted task +; + MOV.B @_OSIntNesting, R6L ; OSIntNesting++; + INC.B R6L + MOV.B R6L, @_OSIntNesting +; + CMP.B #1,R6L ; if (OSIntNesting == 1) { + BNE _OSTickISR_1 + + MOV.L @_OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 ; +; ; } +; +_OSTickISR_1: + JSR @_TickClr +; + JSR @_OSTimeTick ; Tick occurred, call kernel functions +; + JSR @_OSIntExit + + POPALL +; + RTE + + .END diff --git a/Ports/H8SX/Adv/HEW/os_cpu_c.c b/Ports/H8SX/Adv/HEW/os_cpu_c.c new file mode 100644 index 0000000..2a8e26f --- /dev/null +++ b/Ports/H8SX/Adv/HEW/os_cpu_c.c @@ -0,0 +1,308 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8SX Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *stk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT32U *)ptos; /* Load stack pointer */ + + /* Simulate call to your task */ + *--stk = (INT32U)pdata; /* If 'p_arg' passed on stack */ + *--stk = (INT32U)task; /* Return address */ + /* Simulate interrupt stacking */ + *--stk = (INT32U)task; /* PC = Return address to Task, CCR is upper 8 bits */ + *--stk = (INT32U)pdata; /* ER0 = p_arg */ + *--stk = (INT32U)0x11111111; /* ER1 = 0x11111111 */ + *--stk = (INT32U)0x22222222; /* ER2 = 0x22222222 */ + *--stk = (INT32U)0x33333333; /* ER3 = 0x33333333 */ + *--stk = (INT32U)0x44444444; /* ER4 = 0x44444444 */ + *--stk = (INT32U)0x55555555; /* ER5 = 0x55555555 */ + *--stk = (INT32U)0x66666666; /* ER6 = 0x66666666 */ + /* 'pstk' now points at R6 on stack */ + return ((OS_STK *)stk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/H8SX/Adv/HEW/os_dbg.c b/Ports/H8SX/Adv/HEW/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/H8SX/Adv/HEW/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/H8SX/Adv/IAR/os_cpu.h b/Ports/H8SX/Adv/IAR/os_cpu.h new file mode 100644 index 0000000..bb39cef --- /dev/null +++ b/Ports/H8SX/Adv/IAR/os_cpu.h @@ -0,0 +1,125 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include /* IAR intrinsic function prototypes */ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 24-bit wide (32 bits) */ +typedef unsigned char OS_CPU_SR; /* CPU Status Register */ + +/* +********************************************************************************************************* +* Hitachi H8S +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. You MUST +* change the constant in OS_CPU_A.ASM, function OSIntCtxSw() from 10 to 8. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. You MUST change the constant in OS_CPU_A.ASM, function +* OSIntCtxSw() from 8 to 10. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 + +#define OS_ENTER_CRITICAL() __set_imask_ccr(1) + +#define OS_EXIT_CRITICAL() __set_imask_ccr(0) +#endif + + +#if OS_CRITICAL_METHOD == 2 + +#define OS_ENTER_CRITICAL() cpu_sr = __read_ccr(); __or_ccr(0x80) + +#define OS_EXIT_CRITICAL() __write_ccr(cpu_sr); +#endif + + +#if OS_CRITICAL_METHOD == 3 + +#define OS_ENTER_CRITICAL() cpu_sr = __read_ccr(); or_ccr(0x80) + +#define OS_EXIT_CRITICAL() __write_ccr(cpu_sr); +#endif + + +#define OS_TASK_SW() __TRAPA(0) + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/H8SX/Adv/IAR/os_cpu_a.s37 b/Ports/H8SX/Adv/IAR/os_cpu_a.s37 new file mode 100644 index 0000000..93a0797 --- /dev/null +++ b/Ports/H8SX/Adv/IAR/os_cpu_a.s37 @@ -0,0 +1,299 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; H8SX +; (Advanced Mode) +; +; Filename : os_cpu_a.s37 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; Cross references +;******************************************************************************************************** +; + PUBLIC OSStartHighRdy ; Public functions + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + + EXTERN TickClr ; Implement function to clear your tick source + EXTERN OSIntEnter ; External functions + EXTERN OSIntExit + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + EXTERN OSTCBCur ; External variables (uC/OS-II) + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntNesting + EXTERN OSRunning + +;******************************************************************************************************** +; Define vector table +;******************************************************************************************************** + + COMMON INTVEC(2) + + ORG 0008H ; Task switching TRAP0 vector + DC.L OSCtxSw ; (32-bit pointer in ADVANCED mode) + + ORG 0088H ; Timer 0 GRA (Vector 0x0088 on H8SX/1664) + DC.L OSTickISR ; (32-bit pointer in ADVANCED mode) + + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 (H) +; + 2 ER6 (L) (Contains 'p_arg') +; + 4 ER5 (H) +; + 6 ER5 (L) +; + 8 ER4 (H) +; + 10 ER4 (L) +; + 12 ER3 (H) +; + 14 ER3 (L) +; + 16 ER2 (H) +; + 18 ER2 (L) +; + 20 ER1 (H) +; + 22 ER1 (L) +; + 24 ER0 (H) +; + 26 ER0 (L) +; + 28 CCR (Initial value of 0x0000) +; + 30 task (16-bit address of 'task') +; + 32 task (16-bit address of 'task') +; + 34 p_arg (16-bit contents of 'p_arg') +; HIGH MEMORY +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;********************************************************************************************************* + RSEG CODE(1) + +OSStartHighRdy: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B #1, R6L ; Set OSRunning to TRUE + MOV.B R6L, @OSRunning +; + MOV.L @OSTCBHighRdy, ER0 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L ER0, @OSTCBCur + MOV.L @ER0, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. This was caused by the +; execution of a TRAPA #0 instruction (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; SP + 0 ----> 8-bit CCR +; + 1 24-bit PC of task +; + 4 +; HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSCtxSw: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 +; + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +; + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE ; Return to task + + +;********************************************************************************************************* +; PERFORM A CONTEXT SWITCH (From an ISR) +; +; Description : This function is called when an ISR makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows. +; +; LOW MEMORY +; + 0 Return address of OSIntCtxSw() +; + 4 ER3 saved upon entry by OSIntExit +; + 8 ER2 saved upon entry by OSIntExit +; + 12 Return address of OSIntExit() +; OSTCBCur->OSTCBStkPtr -----> + 16 ER6 +; + 20 ER5 +; + 24 ER4 +; + 28 ER3 +; + 32 ER2 +; + 36 ER1 +; + 40 ER0 +; + 44 8-bit CCR & 24-bit PC of task +; + 48 HIGH MEMORY +; +; 3) The stack frame of the task to resume looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr -> + 0 ----> ER6 +; + 4 ER5 +; + 8 ER4 +; + 12 ER3 +; + 16 ER2 +; + 20 ER1 +; + 24 ER0 +; + 28 8-bit CCR & 24-bit PC of task +; + 32 HIGH MEMORY +;********************************************************************************************************* + +OSIntCtxSw: + JSR @OSTaskSwHook ; Execute task switch hook +; + MOV.B @OSPrioHighRdy, R1L ; OSPrioCur = OSPrioHighRdy + MOV.B R1L, @OSPrioCur +; + MOV.L @OSTCBHighRdy, ER6 ; Get new task's SP from its TCB + MOV.L ER6, @OSTCBCur ; OSTCBCur = OSTCBHighRdy + MOV.L @ER6, ER7 +; + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 +; + RTE + + +;********************************************************************************************************* +;* TICK ISR +;* +;* OSTickISR: +;* Push ALL registers onto current task's stack +;* OSIntNesting++; +;* if (OSIntNesting == 1) { +;* OSTCBCur->OSTCBStkPtr = SP; +;* } +;* /* Code to clear interrupt source */ +;* OSTimeTick(); +;* OSIntExit(); +;* Pop ALL registers from current stack; +;* Return from interrupt; +;********************************************************************************************************* + +OSTickISR: + PUSH.L ER0 + PUSH.L ER1 + PUSH.L ER2 + PUSH.L ER3 + PUSH.L ER4 + PUSH.L ER5 + PUSH.L ER6 + + MOV.B @OSIntNesting, R6L ; tell uC/OS-II we're in an ISR + INC.B R6L + MOV.B R6L, @OSIntNesting + + CMP.B #1,R6L ; if (OSNesting == 1) + BNE OSTickISR1 + MOV.L @OSTCBCur, ER6 ; Save current task's SP into its TCB + MOV.L ER7, @ER6 +OSTickISR1: + JSR @TickClr ; Implement function to clear your tick source + + JSR @OSTimeTick ; Notify uC/OS-II about Tick + + JSR @OSIntExit ; Notify uC/OS-II about end of ISR + + POP.L ER6 + POP.L ER5 + POP.L ER4 + POP.L ER3 + POP.L ER2 + POP.L ER1 + POP.L ER0 + + RTE + + END diff --git a/Ports/H8SX/Adv/IAR/os_cpu_c.c b/Ports/H8SX/Adv/IAR/os_cpu_c.c new file mode 100644 index 0000000..65f065a --- /dev/null +++ b/Ports/H8SX/Adv/IAR/os_cpu_c.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The following simulates the stack for a function called by an exception. The pointer +* to the function argument 'p_arg' is placed in R6 because the IAR compiler passes the +* first argument of a function in this register. If your compiler passes the first +* argument on the stack, load it on the stack like in the original uC/OS. +* 2) An INT16U pointer is used because the SMALL model assumes a 16-bit wide stack. +* 3) The H8 is a BIG Endian processor +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT32U *)ptos; /* Load stack pointer */ + + /* Simulate call to your task */ + *--pstk = (INT32U)p_arg; /* If 'p_arg' passed on stack */ + *--pstk = (INT32U)task; /* Return address */ + /* Simulate interrupt stacking */ + *--pstk = (INT32U)task; /* Advanced Mode: 32-Bit program counter */ + /* Simulate ISR Entry saving all registers */ + *--pstk = (INT32U)0x00000000; /* ER0 = 0x00000000 */ + *--pstk = (INT32U)0x11111111; /* ER1 = 0x11111111 */ + *--pstk = (INT32U)0x22222222; /* ER2 = 0x22222222 */ + *--pstk = (INT32U)0x33333333; /* ER3 = 0x33333333 */ + *--pstk = (INT32U)0x44444444; /* ER4 = 0x44444444 */ + *--pstk = (INT32U)0x55555555; /* ER5 = 0x55555555 */ + *--pstk = (INT32U)0x66666666; /* ER6 = 0x66666666 */ + /* 'pstk' now points at R6 on stack */ + return ((OS_STK *)pstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/H8SX/Adv/IAR/os_dbg.c b/Ports/H8SX/Adv/IAR/os_dbg.c new file mode 100644 index 0000000..adbc2c4 --- /dev/null +++ b/Ports/H8SX/Adv/IAR/os_dbg.c @@ -0,0 +1,271 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* H8S +* (Advanced Mode) +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR H8 Compiler +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #ff 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/HCS12/NonPaged/CodeWarrior/OS_CPU.h b/Ports/HCS12/NonPaged/CodeWarrior/OS_CPU.h new file mode 100644 index 0000000..d42db95 --- /dev/null +++ b/Ports/HCS12/NonPaged/CodeWarrior/OS_CPU.h @@ -0,0 +1,119 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S12 Specific code +* (Metrowerks) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx */ +#define WORD INT16S +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() __asm swi; + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* REDEFINE THE PROTOTYPES FOR THE ISRs +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +void OSTickISRHandler(void); + +#if 0 +#define OS_ISR_PROTO_EXT +#endif + diff --git a/Ports/HCS12/NonPaged/CodeWarrior/OS_CPU_C.C b/Ports/HCS12/NonPaged/CodeWarrior/OS_CPU_C.C new file mode 100644 index 0000000..99adae1 --- /dev/null +++ b/Ports/HCS12/NonPaged/CodeWarrior/OS_CPU_C.C @@ -0,0 +1,293 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S12 Specific code +* (Metrowerks) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "includes.h" + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSTaskAbort(void); + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb=ptcb; +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *bstk; + + + (void)&opt; /* 'opt' is not used, prevent warning */ + + bstk = (INT8U *)ptos; /* Load stack pointer */ + + + *--bstk = (INT8U)(((INT32U)OSTaskAbort) >> 8); /* Task return address low (simulated calling function) */ + *--bstk = (INT8U)(((INT32U)OSTaskAbort) >> 16); /* Task return address high (simulated calling function) */ + + *--bstk = (INT8U)(((INT32U)task) >> 8); /* Task start address PCL */ + *--bstk = (INT8U)(((INT32U)task) >> 16); /* Task start address PCH. */ + + *--bstk = (INT8U)0x22; /* Y Register low */ + *--bstk = (INT8U)0x22; /* Y Register high */ + + *--bstk = (INT8U)0x11; /* X Register low */ + *--bstk = (INT8U)0x11; /* X Register high */ + + *--bstk = (INT8U)(((INT16U)p_arg) >> 8); /* A register / D register high task argument */ + *--bstk = (INT8U) ((INT16U)p_arg); /* B register / D register low task argument */ + + *--bstk = (0xC0); /* CCR Register (Disable STOP instruction and XIRQ) */ + + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK ABORT HANDLER +* +* Description: This function serves as the caller function for all tasks. If a task accidently returns, +* the caller will regain control of the CPU and delete the task preventing a system crash.. +* +* Arguments : none +* +* Note(s) : In uC/OS-II, a task should NEVER exit and should instead call OSTaskDel(OS_PRIO_SELF) +* when no longer desired. +********************************************************************************************************* +*/ + +void OSTaskAbort (void) +{ + OSTaskDel(OS_PRIO_SELF); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/HCS12/NonPaged/CodeWarrior/os_cpu_a.asm b/Ports/HCS12/NonPaged/CodeWarrior/os_cpu_a.asm new file mode 100644 index 0000000..a23824a --- /dev/null +++ b/Ports/HCS12/NonPaged/CodeWarrior/os_cpu_a.asm @@ -0,0 +1,236 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; NON PAGED S12 Specific code +; Codewarrior 4.x +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; Notes : THIS FILE *MUST* BE LINKED INTO NON_BANKED MEMORY! +;******************************************************************************************************** + +NON_BANKED: section + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef OS_CPU_SR_Save + xdef OS_CPU_SR_Restore + xdef OSStartHighRdy + xdef OSCtxSw + xdef OSIntCtxSw + xdef OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref OSIntExit + xref OSIntNesting + xref OSPrioCur + xref OSPrioHighRdy + xref OSRunning + xref OSTaskSwHook + xref OSTCBCur + xref OSTCBHighRdy + xref OSTickISR_Handler + xref OSTimeTick + +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the B register as expected by the +; compiler. +;******************************************************************************************************** + +OS_CPU_SR_Save: + tfr ccr,b ; Save CCR in B + sei ; Disable interrupts + rts + +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the CCR to restore. It is assumed that this 'argument' is +; passed in the B register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** + +OS_CPU_SR_Restore: + tfr b,ccr + rts + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + jsr OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab OSRunning ; 4~ + + ldx OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> CCR +; + 1 B +; + 2 A +; + 3 X (H) +; + 4 X (L) +; + 5 Y (H) +; + 6 Y (L) +; + 7 PC(H) +; + 8 PC(L) +;******************************************************************************************************** + + +OSCtxSw: + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +OSIntCtxSw: + jsr OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + rti ; 8~, Run task + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the S12XE's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see APP_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see APP_CFG.H) which corresponds to the number of FRT (Free Running Timer) +; counts to the next interrupt. +; +; 2) All USER interrupts should be modeled EXACTLY like this where the only +; line to be modified is the call to your ISR_Handler and perhaps the call to +; the label name OSTickISR1. +;******************************************************************************************************** + +OSTickISR: + inc OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne OSTickISR1 ; 3~ + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +OSTickISR1: + jsr OSTickISR_Handler + +; cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu.h b/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu.h new file mode 100644 index 0000000..77d3660 --- /dev/null +++ b/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu.h @@ -0,0 +1,145 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S12 Specific Code +* Freescale Serial Monitor +* Banked Memory Model +* Codewarrior 4.x +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* Note(s) : (1) This port will not function in expanded mode. This is due to the fact that the +* OS_TASK_SW() macro utilizes JSR instead of CALL. The CALL instruction may not +* be used in place of JSR since it pushes the PPAGE register on the stack which +* will corrupts the stack frame. JSR only pushes the PC on to the stack which +* is compatible the MC9S12 ISR exception stack handling procedures (see RTI). +* +* (2) This port utilizes JSR instead of SWI when performing a task level context switch +* due to the fact that the Freescale MC9S12 Serial Monitor utilizes the SWI trap +* for break points. +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx */ +#define WORD INT16S +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() asm "jsr OSCtxSw" + + + /* banked, mode this macro creates */ + /* code for "call OSCtxSw" */ + +#define OS_STK_GROWTH 1 /* Stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* REDEFINE THE PROTOTYPES FOR THE ISRs +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +void OSTickISRHandler(void); + + diff --git a/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_a.s b/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_a.s new file mode 100644 index 0000000..11dc2f3 --- /dev/null +++ b/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_a.s @@ -0,0 +1,307 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; MC9S12 Specific Code +; Freescale Serial Monitor +; Banked Memory Model +; Codewarrior 4.x +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; Notes : THIS FILE *MUST* BE LINKED INTO NON_BANKED MEMORY! +;******************************************************************************************************** + +NON_BANKED: section + + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +PPAGE: equ $0030 ; Addres of PPAGE register (assuming MC9S12 (non XGATE part) + + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef OS_CPU_SR_Save + xdef OS_CPU_SR_Restore + xdef OSStartHighRdy + xdef OSCtxSw + xdef OSIntCtxSw + xdef OSTickISR + + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref OSIntExit + xref OSIntNesting + xref OSPrioCur + xref OSPrioHighRdy + xref OSRunning + xref OSTaskSwHook + xref OSTCBCur + xref OSTCBHighRdy + xref OSTickISR_Handler + xref OSTimeTick + + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the D register to pass a single 16-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +OS_CPU_SR_Save: + tfr ccr,b ; It's assumed that 8-bit return value is in register B + sei ; Disable interrupts + rtc ; Return to caller with D containing the previous CCR + +OS_CPU_SR_Restore: + tfr b,ccr ; B contains the CCR value to restore, move to CCR + rtc + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 PPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + call OSTaskSwHook ; Invoke user defined context switch hook + + ldab #$01 ; Indicate that we are multitasking + stab OSRunning + + ldx OSTCBHighRdy ; Point to TCB of highest priority task ready to run + lds 0,x ; Load SP into 68HC12 + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + rti ; Restore task context -> Run task + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. Generally +; a software exception is used to push the task context on to the stack, however, the +; Freescale Serial Monitor application requires use of the SWI instruction. Therefore, +; this function is called by the OS_TASK_SWITCH macro as a jump to sub routine which does +; NOT automatically stack the CCR. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The 'JSR' instruction issued by the OS_TASK_SWITCH macro +; has pushed the PC register on to the stack. SR and PPAGE +; must be added to the stack, along with the other CPU +; registers in order to save the entire context of the +; preempted task. +; +; 3) The stack frame of the task to suspend looks as follows: +; +; --> PUSH REMAINING +; REGISTERS HERE. +; STACK GROWS TOWARD +; LOW MEMORY. +; +; SP + 0 PC(H) +; + 1 PC(L) +; +; 4) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 PPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +;******************************************************************************************************** + +OSCtxSw: + pshy ; Manually push preempted task's context on to the stack + pshx + psha + pshb + pshc + + ldaa PPAGE ; Get current value of PPAGE register + psha ; Push PPAGE register onto current task's stack + + ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y + + call OSTaskSwHook ; Call user task switch hook + + ldx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + stx OSTCBCur + + ldab OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + stab OSPrioCur + + lds 0,x ; Load SP into MC9S12 + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + rti ; Restore preempting task's context -> Run task + + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. The PPAGE register of the preempted task has already +; been stacked during the start of the ISR that is currently running. +; +; Arguments : none +; +; Note(s) : 1) The preempted task's stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 PPAGE ----- Added by the start of the current ISR (ex: OSTickISR) +; + 1 CCR -. +; + 2 B ` +; + 3 A | +; + 4 X (H) | +; + 5 X (L) - Added by the ISR automatic context save. +; + 6 Y (H) | +; + 7 Y (L) . +; + 8 PC(H) , +; + 9 PC(L) -' +; +; 2) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 PPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +;******************************************************************************************************** + +OSIntCtxSw: + call OSTaskSwHook ; Call user task switch hook + + ldx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + stx OSTCBCur + + ldab OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + stab OSPrioCur + + lds 0,x ; Load the SP of the next task + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + rti ; Restore preempting task's context -> Run task + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the S12XE's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see APP_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see APP_CFG.H) which corresponds to the number of FRT (Free Running Timer) +; counts to the next interrupt. +; +; 2) All USER interrupts should be modeled EXACTLY like this where the only +; line to be modified is the call to your ISR_Handler and perhaps the call to +; the label name OSTickISR1. +;******************************************************************************************************** + +OSTickISR: + ldaa PPAGE ; Get current value of PPAGE register + psha ; Push PPAGE register onto current task's stack + + inc OSIntNesting ; Notify uC/OS-II about ISR + + ldab OSIntNesting ; if (OSIntNesting == 1) { + cmpb #$01 + bne OSTickISR1 + + ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; } + +OSTickISR1: + call OSTickISR_Handler + +; cli ; Enable interrupts to allow interrupt nesting + + call OSIntExit ; Notify uC/OS-II about end of ISR, OSIntCtxSw() possible. + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + rti ; Return from interrupt, no higher priority tasks ready (no context switch) + diff --git a/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_c.c b/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_c.c new file mode 100644 index 0000000..12576fd --- /dev/null +++ b/Ports/HCS12/Paged/CodeWarrior/SerialMonitor/os_cpu_c.c @@ -0,0 +1,365 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S12 Specific Code +* Freescale Serial Monitor +* Banked Memory Model +* Codewarrior 4.x +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* Note(s) : (1) This port will not function in expanded mode. This is due to the fact that the +* OS_TASK_SW() macro utilizes JSR instead of CALL. The CALL instruction may not +* be used in place of JSR since it pushes the PPAGE register on the stack which +* will corrupts the stack frame. JSR only pushes the PC on to the stack which +* is compatible the MC9S12 ISR exception stack handling procedures (see RTI). +* +* (2) This port utilizes JSR instead of SWI when performing a task level context switch +* due to the fact that the Freescale MC9S12 Serial Monitor utilizes the SWI trap +* for break points. +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSTaskAbort(void); + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) All your tasks are assumed to be in NON-PAGED memory. However, the tasks can call +* functions in PAGED memory and if a context switch occurs, the proper page will be +* saved/restored by uC/OS-II. Page #0 is stored onto the task's stack as a 'dummy' +* value. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *bstk; + + + (void)&opt; /* 'opt' is not used, prevent warning */ + + bstk = (INT8U *)ptos; /* Load stack pointer */ + + + *--bstk = (INT8U)(((INT32U)OSTaskAbort) >> 8); /* Task return address low (simulated calling function) */ + *--bstk = (INT8U)(((INT32U)OSTaskAbort) >> 16); /* Task return address high (simulated calling function) */ + *--bstk = (INT8U)(((INT32U)OSTaskAbort)); /* Task return address page (simulated calling function) */ + + + /* Format: PCH:PCL:PPAGE */ + *--bstk = (INT8U)(((INT32U)task) >> 8); /* Task start address PCL */ + *--bstk = (INT8U)(((INT32U)task) >> 16); /* Task start address PCH. */ + + + *--bstk = (INT8U)0x22; /* Y Register low */ + *--bstk = (INT8U)0x22; /* Y Register high */ + + + *--bstk = (INT8U)0x11; /* X Register low */ + *--bstk = (INT8U)0x11; /* X Register high */ + + + *--bstk = (INT8U)(((INT16U)p_arg) >> 8); /* A register / D register high task argument */ + *--bstk = (INT8U) ((INT16U)p_arg); /* B register / D register low task argument */ + + + *--bstk = (0xC0); /* CCR Register (Disable STOP instruction and XIRQ) */ + + + *--bstk = (INT8U)task; /* Save the PPAGE register */ + + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + + +/* +********************************************************************************************************* +* TASK ABORT HANDLER +* +* Description: This function serves as the caller function for all tasks. If a task accidently returns, +* the caller will regain control of the CPU and delete the task preventing a system crash.. +* +* Arguments : none +* +* Note(s) : In uC/OS-II, a task should NEVER exit and should instead call OSTaskDel(OS_PRIO_SELF) +* when no longer desired. +********************************************************************************************************* +*/ + +void OSTaskAbort (void) +{ + OSTaskDel(OS_PRIO_SELF); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + diff --git a/Ports/HCS12/Paged/CodeWarrior/os_cpu.h b/Ports/HCS12/Paged/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..5dc55b5 --- /dev/null +++ b/Ports/HCS12/Paged/CodeWarrior/os_cpu.h @@ -0,0 +1,118 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* 68HC12 Specific code +* IAR +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx */ +#define WORD INT16S +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() __asm swi; + +#define OS_STK_GROWTH 1 /* Stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* REDEFINE THE PROTOTYPES FOR THE ISRs +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +void OSTickISRHandler(void); + + diff --git a/Ports/HCS12/Paged/CodeWarrior/os_cpu_a.s b/Ports/HCS12/Paged/CodeWarrior/os_cpu_a.s new file mode 100644 index 0000000..c41c4f3 --- /dev/null +++ b/Ports/HCS12/Paged/CodeWarrior/os_cpu_a.s @@ -0,0 +1,249 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PAGED S12 Specific code +; (METROWERKS) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; Notes : THIS FILE *MUST* BE LINKED INTO NON_BANKED MEMORY! +;******************************************************************************************************** + +NON_BANKED: section + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +PPAGE: equ $0030 ; Addres of PPAGE register (assuming MC9S12 (non XGATE part) + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef OS_CPU_SR_Save + xdef OS_CPU_SR_Restore + xdef OSStartHighRdy + xdef OSCtxSw + xdef OSIntCtxSw + xdef OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref OSIntExit + xref OSIntNesting + xref OSPrioCur + xref OSPrioHighRdy + xref OSRunning + xref OSTaskSwHook + xref OSTCBCur + xref OSTCBHighRdy + xref OSTickISR_Handler + xref OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the D register to pass a single 16-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +OS_CPU_SR_Save: + tfr ccr,b ; It's assumed that 8-bit return value is in register B + sei ; Disable interrupts + rtc ; Return to caller with D containing the previous CCR + +OS_CPU_SR_Restore: + tfr b,ccr ; B contains the CCR value to restore, move to CCR + rtc + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 PPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + call OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab OSRunning ; 4~ + + ldx OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 4~, Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 PPAGE +; + 1 CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +;******************************************************************************************************** + +OSCtxSw: + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + call OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. The PPAGE register of the preempted task has already +; been stacked during the start of the ISR that is currently running. +; +; Arguments : none +;******************************************************************************************************** + +OSIntCtxSw: + call OSTaskSwHook ; 4~, Call user task switch hook + + ldx OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx OSTCBCur ; 3~ + + ldab OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab OSPrioCur ; 3~ + + lds 0,x ; 3~, Load the SP of the next task + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 8~, Run task + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the S12XE's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see APP_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see APP_CFG.H) which corresponds to the number of FRT (Free Running Timer) +; counts to the next interrupt. +; +; 2) All USER interrupts should be modeled EXACTLY like this where the only +; line to be modified is the call to your ISR_Handler and perhaps the call to +; the label name OSTickISR1. +;******************************************************************************************************** + +OSTickISR: + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + inc OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne OSTickISR1 ; 3~ + + ldy OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +OSTickISR1: + call OSTickISR_Handler + +; cli ; 2~, Enable interrupts to allow interrupt nesting + + call OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/HCS12/Paged/CodeWarrior/os_cpu_c.c b/Ports/HCS12/Paged/CodeWarrior/os_cpu_c.c new file mode 100644 index 0000000..32792d6 --- /dev/null +++ b/Ports/HCS12/Paged/CodeWarrior/os_cpu_c.c @@ -0,0 +1,354 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S12 Specific Code +* Banked Memory Model +* Codewarrior 4.x +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "ucos_ii.h" + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSTaskAbort(void); + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) All your tasks are assumed to be in NON-PAGED memory. However, the tasks can call +* functions in PAGED memory and if a context switch occurs, the proper page will be +* saved/restored by uC/OS-II. Page #0 is stored onto the task's stack as a 'dummy' +* value. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT8U *bstk; + + + (void)&opt; /* 'opt' is not used, prevent warning */ + + bstk = (INT8U *)ptos; /* Load stack pointer */ + + + *--bstk = (INT8U)(((INT32U)OSTaskAbort) >> 8); /* Task return address low (simulated calling function) */ + *--bstk = (INT8U)(((INT32U)OSTaskAbort) >> 16); /* Task return address high (simulated calling function) */ + *--bstk = (INT8U)(((INT32U)OSTaskAbort)); /* Task return address page (simulated calling function) */ + + + /* Format: PCH:PCL:PPAGE */ + *--bstk = (INT8U)(((INT32U)task) >> 8); /* Task start address PCL */ + *--bstk = (INT8U)(((INT32U)task) >> 16); /* Task start address PCH. */ + + + *--bstk = (INT8U)0x22; /* Y Register low */ + *--bstk = (INT8U)0x22; /* Y Register high */ + + + *--bstk = (INT8U)0x11; /* X Register low */ + *--bstk = (INT8U)0x11; /* X Register high */ + + + *--bstk = (INT8U)(((INT16U)p_arg) >> 8); /* A register / D register high task argument */ + *--bstk = (INT8U) ((INT16U)p_arg); /* B register / D register low task argument */ + + + *--bstk = (0xC0); /* CCR Register (Disable STOP instruction and XIRQ) */ + + + *--bstk = (INT8U)task; /* Save the PPAGE register */ + + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + + +/* +********************************************************************************************************* +* TASK ABORT HANDLER +* +* Description: This function serves as the caller function for all tasks. If a task accidently returns, +* the caller will regain control of the CPU and delete the task preventing a system crash.. +* +* Arguments : none +* +* Note(s) : In uC/OS-II, a task should NEVER exit and should instead call OSTaskDel(OS_PRIO_SELF) +* when no longer desired. +********************************************************************************************************* +*/ + +void OSTaskAbort (void) +{ + OSTaskDel(OS_PRIO_SELF); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + diff --git a/Ports/HCS12X/Paged/Codewarrior/os_cpu.h b/Ports/HCS12X/Paged/Codewarrior/os_cpu.h new file mode 100644 index 0000000..13c64d6 --- /dev/null +++ b/Ports/HCS12X/Paged/Codewarrior/os_cpu.h @@ -0,0 +1,128 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Paged MC9S12X Specific code +* (Codewarrior V4.5) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT +********************************************************************************************************* +*/ + +#define OS_CPU_INT_DIS_MEAS_EN 0 + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSStartHighRdy(void); +void OSIntCtxSw (void); +void OSCtxSw (void); + +/* +********************************************************************************************************* +* MC9S12X +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +#define OS_TASK_SW() _asm("swi") + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OS_CPU_SR_Save(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OS_CPU_SR_Restore(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif +#endif diff --git a/Ports/HCS12X/Paged/Codewarrior/os_cpu_a.s b/Ports/HCS12X/Paged/Codewarrior/os_cpu_a.s new file mode 100644 index 0000000..8d87192 --- /dev/null +++ b/Ports/HCS12X/Paged/Codewarrior/os_cpu_a.s @@ -0,0 +1,321 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PAGED S12X Specific code +; (CODEWARRIOR) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; Notes : THIS FILE *MUST* BE LINKED INTO NON_BANKED MEMORY! +;******************************************************************************************************** + +NON_BANKED: section + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +PPAGE: equ $0015 ; Addres of PPAGE register (assuming MC9S12XEP100 part) +RPAGE: equ $0016 ; Addres of RPAGE register (assuming MC9S12XEP100 part) +EPAGE: equ $0017 ; Addres of EPAGE register (assuming MC9S12XEP100 part) +GPAGE: equ $0010 ; Addres of GPAGE register (assuming MC9S12XEP100 part) + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef OS_CPU_SR_Save + xdef OS_CPU_SR_Restore + xdef OSStartHighRdy + xdef OSCtxSw + xdef OSIntCtxSw + xdef OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref OSIntExit + xref OSIntNesting + xref OSPrioCur + xref OSPrioHighRdy + xref OSRunning + xref OSTaskSwHook + xref OSTCBCur + xref OSTCBHighRdy + xref OSTickISR_Handler + xref OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the D register to pass a single 16-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +OS_CPU_SR_Save: + tfr ccrw, d ; It's assumed that the 16-bit return value is in register D + sei ; Disable interrupts + rtc ; Return to caller with D containing the previous CCR + +OS_CPU_SR_Restore: + tfr d,ccrw ; D contains the CCR word value to restore, move to CCRW + rtc + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> gPAGE +; + 1 ePAGE +; + 2 rPAGE +; + 3 pPAGE +; + 1 CCRW +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + call OSTaskSwHook ; Invoke user defined context switch hook + + ldab #$01 ; Indicate that we are multitasking + stab OSRunning + + ldx OSTCBHighRdy ; Point to TCB of highest priority task ready to run + lds 0,x ; Load SP into 68HC12 + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + pula ; Get value of RPAGE register + staa RPAGE ; Store into CPU's RPAGE register + + pula ; Get value of EPAGE register + staa EPAGE ; Store into CPU's EPAGE register + + pula ; Get value of GPAGE register + staa GPAGE ; Store into CPU's GPAGE register + + rti ; Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> gPAGE +; + 1 ePAGE +; + 2 rPAGE +; + 3 pPAGE +; + 4 CCR +; + 6 B +; + 7 A +; + 8 X (H) +; + 9 X (L) +; + 10 Y (H) +; + 11 Y (L) +; + 12 PC(H) +; + 13 PC(L) +;******************************************************************************************************** + +OSCtxSw: + ldaa GPAGE ; Get current value of GPAGE register + psha ; Push GPAGE register onto current task's stack + + ldaa EPAGE ; Get current value of EPAGE register + psha ; Push EPAGE register onto current task's stack + + ldaa RPAGE ; Get current value of RPAGE register + psha ; Push RPAGE register onto current task's stack + + ldaa PPAGE ; Get current value of PPAGE register + psha ; Push PPAGE register onto current task's stack + + ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y + + call OSTaskSwHook ; Call user task switch hook + + ldx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + stx OSTCBCur + + ldab OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + stab OSPrioCur + + lds 0,x ; Load SP into 68HC12 + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + pula ; Get value of RPAGE register + staa RPAGE ; Store into CPU's RPAGE register + + pula ; Get value of EPAGE register + staa EPAGE ; Store into CPU's EPAGE register + + pula ; Get value of GPAGE register + staa GPAGE ; Store into CPU's GPAGE register + + rti ; Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. The GPAGE, EPAGE, RPAGE and PPAGE CPU registers of the +; preempted task have already been stacked during the start of the ISR that is currently +; running. +; +; Arguments : none +;******************************************************************************************************** + +OSIntCtxSw: + call OSTaskSwHook ; Call user task switch hook + + ldx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + stx OSTCBCur + + ldab OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + stab OSPrioCur + + lds 0,x ; Load the SP of the next task + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + pula ; Get value of RPAGE register + staa RPAGE ; Store into CPU's RPAGE register + + pula ; Get value of EPAGE register + staa EPAGE ; Store into CPU's EPAGE register + + pula ; Get value of GPAGE register + staa GPAGE ; Store into CPU's GPAGE register + + rti ; Run task + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the S12XE's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see APP_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see APP_CFG.H) which corresponds to the number of FRT (Free Running Timer) +; counts to the next interrupt. +; +; 2) All USER interrupts should be modeled EXACTLY like this where the only +; line to be modified is the call to your ISR_Handler and perhaps the call to +; the label name OSTickISR1. +;******************************************************************************************************** + +OSTickISR: + ldaa GPAGE ; Get current value of GPAGE register + psha ; Push GPAGE register onto current task's stack + + ldaa EPAGE ; Get current value of EPAGE register + psha ; Push EPAGE register onto current task's stack + + ldaa RPAGE ; Get current value of RPAGE register + psha ; Push RPAGE register onto current task's stack + + ldaa PPAGE ; Get current value of PPAGE register + psha ; Push PPAGE register onto current task's stack + + inc OSIntNesting ; Notify uC/OS-II about ISR + + ldab OSIntNesting ; if (OSIntNesting == 1) { + cmpb #$01 + bne OSTickISR1 + + ldy OSTCBCur ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; } + +OSTickISR1: + call OSTickISR_Handler + +; cli ; Optionally enable interrupts to allow interrupt nesting + + call OSIntExit ; Notify uC/OS-II about end of ISR + + pula ; Get value of PPAGE register + staa PPAGE ; Store into CPU's PPAGE register + + pula ; Get value of RPAGE register + staa RPAGE ; Store into CPU's RPAGE register + + pula ; Get value of EPAGE register + staa EPAGE ; Store into CPU's EPAGE register + + pula ; Get value of GPAGE register + staa GPAGE ; Store into CPU's GPAGE register + + rti ; Return from interrupt, no higher priority tasks ready. + diff --git a/Ports/HCS12X/Paged/Codewarrior/os_cpu_c.c b/Ports/HCS12X/Paged/Codewarrior/os_cpu_c.c new file mode 100644 index 0000000..c4eb9fa --- /dev/null +++ b/Ports/HCS12X/Paged/Codewarrior/os_cpu_c.c @@ -0,0 +1,309 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PAGED S12XE Specific code +* (Codewarrior V4.5) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) Take the current values of GPAGE, EPAGE and RPAGE +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)p_arg; /* Simulate call to function with argument */ + *--wstk = (INT16U)(((INT32U)task) >> 8); /* Return address of simulated call. Format: PCH:PCL */ + *--wstk = (INT16U)(((INT32U)task) >> 8); /* Put task return address on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + *--wstk = (INT16U)0x0080; /* CCR: Disable STOP, Int. Level = 0. User Mode */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = *(INT8U *)0x10; /* Save the GPAGE register (see note 6) */ + *--bstk = *(INT8U *)0x17; /* Save the EPAGE register (see note 6) */ + *--bstk = *(INT8U *)0x16; /* Save the RPAGE register (see note 6) */ + *--bstk = (INT8U )task; /* Save the task's PPAGE register value */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + + diff --git a/Ports/HCS12X/Paged/Cosmic/os_cpu.h b/Ports/HCS12X/Paged/Cosmic/os_cpu.h new file mode 100644 index 0000000..2d4c80f --- /dev/null +++ b/Ports/HCS12X/Paged/Cosmic/os_cpu.h @@ -0,0 +1,113 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Paged 68HC12 Specific code +* (COSMIC C V4.2F) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 68HC12 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +//#define OS_TASK_SW() OSCtxSw() +#define OS_TASK_SW() _asm(" swi") + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/HCS12X/Paged/Cosmic/os_cpu_a.S b/Ports/HCS12X/Paged/Cosmic/os_cpu_a.S new file mode 100644 index 0000000..2696ce1 --- /dev/null +++ b/Ports/HCS12X/Paged/Cosmic/os_cpu_a.S @@ -0,0 +1,407 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PAGED S12XE Specific code +; (COSMIC C V4.xxxxxx) +; +; Filename : os_cpu_a.S +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + +OS_TICK_OC: equ 7 ; We will use Output Compare #7 to generate tick interrupts + xref _OSTickOCCnts +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +TFLG1: equ $004E ; I/O port addresses. Assumes all MC9S12XEP100 I/Os start at 0x0000 +TC0: equ $0050 +TC1: equ $0052 +TC2: equ $0054 +TC3: equ $0056 +TC4: equ $0058 +TC5: equ $005A +TC6: equ $005C +TC7: equ $005E + +PPAGE: equ $0015 ; Addres of PPAGE register (assuming MC9S12XEP100 part) +RPAGE: equ $0016 ; Addres of RPAGE register (assuming MC9S12XEP100 part) +EPAGE: equ $0017 ; Addres of EPAGE register (assuming MC9S12XEP100 part) +GPAGE: equ $0010 ; Addres of GPAGE register (assuming MC9S12XEP100 part) + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef _OSCPUSaveSR + xdef _OSCPURestoreSR + xdef _OSStartHighRdy + xdef _OSCtxSw + xdef _OSIntCtxSw + xdef _OSTickISR + + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref _OSIntExit + xref _OSIntNesting + xref _OSPrioCur + xref _OSPrioHighRdy + xref _OSRunning + xref _OSTaskSwHook + xref _OSTCBCur + xref _OSTCBHighRdy + xref _OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the D register to pass a single 16-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +_OSCPUSaveSR: + tfr ccrw,d ; It's assumed that 16-bit return value is in register D + sei ; Disable interrupts + rts ; Return to caller with D containing the previous CCR + + +_OSCPURestoreSR: + tfr d,ccrw ; D contains the CCR value to restore, move to CCR + rts + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> gPAGE +; + 1 ePAGE +; + 2 rPAGE +; + 3 pPAGE +; + 4 CCR +; + 6 B +; + 7 A +; + 8 X (H) +; + 9 X (L) +; + 10 Y (H) +; + 11 Y (L) +; + 12 PC(H) +; + 13 PC(L) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +_OSStartHighRdy: + jsr _OSTaskSwHook ; 4~, Invoke user defined context switch hook + + ldab #$01 ; 2~, Indicate that we are multitasking + stab _OSRunning ; 4~ + + ldx _OSTCBHighRdy ; 3~, Point to TCB of highest priority task ready to run + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + pula ; 3~, Get value of RPAGE register + staa RPAGE ; 3~, Store into CPU's RPAGE register + + pula ; 3~, Get value of EPAGE register + staa EPAGE ; 3~, Store into CPU's EPAGE register + + pula ; 3~, Get value of GPAGE register + staa GPAGE ; 3~, Store into CPU's GPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP CCR +; + 2 B +; + 3 A +; + 4 X (H) +; + 5 X (L) +; + 6 Y (H) +; + 7 Y (L) +; + 8 PC(H) +; + 9 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 --> gPAGE +; + 1 ePAGE +; + 2 rPAGE +; + 3 pPAGE +; + 4 CCR +; + 6 B +; + 7 A +; + 8 X (H) +; + 9 X (L) +; + 10 Y (H) +; + 11 Y (L) +; + 12 PC(H) +; + 13 PC(L) +;******************************************************************************************************** + +_OSCtxSw: + ldaa GPAGE ; 3~, Get current value of GPAGE register + psha ; 2~, Push GPAGE register onto current task's stack + + ldaa EPAGE ; 3~, Get current value of EPAGE register + psha ; 2~, Push EPAGE register onto current task's stack + + ldaa RPAGE ; 3~, Get current value of RPAGE register + psha ; 2~, Push RPAGE register onto current task's stack + + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, + + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + pula ; 3~, Get value of RPAGE register + staa RPAGE ; 3~, Store into CPU's RPAGE register + + pula ; 3~, Get value of EPAGE register + staa EPAGE ; 3~, Store into CPU's EPAGE register + + pula ; 3~, Get value of GPAGE register + staa GPAGE ; 3~, Store into CPU's GPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. +; +; Arguments : none +;******************************************************************************************************** + +_OSIntCtxSw: + jsr _OSTaskSwHook ; 4~, Call user task switch hook + + ldx _OSTCBHighRdy ; 3~, OSTCBCur = OSTCBHighRdy + stx _OSTCBCur ; 3~ + + ldab _OSPrioHighRdy ; 3~, OSPrioCur = OSPrioHighRdy + stab _OSPrioCur ; 3~ + + lds 0,x ; 3~, Load SP into 68HC12 + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + pula ; 3~, Get value of RPAGE register + staa RPAGE ; 3~, Store into CPU's RPAGE register + + pula ; 3~, Get value of EPAGE register + staa EPAGE ; 3~, Store into CPU's EPAGE register + + pula ; 3~, Get value of GPAGE register + staa GPAGE ; 3~, Store into CPU's GPAGE register + + rti ; 8~, Run task + + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the S12XE's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see APP_CFG.H and this file) to generate a tick that occurs every OS_TICK_OC_CNTS +; (see APP_CFG.H) which corresponds to the number of FRT (Free Running Timer) +; counts to the next interrupt. +; +; 2) You must specify which output compare will be used by the tick ISR as follows: +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 0 to use OUTPUT COMPARE #0 +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 1 to use OUTPUT COMPARE #1 +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 2 to use OUTPUT COMPARE #2 +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 3 to use OUTPUT COMPARE #3 +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 4 to use OUTPUT COMPARE #4 +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 5 to use OUTPUT COMPARE #5 +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 6 to use OUTPUT COMPARE #6 +; Set OS_TICK_OC in APP_CFG.H (AND in this file) to 7 to use OUTPUT COMPARE #7 +; +; 3) TFLG1, TC0 ... TC7 are defined in this file. +;******************************************************************************************************** + +_OSTickISR: + ldaa GPAGE ; 3~, Get current value of GPAGE register + psha ; 2~, Push GPAGE register onto current task's stack + + ldaa EPAGE ; 3~, Get current value of EPAGE register + psha ; 2~, Push EPAGE register onto current task's stack + + ldaa RPAGE ; 3~, Get current value of RPAGE register + psha ; 2~, Push RPAGE register onto current task's stack + + ldaa PPAGE ; 3~, Get current value of PPAGE register + psha ; 2~, Push PPAGE register onto current task's stack + + inc _OSIntNesting ; 4~, Notify uC/OS-II about ISR + + ldab _OSIntNesting ; 4~, if (OSIntNesting == 1) { + cmpb #$01 ; 2~ + bne _OSTickISR1 ; 3~ + + ldy _OSTCBCur ; 3~, OSTCBCur->OSTCBStkPtr = Stack Pointer + sts 0,y ; 3~, } + +_OSTickISR1: +if OS_TICK_OC == 0 + ldab #$01 ; 2~, Clear C0F interrupt flag (bit 0) + stab TFLG1 ; 4~ + ldd TC0 ; 5~, Set TC0 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC0 ; 5~ +endif + +if OS_TICK_OC == 1 + ldab #$02 ; 2~, Clear C1F interrupt flag (bit 1) + stab TFLG1 ; 4~ + ldd TC1 ; 5~, Set TC1 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC1 ; 5~ +endif + +if OS_TICK_OC == 2 + ldab #$04 ; 2~, Clear C2F interrupt flag (bit 2) + stab TFLG1 ; 4~ + ldd TC2 ; 5~, Set TC2 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC2 ; 5~ +endif + +if OS_TICK_OC == 3 + ldab #$08 ; 2~, Clear C3F interrupt flag (bit 3) + stab TFLG1 ; 4~ + ldd TC3 ; 5~, Set TC3 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC3 ; 5~ +endif + +if OS_TICK_OC == 4 + ldab #$10 ; 2~, Clear C4F interrupt flag (bit 4) + stab TFLG1 ; 4~ + ldd TC4 ; 5~, Set TC4 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC4 ; 5~ +endif + +if OS_TICK_OC == 5 + ldab #$20 ; 2~, Clear C5F interrupt flag (bit 5) + stab TFLG1 ; 4~ + ldd TC5 ; 5~, Set TC5 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC5 ; 5~ +endif + +if OS_TICK_OC == 6 + ldab #$40 ; 2~, Clear C6F interrupt flag (bit 6) + stab TFLG1 ; 4~ + ldd TC6 ; 5~, Set TC6 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC6 ; 5~ +endif + +if OS_TICK_OC == 7 + ldab #$80 ; 2~, Clear C7F interrupt flag (bit 7) + stab TFLG1 ; 4~ + ldd TC7 ; 5~, Set TC7 to present time + desired counts to next ISR + addd _OSTickOCCnts ; 3~ + std TC7 ; 5~ +endif + + cli ; 2~, Enable interrupts to allow interrupt nesting + + jsr _OSTimeTick ; 6~+, Call uC/OS-II's tick updating function + + jsr _OSIntExit ; 6~+, Notify uC/OS-II about end of ISR + + pula ; 3~, Get value of PPAGE register + staa PPAGE ; 3~, Store into CPU's PPAGE register + + pula ; 3~, Get value of RPAGE register + staa RPAGE ; 3~, Store into CPU's RPAGE register + + pula ; 3~, Get value of EPAGE register + staa EPAGE ; 3~, Store into CPU's EPAGE register + + pula ; 3~, Get value of GPAGE register + staa GPAGE ; 3~, Store into CPU's GPAGE register + + rti ; 12~, Return from interrupt, no higher priority tasks ready. diff --git a/Ports/HCS12X/Paged/Cosmic/os_cpu_c.c b/Ports/HCS12X/Paged/Cosmic/os_cpu_c.c new file mode 100644 index 0000000..3130244 --- /dev/null +++ b/Ports/HCS12X/Paged/Cosmic/os_cpu_c.c @@ -0,0 +1,294 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PAGED S12XE Specific code +* (COSMIC C V4.xxxxxx) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) XIRQ interrupts are disabled when your task starts executing. You can change this by +* clearing BIT6 in the CCR. +* 2) The STOP instruction is disabled when your task starts executing. You can change this +* by clearing BIT7 in the CCR. +* 3) The other interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 4) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 5) Registers are initialized to make them easy to differentiate with a debugger. +* 6) All your tasks are assumed to be in NON-PAGED memory. However, the tasks can call +* functions in PAGED memory and if a context switch occurs, the proper page will be +* saved/restored by uC/OS-II. Page #0 is stored onto the task's stack as a 'dummy' +* value. +* 7) Take the default values of GPAGE, EPAGE and RPAGE out of your registers. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)pdata; /* Simulate call to NON-BANKED function with argument */ + *--wstk = (INT16U)task; + *--wstk = (INT16U)task; /* Put pointer to task on top of stack */ + *--wstk = (INT16U)0x2222; /* Y Register */ + *--wstk = (INT16U)0x1111; /* X Register */ + *--wstk = (INT16U)0xBBAA; /* D Register */ + *--wstk = (INT16U)0x0080; /* CCR Register (Disable STOP instruction) I-Level = 0; User Mode */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = *(INT8U *)0x10; /* Save the GPAGE register (see note 7) */ + *--bstk = *(INT8U *)0x17; /* Save the EPAGE register (see note 7) */ + *--bstk = *(INT8U *)0x16; /* Save the RPAGE register (see note 7) */ + *--bstk = *(INT8U *)0x15; /* Save the PPAGE register (Always page 0, see note 6) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + diff --git a/Ports/HCS12X/Paged/Cosmic/os_dbg.c b/Ports/HCS12X/Paged/Cosmic/os_dbg.c new file mode 100644 index 0000000..64a9118 --- /dev/null +++ b/Ports/HCS12X/Paged/Cosmic/os_dbg.c @@ -0,0 +1,266 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/LatticeMico32/GNU/MicroC_malloc_lock.c b/Ports/LatticeMico32/GNU/MicroC_malloc_lock.c new file mode 100644 index 0000000..8a89892 --- /dev/null +++ b/Ports/LatticeMico32/GNU/MicroC_malloc_lock.c @@ -0,0 +1,79 @@ +/* + * This file contains implementation for multithread protection + * when calling malloc/free from MicroC/OS tasks. + */ +#include +#include "ucos_ii.h" +#include "MicroC_malloc_lock.h" + + +static OS_EVENT* __microC_lock; +static int __microC_lock_owner_id; +static int __microC_lock_count; + + +/* + * This function must be called after initializing the + * OS (OSInit) and prior to any task calling malloc + * or free routines from within the tasks. This function uses + * semaphore in lieu of a mutex as the MicroC mutex requires + * specifying task-priority. + * + * This function returns 0 if successful else returns a non-zero + * value. + */ +int InitMallocLock(void) +{ + /* initialize lock properties */ + __microC_lock_owner_id = -1; + __microC_lock_count = 0; + + + /* + * Create a semaphore with an initial count of 1 i.e. + * only one task can grab it. + */ + __microC_lock = OSSemCreate(1); + if(__microC_lock == (OS_EVENT *)0) + return(1); + + + /* all done */ + return(0); +} + + +/* + * malloc/free calls this function and passes a pointer to + * the task's reent structure. This structure however does + * not contain any protection information for MicroC. So + * this function simply ignores it. + */ +void __malloc_lock(struct _reent *ptr) +{ + INT8U err; + + if (OSRunning == OS_TRUE) { + /* wait for lock to be available */ + OSSemPend(__microC_lock, 0, &err); + } + + return; +} + + +/* + * malloc/free calls this function and passes a pointer to + * the task's reent structure. This structure however does + * not contain any protection information for MicroC. So + * this function simply ignores it. + */ +void __malloc_unlock(struct _reent *ptr) +{ + if(OSRunning == OS_TRUE){ + OSSemPost( __microC_lock ); + } + + return; +} + diff --git a/Ports/LatticeMico32/GNU/MicroC_malloc_lock.h b/Ports/LatticeMico32/GNU/MicroC_malloc_lock.h new file mode 100644 index 0000000..6dbda3e --- /dev/null +++ b/Ports/LatticeMico32/GNU/MicroC_malloc_lock.h @@ -0,0 +1,18 @@ +#ifndef MICROC_MALLOC_LOCK_H_ +#define MICROC_MALLOC_LOCK_H_ + +/* + * This function must be called after initializing the + * OS (OSInit) and prior to any task calling malloc + * or free routines from within the tasks. + * + * This function need not be called if not using standard + * libc functions (especially malloc, free, printf, file-ops) + * within tasks i.e. anything that needs malloc/free. + * + * This function returns 0 if successful else returns a non-zero + * value. + */ +int InitMallocLock(void); + +#endif /*MICROC_MALLOC_LOCK_H_*/ diff --git a/Ports/LatticeMico32/GNU/os_cpu.h b/Ports/LatticeMico32/GNU/os_cpu.h new file mode 100644 index 0000000..938eca4 --- /dev/null +++ b/Ports/LatticeMico32/GNU/os_cpu.h @@ -0,0 +1,110 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* LATTICEMICO32 Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : LatticeMico32 +* Toolchain : GNU C/C++ Compiler +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned int BOOLEAN; /* BOOLEAN unsigned char */ +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; +typedef double FP64; + +typedef unsigned int OS_STK; /* Each stack entry is 32-bits wide */ +typedef unsigned int volatile OS_CPU_SR; /* The CPU Status Word is 32-bits wide. */ + +/* +********************************************************************************************************* +* CRITICAL SECTIONS MANAGEMENT +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 3 + +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} + +#endif + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() OSCtxSw() /* See OS_CPU_A.S */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +OS_CPU_SR OS_CPU_SR_Save(void); /* See OS_CPU_A.S */ +void OS_CPU_SR_Restore(OS_CPU_SR); /* See OS_CPU_A.S */ + +#endif diff --git a/Ports/LatticeMico32/GNU/os_cpu_a.s b/Ports/LatticeMico32/GNU/os_cpu_a.s new file mode 100644 index 0000000..12568bc --- /dev/null +++ b/Ports/LatticeMico32/GNU/os_cpu_a.s @@ -0,0 +1,264 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* LATTICEMICO32 Port +* +* Filename : os_cpu_a.s +* Version : V2.93.00 +********************************************************************************************************* +* For : LatticeMico32 +* Toolchain : GNU C/C++ Compiler +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSIntCtxSw + .global OSCtxSw + .global OSStartHighRdy + +/* +********************************************************************************************************* +* CODE GENERATION DIRECTIVES +********************************************************************************************************* +*/ + + .text + +/* +********************************************************************************************************* +* CRITICAL SECTION METHOD 3 FUNCTIONS +* +* Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +* void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +* +* +* Note(s) : 1) These functions are used in general like this: +* +* void Task (void *p_arg) +* { +* +* #if (OS_CRITICAL_METHOD == 3) +* OS_CPU_SR os_cpu_sr; +* #endif +* +* : +* : +* OS_ENTER_CRITICAL(); +* : +* : +* OS_EXIT_CRITICAL(); +* : +* : +* } +********************************************************************************************************* +*/ + +OS_CPU_SR_Save: + rcsr r1, ie + wcsr ie, r0 + ret + +OS_CPU_SR_Restore: + wcsr ie, r1 + ret + +/* +********************************************************************************************************* +* PERFORM A CONTEXT SWITCH +* void OSCtxSw(void) - from task level +* void OSIntCtxSw(void) - from interrupt level +* +* Note(s): 1) Upon entry: +* OSTCBCur points to the OS_TCB of the task to suspend, +* OSTCBHighRdy points to the OS_TCB of the task to resume +* 2) If the task being suspended is being suspended from a task-level, then the caller- +* saved registers are already saved and in this case we need to save callee-saved registers +* only. If the task being suspended is via a interrupt then the caller-saved registers are +* already saved by the interrupt service routine. Hence, either case, the routines remain +* the same. +* 3) We must save the state of ie and must not enable it explicitly. From an interrupt-level +* invocation, the main ISR is assumed to have set the IE-bit AND EIE-bit to zero. +* 4) Regarding EA/RA: +* a) For the task to suspend, EA does NOT need to be saved. The context switch is invoked +* by a function call, and the saved RA will be loaded into EA next time the task is +* activated. +* b) For the task to resume, EA is made the same as RA, because this function returns with +* ERET instead of RET. +********************************************************************************************************* +*/ + +OSIntCtxSw: +OSCtxSw: + xor r0, r0, r0 + addi sp, sp, -92 /* Create space on the stack */ + + /* SAVE CURRENT TASK'S CONTEXT: */ + sw (sp+ 4), r11 /* Save R11-R27 */ + sw (sp+ 8), r12 + sw (sp+12), r13 + sw (sp+16), r14 + sw (sp+20), r15 + sw (sp+24), r16 + sw (sp+28), r17 + sw (sp+32), r18 + sw (sp+36), r19 + sw (sp+40), r20 + sw (sp+44), r21 + sw (sp+48), r22 + sw (sp+52), r23 + sw (sp+56), r24 + sw (sp+60), r25 + sw (sp+64), r26 + sw (sp+68), r27 /* Save frame pointer */ + + + sw (sp+84), r1 /* Save r1, which may contain the task argument */ + rcsr r1, ie /* Save IE */ + sw (sp+72), r1 + sw (sp+80), ra /* Save RA value (see also Note #4) */ + + orhi r1, r0, hi(_impure_ptr) /* Save impure_ptr */ + ori r1, r1, lo(_impure_ptr) + lw r2, (r1+0) + sw (sp+88), r2 + + orhi r1, r0, hi(OSTCBCur) /* OSTCBCur->OSTCBStkPtr = SP; */ + ori r1, r1, lo(OSTCBCur) + lw r2, (r1+0) + sw (r2+0), sp + + calli OSTaskSwHook /* OSTaskSwHook(); */ + + orhi r1, r0, hi(OSPrioCur) /* OSPrioCur = OSPrioHighRdy; */ + ori r1, r1, lo(OSPrioCur) + orhi r2, r0, hi(OSPrioHighRdy) + ori r2, r2, lo(OSPrioHighRdy) + lb r3, (r2+0) + sb (r1+0), r3 + + orhi r1, r0, hi(OSTCBCur) /* OSTCBCur = OSTCBHighRdy; */ + ori r1, r1, lo(OSTCBCur) + orhi r2, r0, hi(OSTCBHighRdy) + ori r2, r2, lo(OSTCBHighRdy) + lw r3, (r2+0) + sw (r1+0), r3 + + lw sp, (r3+0) /* SP = OSTCBHighRdy->OSTCBStkPtr; */ + + /* RESTORE NEW TASK'S CONTEXT: */ + lw r1, (sp+72) /* Restore state of IE */ + wcsr ie, r1 + lw ea, (sp+80) /* Restore EA */ + lw ra, (sp+80) /* Restore RA */ + + + lw r11, (sp+ 4) /* Restore R11-R27 */ + lw r12, (sp+ 8) + lw r13, (sp+12) + lw r14, (sp+16) + lw r15, (sp+20) + lw r16, (sp+24) + lw r17, (sp+28) + lw r18, (sp+32) + lw r19, (sp+36) + lw r20, (sp+40) + lw r21, (sp+44) + lw r22, (sp+48) + lw r23, (sp+52) + lw r24, (sp+56) + lw r25, (sp+60) + lw r26, (sp+64) + lw r27, (sp+68) /* Restore frame pointer */ + orhi r1, r0, hi(_impure_ptr) /* Restore impure_ptr */ + ori r1, r1, lo(_impure_ptr) + lw r2, (sp+88) + sw (r1+0), r2 + lw r1, (sp+84) /* Restore r1, which may contain the task argument */ + + addi sp, sp, 92 /* Restore stack */ + eret /* Return (from exception) and copy EIE to IE */ + nop + nop + nop + nop + +/* +********************************************************************************************************* +* START MULTITASKING +* void OSStartHighRdy(void) +* +* Note(s) : 1) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE, +* c) Switch to the highest priority task. +********************************************************************************************************* +*/ + +OSStartHighRdy: + + xor r0, r0, r0 /* Disable interrupts */ + wcsr ie, r0 + + calli OSTaskSwHook /* OSTaskSwHook(); */ + + orhi r2, r0, hi(OSRunning) /* OSRunning = TRUE; */ + ori r2, r2, lo(OSRunning) + ori r3, r0, 0x1 + sw (r2+0), r3 + + /* SWITCH TO HIGHEST PRIORITY TASK: */ + orhi r1, r0, hi(OSTCBHighRdy) /* Get highest priority task TCB address */ + ori r1, r1, lo(OSTCBHighRdy) + lw r4, (r1+0) + lw sp, (r4+0) + + lw fp, (sp+68) /* Restore frame pointer */ + lw ea, (sp+80) /* Restore exception address */ + + lw r1, (sp+72) /* Restore state of IE */ + wcsr ie, r1 + + orhi r1, r0, hi(_impure_ptr) /* Restore value of impute_ptr */ + ori r1, r1, lo(_impure_ptr) + lw r2, (sp+88) + sw (r1+0), r2 + + lw r1, (sp+84) /* Restore R1; this contains the task argument */ + + addi sp, sp, 92 /* Free stack space used by register context */ + + eret /* Perform ERET to set IE bit from saved value */ + nop + nop + nop + nop diff --git a/Ports/LatticeMico32/GNU/os_cpu_c.c b/Ports/LatticeMico32/GNU/os_cpu_c.c new file mode 100644 index 0000000..9ae5166 --- /dev/null +++ b/Ports/LatticeMico32/GNU/os_cpu_c.c @@ -0,0 +1,303 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* LATTICEMICO32 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : LatticeMico32 +* Toolchain : GNU C/C++ Compiler +********************************************************************************************************* +*/ + +#include +#include + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *stk; + struct _reent *impure_ptr; + unsigned int ival; + + + stk = (INT32U *)ptos; + ival = (INT32U)ptos - sizeof(struct _reent); + impure_ptr = (struct _reent*)ival; + + _REENT_INIT_PTR(impure_ptr); + + /* Create task frame for stack */ + stk = (INT32U *)impure_ptr; + stk = stk - 23; + *(stk + 22) = (INT32U)impure_ptr; /* Load value of impure_ptr */ + *(stk + 21) = (INT32U)p_arg; /* Load the task-argument */ + *(stk + 17) = (INT32U)impure_ptr; /* Load the frame-pointer */ + *(stk + 19) = (INT32U)task; /* Load the return-address */ + *(stk + 20) = (INT32U)task; /* Load the exception return-address */ + *(stk + 18) = 0x2; /* Set the state of ie to perform an eret with ... */ + /* ... interrupts enabled */ + + return ((OS_STK *)stk); /* Return the new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif + +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/LatticeMico32/GNU/os_dbg.c b/Ports/LatticeMico32/GNU/os_dbg.c new file mode 100644 index 0000000..a69a2ca --- /dev/null +++ b/Ports/LatticeMico32/GNU/os_dbg.c @@ -0,0 +1,305 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* LATTICEMICO32 Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : LatticeMico32 +* Toolchain : GNU C/C++ Compiler +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #ff 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/M14K/CodeSourcery/os_cpu.h b/Ports/M14K/CodeSourcery/os_cpu.h new file mode 100644 index 0000000..529538e --- /dev/null +++ b/Ports/M14K/CodeSourcery/os_cpu.h @@ -0,0 +1,113 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MIPS14K +* MicroMips +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include "cpu.h" + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8-bit quantity */ +typedef signed char INT8S; /* Signed 8-bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16-bit quantity */ +typedef signed short INT16S; /* Signed 16-bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32-bit quantity */ +typedef signed int INT32S; /* Signed 32-bit quantity */ +typedef float FP32; +typedef double FP64; + +typedef unsigned int OS_STK; /* Each stack entry is 32 bits wide */ +typedef unsigned int volatile OS_CPU_SR; /* The CPU Status Word is 32-bits wide. This variable*/ + /* MUST be volatile for proper operation. Refer to */ + /* os_cpu_a.s for more details. */ + +/* +********************************************************************************************************* +* CRITICAL SECTIONS MANAGEMENT +* +* Method #1: Disable/Enable interrupts using simple instructions. After a critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts and preserve the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts and preserve the state of interrupts. Generally speaking, you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save(); +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr); + +/* +********************************************************************************************************* +* M14K +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("\tsyscall\n"); + + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +void OSIntCtxSw(void); +void OSStartHighRdy(void); +void ExceptionHandler(void); +void InterruptHandler(void); + +void TickInterruptClear(void); +void CoreTmrInit(CPU_INT32U tmr_reload); +void TickISR(CPU_INT32U tmr_reload); + +OS_CPU_SR OS_CPU_SR_Save(void); /* See os_cpu_a.s */ +void OS_CPU_SR_Restore(OS_CPU_SR); /* See os_cpu_a.s */ + + + diff --git a/Ports/M14K/CodeSourcery/os_cpu_a.S b/Ports/M14K/CodeSourcery/os_cpu_a.S new file mode 100644 index 0000000..6b88b92 --- /dev/null +++ b/Ports/M14K/CodeSourcery/os_cpu_a.S @@ -0,0 +1,841 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MIPS14K +* MicroMips +* +* Filename : os_cpu_a.S +* Version : V2.93.00 +********************************************************************************************************* +*/ + + .section .text,"ax",@progbits + .set noreorder + .set noat + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + + .global OSStartHighRdy + .global OSIntCtxSw + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global InterruptHandler + .global ExceptionHandler + .global TickInterruptClear + .global CoreTmrInit + .global TickISR + .global DisableInterruptSource + .global EnableInterruptSource + +/* +********************************************************************************************************* +* CONSTANTS USED TO ACCESS TASK CONTEXT STACK +********************************************************************************************************* +*/ + +.equ STK_OFFSET_SR, 4 +.equ STK_OFFSET_EPC, STK_OFFSET_SR + 4 +.equ STK_OFFSET_LO, STK_OFFSET_EPC + 4 +.equ STK_OFFSET_HI, STK_OFFSET_LO + 4 +.equ STK_OFFSET_GPR1, STK_OFFSET_HI + 4 +.equ STK_OFFSET_GPR2, STK_OFFSET_GPR1 + 4 +.equ STK_OFFSET_GPR3, STK_OFFSET_GPR2 + 4 +.equ STK_OFFSET_GPR4, STK_OFFSET_GPR3 + 4 +.equ STK_OFFSET_GPR5, STK_OFFSET_GPR4 + 4 +.equ STK_OFFSET_GPR6, STK_OFFSET_GPR5 + 4 +.equ STK_OFFSET_GPR7, STK_OFFSET_GPR6 + 4 +.equ STK_OFFSET_GPR8, STK_OFFSET_GPR7 + 4 +.equ STK_OFFSET_GPR9, STK_OFFSET_GPR8 + 4 +.equ STK_OFFSET_GPR10, STK_OFFSET_GPR9 + 4 +.equ STK_OFFSET_GPR11, STK_OFFSET_GPR10 + 4 +.equ STK_OFFSET_GPR12, STK_OFFSET_GPR11 + 4 +.equ STK_OFFSET_GPR13, STK_OFFSET_GPR12 + 4 +.equ STK_OFFSET_GPR14, STK_OFFSET_GPR13 + 4 +.equ STK_OFFSET_GPR15, STK_OFFSET_GPR14 + 4 +.equ STK_OFFSET_GPR16, STK_OFFSET_GPR15 + 4 +.equ STK_OFFSET_GPR17, STK_OFFSET_GPR16 + 4 +.equ STK_OFFSET_GPR18, STK_OFFSET_GPR17 + 4 +.equ STK_OFFSET_GPR19, STK_OFFSET_GPR18 + 4 +.equ STK_OFFSET_GPR20, STK_OFFSET_GPR19 + 4 +.equ STK_OFFSET_GPR21, STK_OFFSET_GPR20 + 4 +.equ STK_OFFSET_GPR22, STK_OFFSET_GPR21 + 4 +.equ STK_OFFSET_GPR23, STK_OFFSET_GPR22 + 4 +.equ STK_OFFSET_GPR24, STK_OFFSET_GPR23 + 4 +.equ STK_OFFSET_GPR25, STK_OFFSET_GPR24 + 4 +.equ STK_OFFSET_GPR26, STK_OFFSET_GPR25 + 4 +.equ STK_OFFSET_GPR27, STK_OFFSET_GPR26 + 4 +.equ STK_OFFSET_GPR28, STK_OFFSET_GPR27 + 4 +.equ STK_OFFSET_GPR30, STK_OFFSET_GPR28 + 4 +.equ STK_OFFSET_GPR31, STK_OFFSET_GPR30 + 4 +.equ STK_CTX_SIZE, STK_OFFSET_GPR31 + 4 + +/* +********************************************************************************************************* +* OSStartHighRdy() +* +* Description: Starts the highest priority task that is available to run. OSStartHighRdy() MUST: +* +* a) Call OSTaskSwHook() +* b) Set OSRunning to TRUE +* c) Switch to the highest priority task. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +* +* Note(s): 1) OSTaskStkInit(), which is responsible for initializing each task's stack, sets bit 0 of the +* entry corresponding to the Status register. Thus, interrupts will be enabled when each +* task first runs. +********************************************************************************************************* +*/ + + .ent OSStartHighRdy +OSStartHighRdy: + + la $8, OSTaskSwHook /* Call OSTaskSwHook() */ + + addu $9, $31, $0 /* Mask off the ISAMode bit */ + srl $9, 16 + andi $31, 0xFFFE + sll $9, 16 + addu $31, $31, $9 + + jalr $8 + nop + + addi $8, $0, 1 /* Indicate that the OS is running */ + la $9, OSRunning + sb $8, 0($9) + + la $8, OSTCBHighRdy /* Update the current TCB */ + lw $9, 0($8) + lw $29, 0($9) /* Load the new task's stack pointer */ + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mthi $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + ei + + jr $31 /* Resume execution in the new task */ + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + + .end OSStartHighRdy + +/* +********************************************************************************************************* +* OSIntCtxSw() +* +* Description: This function is used to perform a context switch following an ISR. +* +* OSIntCtxSw() implements the following pseudo-code: +* +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore the Status register and the EPC to their prior states; +* Restore the LO and HI registers; +* Restore each of the general purpose registers; +* Adjust the stack pointer; +* Execute an eret instruction to begin executing the new task; +* +* Upon entry, the registers of the task being suspended have already been saved onto that +* task's stack and the SP for the task has been saved in its OS_TCB by the ISR. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + + .ent OSIntCtxSw +OSIntCtxSw: + + la $8, OSTaskSwHook /* Call OSTaskSwHook() */ + + addu $9, $31, $0 /* Mask off the ISAMode bit */ + srl $9, 16 + andi $31, 0xFFFE + sll $9, 16 + addu $31, $31, $9 + + jalr $8 + nop + + la $8, OSPrioHighRdy /* Update the current priority */ + lbu $9, 0($8) + la $10, OSPrioCur + sb $9, 0($10) + + la $8, OSTCBHighRdy /* Update the current TCB */ + lw $9, 0($8) + la $10, OSTCBCur + sw $9, 0($10) + + lw $29, 0($9) /* Load the new task's stack pointer */ + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mthi $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + + ei + + eret /* Resume execution in new task */ + + .end OSIntCtxSw + +/* +********************************************************************************************************* +* DISABLE INTERRUPTS +* OS_CPU_SR OS_CPU_SR_Save(void); +* +* Description: This function saves the state of the Status register and then disables interrupts via this +* register. This objective is accomplished with a single instruction, di. The di +* instruction's operand, $2, is the general purpose register to which the Status register's +* value is saved. This value can be read by C functions that call OS_CPU_SR_Save(). +* +* Arguments : None +* +* Returns : The previous state of the Status register +********************************************************************************************************* +*/ + + .ent OS_CPU_SR_Save +OS_CPU_SR_Save: + + jr $31 + di $2 /* Disable interrupts, and move the old value of the... */ + /* ...Status register into v0 ($2) */ + .end OS_CPU_SR_Save + +/* +********************************************************************************************************* +* ENABLE INTERRUPTS +* void OS_CPU_SR_Restore(OS_CPU_SR sr); +* +* Description: This function must be used in tandem with OS_CPU_SR_Save(). Calling OS_CPU_SR_Restore() +* causes the value returned by OS_CPU_SR_Save() to be placed in the Status register. +* +* Arguments : The value to be placed in the Status register +* +* Returns : None +********************************************************************************************************* +*/ + + .ent OS_CPU_SR_Restore +OS_CPU_SR_Restore: + + jr $31 + mtc0 $4, $12, 0 /* Restore the status register to its previous state */ + + .end OS_CPU_SR_Restore + + .section .timer_handler,"ax",@progbits + +/* +********************************************************************************************************* +* InterruptHandler +* +* Description: This function handles all generated hardware interrupts, saving the current task's +* context. The task is then restored once the pending interrupts have been processed. +* +* The interrupted task's context is saved onto its stack as follows: +* +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + + .ent InterruptHandler +InterruptHandler: + di /* Disable Interrupts */ + + addi $29, $29, -STK_CTX_SIZE /* Adjust the stack pointer */ + + sw $1, STK_OFFSET_GPR1($29) /* Save the General Pupose Registers */ + sw $2, STK_OFFSET_GPR2($29) + sw $3, STK_OFFSET_GPR3($29) + sw $4, STK_OFFSET_GPR4($29) + sw $5, STK_OFFSET_GPR5($29) + sw $6, STK_OFFSET_GPR6($29) + sw $7, STK_OFFSET_GPR7($29) + sw $8, STK_OFFSET_GPR8($29) + sw $9, STK_OFFSET_GPR9($29) + sw $10, STK_OFFSET_GPR10($29) + sw $11, STK_OFFSET_GPR11($29) + sw $12, STK_OFFSET_GPR12($29) + sw $13, STK_OFFSET_GPR13($29) + sw $14, STK_OFFSET_GPR14($29) + sw $15, STK_OFFSET_GPR15($29) + sw $16, STK_OFFSET_GPR16($29) + sw $17, STK_OFFSET_GPR17($29) + sw $18, STK_OFFSET_GPR18($29) + sw $19, STK_OFFSET_GPR19($29) + sw $20, STK_OFFSET_GPR20($29) + sw $21, STK_OFFSET_GPR21($29) + sw $22, STK_OFFSET_GPR22($29) + sw $23, STK_OFFSET_GPR23($29) + sw $24, STK_OFFSET_GPR24($29) + sw $25, STK_OFFSET_GPR25($29) + sw $26, STK_OFFSET_GPR26($29) + sw $27, STK_OFFSET_GPR27($29) + sw $28, STK_OFFSET_GPR28($29) + sw $30, STK_OFFSET_GPR30($29) + sw $31, STK_OFFSET_GPR31($29) + /* Save the contents of the LO and HI registers */ + mflo $8 + mfhi $9 + sw $8, STK_OFFSET_LO($29) + sw $9, STK_OFFSET_HI($29) + + mfc0 $8, $14, 0 /* Save the EPC */ + sw $8, STK_OFFSET_EPC($29) + + mfc0 $8, $12, 0 + sw $8, STK_OFFSET_SR($29) + + la $8, OSIntNesting /* See if OSIntNesting == 0 */ + lbu $9, 0($8) + bne $0, $9, TICK_INC_NESTING + nop + + la $10, OSTCBCur /* Save the current task's stack pointer */ + lw $11, 0($10) + sw $29, 0($11) + +TICK_INC_NESTING: + + addi $9, $9, 1 /* Increment OSIntNesting */ + sb $9, 0($8) + +INT_LOOP: + + mfc0 $8, $13 /* Get the "Interrupt Pending" field from the Cause reg */ + + li $9, 0x3 /* Mask out the "Interrupt Pending" field */ + sll $9, 16 + li $10, 0xFC00 + addu $9, $10 + + and $8, $9 + + clz $8, $8 /* Count leading zeros to find all pending interrupts */ + move $4, $8 + la $8, BSP_Interrupt_Handler /* Call BSP_Interrupt_Handler() to handle the interrupt */ + + li $9, 32 /* Load the compared value for the loop(while cnt != 32)*/ + beq $4, $9, INT_LOOP_END + nop + + addu $9, $31, $0 /* Mask off the ISAMode bit */ + srl $9, 16 + andi $31, 0xFFFE + sll $9, 16 + addu $31, $31, $9 + + jalr $8 + nop + + b INT_LOOP + nop + +INT_LOOP_END: + + la $8, OSIntExit /* Call OSIntExit() */ + + addu $9, $31, $0 /* Mask off the ISAMode bit */ + srl $9, 16 + andi $31, 0xFFFE + sll $9, 16 + addu $31, $31, $9 + + jalr $8 + nop + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mtlo $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + + ei /* Enable Interrupts */ + + eret + + .end InterruptHandler + + .section .gen_excpt,"ax",@progbits + +/* +********************************************************************************************************* +* ExceptionHandler +* +* Description: This function handles all generated exceptions, saving the current task's context. The +* task is then restored once the pending interrupts have been processed. +* +* The interrupted task's context is saved onto its stack as follows: +* +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + + .ent ExceptionHandler +ExceptionHandler: + di + + addi $29, $29, -STK_CTX_SIZE /* Adjust the stack pointer */ + + sw $1, STK_OFFSET_GPR1($29) /* Save the General Pupose Registers */ + sw $2, STK_OFFSET_GPR2($29) + sw $3, STK_OFFSET_GPR3($29) + sw $4, STK_OFFSET_GPR4($29) + sw $5, STK_OFFSET_GPR5($29) + sw $6, STK_OFFSET_GPR6($29) + sw $7, STK_OFFSET_GPR7($29) + sw $8, STK_OFFSET_GPR8($29) + sw $9, STK_OFFSET_GPR9($29) + sw $10, STK_OFFSET_GPR10($29) + sw $11, STK_OFFSET_GPR11($29) + sw $12, STK_OFFSET_GPR12($29) + sw $13, STK_OFFSET_GPR13($29) + sw $14, STK_OFFSET_GPR14($29) + sw $15, STK_OFFSET_GPR15($29) + sw $16, STK_OFFSET_GPR16($29) + sw $17, STK_OFFSET_GPR17($29) + sw $18, STK_OFFSET_GPR18($29) + sw $19, STK_OFFSET_GPR19($29) + sw $20, STK_OFFSET_GPR20($29) + sw $21, STK_OFFSET_GPR21($29) + sw $22, STK_OFFSET_GPR22($29) + sw $23, STK_OFFSET_GPR23($29) + sw $24, STK_OFFSET_GPR24($29) + sw $25, STK_OFFSET_GPR25($29) + sw $26, STK_OFFSET_GPR26($29) + sw $27, STK_OFFSET_GPR27($29) + sw $28, STK_OFFSET_GPR28($29) + sw $30, STK_OFFSET_GPR30($29) + sw $31, STK_OFFSET_GPR31($29) + /* Save the contents of the LO and HI registers */ + mflo $8 + mfhi $9 + sw $8, STK_OFFSET_LO($29) + sw $9, STK_OFFSET_HI($29) + + mfc0 $8, $14, 0 /* Save the EPC */ + addi $8, $8, 4 + sw $8, STK_OFFSET_EPC($29) + + mfc0 $8, $12, 0 + sw $8, STK_OFFSET_SR($29) + + la $10, OSTCBCur /* Save the current task's stack pointer */ + lw $11, 0($10) + sw $29, 0($11) + + la $8, BSP_Exception_Handler /* Call BSP_ISR_Handler() to handle the interrupt */ + + addu $9, $31, $0 /* Mask off the ISAMode bit */ + srl $9, 16 + andi $31, 0xFFFE + sll $9, 16 + addu $31, $31, $9 + + jalr $8 + nop + + la $10, OSTCBCur + lw $9, 0($10) + + lw $29, 0($9) /* Load the new task's stack pointer */ + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mtlo $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + + ei + + eret + + .end ExceptionHandler + +/* +********************************************************************************************************* +* TickInterruptClear() +* +* Description : This function writes a value of '0' to the Compare register so that the timer interrupt +* pending is cleared +* +* Arguments : None +* +* Returns : None +* +* Note(s) : This function MUST be called before OSStart due to the fact that the count register is +* automatically started at run time. Because of this, the timer interrupt occurs during +* the start up code and before the initialization of the Tick ISR, which should be done +* in the first task +********************************************************************************************************* +*/ + + .ent TickInterruptClear +TickInterruptClear: + + mtc0 $0, $11 /* Set up the period in the compare reg */ + jr $31 + ehb + + .end TickInterruptClear + +/* +********************************************************************************************************* +* CoreTmrInit() +* +* Description: This function should initialize the timers used by your application +* +* Arguments : tmr_reload($4) Value that the compare register is incremented by to simulate the correct + clock frequency +* +* Returns : None +********************************************************************************************************* +*/ + + .ent CoreTmrInit +CoreTmrInit: + + mtc0 $4, $11 /* Set up the period in the compare reg */ + ehb + mtc0 $0, $9 /* Clear the count reg */ + jr $31 + ehb + + .end CoreTmrInit + +/* +********************************************************************************************************* +* TickISR() +* +* Description : This function provides the ISR executed at each Core clock tick +* +* Arguments : tmr_reload($4) Value that the compare register is incremented by to simulate the correct +* clock frequency +* +* Returns : None +********************************************************************************************************* +*/ + + .ent TickISR +TickISR: + + move $16, $31 + + mfc0 $8, $11 /* Get the old compare time */ + addu $8, $4 /* Add the increment value BSP_TMR_RELOAD */ + mtc0 $8, $11 /* Set up the period in the compare reg */ + + la $8, OSTimeTick /* Call OSTimeTick() to signal to the OS a clock tick */ + + addu $9, $31, $0 /* Mask off the ISAMode bit */ + srl $9, 16 + andi $31, 0xFFFE + sll $9, 16 + addu $31, $31, $9 + + jalr $8 + nop + + move $31, $16 + jr $31 + nop + + .end TickISR + +/* +********************************************************************************************************* +* DisableInterruptSource() +* +* Description : This function disables a particular hardware interrupt source +* +* Arguments : src_nbr($4) Hardware interrupt source to disable +* +* Returns : None +********************************************************************************************************* +*/ + + .ent DisableInterruptSource +DisableInterruptSource: + + mfc0 $8, $12 + and $8, $4 + mtc0 $8, $12 + jr $31 + nop + + .end DisableInterruptSource + +/* +********************************************************************************************************* +* EnableInterruptSource() +* +* Description : This function enables a particular hardware interrupt source +* +* Arguments : src_nbr($4) Hardware interrupt source to enable +* +* Returns : None +********************************************************************************************************* +*/ + + .ent EnableInterruptSource +EnableInterruptSource: + + sll $4, 10 + mfc0 $8, $12 + or $8, $4 + mtc0 $8, $12 + jr $31 + nop + + .end EnableInterruptSource + + + + + + diff --git a/Ports/M14K/CodeSourcery/os_cpu_c.c b/Ports/M14K/CodeSourcery/os_cpu_c.c new file mode 100644 index 0000000..b0914b8 --- /dev/null +++ b/Ports/M14K/CodeSourcery/os_cpu_c.c @@ -0,0 +1,369 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MIPS14K +* MicroMips +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + +#include "includes.h" + +/* +********************************************************************************************************* +* HARDWARE INTERRUPT VECTOR +********************************************************************************************************* +*/ + +extern char vec[], endvec[]; /* Create the hardware interrupt vector */ +asm (".set push\n" + ".set nomicromips\n" + ".align 2\n" + "vec:\n" + "\tla $26,InterruptHandler\n" + "\tjr $26\n" + "endvec:\n" + ".set pop\n"); + +/* +********************************************************************************************************* +* EXCEPTION VECTOR +********************************************************************************************************* +*/ + +extern char vec2[], endvec2[]; /* Create the exception vector */ +asm (".set push\n" + ".set nomicromips\n" + ".align 2\n" + "vec2:\n" + "\tla $26,ExceptionHandler\n" + "\tjr $26\n" + "endvec2:\n" + ".set pop\n"); + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : None +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ + memcpy ((void *) 0x80000200, vec, endvec - vec); /* Install the hardware interrupt vector */ + memcpy ((void *) 0x80000180, vec2, endvec2 - vec2); /* Install the exception vector */ + mips_clean_cache (0x80000200, 0x80); /* Remove the old vectors from cache. */ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : None +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called whenever a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called when a task returns without being properly deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task that was accidently returned. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskReturnHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : None +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : None +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is processor-specific. +* +* Arguments : task is a pointer to the task code. +* +* p_arg is a pointer to a user supplied data area +* +* ptos is a pointer to the top of stack. OSTaskStkInit() assumes that 'ptos' points to +* a free entry on the stack. If OS_STK_GROWTH is set to 1 then 'ptos' will contain +* the HIGHEST valid address of the stack. Similarly, if OS_STK_GROWTH is set to 0, +* 'ptos' will contain the lowest valid address of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit() +* (see ucos_ii.h for OS_TASK_OPT_???). +* +* Returns : The location corresponding to the top of the stack +* +* Note(s) : 1) Interrupts are enabled when each task starts executing. +* +* 2) An initialized stack has the structure shown below. +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* + 0x24 GPR[5] +* + 0x28 GPR[6] +* + 0x2C GPR[7] +* + 0x30 GPR[8] +* + 0x34 GPR[9] +* + 0x38 GPR[10] +* + 0x3C GPR[11] +* + 0x40 GPR[12] +* + 0x44 GPR[13] +* + 0x48 GPR[14] +* + 0x4C GPR[15] +* + 0x50 GPR[16] +* + 0x54 GPR[17] +* + 0x58 GPR[18] +* + 0x5C GPR[19] +* + 0x60 GPR[20] +* + 0x64 GPR[21] +* + 0x68 GPR[22] +* + 0x6C GPR[23] +* + 0x70 GPR[24] +* + 0x74 GPR[25] +* + 0x78 GPR[26] +* + 0x7C GPR[27] +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + INT32U *pstk; + INT32U sr_val; + INT32U gp_val; + + + (void)opt; /* Prevent compiler warning for unused arguments */ + + asm volatile("mfc0 %0,$12" : "=r"(sr_val)); + sr_val |= 0x0000C001; /* Initialize stack to allow for tick interrupt */ + + asm volatile("addi %0,$28,0" : "=r"(gp_val)); + + pstk = (INT32U *)ptos; + + pstk--; /* Ensure that a free entry is being referenced */ + *pstk-- = (INT32U)task; /* GPR[31] (ra) is used by OSStartHighRdy() */ + *pstk-- = (INT32U)0x30303030; /* GPR[30] */ + *pstk-- = gp_val; /* GPR[28] */ + *pstk-- = (INT32U)0x27272727; /* GPR[27] */ + *pstk-- = (INT32U)0x26262626; /* GPR[26] */ + *pstk-- = (INT32U)0x25252525; /* GPR[25] */ + *pstk-- = (INT32U)0x24242424; /* GPR[24] */ + *pstk-- = (INT32U)0x23232323; /* GPR[23] */ + *pstk-- = (INT32U)0x22222222; /* GPR[22] */ + *pstk-- = (INT32U)0x21212121; /* GPR[21] */ + *pstk-- = (INT32U)0x20202020; /* GPR[20] */ + *pstk-- = (INT32U)0x19191919; /* GPR[19] */ + *pstk-- = (INT32U)0x18181818; /* GPR[18] */ + *pstk-- = (INT32U)0x17171717; /* GPR[17] */ + *pstk-- = (INT32U)0x16161616; /* GPR[16] */ + *pstk-- = (INT32U)0x15151515; /* GPR[15] */ + *pstk-- = (INT32U)0x14141414; /* GPR[14] */ + *pstk-- = (INT32U)0x13131313; /* GPR[13] */ + *pstk-- = (INT32U)0x12121212; /* GPR[12] */ + *pstk-- = (INT32U)0x11111111; /* GPR[11] */ + *pstk-- = (INT32U)0x10101010; /* GPR[10] */ + *pstk-- = (INT32U)0x09090909; /* GPR[9] */ + *pstk-- = (INT32U)0x08080808; /* GPR[8] */ + *pstk-- = (INT32U)0x07070707; /* GPR[7] */ + *pstk-- = (INT32U)0x06060606; /* GPR[6] */ + *pstk-- = (INT32U)0x05050505; /* GPR[5] */ + *pstk-- = (INT32U)0x04040404; /* GPR[4] */ + *pstk-- = (INT32U)0x03030303; /* GPR[3] */ + *pstk-- = (INT32U)0x02020202; /* GPR[2] */ + *pstk-- = (INT32U)0x01010101; /* GPR[1] */ + *pstk-- = (INT32U)0x00000000; /* Special Purpose HI Register */ + *pstk-- = (INT32U)0x00000000; /* Special Purpose LO Register */ + *pstk-- = (INT32U)task; /* EPC */ + *pstk-- = sr_val; /* SR */ + + return ((OS_STK *)pstk); /* Return new top of stack */ +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform +* other operations during a contex switch. +* +* Arguments : None +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer OSTCBHighRdy points to the TCB of the task that +* will be switched in (i.e. the highest priority task), and that OSTCBCur points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called after every tick interrupt. +* +* Arguments : None +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif + diff --git a/Ports/M16C/M16C60/HEW/os_cpu.h b/Ports/M16C/M16C60/HEW/os_cpu.h new file mode 100644 index 0000000..7913b25 --- /dev/null +++ b/Ports/M16C/M16C60/HEW/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef INT16U OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M16C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 1 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() asm("STC FLG, $@", cpu_sr);asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("LDC $@, FLG", cpu_sr) /* Enable interrupts */ +#endif +/* +********************************************************************************************************* +* RENESAS M16C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/M16C/M16C60/HEW/os_cpu_a.a30 b/Ports/M16C/M16C60/HEW/os_cpu_a.a30 new file mode 100644 index 0000000..25e66b2 --- /dev/null +++ b/Ports/M16C/M16C60/HEW/os_cpu_a.a30 @@ -0,0 +1,200 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas M16C Port +; +; Filename : os_cpu_a.a30 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas M16C +; Toolchain : Renesas HEW IDE with the NC30 compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .GLB _OSTCBCur ; Declared as OS_TCB * , 32-bit long + .GLB _OSTCBHighRdy ; Declared as OS_TCB * , 32-bit long + .GLB _OSPrioCur ; Declared as INT8U , 8-bit long + .GLB _OSPrioHighRdy ; Declared as INT8U , 8-bit long + .GLB _OSIntNesting ; Declared as INT8U , 8-bit long + .GLB _OSRunning ; Declared as Boolean (unsigned char), 8-bit long + + .GLB _OSIntExit ; External functions written in C + .GLB _OSTimeTick + .GLB _OSTaskSwHook + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + + .SECTION program + .GLB _OSStartHighRdy + +_OSStartHighRdy: + JSR _OSTaskSwHook + + MOV.W _OSTCBHighRdy, A0 ; ISP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + MOV.B #01H, _OSRunning ; OSRunning = TRUE + + POPM R0,R1,R2,R3,A0,A1,SB,FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + + .SECTION program + .GLB _OSCtxSw + +_OSCtxSw: + PUSHM R0,R1,R2,R3,A0,A1,SB,FB + + MOV.W _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] + + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.W _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + + .SECTION program + .GLB _OSIntCtxSw + +_OSIntCtxSw: + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.W _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + + .SECTION program + .GLB _OSTickISR + +_OSTickISR: + + PUSHM R0,R1,R2,R3,A0,A1,SB,FB ; Save current task's registers + + INC.B _OSIntNesting ; OSIntNesting++ + CMP.B #1,_OSIntNesting ; if (OSIntNesting == 1) { + JNE _OSTickISR1 + + MOV.W _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] ; } + +_OSTickISR1: + JSR _OSTimeTick ; OSTimeTick() + + JSR _OSIntExit ; OSIntExit() + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack + + REIT + + + + .END diff --git a/Ports/M16C/M16C60/HEW/os_cpu_c.c b/Ports/M16C/M16C60/HEW/os_cpu_c.c new file mode 100644 index 0000000..5678662 --- /dev/null +++ b/Ports/M16C/M16C60/HEW/os_cpu_c.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 16 bits wide. +* +* +--------+--------+-----------------+ +* SP ----> | FLG(H) | PC(H) | FLG (L) | +* +-----------------------------------+ +* | PC(L) | +* +-----------------------------------+ +* | FB | +* +-----------------------------------+ +* | SB | +* +-----------------------------------+ +* | A1 | +* +-----------------------------------+ +* | A0 | +* +-----------------------------------+ +* | R3 | +* +-----------------------------------+ +* | pdata(H) (R1) | +* +-----------------------------------+ +* | pdata(L) (R1) | +* +-----------------------------------+ +* PTOS ----> | R0 | +* +-----------------------------------+ +* +********************************************************************************************************* +*/ + + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk16; + INT16U flag; + + + flag = 0x0040; + pstk16 = (INT16U *)ptos; + pstk16--; + + /* Simulate ISR entry */ + *pstk16-- = (flag & 0x00FF) /* ... The lowest byte of the FLAG register */ + | (((INT32U)task >> 8) & 0x00000F00) /* ... The highest nibble of the PC register */ + | ((flag << 4) & 0xF000); /* ... The highest nibble of the FLAG register */ + *pstk16-- = (((INT32U)task ) & 0x0000FFFF); /* ... The lowest bytes of the PC register */ + + /* Save registers onto stack frame */ + *pstk16-- = (INT16U)0xFBFB; /* ... FB register */ + *pstk16-- = (INT16U)0x3B3B; /* ... SB register */ + *pstk16-- = (INT16U)0xA1A1; /* ... A1 register */ + *pstk16-- = (INT16U)0xA0A0; /* ... A0 register */ + *pstk16-- = (INT16U)0x3333; /* ... R3 register */ + *pstk16-- = (INT32U)pdata >> 16L; /* ... Pass argument in R2 register */ + *pstk16-- = (INT32U)pdata & 0x0000FFFFL; /* ... Pass argument in R1 register */ + *pstk16 = (INT16U)0x0000; /* ... R0 register */ + + return ((OS_STK *)pstk16); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/M16C/M16C60/HEW/os_dbg.c b/Ports/M16C/M16C60/HEW/os_dbg.c new file mode 100644 index 0000000..c301ad9 --- /dev/null +++ b/Ports/M16C/M16C60/HEW/os_dbg.c @@ -0,0 +1,273 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#include + + /* The following #define tells the IAR compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/M16C/M16C60/IAR/os_cpu.h b/Ports/M16C/M16C60/IAR/os_cpu.h new file mode 100644 index 0000000..e6dae80 --- /dev/null +++ b/Ports/M16C/M16C60/IAR/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : IAR's EW for M16C +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef INT16U OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M16C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 1 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() asm("STC FLG, $@", cpu_sr);asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("LDC $@, FLG", cpu_sr) /* Enable interrupts */ +#endif +/* +********************************************************************************************************* +* RENESAS M16C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/M16C/M16C60/IAR/os_cpu_a.asm b/Ports/M16C/M16C60/IAR/os_cpu_a.asm new file mode 100644 index 0000000..5b5b82b --- /dev/null +++ b/Ports/M16C/M16C60/IAR/os_cpu_a.asm @@ -0,0 +1,198 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas M16C Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas M16C +; Toolchain : IAR's EW for M16C +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + RSEG CSTACK + + RSEG ISTACK + + RSEG UDATA0 + + EXTERN OSTCBCur ; Declared as OS_TCB * , 32-bit long + EXTERN OSTCBHighRdy ; Declared as OS_TCB * , 32-bit long + EXTERN OSPrioCur ; Declared as INT8U , 8-bit long + EXTERN OSPrioHighRdy ; Declared as INT8U , 8-bit long + EXTERN OSIntNesting ; Declared as INT8U , 8-bit long + EXTERN OSRunning ; Declared as Boolean (unsigned char), 8-bit long + + RSEG CODE(1) + + EXTERN OSIntExit ; External functions written in C + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + .EVEN + +OSStartHighRdy: + JSR OSTaskSwHook + + MOV.W OSTCBHighRdy, A0 ; ISP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + MOV.B #01H, OSRunning ; OSRunning = TRUE + + POPM R0,R1,R2,R3,A0,A1,SB,FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + + .EVEN + +OSCtxSw: + PUSHM R0,R1,R2,R3,A0,A1,SB,FB + + MOV.W OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] + + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.W OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + + .EVEN + +OSIntCtxSw: + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.W OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + + .EVEN + +OSTickISR: + + PUSHM R0,R1,R2,R3,A0,A1,SB,FB ; Save current task's registers + + INC.B OSIntNesting ; OSIntNesting++ + CMP.B #1,OSIntNesting ; if (OSIntNesting == 1) { + JNE OSTickISR1 + + MOV.W OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] ; } + +OSTickISR1: + JSR OSTimeTick ; OSTimeTick() + + JSR OSIntExit ; OSIntExit() + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack + + REIT + + + + END diff --git a/Ports/M16C/M16C60/IAR/os_cpu_c.c b/Ports/M16C/M16C60/IAR/os_cpu_c.c new file mode 100644 index 0000000..df1fe80 --- /dev/null +++ b/Ports/M16C/M16C60/IAR/os_cpu_c.c @@ -0,0 +1,319 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : IAR's EW for M16C +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 16 bits wide. +* +* +--------+--------+-----------------+ +* SP ----> | FLG(H) | PC(H) | FLG (L) | +* +-----------------------------------+ +* | PC(L) | +* +-----------------------------------+ +* | FB | +* +-----------------------------------+ +* | SB | +* +-----------------------------------+ +* | A1 | +* +-----------------------------------+ +* | A0 | +* +-----------------------------------+ +* | R3 | +* +-----------------------------------+ +* | pdata(H) (R1) | +* +-----------------------------------+ +* | pdata(L) (R1) | +* +-----------------------------------+ +* PTOS ----> | R0 | +* +-----------------------------------+ +* +********************************************************************************************************* +*/ + + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk16; + INT16U flag; + + + flag = 0x0040; + pstk16 = (INT16U *)ptos; + pstk16--; + + /* Simulate ISR entry */ + *pstk16-- = (flag & 0x00FF) /* ... The lowest byte of the FLAG register */ + | (((INT32U)task >> 8) & 0x00000F00) /* ... The highest nibble of the PC register */ + | ((flag << 4) & 0xF000); /* ... The highest nibble of the FLAG register */ + *pstk16-- = (((INT32U)task ) & 0x0000FFFF); /* ... The lowest bytes of the PC register */ + + /* Save registers onto stack frame */ + *pstk16-- = (INT16U)0xFBFB; /* ... FB register */ + *pstk16-- = (INT16U)0x3B3B; /* ... SB register */ + *pstk16-- = (INT16U)0xA1A1; /* ... A1 register */ + *pstk16-- = (INT16U)0xA0A0; /* ... A0 register */ + *pstk16-- = (INT16U)0x3333; /* ... R3 register */ + *pstk16-- = (INT32U)pdata >> 16L; /* ... Pass argument in R2 register */ + *pstk16-- = (INT32U)pdata & 0x0000FFFFL; /* ... Pass argument in R1 register */ + *pstk16 = (INT16U)0x0000; /* ... R0 register */ + + return ((OS_STK *)pstk16); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/M16C/M16C60/IAR/os_dbg.c b/Ports/M16C/M16C60/IAR/os_dbg.c new file mode 100644 index 0000000..b220fb0 --- /dev/null +++ b/Ports/M16C/M16C60/IAR/os_dbg.c @@ -0,0 +1,273 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : IAR's EW for M16C +********************************************************************************************************* +*/ + +#include + + /* The following #define tells the IAR compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/M16C/Tiny/HEW/os_cpu.h b/Ports/M16C/Tiny/HEW/os_cpu.h new file mode 100644 index 0000000..7913b25 --- /dev/null +++ b/Ports/M16C/Tiny/HEW/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef INT16U OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M16C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 1 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() asm("STC FLG, $@", cpu_sr);asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("LDC $@, FLG", cpu_sr) /* Enable interrupts */ +#endif +/* +********************************************************************************************************* +* RENESAS M16C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/M16C/Tiny/HEW/os_cpu_a.a30 b/Ports/M16C/Tiny/HEW/os_cpu_a.a30 new file mode 100644 index 0000000..bebefc7 --- /dev/null +++ b/Ports/M16C/Tiny/HEW/os_cpu_a.a30 @@ -0,0 +1,201 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas M16C Port +; +; Filename : os_cpu_a.a30 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas M16C +; Toolchain : Renesas HEW IDE with the NC30 compiler +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .GLB _OSTCBCur ; Declared as OS_TCB * , 32-bit long + .GLB _OSTCBHighRdy ; Declared as OS_TCB * , 32-bit long + .GLB _OSPrioCur ; Declared as INT8U , 8-bit long + .GLB _OSPrioHighRdy ; Declared as INT8U , 8-bit long + .GLB _OSIntNesting ; Declared as INT8U , 8-bit long + .GLB _OSRunning ; Declared as Boolean (unsigned char), 8-bit long + + .GLB _OSIntExit ; External functions written in C + .GLB _OSTimeTick + .GLB _OSTaskSwHook + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + + .SECTION program + .GLB _OSStartHighRdy + +_OSStartHighRdy: + JSR _OSTaskSwHook + + MOV.W _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + MOV.B #01H, _OSRunning ; OSRunning = TRUE + + POPM R0,R1,R2,R3,A0,A1,SB,FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + + .SECTION program + .GLB _OSCtxSw + +_OSCtxSw: + PUSHM R0,R1,R2,R3,A0,A1,SB,FB + + MOV.W _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC SP, [A0] + + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.W _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + + .SECTION program + .GLB _OSIntCtxSw + +_OSIntCtxSw: + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.W _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + + .SECTION program + .GLB _OSTickISR + +_OSTickISR: + + PUSHM R0,R1,R2,R3,A0,A1,SB,FB ; Save current task's registers + + INC.B _OSIntNesting ; OSIntNesting++ + CMP.B #1,_OSIntNesting ; if (OSIntNesting == 1) { + JNE _OSTickISR1 + + MOV.W _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC SP, [A0] ; } + +_OSTickISR1: + JSR _OSTimeTick ; OSTimeTick() + + JSR _OSIntExit ; OSIntExit() + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack + + REIT + + + + .END diff --git a/Ports/M16C/Tiny/HEW/os_cpu_c.c b/Ports/M16C/Tiny/HEW/os_cpu_c.c new file mode 100644 index 0000000..22ef1bb --- /dev/null +++ b/Ports/M16C/Tiny/HEW/os_cpu_c.c @@ -0,0 +1,304 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 16 bits wide. +* +* +--------+--------+-----------------+ +* SP ----> | FLG(H) | PC(H) | FLG (L) | +* +-----------------------------------+ +* | PC(L) | +* +-----------------------------------+ +* | FB | +* +-----------------------------------+ +* | SB | +* +-----------------------------------+ +* | A1 | +* +-----------------------------------+ +* | A0 | +* +-----------------------------------+ +* | R3 | +* +-----------------------------------+ +* | pdata(H) (R1) | +* +-----------------------------------+ +* | pdata(L) (R1) | +* +-----------------------------------+ +* PTOS ----> | R0 | +* +-----------------------------------+ +* +********************************************************************************************************* +*/ + + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk16; + INT16U flag; + + + flag = 0x0040; + pstk16 = (INT16U *)ptos; + pstk16--; + + /* Simulate ISR entry */ + *pstk16-- = (flag & 0x00FF) /* ... The lowest byte of the FLAG register */ + | (((INT32U)task >> 8) & 0x00000F00) /* ... The highest nibble of the PC register */ + | ((flag << 4) & 0xF000); /* ... The highest nibble of the FLAG register */ + *pstk16-- = (((INT32U)task ) & 0x0000FFFF); /* ... The lowest bytes of the PC register */ + + /* Save registers onto stack frame */ + *pstk16-- = (INT16U)0xFBFB; /* ... FB register */ + *pstk16-- = (INT16U)0x3B3B; /* ... SB register */ + *pstk16-- = (INT16U)0xA1A1; /* ... A1 register */ + *pstk16-- = (INT16U)0xA0A0; /* ... A0 register */ + *pstk16-- = (INT16U)0x3333; /* ... R3 register */ + *pstk16-- = (INT32U)pdata >> 16L; /* ... Pass argument in R2 register */ + *pstk16-- = (INT32U)pdata & 0x0000FFFFL; /* ... Pass argument in R1 register */ + *pstk16 = (INT16U)0x0000; /* ... R0 register */ + + return ((OS_STK *)pstk16); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/M16C/Tiny/HEW/os_dbg.c b/Ports/M16C/Tiny/HEW/os_dbg.c new file mode 100644 index 0000000..c301ad9 --- /dev/null +++ b/Ports/M16C/Tiny/HEW/os_dbg.c @@ -0,0 +1,273 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#include + + /* The following #define tells the IAR compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/M16C/Tiny/IAR/os_cpu.h b/Ports/M16C/Tiny/IAR/os_cpu.h new file mode 100644 index 0000000..e6dae80 --- /dev/null +++ b/Ports/M16C/Tiny/IAR/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : IAR's EW for M16C +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef INT16U OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M16C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 1 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() asm("STC FLG, $@", cpu_sr);asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("LDC $@, FLG", cpu_sr) /* Enable interrupts */ +#endif +/* +********************************************************************************************************* +* RENESAS M16C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/M16C/Tiny/IAR/os_cpu_a.asm b/Ports/M16C/Tiny/IAR/os_cpu_a.asm new file mode 100644 index 0000000..59eb243 --- /dev/null +++ b/Ports/M16C/Tiny/IAR/os_cpu_a.asm @@ -0,0 +1,199 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas M16C Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas M16C +; Toolchain : IAR's EW for M16C +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + RSEG CSTACK + + RSEG ISTACK + + RSEG UDATA0 + + EXTERN OSTCBCur ; Declared as OS_TCB * , 32-bit long + EXTERN OSTCBHighRdy ; Declared as OS_TCB * , 32-bit long + EXTERN OSPrioCur ; Declared as INT8U , 8-bit long + EXTERN OSPrioHighRdy ; Declared as INT8U , 8-bit long + EXTERN OSIntNesting ; Declared as INT8U , 8-bit long + EXTERN OSRunning ; Declared as Boolean (unsigned char), 8-bit long + + RSEG CODE(1) + + EXTERN OSIntExit ; External functions written in C + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + .EVEN + +OSStartHighRdy: + JSR OSTaskSwHook + + MOV.W OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + MOV.B #01H, OSRunning ; OSRunning = TRUE + + POPM R0,R1,R2,R3,A0,A1,SB,FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + + .EVEN + +OSCtxSw: + PUSHM R0,R1,R2,R3,A0,A1,SB,FB + + MOV.W OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC SP, [A0] + + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.W OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + + .EVEN + +OSIntCtxSw: + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.W OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.W OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.W OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + + .EVEN + +OSTickISR: + + PUSHM R0,R1,R2,R3,A0,A1,SB,FB ; Save current task's registers + + INC.B OSIntNesting ; OSIntNesting++ + CMP.B #1,OSIntNesting ; if (OSIntNesting == 1) { + JNE OSTickISR1 + + MOV.W OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC SP, [A0] ; } + +OSTickISR1: + JSR OSTimeTick ; OSTimeTick() + + JSR OSIntExit ; OSIntExit() + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack + + REIT + + + + END diff --git a/Ports/M16C/Tiny/IAR/os_cpu_c.c b/Ports/M16C/Tiny/IAR/os_cpu_c.c new file mode 100644 index 0000000..2ccb7b9 --- /dev/null +++ b/Ports/M16C/Tiny/IAR/os_cpu_c.c @@ -0,0 +1,303 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : IAR's EW for M16C +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 16 bits wide. +* +* +--------+--------+-----------------+ +* SP ----> | FLG(H) | PC(H) | FLG (L) | +* +-----------------------------------+ +* | PC(L) | +* +-----------------------------------+ +* | FB | +* +-----------------------------------+ +* | SB | +* +-----------------------------------+ +* | A1 | +* +-----------------------------------+ +* | A0 | +* +-----------------------------------+ +* | R3 | +* +-----------------------------------+ +* | pdata(H) (R1) | +* +-----------------------------------+ +* | pdata(L) (R1) | +* +-----------------------------------+ +* PTOS ----> | R0 | +* +-----------------------------------+ +* +********************************************************************************************************* +*/ + + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk16; + INT16U flag; + + + flag = 0x0040; + pstk16 = (INT16U *)ptos; + pstk16--; + + /* Simulate ISR entry */ + *pstk16-- = (flag & 0x00FF) /* ... The lowest byte of the FLAG register */ + | (((INT32U)task >> 8) & 0x00000F00) /* ... The highest nibble of the PC register */ + | ((flag << 4) & 0xF000); /* ... The highest nibble of the FLAG register */ + *pstk16-- = (((INT32U)task ) & 0x0000FFFF); /* ... The lowest bytes of the PC register */ + + /* Save registers onto stack frame */ + *pstk16-- = (INT16U)0xFBFB; /* ... FB register */ + *pstk16-- = (INT16U)0x3B3B; /* ... SB register */ + *pstk16-- = (INT16U)0xA1A1; /* ... A1 register */ + *pstk16-- = (INT16U)0xA0A0; /* ... A0 register */ + *pstk16-- = (INT16U)0x3333; /* ... R3 register */ + *pstk16-- = (INT32U)pdata >> 16L; /* ... Pass argument in R2 register */ + *pstk16-- = (INT32U)pdata & 0x0000FFFFL; /* ... Pass argument in R1 register */ + *pstk16 = (INT16U)0x0000; /* ... R0 register */ + + return ((OS_STK *)pstk16); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/M16C/Tiny/IAR/os_dbg.c b/Ports/M16C/Tiny/IAR/os_dbg.c new file mode 100644 index 0000000..b220fb0 --- /dev/null +++ b/Ports/M16C/Tiny/IAR/os_dbg.c @@ -0,0 +1,273 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : IAR's EW for M16C +********************************************************************************************************* +*/ + +#include + + /* The following #define tells the IAR compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/M32C/M16C80/HEW/os_cpu.h b/Ports/M32C/M16C80/HEW/os_cpu.h new file mode 100644 index 0000000..60e5fea --- /dev/null +++ b/Ports/M32C/M16C80/HEW/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M32C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M32C +* Toolchain : IAR's EW for M32C +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef INT16U OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M32C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 1 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() asm("STC FLG, $@", cpu_sr);asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("LDC $@, FLG", cpu_sr) /* Enable interrupts */ +#endif +/* +********************************************************************************************************* +* RENESAS M32C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/M32C/M16C80/HEW/os_cpu_a.a30 b/Ports/M32C/M16C80/HEW/os_cpu_a.a30 new file mode 100644 index 0000000..f46cf81 --- /dev/null +++ b/Ports/M32C/M16C80/HEW/os_cpu_a.a30 @@ -0,0 +1,189 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas M32C Port +; +; Filename : os_cpu_a.a30 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas M32C +; Toolchain : Renesas HEW IDE with the NC30 compiler +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .GLB _OSTCBCur ; Declared as OS_TCB * , 32-bit long + .GLB _OSTCBHighRdy ; Declared as OS_TCB * , 32-bit long + .GLB _OSPrioCur ; Declared as INT8U , 8-bit long + .GLB _OSPrioHighRdy ; Declared as INT8U , 8-bit long + .GLB _OSIntNesting ; Declared as INT8U , 8-bit long + .GLB _OSRunning ; Declared as Boolean (unsigned char), 8-bit long + + .GLB _OSIntExit ; External functions written in C + .GLB _OSTimeTick + .GLB _OSTaskSwHook + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + .SECTION program + .GLB _OSStartHighRdy + +_OSStartHighRdy: + JSR _OSTaskSwHook + + MOV.L _OSTCBHighRdy, A0 ; ISP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + MOV.B #01H, _OSRunning ; OSRunning = TRUE + + POPM R0,R1,R2,R3,A0,A1,SB,FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + + .SECTION program + .GLB _OSCtxSw + +_OSCtxSw: + PUSHM R0,R1,R2,R3,A0,A1,SB,FB + + MOV.L _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] + + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.L _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + + .SECTION program + .GLB _OSIntCtxSw + +_OSIntCtxSw: + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.L _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + + .SECTION program + .GLB _OSTickISR + +_OSTickISR: + + PUSHM R0,R1,R2,R3,A0,A1,SB,FB ; Save current task's registers + + INC.B _OSIntNesting ; OSIntNesting++ + CMP.B #1,_OSIntNesting ; if (OSIntNesting == 1) { + JNE _OSTickISR1 + + MOV.L _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] ; } + +_OSTickISR1: + JSR _OSTimeTick ; OSTimeTick() + + JSR _OSIntExit ; OSIntExit() + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack + + REIT + + + .END diff --git a/Ports/M32C/M16C80/HEW/os_cpu_c.c b/Ports/M32C/M16C80/HEW/os_cpu_c.c new file mode 100644 index 0000000..c031ed6 --- /dev/null +++ b/Ports/M32C/M16C80/HEW/os_cpu_c.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M32C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M32C +* Toolchain : IAR's EW for M32C +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +*********************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 16 bits wide. +* +* SP -> pdata (L) +* pdata (H) +* task (L) +* task (H) +* R0 +* R1 +* R2 +* R3 +* A0 (L) +* A0 (H) +* A1 (L) +* A1 (H) +* FB (L) +* FB (H) +* task (L) +* task (H) +* ptos -> FLG +*********************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk16; + + + pstk16 = (INT16U *)ptos; /* Load top of stack for this task */ + /* Simulate call to 'task()' with argument */ + *pstk16-- = (INT32U)pdata >> 16L; /* ... Push of argument 'pdata' */ + *pstk16-- = (INT32U)pdata & 0x0000FFFFL; + *pstk16-- = (INT32U)task >> 16L; /* ... Push of the task start address */ + *pstk16-- = (INT32U)task & 0x0000FFFFL; + + /* Simulate ISR entry and push all registers onto ISP */ + *pstk16-- = (INT16U)0x0040; /* ... FLG register: IPL=0, ISP selected, Interrupts enabled */ + *pstk16-- = (INT32U)task >> 16L; /* ... Push of the task start address */ + *pstk16-- = (INT32U)task & 0x0000FFFFL; + + /* Save registers onto stack frame */ + *pstk16-- = (INT16U)0xFBFB; /* ... FB register */ + *pstk16-- = (INT16U)0xFBFB; + *pstk16-- = (INT16U)0x3B3B; /* ... SB register */ + *pstk16-- = (INT16U)0x3B3B; + *pstk16-- = (INT16U)0xA1A1; /* ... A1 register */ + *pstk16-- = (INT16U)0xA1A1; + *pstk16-- = (INT16U)0xA0A0; /* ... A0 register */ + *pstk16-- = (INT16U)0xA0A0; + *pstk16-- = (INT16U)0x3333; /* ... R3 register */ + *pstk16-- = (INT16U)0x2222; /* ... R2 register */ + *pstk16-- = (INT16U)0x1111; /* ... R1 register */ + *pstk16 = (INT16U)0x0000; /* ... R0 register */ + + return ((OS_STK *)pstk16); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/M32C/M16C80/HEW/os_dbg.c b/Ports/M32C/M16C80/HEW/os_dbg.c new file mode 100644 index 0000000..e894ccc --- /dev/null +++ b/Ports/M32C/M16C80/HEW/os_dbg.c @@ -0,0 +1,271 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M32C Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M32C +* Toolchain : IAR's EW for M32C +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/M32C/M16C80/IAR/os_cpu.h b/Ports/M32C/M16C80/IAR/os_cpu.h new file mode 100644 index 0000000..60e5fea --- /dev/null +++ b/Ports/M32C/M16C80/IAR/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M32C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M32C +* Toolchain : IAR's EW for M32C +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef INT16U OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M32C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 1 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() asm("STC FLG, $@", cpu_sr);asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("LDC $@, FLG", cpu_sr) /* Enable interrupts */ +#endif +/* +********************************************************************************************************* +* RENESAS M32C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/M32C/M16C80/IAR/os_cpu_a.asm b/Ports/M32C/M16C80/IAR/os_cpu_a.asm new file mode 100644 index 0000000..035d037 --- /dev/null +++ b/Ports/M32C/M16C80/IAR/os_cpu_a.asm @@ -0,0 +1,199 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas M32C Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas M32C +; Toolchain : IAR's EW for M32C +;******************************************************************************************************** + + + MODULE OS_CPU_A + +;********************************************************************************************** +; Section Control +;********************************************************************************************** + + RSEG CSTACK + + RSEG ISTACK + + RSEG UDATA0 + EXTERN OSTCBCur ; Declared as OS_TCB *, 24-bit long + EXTERN OSTCBHighRdy ; Declared as OS_TCB *, 24-bit long + EXTERN OSPrioCur ; Declared as INT8U, 8-bit long + EXTERN OSPrioHighRdy ; Declared as INT8U, 8-bit long + EXTERN OSIntNesting ; Declared as INT8U, 8-bit long + EXTERN OSRunning ; Declared as Boolean (unsigned char), 8-bit long + + RSEG CODE(1) + + EXTERN OSIntExit ; External functions written in C + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + .EVEN + +OSStartHighRdy: + JSR OSTaskSwHook + + MOV.L OSTCBHighRdy, A0 ; ISP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + MOV.B #01H, OSRunning ; OSRunning = TRUE + + POPM R0,R1,R2,R3,A0,A1,SB,FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + + .EVEN + +OSCtxSw: + PUSHM R0,R1,R2,R3,A0,A1,SB,FB + + MOV.L OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] + + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.L OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + + .EVEN + +OSIntCtxSw: + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.L OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore all processor registers from the new task's stack + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + + .EVEN + +OSTickISR: + + PUSHM R0,R1,R2,R3,A0,A1,SB,FB ; Save current task's registers + + INC.B OSIntNesting ; OSIntNesting++ + CMP.B #1,OSIntNesting ; if (OSIntNesting == 1) { + JNE OSTickISR1 + + MOV.L OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] ; } + +OSTickISR1: + JSR OSTimeTick ; OSTimeTick() + + JSR OSIntExit ; OSIntExit() + + POPM R0,R1,R2,R3,A0,A1,SB,FB ; Restore registers from the new task's stack + + REIT + + + END diff --git a/Ports/M32C/M16C80/IAR/os_cpu_c.c b/Ports/M32C/M16C80/IAR/os_cpu_c.c new file mode 100644 index 0000000..c031ed6 --- /dev/null +++ b/Ports/M32C/M16C80/IAR/os_cpu_c.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M32C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M32C +* Toolchain : IAR's EW for M32C +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +#if OS_VIEW_MODULE > 0 +#include +#include +#endif + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +*********************************************************************************************** +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 16 bits wide. +* +* SP -> pdata (L) +* pdata (H) +* task (L) +* task (H) +* R0 +* R1 +* R2 +* R3 +* A0 (L) +* A0 (H) +* A1 (L) +* A1 (H) +* FB (L) +* FB (H) +* task (L) +* task (H) +* ptos -> FLG +*********************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *pstk16; + + + pstk16 = (INT16U *)ptos; /* Load top of stack for this task */ + /* Simulate call to 'task()' with argument */ + *pstk16-- = (INT32U)pdata >> 16L; /* ... Push of argument 'pdata' */ + *pstk16-- = (INT32U)pdata & 0x0000FFFFL; + *pstk16-- = (INT32U)task >> 16L; /* ... Push of the task start address */ + *pstk16-- = (INT32U)task & 0x0000FFFFL; + + /* Simulate ISR entry and push all registers onto ISP */ + *pstk16-- = (INT16U)0x0040; /* ... FLG register: IPL=0, ISP selected, Interrupts enabled */ + *pstk16-- = (INT32U)task >> 16L; /* ... Push of the task start address */ + *pstk16-- = (INT32U)task & 0x0000FFFFL; + + /* Save registers onto stack frame */ + *pstk16-- = (INT16U)0xFBFB; /* ... FB register */ + *pstk16-- = (INT16U)0xFBFB; + *pstk16-- = (INT16U)0x3B3B; /* ... SB register */ + *pstk16-- = (INT16U)0x3B3B; + *pstk16-- = (INT16U)0xA1A1; /* ... A1 register */ + *pstk16-- = (INT16U)0xA1A1; + *pstk16-- = (INT16U)0xA0A0; /* ... A0 register */ + *pstk16-- = (INT16U)0xA0A0; + *pstk16-- = (INT16U)0x3333; /* ... R3 register */ + *pstk16-- = (INT16U)0x2222; /* ... R2 register */ + *pstk16-- = (INT16U)0x1111; /* ... R1 register */ + *pstk16 = (INT16U)0x0000; /* ... R0 register */ + + return ((OS_STK *)pstk16); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/M32C/M16C80/IAR/os_dbg.c b/Ports/M32C/M16C80/IAR/os_dbg.c new file mode 100644 index 0000000..1848f3c --- /dev/null +++ b/Ports/M32C/M16C80/IAR/os_dbg.c @@ -0,0 +1,271 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M32C Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M32C +* Toolchain : IAR's EW for M32C +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/M683xx/68332/COSMIC/os_cpu.h b/Ports/M683xx/68332/COSMIC/os_cpu.h new file mode 100644 index 0000000..6b2a9f9 --- /dev/null +++ b/Ports/M683xx/68332/COSMIC/os_cpu.h @@ -0,0 +1,147 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* M683xx Specific code +* COSMIC C V4.1 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register (SR = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Motorola 683xx +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* Note: COSMIC allows an alternate method which doesn't incur the penalty of a function call +* and return. This is done through the use of the _asm() directive. Note that D7 is +* used to pass arguments. +* +* Note(s) : 1) The COSMIC compiler doesn't currently handle OS_CRITICAL_METHOD #2 because it doesn't +* correctly keep track of the stack pointer manipulation through 'asm()' calls. You should +* thus NOT be using it. +* 2) Method #3 is the preferred method to use to disable insterrupts. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() _asm(" ORI #$0700,SR\n") +#define OS_EXIT_CRITICAL() _asm(" AND #$0F800,SR\n") +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() _asm(" MOVE SR,-(A7)\n ORI #$0700,SR\n") +#define OS_EXIT_CRITICAL() _asm(" MOVE (A7)+,SR\n") +#endif + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + + +#if 0 +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() cpu_sr = _asm("CLR.L D7\n MOVE.W SR,D7\n ORI #$0700,SR\n") +#define OS_EXIT_CRITICAL() _asm("MOVE.W D7,SR\n", cpu_sr) +#endif +#endif + +#define OS_TASK_SW() _asm(" TRAP #15\n") + + +#define OS_STK_GROWTH 1 /* Define stack growth: 1 = Down, 0 = Up */ + + +#define CPU_INT_DIS() _asm(" ORI #$0700,SR\n") /* Disable interrupts */ +#define CPU_INT_EN() _asm(" AND #$0F800,SR\n") /* Enable interrupts */ + + +#define OS_INITIAL_SR 0x2000 /* Supervisor mode, interrupts enabled */ + +#define OS_TRAP_NBR 15 /* OSCtxSw() invoked through TRAP #15 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSIntExit68K(void); + +#if OS_CRITICAL_METHOD == 3 +OS_CPU_SR OSCPUSaveSR(void); /* Return the value of the CCR register and then ... */ + /* ... disable interrupts via SEI instruction. */ +void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); /* Set CCR register to 'os_cpu_sr' */ +#endif + +#endif diff --git a/Ports/M683xx/68332/COSMIC/os_cpu_a.s b/Ports/M683xx/68332/COSMIC/os_cpu_a.s new file mode 100644 index 0000000..405ab50 --- /dev/null +++ b/Ports/M683xx/68332/COSMIC/os_cpu_a.s @@ -0,0 +1,412 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; 683xx Specific code +; COSMIC C V4.1 +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; CONFIGURATION CONSTANTS +;******************************************************************************************************** + + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef _OSCPUSaveSR + xdef _OSCPURestoreSR + xdef _OSCtxSw + xdef _OSIntCtxSw ; Satisfy OSIntExit() in OS_CORE.C + xdef _OSIntExit68K + xdef _OSStartHighRdy + xdef _OSTickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref _OSCtxSwCtr + xref _OSIntExit + xref _OSIntNesting + xref _OSLockNesting + xref _OSPrioCur + xref _OSPrioHighRdy + xref _OSRdyGrp + xref _OSRdyTbl + xref _OSRunning + xref _OSTaskSwHook + xref _OSTCBCur + xref _OSTCBHighRdy + xref _OSTCBPrioTbl + xref _OSTimeTick + xref _OSUnMapTbl + +;******************************************************************************************************** +; OSCPUSaveSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #3 function to preserve the state of the +; interrupt disable flag in order to be able to restore it later. +; +; Arguments : none +; +; Returns : It is assumed that the return value is placed in the D7 register as expected by the +; compiler. +;******************************************************************************************************** + +_OSCPUSaveSR: + MOVE.W SR,D7 ; Copy SR into D7 + ORI #$0700,SR ; Disable interrupts + RTS + +;******************************************************************************************************** +; OSCPURestoreSR() for OS_CRITICAL_METHOD #3 +; +; Description : This functions implements the OS_CRITICAL_METHOD #function to restore the state of the +; interrupt flag. +; +; Arguments : os_cpu_sr is the contents of the SR to restore. It is assumed that this 'argument' is +; passed in the D7 register of the CPU by the compiler. +; +; Returns : None +;******************************************************************************************************** + +_OSCPURestoreSR: + MOVE.W D7,SR + RTS + + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 (H) Low Memory +; + 2 D0 (L) +; + 4 D1 (H) +; + 6 D1 (L) +; + 8 D2 (H) +; + 10 D2 (L) +; + 12 D3 (H) +; + 14 D3 (L) +; + 16 D4 (H) +; + 18 D4 (L) +; + 20 D5 (H) +; + 22 D5 (L) +; + 24 D6 (H) +; + 26 D6 (L) +; + 28 D7 (H) +; + 30 D7 (L) +; + 32 A0 (H) +; + 34 A0 (L) +; + 36 A1 (H) +; + 38 A1 (L) +; + 40 A2 (H) +; + 42 A2 (L) +; + 44 A3 (H) +; + 46 A3 (L) +; + 48 A4 (H) +; + 50 A4 (L) +; + 52 A5 (H) +; + 54 A5 (L) +; + 56 A6 (H) +; + 58 A6 (L) +; + 60 OS_INITIAL_SR +; + 62 task (H) +; + 64 task (L) +; + 66 0x80 + 4 * TRAP# +; + 68 task (H) +; + 70 task (L) +; + 72 pdata (H) +; + 74 pdata (L) High Memory +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +_OSStartHighRdy: + JSR _OSTaskSwHook ; Invoke user defined context switch hook + ADDQ.B #1,_OSRunning ; Indicate that we are multitasking + + MOVE.L (_OSTCBHighRdy),A1 ; Point to TCB of highest priority task ready to run + MOVE.L (A1),A7 ; Get the stack pointer of the task to resume + + MOVEM.L (A7)+,A0-A6/D0-D7 ; Restore the CPU registers + + RTE ; Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows (the registers for +; task to suspend need to be saved): +; +; SP + 0 ----> SR Low Memory +; + 2 0x80 + 4 * TRAP# +; + 4 PC of task (H) +; + 6 PC of task (L) High Memory +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> D0 (H) Low Memory +; + 2 D0 (L) +; + 4 D1 (H) +; + 6 D1 (L) +; + 8 D2 (H) +; + 10 D2 (L) +; + 12 D3 (H) +; + 14 D3 (L) +; + 16 D4 (H) +; + 18 D4 (L) +; + 20 D5 (H) +; + 22 D5 (L) +; + 24 D6 (H) +; + 26 D6 (L) +; + 28 D7 (H) +; + 30 D7 (L) +; + 32 A0 (H) +; + 34 A0 (L) +; + 36 A1 (H) +; + 38 A1 (L) +; + 40 A2 (H) +; + 42 A2 (L) +; + 44 A3 (H) +; + 46 A3 (L) +; + 48 A4 (H) +; + 50 A4 (L) +; + 52 A5 (H) +; + 54 A5 (L) +; + 56 A6 (H) +; + 58 A6 (L) +; + 60 OS_INITIAL_SR +; + 62 PC of task (H) +; + 64 PC of task (L) +; + 66 0x80 + 4 * TRAP# High Memory +;******************************************************************************************************** + +_OSCtxSw: + MOVEM.L A0-A6/D0-D7,-(A7) ; 72~ Save the registers of the current task + + MOVE.L (_OSTCBCur),A1 ; 4~ Save the stack pointer in the suspended task TCB + MOVE.L A7,(A1) ; 4~ + + JSR _OSTaskSwHook ; 13~ Invoke user defined context switch hook + + MOVE.L (_OSTCBHighRdy),A1 ; 4~ OSTCBCur = OSTCBHighRdy + MOVE.L A1,(_OSTCBCur) ; 4~ + MOVE.L (A1),A7 ; 4~ Get the stack pointer of the task to resume + + MOVE.B _OSPrioHighRdy,_OSPrioCur ; 6~ OSPrioCur = OSPrioHighRdy + + MOVEM.L (A7)+,A0-A6/D0-D7 ; 70~ Restore the CPU registers + + RTE ; 24~ Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is provided for backward compatibility and your ISR MUST NOT call +; OSIntExit(). Instead, your ISR MUST JUMP to OSIntExit68K(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame upon entry: +; +;******************************************************************************************************** + +_OSIntCtxSw: + ADDA.L #18,A7 ; Adjust the stack + + MOVE.L (_OSTCBCur),A1 ; Save the stack pointer in the suspended task TCB + MOVE.L A7,(A1) + + JSR _OSTaskSwHook ; Invoke user defined context switch hook + + MOVE.L (_OSTCBHighRdy),A1 ; OSTCBCur = OSTCBHighRdy + MOVE.L A1,(_OSTCBCur) + + MOVE.B _OSPrioHighRdy,_OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOVE.L (A1),A7 ; Get the stack pointer of the task to resume + + MOVEM.L (A7)+,A0-A6/D0-D7 ; Restore the CPU registers + + RTE ; Run task + +;******************************************************************************************************** +; INTERRUPT EXIT FUNCTION +; +; Description : Your ISR MUST JUMP to this function when it is done. +; +; Arguments : none +; +; Note(s) : 1) Stack frame upon entry: +; +; SP + 0 ----> D0 (H) Low Memory +; + 2 D0 (L) +; + 4 D1 (H) +; + 6 D1 (L) +; + 8 D2 (H) +; + 10 D2 (L) +; + 12 D3 (H) +; + 14 D3 (L) +; + 16 D4 (H) +; + 18 D4 (L) +; + 20 D5 (H) +; + 22 D5 (L) +; + 24 D6 (H) +; + 26 D6 (L) +; + 28 D7 (H) +; + 30 D7 (L) +; + 32 A0 (H) +; + 34 A0 (L) +; + 36 A1 (H) +; + 38 A1 (L) +; + 40 A2 (H) +; + 42 A2 (L) +; + 44 A3 (H) +; + 46 A3 (L) +; + 48 A4 (H) +; + 50 A4 (L) +; + 52 A5 (H) +; + 54 A5 (L) +; + 56 A6 (H) +; + 58 A6 (L) +; + 60 Task or ISR's SR +; + 62 PC of task (H) +; + 64 PC of task (L) +; + 66 0x80 + 4 * TRAP# High Memory +;******************************************************************************************************** + +_OSIntExit68K: + ORI #$0700,SR ; Disable interrupts + + SUBQ.B #1,_OSIntNesting ; OSIntNesting--; + BNE OSIntExit68K_Exit + + MOVE.B _OSLockNesting,D0 ; if (OSLockNesting == 0) { + BNE OSIntExit68K_Exit + + MOVE.W (60,A7),D0 ; if (LAST nested ISR) { + ANDI.W #$0700,D0 + BNE OSIntExit68K_Exit + + MOVEQ.L #0,D0 ; y = OSUnMapTbl[OSRdyGrp]; + MOVE.B _OSRdyGrp,D0 + MOVE.L D0,A0 + MOVE.B (_OSUnMapTbl,A0),D2 + + MOVE.B D2,D0 ; OSPrioHighRdy = (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]); + LSL.B #3,D0 + MOVEQ.L #0,D1 + MOVE.B D2,D1 + MOVE.L D1,A0 + MOVEQ.L #0,D1 + MOVE.B (_OSRdyTbl,A0),D1 + MOVE.L D1,A0 + ADD.B (_OSUnMapTbl,A0),D0 + + MOVE.B D0,_OSPrioHighRdy ; if (OSPrioHighRdy != OSPrioCur) { + CMP.B _OSPrioCur,D0 + BEQ OSIntExit68K_Exit + + MOVEQ.L #0,D1 ; OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; + MOVE.B D0,D1 + LSL.L #2,D1 + MOVE.L D1,A0 + MOVE.L (_OSTCBPrioTbl,A0),_OSTCBHighRdy + + + ADDQ.L #1,_OSCtxSwCtr ; OSCtxSwCtr++; + ; PERFORM INTERRUPT LEVEL CONTEXT SWITCH: + MOVE.L (_OSTCBCur),A1 ; Save the stack pointer in the suspended task TCB + MOVE.L A7,(A1) + + JSR _OSTaskSwHook ; Invoke user defined context switch hook + + MOVE.L (_OSTCBHighRdy),A1 ; OSTCBCur = OSTCBHighRdy + MOVE.L A1,(_OSTCBCur) + + MOVE.B _OSPrioHighRdy,_OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOVE.L (A1),A7 ; Get the stack pointer of the task to resume + +OSIntExit68K_Exit: + MOVEM.L (A7)+,A0-A6/D0-D7 ; Restore the CPU registers + + RTE ; Return to task or nested ISR + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. +; +; Arguments : none +; +; Note(s) : The following C-like pseudo-code describe the operation being performed in the code below. +; +; OSIntNesting++; +; Save all registers on the current task's stack; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; Clear the interrupt source; +; OSTimeTick(); Notify uC/OS-II that a tick has occured +; JUMP to OSIntExit68K; Notify uC/OS-II about end of ISR +;******************************************************************************************************** + +_OSTickISR: + ADDQ.B #1,_OSIntNesting ; OSIntNesting++; + + MOVEM.L A0-A6/D0-D7,-(A7) ; Save the registers of the current task + + CMPI #1,_OSIntNesting ; if (OSIntNesting == 1) { + BNE _OSTickISR1 +; + MOVE.L (_OSTCBCur),A1 ; OSTCBCur->OSTCBStkPtr = SP; + MOVE.L A7,(A1) ; } + +_OSTickISR1: +; CLEAR the INTERRUPT source! + + JSR _OSTimeTick ; Call uC/OS-II's tick updating function + + JMP _OSIntExit68K ; Exit ISR through uC/OS-II + + END diff --git a/Ports/M683xx/68332/COSMIC/os_cpu_c.c b/Ports/M683xx/68332/COSMIC/os_cpu_c.c new file mode 100644 index 0000000..1e2eb73 --- /dev/null +++ b/Ports/M683xx/68332/COSMIC/os_cpu_c.c @@ -0,0 +1,271 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* 683xx Specific code +* COSMIC C V4.1 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) The initial value of the Status Register (SR) is OS_INITIAL_SR sets the 683xx processor +* to run in SUPERVISOR mode. It is assumed that all uC/OS-II tasks run in supervisor +* mode. +* 2) You can pass the above options in the 'opt' argument. You MUST only use the upper +* 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make changes +* to the code below, you will need to ensure that it doesn't affect the behaviour of +* OSTaskIdle() and OSTaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + INT16U *pstk16; + + + opt = opt; /* 'opt' is not used, prevent warning */ + /* Load stack pointer and align on 32-bit bound */ + pstk32 = (INT32U *)((INT32U)ptos & 0xFFFFFFFCL); + /* -- SIMULATE CALL TO FUNCTION WITH ARGUMENT -- */ + *--pstk32 = (INT32U)pdata; /* pdata */ + *--pstk32 = (INT32U)task; /* Task return address */ + pstk16 = (INT16U *)pstk32; /* Switch to 16-bit wide stack */ + /* ------ SIMULATE INTERRUPT STACK FRAME ------- */ + *--pstk16 = (INT16U)(0x0080 + 4 * OS_TRAP_NBR); /* Format/Vector */ + pstk32 = (INT32U *)pstk16; /* Switch to 32-bit wide stack */ + *--pstk32 = (INT32U)task; /* Task return address */ + pstk16 = (INT16U *)pstk32; /* Switch to 16-bit wide stack */ + *--pstk16 = (INT16U)OS_INITIAL_SR; /* Initial Status Register value for the task */ + pstk32 = (INT32U *)pstk16; /* Switch to 32-bit wide stack */ + /* ------- SAVE ALL PROCESSOR REGISTERS -------- */ + *--pstk32 = (INT32U)0x00A600A6L; /* Register A6 */ + *--pstk32 = (INT32U)0x00A500A5L; /* Register A5 */ + *--pstk32 = (INT32U)0x00A400A4L; /* Register A4 */ + *--pstk32 = (INT32U)0x00A300A3L; /* Register A3 */ + *--pstk32 = (INT32U)0x00A200A2L; /* Register A2 */ + *--pstk32 = (INT32U)0x00A100A1L; /* Register A1 */ + *--pstk32 = (INT32U)0x00A000A0L; /* Register A0 */ + *--pstk32 = (INT32U)0x00D700D7L; /* Register D7 */ + *--pstk32 = (INT32U)0x00D600D6L; /* Register D6 */ + *--pstk32 = (INT32U)0x00D500D5L; /* Register D5 */ + *--pstk32 = (INT32U)0x00D400D4L; /* Register D4 */ + *--pstk32 = (INT32U)0x00D300D3L; /* Register D3 */ + *--pstk32 = (INT32U)0x00D200D2L; /* Register D2 */ + *--pstk32 = (INT32U)0x00D100D1L; /* Register D1 */ + *--pstk32 = (INT32U)0x00D000D0L; /* Register D0 */ + return ((OS_STK *)pstk32); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/M683xx/68332/COSMIC/os_dbg.c b/Ports/M683xx/68332/COSMIC/os_dbg.c new file mode 100644 index 0000000..e9180c7 --- /dev/null +++ b/Ports/M683xx/68332/COSMIC/os_dbg.c @@ -0,0 +1,267 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSIntExitY) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/MC9S08/NonPaged/Codewarrior/OS_CPU.h b/Ports/MC9S08/NonPaged/Codewarrior/OS_CPU.h new file mode 100644 index 0000000..cf4aeb2 --- /dev/null +++ b/Ports/MC9S08/NonPaged/Codewarrior/OS_CPU.h @@ -0,0 +1,118 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S08 Specific code +* Codewarrior +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx */ +#define WORD INT16S +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Freescale MC9S08 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() __asm swi; + +#define OS_STK_GROWTH 1 /* Stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* REDEFINE THE PROTOTYPES FOR THE ISRs +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +void OSTickISRHandler(void); + + diff --git a/Ports/MC9S08/NonPaged/Codewarrior/os_cpu_a.s b/Ports/MC9S08/NonPaged/Codewarrior/os_cpu_a.s new file mode 100644 index 0000000..37c3fc8 --- /dev/null +++ b/Ports/MC9S08/NonPaged/Codewarrior/os_cpu_a.s @@ -0,0 +1,263 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Non Paged MC908 Specific code +; (Codewarrior) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; Notes : THIS FILE *MUST* BE LINKED INTO NON_BANKED MEMORY! +;******************************************************************************************************** + +NON_BANKED: section + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef OS_CPU_SR_Save + xdef OS_CPU_SR_Restore + xdef OSStartHighRdy + xdef OSCtxSw + xdef OSIntCtxSw + xdef Tmr_TickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref OSIntExit + xref OSIntNesting + xref OSPrioCur + xref OSPrioHighRdy + xref OSRunning + xref OSTaskSwHook + xref OSTCBCur + xref OSTCBHighRdy + xref Tmr_TickISR_Handler + xref OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the A register to pass a single 8-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +OS_CPU_SR_Save: + tpa ; Transfer the CCR to A. + sei ; Disable interrupts + rts ; Return to caller with A containing the previous CCR + +OS_CPU_SR_Restore: + tap ; Restore the CCR from the function argument stored in A + rts + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 H (Stacked and unstacked by the OS port) +; + 1 CCR (Stacked and unstacked by the MC9S08) +; + 2 A (Stacked and unstacked by the MC9S08) +; + 3 X (Stacked and unstacked by the MC9S08) +; + 4 PC(H) (Stacked and unstacked by the MC9S08) +; + 5 PC(L) (Stacked and unstacked by the MC9S08) +; + 6 p_arg(H) (Stacked and unstacked by the OS port) +; + 7 p_arg(L) (Stacked and unstacked by the OS port) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + jsr OSTaskSwHook ; Invoke user defined context switch hook + + lda #$01 ; Indicate that we are multitasking + sta OSRunning ; Store the running state back to memory + + ldhx OSTCBHighRdy ; Point to TCB of highest priority task ready to run + ldhx 0, x ; Dereference OSTCBHighRdy to obtain the stack address + txs ; Transfer the tasks stack pointer back to the stack pointer register + + pulh ; Restore H + + rti ; Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run and +; is implemented as a software interrupt (SWI). SWI will push CCR, A, X, and PC +; on to the stack before calling this function. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 H (Stacked and unstacked by the OS port) +; + 1 CCR (Stacked and unstacked by the MC9S08) +; + 2 A (Stacked and unstacked by the MC9S08) +; + 3 X (Stacked and unstacked by the MC9S08) +; + 4 PC(H) (Stacked and unstacked by the MC9S08) +; + 5 PC(L) (Stacked and unstacked by the MC9S08) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 H (Stacked and unstacked by the OS port) +; + 1 CCR (Stacked and unstacked by the MC9S08) +; + 2 A (Stacked and unstacked by the MC9S08) +; + 3 X (Stacked and unstacked by the MC9S08) +; + 4 PC(H) (Stacked and unstacked by the MC9S08) +; + 5 PC(L) (Stacked and unstacked by the MC9S08) +;******************************************************************************************************** + +OSCtxSw: + pshh ; Push H on to the stack + + tsx ; Copy the stack pointer into HX + pshx ; Store the stack pointer on the stack + pshh + ldhx OSTCBCur ; Obtain OSTCBCur in HX + + pula ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sta 0, x + pula + sta 1, x + + jsr OSTaskSwHook ; Call user task switch hook + + lda OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + sta OSPrioCur + + ldhx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + sthx OSTCBCur + ldhx 0, x ; Dereference OSTCBHighRdy to obtain the stack address + txs ; Copy the next tasks stack pointer into the stack pointer register + + pulh ; Restore H + + rti ; Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. The H register of the preempted task has +; been stacked during the start of the ISR that is currently running. +; +; Arguments : none +; +; Notes : 1) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 H (Stacked and unstacked by the ISR entry code) +; + 1 CCR (Stacked and unstacked by the MC9S08) +; + 2 A (Stacked and unstacked by the MC9S08) +; + 3 X (Stacked and unstacked by the MC9S08) +; + 4 PC(H) (Stacked and unstacked by the MC9S08) +; + 5 PC(L) (Stacked and unstacked by the MC9S08) +;******************************************************************************************************** + +OSIntCtxSw: + jsr OSTaskSwHook ; Call user task switch hook + + lda OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + sta OSPrioCur + + ldhx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + sthx OSTCBCur + ldhx 0, x ; Dereference OSTCBHighRdy to obtain the stack address + txs ; Copy the next tasks stack pointer into the stack pointer register + + pulh ; Restore H + + rti ; Run task + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the MC9S08's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see APP_CFG.H and this file) to generate a tick that occurs every (1 / OS_TICKS_PER_SECOND) +; seconds. +; +; 2) All USER interrupts should be modeled EXACTLY like this where the only +; line to be modified is the call to your ISR_Handler and perhaps the call to +; the label name OSTickISR1. +;******************************************************************************************************** + +Tmr_TickISR: + pshh ; Push the H register on to the stack + + lda OSIntNesting ; + add #1 ; Notify uC/OS-II about the interrupt + sta OSIntNesting + + cmpa #$01 ; if (OSIntNesting == 1) { + bne Tmr_TickISR1 ; + + tsx ; Copy the stack pointer into HX + pshx ; Store the stack pointer on the stack + pshh + ldhx OSTCBCur ; Obtain OSTCBCur in HX + + pula ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sta 0, x + pula + sta 1, x ; } + +Tmr_TickISR1: + jsr Tmr_TickISR_Handler + + jsr OSIntExit ; Notify uC/OS-II about end of ISR, a context switch may occur from within OSIntExit(). + + pulh ; No context switch necessary, restore the H register + + rti ; Return from interrupt to interrupted task. diff --git a/Ports/MC9S08/NonPaged/Codewarrior/os_cpu_c.c b/Ports/MC9S08/NonPaged/Codewarrior/os_cpu_c.c new file mode 100644 index 0000000..1a4a1d8 --- /dev/null +++ b/Ports/MC9S08/NonPaged/Codewarrior/os_cpu_c.c @@ -0,0 +1,303 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S08 Codewarrior Non Paged Memory Model +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 2) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +* 4) After this function exits, the new tasks stack will look as follows: +* OSTCBHighRdy->OSTCBStkPtr -> + 0 H +* + 1 CCR +* + 2 A +* + 3 X +* + 4 Return Address high byte +* + 5 Return Address low byte +* + 6 p_arg high byte +* + 7 p_arg low byte +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)p_arg; /* Simulate call to function with argument */ + *--wstk = (INT16U)task; /* Return address. Format: PCH:PCL */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = (INT8U)0x22; /* X Register */ + *--bstk = (INT8U)0xAA; /* A Register */ + *--bstk = (0x00); /* CCR Register (IRQ Enabled!) */ + *--bstk = (INT8U)0x11; /* Save the H reg. (First to be pulled when task started) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + diff --git a/Ports/MC9S08/Paged/Codewarrior/OS_CPU.h b/Ports/MC9S08/Paged/Codewarrior/OS_CPU.h new file mode 100644 index 0000000..cf4aeb2 --- /dev/null +++ b/Ports/MC9S08/Paged/Codewarrior/OS_CPU.h @@ -0,0 +1,118 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S08 Specific code +* Codewarrior +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx */ +#define WORD INT16S +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +typedef unsigned char OS_STK; /* Each stack entry is 8-bit wide */ +typedef unsigned char OS_CPU_SR; /* Define size of CPU status register (PSW = 16 bits) */ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +/* +********************************************************************************************************* +* Freescale MC9S08 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +* NOTE(s) : 1) The current version of the compiler does NOT allow method #2 to be used without changing +* the processor independent portion of uC/OS-II. +* 2) The current version of the compiler does NOT allow method #3 either. However, this can +* be implemented in OS_CPU_A.S by defining the functions: OSCPUSaveSR() and +* OSCPURestoreSR(). +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr) /* Enable interrupts */ +#endif + + +#define OS_TASK_SW() __asm swi; + +#define OS_STK_GROWTH 1 /* Stack growth: 1 = Down, 0 = Up */ + + +/* +********************************************************************************************************* +* REDEFINE THE PROTOTYPES FOR THE ISRs +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Save(void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +void OSTickISRHandler(void); + + diff --git a/Ports/MC9S08/Paged/Codewarrior/os_cpu_a.s b/Ports/MC9S08/Paged/Codewarrior/os_cpu_a.s new file mode 100644 index 0000000..9e44f0b --- /dev/null +++ b/Ports/MC9S08/Paged/Codewarrior/os_cpu_a.s @@ -0,0 +1,278 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PAGED MC908 Specific code +; (Codewarrior) +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; Notes : THIS FILE *MUST* BE LINKED INTO NON_BANKED MEMORY! +;******************************************************************************************************** + +NON_BANKED: section + +;******************************************************************************************************** +; I/O PORT ADDRESSES +;******************************************************************************************************** + +PPAGE: equ $0078 ; Addres of PPAGE register (Using MC9S08QE128 as a reference) + +;******************************************************************************************************** +; PUBLIC DECLARATIONS +;******************************************************************************************************** + + xdef OS_CPU_SR_Save + xdef OS_CPU_SR_Restore + xdef OSStartHighRdy + xdef OSCtxSw + xdef OSIntCtxSw + xdef Tmr_TickISR + +;******************************************************************************************************** +; EXTERNAL DECLARATIONS +;******************************************************************************************************** + + xref OSIntExit + xref OSIntNesting + xref OSPrioCur + xref OSPrioHighRdy + xref OSRunning + xref OSTaskSwHook + xref OSTCBCur + xref OSTCBHighRdy + xref Tmr_TickISR_Handler + xref OSTimeTick + +;******************************************************************************************************** +; SAVE THE CCR AND DISABLE INTERRUPTS +; & +; RESTORE CCR +; +; Description : These function implements OS_CRITICAL_METHOD #3 +; +; Arguments : The function prototypes for the two functions are: +; 1) OS_CPU_SR OSCPUSaveSR(void) +; where OS_CPU_SR is the contents of the CCR register prior to disabling +; interrupts. +; 2) void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); +; 'os_cpu_sr' the the value of the CCR to restore. +; +; Note(s) : 1) It's assumed that the compiler uses the A register to pass a single 8-bit argument +; to and from an assembly language function. +;******************************************************************************************************** + +OS_CPU_SR_Save: + tpa ; Transfer the CCR to A. + sei ; Disable interrupts + rtc ; Return to caller with A containing the previous CCR + +OS_CPU_SR_Restore: + tap ; Restore the CCR from the function argument stored in A + rtc + +;******************************************************************************************************** +; START HIGHEST PRIORITY TASK READY-TO-RUN +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame is assumed to look as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 H (Stacked and unstacked by the OS port) +; + 1 PPAGE (Stacked and unstacked by the OS port) +; + 2 CCR (Stacked and unstacked by the MC9S08) +; + 3 A (Stacked and unstacked by the MC9S08) +; + 6 X (Stacked and unstacked by the MC9S08) +; + 7 PC(H) (Stacked and unstacked by the MC9S08) +; + 8 PC(L) (Stacked and unstacked by the MC9S08) +; +; 2) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task by loading the stack pointer of the +; highest priority task into the SP register and execute an RTI instruction. +;******************************************************************************************************** + +OSStartHighRdy: + call OSTaskSwHook ; Invoke user defined context switch hook + + lda #$01 ; Indicate that we are multitasking + sta OSRunning ; Store the running state back to memory + + ldhx OSTCBHighRdy ; Point to TCB of highest priority task ready to run + ldhx 0, x ; Dereference OSTCBHighRdy to obtain the stack address + txs ; Transfer the tasks stack pointer back to the stack pointer register + + pulh ; Restore H + + pula ; Get value of PPAGE register + sta PPAGE ; Store into CPU's PPAGE register + + rti ; Run task + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description : This function is called when a task makes a higher priority task ready-to-run. +; +; Arguments : none +; +; Note(s) : 1) Upon entry, +; OSTCBCur points to the OS_TCB of the task to suspend +; OSTCBHighRdy points to the OS_TCB of the task to resume +; +; 2) The stack frame of the task to suspend looks as follows: +; +; SP + 0 PC(H) +; + 1 PC(L) +; +; 3) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 H (Stacked and unstacked by the OS port) +; + 1 PPAGE (Stacked and unstacked by the OS port) +; + 2 CCR (Stacked and unstacked by the MC9S08) +; + 3 A (Stacked and unstacked by the MC9S08) +; + 6 X (Stacked and unstacked by the MC9S08) +; + 7 PC(H) (Stacked and unstacked by the MC9S08) +; + 8 PC(L) (Stacked and unstacked by the MC9S08) +;******************************************************************************************************** + +OSCtxSw: + lda PPAGE ; Get current value of PPAGE register + psha ; Push PPAGE register onto current task's stack + + pshh ; Push H on to the stack + + tsx ; Copy the stack pointer into HX + pshx ; Store the stack pointer on the stack + pshh + ldhx OSTCBCur ; Obtain OSTCBCur in HX + + pula ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sta 0, x + pula + sta 1, x + + call OSTaskSwHook ; Call user task switch hook + + lda OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + sta OSPrioCur + + ldhx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + sthx OSTCBCur + ldhx 0, x ; Dereference OSTCBHighRdy to obtain the stack address + txs ; Copy the next tasks stack pointer into the stack pointer register + + pulh ; Restore H + + pula ; Get value of PPAGE register + sta PPAGE ; Store into CPU's PPAGE register + + rti ; Run task + +;******************************************************************************************************** +; INTERRUPT LEVEL CONTEXT SWITCH +; +; Description : This function is called by OSIntExit() to perform a context switch to a task that has +; been made ready-to-run by an ISR. The H and PPAGE registers of the preempted task have +; been stacked during the start of the ISR that is currently running. +; +; Arguments : none +; +; Notes : 1) The stack frame of the task to resume looks as follows: +; +; OSTCBHighRdy->OSTCBStkPtr + 0 H (Stacked and unstacked by the ISR entry code) +; + 1 PPAGE (Stacked and unstacked by the ISR entry code) +; + 2 CCR (Stacked and unstacked by the MC9S08) +; + 3 A (Stacked and unstacked by the MC9S08) +; + 6 X (Stacked and unstacked by the MC9S08) +; + 7 PC(H) (Stacked and unstacked by the MC9S08) +; + 8 PC(L) (Stacked and unstacked by the MC9S08) +;******************************************************************************************************** + +OSIntCtxSw: + call OSTaskSwHook ; Call user task switch hook + + lda OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy + sta OSPrioCur + + ldhx OSTCBHighRdy ; OSTCBCur = OSTCBHighRdy + sthx OSTCBCur + ldhx 0, x ; Dereference OSTCBHighRdy to obtain the stack address + txs ; Copy the next tasks stack pointer into the stack pointer register + + pulh ; Restore H + + pula ; Get value of PPAGE register + sta PPAGE ; Store into CPU's PPAGE register + + rti ; Run task + +;******************************************************************************************************** +; SYSTEM TICK ISR +; +; Description : This function is the ISR used to notify uC/OS-II that a system tick has occurred. You +; must setup the MC9S08's interrupt vector table so that an OUTPUT COMPARE interrupt +; vectors to this function. +; +; Arguments : none +; +; Notes : 1) The 'tick ISR' assumes the we are using the Output Compare specified by OS_TICK_OC +; (see APP_CFG.H and this file) to generate a tick that occurs every (1 / OS_TICKS_PER_SECOND) +; seconds. +; +; 2) All USER interrupts should be modeled EXACTLY like this where the only +; line to be modified is the call to your ISR_Handler and perhaps the call to +; the label name OSTickISR1. +;******************************************************************************************************** + +Tmr_TickISR: + lda PPAGE ; Get current value of PPAGE register + psha ; Push PPAGE register onto current task's stack + + pshh ; Push the H register on to the stack + + lda OSIntNesting ; + add #1 ; Notify uC/OS-II about the interrupt + sta OSIntNesting + + cmpa #$01 ; + bne Tmr_TickISR1 ; + + tsx ; Copy the stack pointer into HX + pshx ; Store the stack pointer on the stack + pshh + ldhx OSTCBCur ; Obtain OSTCBCur in HX + + pula ; OSTCBCur->OSTCBStkPtr = Stack Pointer + sta 0, x + pula + sta 1, x ; } + +Tmr_TickISR1: + call Tmr_TickISR_Handler + + call OSIntExit ; Notify uC/OS-II about end of ISR + + pulh ; Restore the H register + + pula ; Get value of PPAGE register + sta PPAGE ; Store into CPU's PPAGE register + + rti ; Return from interrupt, no higher priority tasks ready. diff --git a/Ports/MC9S08/Paged/Codewarrior/os_cpu_c.c b/Ports/MC9S08/Paged/Codewarrior/os_cpu_c.c new file mode 100644 index 0000000..d7e38bf --- /dev/null +++ b/Ports/MC9S08/Paged/Codewarrior/os_cpu_c.c @@ -0,0 +1,307 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MC9S08 Codewarrior Banked Memory Model +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts (i.e. maskable interrupts) are enabled when your task starts +* executing. You can change this by setting BIT4 in the CCR. +* 2) You can change pass the above options in the 'opt' argument. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 3) Registers are initialized to make them easy to differentiate with a debugger. +* 4) After this function exits, the new tasks stack will look as follows: +* OSTCBHighRdy->OSTCBStkPtr -> + 0 H +* + 1 PPAGE +* + 2 CCR +* + 3 A +* + 4 X +* + 5 PC(H) +* + 6 PC(L) +* + 7 Return Address high byte +* + 8 Return Address low byte +* + 9 p_arg high byte +* + 10 p_arg low byte +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *wstk; + INT8U *bstk; + + opt = opt; /* 'opt' is not used, prevent warning */ + wstk = (INT16U *)ptos; /* Load stack pointer */ + *--wstk = (INT16U)p_arg; /* Simulate call to function with argument */ + *--wstk = (INT16U)(task); /* Return address. Format: PPAGE:PCH:PCL (ignore PPage) */ + bstk = (INT8U *)wstk; /* Convert WORD ptr to BYTE ptr to set CCR */ + *--bstk = (INT8U)0x22; /* X Register */ + *--bstk = (INT8U)0xAA; /* A Register */ + *--bstk = (0x00); /* CCR Register (IRQ Enabled!) */ + *--bstk = (INT8U)((INT32U)(task) >> 16); /* Save the PPAGE register */ + *--bstk = (INT8U)0x11; /* Save the H reg. (First to be pulled when task started) */ + return ((OS_STK *)bstk); /* Return pointer to new top-of-stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + diff --git a/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu.h b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu.h new file mode 100644 index 0000000..55873a1 --- /dev/null +++ b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu.h @@ -0,0 +1,106 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MIPS32 4K +* MPLAB +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8-bit quantity */ +typedef signed char INT8S; /* Signed 8-bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16-bit quantity */ +typedef signed short INT16S; /* Signed 16-bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32-bit quantity */ +typedef signed int INT32S; /* Signed 32-bit quantity */ +typedef float FP32; +typedef double FP64; + +typedef unsigned int OS_STK; /* Each stack entry is 32 bits wide */ +typedef unsigned int volatile OS_CPU_SR; /* The CPU Status Word is 32-bits wide. This variable */ + /* MUST be volatile for proper operation. Refer to */ + /* os_cpu_a.s for more details. */ + +/* +********************************************************************************************************* +* CRITICAL SECTIONS MANAGEMENT +* +* Method #1: Disable/Enable interrupts using simple instructions. After a critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts and preserve the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts and preserve the state of interrupts. Generally speaking, you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save(); +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr); + +/* +********************************************************************************************************* +* MIPS32 4K +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ + +#define OS_TASK_SW() asm volatile("syscall"); + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); +void CoreTimerIntHandler(void); + +OS_CPU_SR OS_CPU_SR_Save(void); /* See os_cpu_a.s */ +void OS_CPU_SR_Restore(OS_CPU_SR); /* See os_cpu_a.s */ + + + diff --git a/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_a.S b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_a.S new file mode 100644 index 0000000..7eb4574 --- /dev/null +++ b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_a.S @@ -0,0 +1,707 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MIPS32 4K +* MPLAB +* +* Filename : os_cpu_a.S +* Version : V2.93.00 +********************************************************************************************************* +*/ + + .section .text,"ax",@progbits + .set noreorder + .set noat + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + + .global OSStartHighRdy + .global OSIntCtxSw + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSCtxSw + .global CoreTimerIntHandler + +/* +********************************************************************************************************* +* CONSTANTS USED TO ACCESS TASK CONTEXT STACK +********************************************************************************************************* +*/ + +.equ STK_OFFSET_SR, 4 +.equ STK_OFFSET_EPC, STK_OFFSET_SR + 4 +.equ STK_OFFSET_LO, STK_OFFSET_EPC + 4 +.equ STK_OFFSET_HI, STK_OFFSET_LO + 4 +.equ STK_OFFSET_GPR1, STK_OFFSET_HI + 4 +.equ STK_OFFSET_GPR2, STK_OFFSET_GPR1 + 4 +.equ STK_OFFSET_GPR3, STK_OFFSET_GPR2 + 4 +.equ STK_OFFSET_GPR4, STK_OFFSET_GPR3 + 4 +.equ STK_OFFSET_GPR5, STK_OFFSET_GPR4 + 4 +.equ STK_OFFSET_GPR6, STK_OFFSET_GPR5 + 4 +.equ STK_OFFSET_GPR7, STK_OFFSET_GPR6 + 4 +.equ STK_OFFSET_GPR8, STK_OFFSET_GPR7 + 4 +.equ STK_OFFSET_GPR9, STK_OFFSET_GPR8 + 4 +.equ STK_OFFSET_GPR10, STK_OFFSET_GPR9 + 4 +.equ STK_OFFSET_GPR11, STK_OFFSET_GPR10 + 4 +.equ STK_OFFSET_GPR12, STK_OFFSET_GPR11 + 4 +.equ STK_OFFSET_GPR13, STK_OFFSET_GPR12 + 4 +.equ STK_OFFSET_GPR14, STK_OFFSET_GPR13 + 4 +.equ STK_OFFSET_GPR15, STK_OFFSET_GPR14 + 4 +.equ STK_OFFSET_GPR16, STK_OFFSET_GPR15 + 4 +.equ STK_OFFSET_GPR17, STK_OFFSET_GPR16 + 4 +.equ STK_OFFSET_GPR18, STK_OFFSET_GPR17 + 4 +.equ STK_OFFSET_GPR19, STK_OFFSET_GPR18 + 4 +.equ STK_OFFSET_GPR20, STK_OFFSET_GPR19 + 4 +.equ STK_OFFSET_GPR21, STK_OFFSET_GPR20 + 4 +.equ STK_OFFSET_GPR22, STK_OFFSET_GPR21 + 4 +.equ STK_OFFSET_GPR23, STK_OFFSET_GPR22 + 4 +.equ STK_OFFSET_GPR24, STK_OFFSET_GPR23 + 4 +.equ STK_OFFSET_GPR25, STK_OFFSET_GPR24 + 4 +.equ STK_OFFSET_GPR26, STK_OFFSET_GPR25 + 4 +.equ STK_OFFSET_GPR27, STK_OFFSET_GPR26 + 4 +.equ STK_OFFSET_GPR28, STK_OFFSET_GPR27 + 4 +.equ STK_OFFSET_GPR30, STK_OFFSET_GPR28 + 4 +.equ STK_OFFSET_GPR31, STK_OFFSET_GPR30 + 4 +.equ STK_CTX_SIZE, STK_OFFSET_GPR31 + 4 + +/* +********************************************************************************************************* +* OSStartHighRdy() +* +* Description: Starts the highest priority task that is available to run. OSStartHighRdy() MUST: +* +* a) Call OSTaskSwHook() +* b) Set OSRunning to TRUE +* c) Switch to the highest priority task. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +* +* Note(s): 1) OSTaskStkInit(), which is responsible for initializing each task's stack, sets bit 0 of the +* entry corresponding to the Status register. Thus, interrupts will be enabled when each +* task first runs. +********************************************************************************************************* +*/ + + .ent OSStartHighRdy +OSStartHighRdy: + + la $8, OSTaskSwHook /* Call OSTaskSwHook() */ + jalr $8 + nop + + addi $8, $0, 1 /* Indicate that the OS is running */ + la $9, OSRunning + sb $8, 0($9) + + la $8, OSTCBHighRdy /* Update the current TCB */ + lw $9, 0($8) + lw $29, 0($9) /* Load the new task's stack pointer */ + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mthi $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + eret /* Begin execution of the task */ + + .end OSStartHighRdy + +/* +********************************************************************************************************* +* OSIntCtxSw() +* +* Description: This function is used to perform a context switch following an ISR. +* +* OSIntCtxSw() implements the following pseudo-code: +* +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore the Status register and the EPC to their prior states; +* Restore the LO and HI registers; +* Restore each of the general purpose registers; +* Adjust the stack pointer; +* Execute an eret instruction to begin executing the new task; +* +* Upon entry, the registers of the task being suspended have already been saved onto that +* task's stack and the SP for the task has been saved in its OS_TCB by the ISR. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + + .ent OSIntCtxSw +OSIntCtxSw: + + la $8, OSTaskSwHook /* Call OSTaskSwHook() */ + jalr $8 + nop + + la $8, OSPrioHighRdy /* Update the current priority */ + lbu $9, 0($8) + la $10, OSPrioCur + sb $9, 0($10) + + la $8, OSTCBHighRdy /* Update the current TCB */ + lw $9, 0($8) + la $10, OSTCBCur + sw $9, 0($10) + + lw $29, 0($9) /* Load the new task's stack pointer */ + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mthi $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + + eret /* Resume execution in new task */ + + .end OSIntCtxSw + +/* +********************************************************************************************************* +* DISABLE INTERRUPTS +* OS_CPU_SR OS_CPU_SR_Save(void); +* +* Description: This function saves the state of the Status register and then disables interrupts via this +* register. This objective is accomplished with a single instruction, di. The di +* instruction's operand, $2, is the general purpose register to which the Status register's +* value is saved. This value can be read by C functions that call OS_CPU_SR_Save(). +* +* Arguments : None +* +* Returns : The previous state of the Status register +********************************************************************************************************* +*/ + + .ent OS_CPU_SR_Save +OS_CPU_SR_Save: + + di $2 /* Disable interrupts, and move the old value of the... */ + /* ...Status register into v0 ($2) */ + jr $31 + nop + + .end OS_CPU_SR_Save + +/* +********************************************************************************************************* +* ENABLE INTERRUPTS +* void OS_CPU_SR_Restore(OS_CPU_SR sr); +* +* Description: This function must be used in tandem with OS_CPU_SR_Save(). Calling OS_CPU_SR_Restore() +* causes the value returned by OS_CPU_SR_Save() to be placed in the Status register. +* +* Arguments : The value to be placed in the Status register +* +* Returns : None +********************************************************************************************************* +*/ + + .ent OS_CPU_SR_Restore +OS_CPU_SR_Restore: + + mtc0 $4, $12, 0 /* Restore the status register to its previous state */ + jr $31 + nop + + .end OS_CPU_SR_Restore + + + .section .gen_excpt,"ax",@progbits + +/* +********************************************************************************************************* +* OSCtxSw +* +* Description: Performs a Context switch from a task. This function is ALWAYS called with interrupts +* DISABLED. +* +* OSCtxSw() implements the following pseudo-code: +* +* Adjust the stack pointer; +* Save each of the general purpose registers; +* Save the LO and HI registers; +* Save the EPC and the Status register; +* Verify that a syscall exception (corresponding to OS_TASK_SW) occurred; +* OSTCBCur->OSTCBStkPtr = SP; +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore the Status register and the EPC to their prior states; +* Restore the LO and HI registers; +* Restore each of the general purpose registers; +* Adjust the stack pointer; +* Execute an eret instruction to begin executing the new task; +* +* The stack frame of the task to suspend will look as follows when OSCtxSw() is done: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +* +* The stack frame of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + + .ent OSCtxSw +OSCtxSw: + + addi $29, $29, -STK_CTX_SIZE /* Adjust the stack pointer */ + + sw $1, STK_OFFSET_GPR1($29) /* Save the General Pupose Registers */ + sw $2, STK_OFFSET_GPR2($29) + sw $3, STK_OFFSET_GPR3($29) + sw $4, STK_OFFSET_GPR4($29) + sw $5, STK_OFFSET_GPR5($29) + sw $6, STK_OFFSET_GPR6($29) + sw $7, STK_OFFSET_GPR7($29) + sw $8, STK_OFFSET_GPR8($29) + sw $9, STK_OFFSET_GPR9($29) + sw $10, STK_OFFSET_GPR10($29) + sw $11, STK_OFFSET_GPR11($29) + sw $12, STK_OFFSET_GPR12($29) + sw $13, STK_OFFSET_GPR13($29) + sw $14, STK_OFFSET_GPR14($29) + sw $15, STK_OFFSET_GPR15($29) + sw $16, STK_OFFSET_GPR16($29) + sw $17, STK_OFFSET_GPR17($29) + sw $18, STK_OFFSET_GPR18($29) + sw $19, STK_OFFSET_GPR19($29) + sw $20, STK_OFFSET_GPR20($29) + sw $21, STK_OFFSET_GPR21($29) + sw $22, STK_OFFSET_GPR22($29) + sw $23, STK_OFFSET_GPR23($29) + sw $24, STK_OFFSET_GPR24($29) + sw $25, STK_OFFSET_GPR25($29) + sw $26, STK_OFFSET_GPR26($29) + sw $27, STK_OFFSET_GPR27($29) + sw $28, STK_OFFSET_GPR28($29) + sw $30, STK_OFFSET_GPR30($29) + sw $31, STK_OFFSET_GPR31($29) + /* Save the contents of the LO and HI registers */ + mflo $8 + mfhi $9 + sw $8, STK_OFFSET_LO($29) + sw $9, STK_OFFSET_HI($29) + + mfc0 $8, $14, 0 /* Save the EPC */ + addi $8, $8, 4 /* EPC will reference the instruction following syscall */ + sw $8, STK_OFFSET_EPC($29) + + mfc0 $8, $12, 0 /* Save the Status register */ + sw $8, STK_OFFSET_SR($29) + + ori $8, $0, 0x007C /* Switch context only if a syscall exception occurred */ + mfc0 $9, $13, 0 + and $9, $9, $8 + ori $10, $0, 0x0020 + beq $9, $10, SAVE_SP + nop + + la $8, BSP_Except_Handler /* Call BSP_Except_Handler() for exceptions not... */ + jalr $8 /* ...triggered by syscall. */ + nop + + b RESTORE_CTX + nop + +SAVE_SP: + + la $8, OSTCBCur /* Save the current task's stack pointer */ + lw $9, 0($8) + sw $29, 0($9) + + la $8, OSTaskSwHook /* Call OSTaskSwHook() */ + jalr $8 + nop + + la $8, OSPrioHighRdy /* Update the current priority */ + lbu $9, 0($8) + la $10, OSPrioCur + sb $9, 0($10) + + la $8, OSTCBHighRdy /* Update the current TCB */ + lw $9, 0($8) + la $10, OSTCBCur + sw $9, 0($10) + + lw $29, 0($9) /* Load the new task's stack pointer */ + +RESTORE_CTX: + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mthi $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + + eret /* Resume execution in new task */ + + .end OSCtxSw + + + .section .timer_handler,"ax",@progbits + +/* +********************************************************************************************************* +* CoreTimerIntHandler +* +* Description: The core timer, which is implemented by the Coprocessor 0 Count and Compare registers, +* is the source of uC/OS-II's tick interrupts. This function handles those interrupts, +* saving the current task's context and then calling OSTimeTick(), uC/OS-II's CPU- +* independent routine for processing tick interrupts. +* +* The interrupted task's context is saved onto its stack as follows: +* +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* | +* | +* \ / +* V +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + + .ent CoreTimerIntHandler +CoreTimerIntHandler: + + addi $29, $29, -STK_CTX_SIZE /* Adjust the stack pointer */ + + sw $1, STK_OFFSET_GPR1($29) /* Save the General Pupose Registers */ + sw $2, STK_OFFSET_GPR2($29) + sw $3, STK_OFFSET_GPR3($29) + sw $4, STK_OFFSET_GPR4($29) + sw $5, STK_OFFSET_GPR5($29) + sw $6, STK_OFFSET_GPR6($29) + sw $7, STK_OFFSET_GPR7($29) + sw $8, STK_OFFSET_GPR8($29) + sw $9, STK_OFFSET_GPR9($29) + sw $10, STK_OFFSET_GPR10($29) + sw $11, STK_OFFSET_GPR11($29) + sw $12, STK_OFFSET_GPR12($29) + sw $13, STK_OFFSET_GPR13($29) + sw $14, STK_OFFSET_GPR14($29) + sw $15, STK_OFFSET_GPR15($29) + sw $16, STK_OFFSET_GPR16($29) + sw $17, STK_OFFSET_GPR17($29) + sw $18, STK_OFFSET_GPR18($29) + sw $19, STK_OFFSET_GPR19($29) + sw $20, STK_OFFSET_GPR20($29) + sw $21, STK_OFFSET_GPR21($29) + sw $22, STK_OFFSET_GPR22($29) + sw $23, STK_OFFSET_GPR23($29) + sw $24, STK_OFFSET_GPR24($29) + sw $25, STK_OFFSET_GPR25($29) + sw $26, STK_OFFSET_GPR26($29) + sw $27, STK_OFFSET_GPR27($29) + sw $28, STK_OFFSET_GPR28($29) + sw $30, STK_OFFSET_GPR30($29) + sw $31, STK_OFFSET_GPR31($29) + /* Save the contents of the LO and HI registers */ + mflo $8 + mfhi $9 + sw $8, STK_OFFSET_LO($29) + sw $9, STK_OFFSET_HI($29) + + mfc0 $8, $14, 0 /* Save the EPC */ + sw $8, STK_OFFSET_EPC($29) + + mfc0 $8, $12, 0 + sw $8, STK_OFFSET_SR($29) + + la $8, OSIntNesting /* See if OSIntNesting == 0 */ + lbu $9, 0($8) + bne $0, $9, TICK_INC_NESTING + nop + + la $10, OSTCBCur /* Save the current task's stack pointer */ + lw $11, 0($10) + sw $29, 0($11) + +TICK_INC_NESTING: + + addi $9, $9, 1 /* Increment OSIntNesting */ + sb $9, 0($8) + + mfc0 $8, $12, 0 /* Update the Status register's IPL bits */ + mfc0 $9, $13, 0 + andi $9, $9, 0xFC00 + ins $8, $0, 10, 6 + or $8, $8, $9 + mtc0 $8, $12, 0 + + la $8, BSP_TickISR_Handler /* Call BSP_TickISR_Handler() to handle the interrupt */ + jalr $8 + nop + + la $8, OSTimeTick /* Call OSTimeTick() */ + jalr $8 + nop + + la $8, OSIntExit /* Call OSIntExit() */ + jalr $8 + nop + + lw $8, STK_OFFSET_SR($29) /* Restore the Status register */ + mtc0 $8, $12, 0 + + lw $8, STK_OFFSET_EPC($29) /* Restore the EPC */ + mtc0 $8, $14, 0 + + lw $8, STK_OFFSET_LO($29) /* Restore the contents of the LO and HI registers */ + lw $9, STK_OFFSET_HI($29) + mtlo $8 + mthi $9 + + lw $31, STK_OFFSET_GPR31($29) /* Restore the General Purpose Registers */ + lw $30, STK_OFFSET_GPR30($29) + lw $28, STK_OFFSET_GPR28($29) + lw $27, STK_OFFSET_GPR27($29) + lw $26, STK_OFFSET_GPR26($29) + lw $25, STK_OFFSET_GPR25($29) + lw $24, STK_OFFSET_GPR24($29) + lw $23, STK_OFFSET_GPR23($29) + lw $22, STK_OFFSET_GPR22($29) + lw $21, STK_OFFSET_GPR21($29) + lw $20, STK_OFFSET_GPR20($29) + lw $19, STK_OFFSET_GPR19($29) + lw $18, STK_OFFSET_GPR18($29) + lw $17, STK_OFFSET_GPR17($29) + lw $16, STK_OFFSET_GPR16($29) + lw $15, STK_OFFSET_GPR15($29) + lw $14, STK_OFFSET_GPR14($29) + lw $13, STK_OFFSET_GPR13($29) + lw $12, STK_OFFSET_GPR12($29) + lw $11, STK_OFFSET_GPR11($29) + lw $10, STK_OFFSET_GPR10($29) + lw $9, STK_OFFSET_GPR9($29) + lw $8, STK_OFFSET_GPR8($29) + lw $7, STK_OFFSET_GPR7($29) + lw $6, STK_OFFSET_GPR6($29) + lw $5, STK_OFFSET_GPR5($29) + lw $4, STK_OFFSET_GPR4($29) + lw $3, STK_OFFSET_GPR3($29) + lw $2, STK_OFFSET_GPR2($29) + lw $1, STK_OFFSET_GPR1($29) + + addi $29, $29, STK_CTX_SIZE /* Adjust the stack pointer */ + + eret + + .end CoreTimerIntHandler + + diff --git a/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_c.c b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_c.c new file mode 100644 index 0000000..10ece98 --- /dev/null +++ b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_cpu_c.c @@ -0,0 +1,321 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MIPS32 4K +* MPLAB +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : None +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : None +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called whenever a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskCreateHook(ptcb); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : None +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : None +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is processor-specific. +* +* Arguments : task is a pointer to the task code. +* +* p_arg is a pointer to a user supplied data area +* +* ptos is a pointer to the top of stack. OSTaskStkInit() assumes that 'ptos' points to +* a free entry on the stack. If OS_STK_GROWTH is set to 1 then 'ptos' will contain +* the HIGHEST valid address of the stack. Similarly, if OS_STK_GROWTH is set to 0, +* 'ptos' will contain the lowest valid address of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit() +* (see ucos_ii.h for OS_TASK_OPT_???). +* +* Returns : The location corresponding to the top of the stack +* +* Note(s) : 1) Interrupts are enabled when each task starts executing. +* +* 2) An initialized stack has the structure shown below. +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Free Entry (LOW Memory) +* + 0x04 Status Register +* + 0x08 EPC +* + 0x0C Special Purpose LO Register +* + 0x10 Special Purpose HI Register +* + 0x14 GPR[1] +* + 0x18 GPR[2] +* + 0x1C GPR[3] +* + 0x20 GPR[4] +* + 0x24 GPR[5] +* + 0x28 GPR[6] +* + 0x2C GPR[7] +* + 0x30 GPR[8] +* + 0x34 GPR[9] +* + 0x38 GPR[10] +* + 0x3C GPR[11] +* + 0x40 GPR[12] +* + 0x44 GPR[13] +* + 0x48 GPR[14] +* + 0x4C GPR[15] +* + 0x50 GPR[16] +* + 0x54 GPR[17] +* + 0x58 GPR[18] +* + 0x5C GPR[19] +* + 0x60 GPR[20] +* + 0x64 GPR[21] +* + 0x68 GPR[22] +* + 0x6C GPR[23] +* + 0x70 GPR[24] +* + 0x74 GPR[25] +* + 0x78 GPR[26] +* + 0x7C GPR[27] +* + 0x80 GPR[28] +* + 0x84 GPR[30] +* + 0x88 GPR[31] (HIGH Memory) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + INT32U sr_val; + INT32U gp_val; + + + (void)opt; /* Prevent compiler warning for unused arguments */ + + asm volatile("mfc0 %0,$12" : "=r"(sr_val)); + sr_val |= 0x00000003; + + asm volatile("addi %0,$28,0" : "=r"(gp_val)); + + pstk = (INT32U *)ptos; + + pstk--; /* Ensure that a free entry is being referenced */ + *pstk-- = (INT32U)task; /* GPR[31] (ra) is used by OSStartHighRdy() */ + *pstk-- = (INT32U)0x30303030; /* GPR[30] */ + *pstk-- = gp_val; /* GPR[28] */ + *pstk-- = (INT32U)0x27272727; /* GPR[27] */ + *pstk-- = (INT32U)0x26262626; /* GPR[26] */ + *pstk-- = (INT32U)0x25252525; /* GPR[25] */ + *pstk-- = (INT32U)0x24242424; /* GPR[24] */ + *pstk-- = (INT32U)0x23232323; /* GPR[23] */ + *pstk-- = (INT32U)0x22222222; /* GPR[22] */ + *pstk-- = (INT32U)0x21212121; /* GPR[21] */ + *pstk-- = (INT32U)0x20202020; /* GPR[20] */ + *pstk-- = (INT32U)0x19191919; /* GPR[19] */ + *pstk-- = (INT32U)0x18181818; /* GPR[18] */ + *pstk-- = (INT32U)0x17171717; /* GPR[17] */ + *pstk-- = (INT32U)0x16161616; /* GPR[16] */ + *pstk-- = (INT32U)0x15151515; /* GPR[15] */ + *pstk-- = (INT32U)0x14141414; /* GPR[14] */ + *pstk-- = (INT32U)0x13131313; /* GPR[13] */ + *pstk-- = (INT32U)0x12121212; /* GPR[12] */ + *pstk-- = (INT32U)0x11111111; /* GPR[11] */ + *pstk-- = (INT32U)0x10101010; /* GPR[10] */ + *pstk-- = (INT32U)0x09090909; /* GPR[9] */ + *pstk-- = (INT32U)0x08080808; /* GPR[8] */ + *pstk-- = (INT32U)0x07070707; /* GPR[7] */ + *pstk-- = (INT32U)0x06060606; /* GPR[6] */ + *pstk-- = (INT32U)0x05050505; /* GPR[5] */ + *pstk-- = (INT32U)0x04040404; /* GPR[4] */ + *pstk-- = (INT32U)0x03030303; /* GPR[3] */ + *pstk-- = (INT32U)0x02020202; /* GPR[2] */ + *pstk-- = (INT32U)0x01010101; /* GPR[1] */ + *pstk-- = (INT32U)0x00000000; /* Special Purpose HI Register */ + *pstk-- = (INT32U)0x00000000; /* Special Purpose LO Register */ + *pstk-- = (INT32U)task; /* EPC */ + *pstk-- = sr_val; /* SR */ + + return ((OS_STK *)pstk); /* Return new top of stack */ +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform +* other operations during a contex switch. +* +* Arguments : None +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer OSTCBHighRdy points to the TCB of the task that +* will be switched in (i.e. the highest priority task), and that OSTCBCur points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ + +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif + +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called after every tick interrupt. +* +* Arguments : None +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif +} +#endif diff --git a/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_dbg.c b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_dbg.c new file mode 100644 index 0000000..f87ac01 --- /dev/null +++ b/Ports/MIPS32-4K/Vectored-Interrupt/MPLAB-PIC32-GCC/os_dbg.c @@ -0,0 +1,299 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* MIPS32 4K +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + + /* The following #define tells the compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/MSP430/IAR/OS_CPU.H b/Ports/MSP430/IAR/OS_CPU.H new file mode 100644 index 0000000..b6a090b --- /dev/null +++ b/Ports/MSP430/IAR/OS_CPU.H @@ -0,0 +1,116 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI MSP430 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (SR = 16 bits) */ + +/* +********************************************************************************************************* +* TI MSP430 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED! +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() _DINT() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() _EINT() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* MSP430 +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on MSP430 */ + +#define OS_TASK_SW() OSCtxSw() /* Task level context switch routine */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK *OSISRStkPtr; /* Pointer to top-of ISR stack */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +OS_CPU_SR OSCPUSaveSR(void); +void OSCPURestoreSR(OS_CPU_SR cpu_sr); diff --git a/Ports/MSP430/IAR/Os_cpu_a.s43 b/Ports/MSP430/IAR/Os_cpu_a.s43 new file mode 100644 index 0000000..23d853b --- /dev/null +++ b/Ports/MSP430/IAR/Os_cpu_a.s43 @@ -0,0 +1,299 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; TI MSP430 +; +; Filename : os_cpu_a.s43 +; Version : V2.93.00 +;******************************************************************************************************** + +#include + +;******************************************************************************************************** +; MACRO DEFINITIONS +;******************************************************************************************************** + +PUSHALL MACRO + push r4 + push r5 + push r6 + push r7 + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + ENDM + +POPALL MACRO + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop r7 + pop r6 + pop r5 + pop r4 + ENDM + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSIntExit + EXTERN OSIntNesting + + EXTERN OSISRStkPtr + + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + + EXTERN OSRunning + + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + + EXTERN OSTaskSwHook + EXTERN OSTimeTick + + PUBLIC OSCtxSw + PUBLIC OSCPURestoreSR + PUBLIC OSCPUSaveSR + PUBLIC OSIntCtxSw + PUBLIC OSStartHighRdy + PUBLIC WDT_ISR + +;******************************************************************************************************** +; START HIGHEST PRIORITY READY TASK +; +; Description: This function is called by OSStart() to start the highest priority task that is ready to run. +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + RSEG CODE ; Program code + +OSStartHighRdy + call #OSTaskSwHook + + mov.b #1, &OSRunning ; kernel running + + mov.w SP, &OSISRStkPtr ; save interrupt stack + + mov.w &OSTCBHighRdy, R13 ; load highest ready task stack + mov.w @R13, SP + + POPALL ; pop all registers + + reti ; emulate return from interrupt + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description: This function is called by OS_Sched() to perform a task level context switch. +; +; Note : OSCtxSw() MUST: +; a) Save the current task's registers onto the current task stack +; b) Save the SP into the current task's OS_TCB +; c) Call OSTaskSwHook() +; d) Copy OSPrioHighRdy to OSPrioCur +; e) Copy OSTCBHighRdy to OSTCBCur +; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; g) Restore all the registers from the high priority task stack +; h) Perform a return from interrupt +;******************************************************************************************************** + +OSCtxSw + push sr ; emulate interrupt by also saving the SR + PUSHALL ; push all registers + + mov.w &OSTCBCur, R13 ; OSTCBCur->OSTCBStkPtr = SP + mov.w SP, 0(R13) + + call #OSTaskSwHook + + mov.b &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy + mov.b R13, &OSPrioCur ; + + mov.w &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy + mov.w R13, &OSTCBCur ; + + mov.w @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr + + POPALL ; pop all registers + + reti ; return from interrup + + +;******************************************************************************************************** +; ISR LEVEL CONTEXT SWITCH +; +; Description: This function is called by OSIntExit() to perform an ISR level context switch. +; +; Note : OSIntCtxSw() MUST: +; a) Call OSTaskSwHook() +; b) Copy OSPrioHighRdy to OSPrioCur +; c) Copy OSTCBHighRdy to OSTCBCur +; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; e) Restore all the registers from the high priority task stack +; f) Perform a return from interrupt +;******************************************************************************************************** + +OSIntCtxSw + + call #OSTaskSwHook + + mov.b &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy + mov.b R13, &OSPrioCur ; + + mov.w &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy + mov.w R13, &OSTCBCur ; + + mov.w @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr + + POPALL ; pop all registers + + reti ; return from interrup + + +;******************************************************************************************************** +; TICK ISR +; +; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source. +; +; Notes : 1) The following C pseudo-code describes the operations being performed in the code below. +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; SP = OSISRStkPtr; /* Use the ISR stack from now on */ +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; DISABLE general interrupts; /* Must DI before calling OSIntExit() */ +; OSIntExit(); +; if (OSIntNesting == 0) { +; SP = OSTCBHighRdy->OSTCBStkPtr; /* Restore the current task's stack */ +; } +; Restore the CPU registers +; Return from interrupt. +; +; 2) ALL ISRs should be written like this! +; +; 3) You MUST disable general interrupts BEFORE you call OSIntExit() because an interrupt +; COULD occur just as OSIntExit() returns and thus, the new ISR would save the SP of +; the ISR stack and NOT the SP of the task stack. This of course will most likely cause +; the code to crash. By disabling interrupts BEFORE OSIntExit(), interrupts would be +; disabled when OSIntExit() would return. This assumes that you are using OS_CRITICAL_METHOD +; #3 (which is the prefered method). +; +; 4) If you DON'T use a separate ISR stack then you don't need to disable general interrupts +; just before calling OSIntExit(). The pseudo-code for an ISR would thus look like this: +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; OSIntExit(); +; Restore the CPU registers +; Return from interrupt. +;******************************************************************************************************** + +WDT_ISR ; wd timer ISR + PUSHALL ; push all registers + + bic.b #0x01, IE1 ; disable wd timer interrupt + + cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0) + jne WDT_ISR_1 + + mov.w &OSTCBCur, R13 ; save task stack + mov.w SP, 0(R13) + + mov.w &OSISRStkPtr, SP ; load interrupt stack + +WDT_ISR_1 + inc.b &OSIntNesting ; increase OSIntNesting + bis.b #0x01, IE1 ; enable wd timer interrupt + + EINT ; enable general interrupt to allow for interrupt nesting + + call #OSTimeTick ; call ticks routine + + DINT ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit() + + call #OSIntExit ; call ticks routine + + cmp.b #0, &OSIntNesting ; if (OSIntNesting == 0) + jne WDT_ISR_2 + + mov.w &OSTCBHighRdy, R13 ; restore task stack SP + mov.w @R13, SP + +WDT_ISR_2 + POPALL ; pop all registers + + reti ; return from interrupt + + +;******************************************************************************************************** +; SAVE AND RESTORE THE CPU'S STATUS REGISTER +; +; Description: These functions are used to implement OS_CRITICAL_METHOD #3 by saving the status register +; in a local variable of the calling function and then, disables interrupts. +; +; Notes : R12 is assumed to hold the argument passed to OSCPUSaveSR() and also, the value returned +; by OSCPURestoreSR(). +;******************************************************************************************************** + +OSCPUSaveSR + MOV.W SR,R12 + DINT + RET + + +OSCPURestoreSR + MOV.W R12,SR + RET + +;******************************************************************************************************** +; WD TIMER INTERRUPT VECTOR ENTRY +; +; MSP430x11x1/MSP430F14x Interrupt vectors +;******************************************************************************************************** + COMMON INTVEC + + ORG WDT_VECTOR +WDT_VEC DW WDT_ISR ; interrupt vector. Watchdog/Timer, Timer mode + + END diff --git a/Ports/MSP430/IAR/Os_cpu_c.c b/Ports/MSP430/IAR/Os_cpu_c.c new file mode 100644 index 0000000..22a85d9 --- /dev/null +++ b/Ports/MSP430/IAR/Os_cpu_c.c @@ -0,0 +1,280 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI MSP430 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR System Embedded Workbench for TI MSP430 V1.26A +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if 0 + LPM0; /* Enter low power mode */ +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : The register passing convention for the IAR compiler is that the LEFTMOST two parameters +* are passed in registers: +* 1st parameter: R12 for a 16-bit value or, R13:R12 for a 32-bit value +* 2nd parameter: R14 for a 16-bit value or, R15:R14 for a 32-bit value +* +* OSTaskStkInit() thus needs to place 'p_arg' in R12 since when the task is started, 'p_arg' +* is the FIRST argument of the task declaration: +* +* void Task (void *p_arg) +* { +* } +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U *top; + + + opt = opt; + top = (INT16U *)ptos; + top--; + *top = (INT16U)task; + top--; + *top = (INT16U)task; /* Interrupt return pointer */ + top--; + *top = (INT16U)0x0008; /* Status register */ + top--; + *top = (INT16U)0x0404; + top--; + *top = (INT16U)0x0505; + top--; + *top = (INT16U)0x0606; + top--; + *top = (INT16U)0x0707; + top--; + *top = (INT16U)0x0808; + top--; + *top = (INT16U)0x0909; + top--; + *top = (INT16U)0x1010; + top--; + *top = (INT16U)0x1111; + top--; + *top = (INT16U)p_arg; /* Pass 'p_arg' through register R12 */ + top--; + *top = (INT16U)0x1313; + top--; + *top = (INT16U)0x1414; + top--; + *top = (INT16U)0x1515; + return ((OS_STK *)top); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/MSP430/IAR/os_dbg.c b/Ports/MSP430/IAR/os_dbg.c new file mode 100644 index 0000000..0d1ed38 --- /dev/null +++ b/Ports/MSP430/IAR/os_dbg.c @@ -0,0 +1,268 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/MSP430X/CCS/MSP430x5xx/os_cpu.h b/Ports/MSP430X/CCS/MSP430x5xx/os_cpu.h new file mode 100644 index 0000000..1b7097f --- /dev/null +++ b/Ports/MSP430X/CCS/MSP430x5xx/os_cpu.h @@ -0,0 +1,128 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI MSP430X +* MSP430x5xx +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (SR = 16 bits) */ + +/* +********************************************************************************************************* +* TI MSP430 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED! +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() _DINT() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() _EINT() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* MSP430 +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on MSP430 */ + +#define OS_TASK_SW() OSCtxSw() /* Task level context switch routine */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK *OSISRStkPtr; /* Pointer to top-of ISR stack */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S85 */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +#endif diff --git a/Ports/MSP430X/CCS/MSP430x5xx/os_cpu_a.s43 b/Ports/MSP430X/CCS/MSP430x5xx/os_cpu_a.s43 new file mode 100644 index 0000000..a34f9dc --- /dev/null +++ b/Ports/MSP430X/CCS/MSP430x5xx/os_cpu_a.s43 @@ -0,0 +1,318 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; TI MSP430X +; MSP430x5xx +; +; Filename : os_cpu_a.s43 +; Version : V2.93.00 +;******************************************************************************************************** + + .cdecls C, LIST, "msp430.h" + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + .ref OSIntExit + .ref OSIntNesting + .ref OSISRStkPtr + .ref OSPrioCur + .ref OSPrioHighRdy + .ref OSRunning + .ref OSTCBCur + .ref OSTCBHighRdy + .ref OSTaskSwHook + .ref OSTimeTick + + .global OSCtxSw + .global OSIntCtxSw + .global OSStartHighRdy + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSTickISR + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .text ; Program code + .align 2 ; 16-bit alignment + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;*********************************************************************************************************************************************************************************************************** + + .asmfunc +OS_CPU_SR_Save: + MOV.W SR, R12 + DINT + NOP + RETA + .endasmfunc + + .asmfunc +OS_CPU_SR_Restore: + MOV.W R12, SR + NOP + RETA + .endasmfunc + +;******************************************************************************************************** +; START HIGHEST PRIORITY READY TASK +; +; Description: This function is called by OSStart() to start the highest priority task that is ready to run. +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + .asmfunc +OSStartHighRdy: + CALLA #OSTaskSwHook + + MOV.B #1, &OSRunning ; kernel running + + MOVX.A SP, &OSISRStkPtr ; save interrupt stack + + MOVX.A &OSTCBHighRdy, R13 ; load highest ready task stack + MOVX.A @R13, SP + + POPM.A #12, R15 + + + RETI ; emulate return from interrupt + .endasmfunc + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description: This function is called by OS_Sched() to perform a task level context switch. +; +; Note : OSCtxSw() MUST: +; a) Save the current task's registers onto the current task stack +; b) Save the SP into the current task's OS_TCB +; c) Call OSTaskSwHook() +; d) Copy OSPrioHighRdy to OSPrioCur +; e) Copy OSTCBHighRdy to OSTCBCur +; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; g) Restore all the registers from the high priority task stack +; h) Perform a return from interrupt +;******************************************************************************************************** + + .asmfunc +OSCtxSw: + POP.W R12 ; Pop lower 16 bits of PC. + POP.W R13 ; Pop upper 4 bits of PC. + + PUSH.W R12 ; Save lower 16 bits of PC. + + RLAM.A #4, R13 ; Save SR + upper 4 bits of PC. + RLAM.A #4, R13 + RLAM.A #4, R13 + MOVX.W SR, R12 + ADDX.A R13, R12 + PUSH.W R12 + + PUSHM.A #12, R15 ; Save R4-R15. + + MOVX.A &OSTCBCur, R13 ; OSTCBCur->OSTCBStkPtr = SP + MOVX.A SP, 0(R13) + + CALLA #OSTaskSwHook + + MOV.B &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy + MOV.B R13, &OSPrioCur + + MOVX.A &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy + MOVX.A R13, &OSTCBCur + + MOVX.A @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr + + POPM.A #12, R15 ; Restore R4-R15. + + RETI ; Return from interrupt. + .endasmfunc + + +;******************************************************************************************************** +; ISR LEVEL CONTEXT SWITCH +; +; Description: This function is called by OSIntExit() to perform an ISR level context switch. +; +; Note : OSIntCtxSw() MUST: +; a) Call OSTaskSwHook() +; b) Copy OSPrioHighRdy to OSPrioCur +; c) Copy OSTCBHighRdy to OSTCBCur +; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; e) Restore all the registers from the high priority task stack +; f) Perform a return from interrupt +;******************************************************************************************************** + + .asmfunc +OSIntCtxSw: + CALLA #OSTaskSwHook + + MOV.B &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy + MOV.B R13, &OSPrioCur + + MOVX.A &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy + MOVX.A R13, &OSTCBCur + + MOVX.A @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr + + POPM.A #12, R15 + + RETI ; return from interrupt + .endasmfunc + + +;******************************************************************************************************** +; TICK ISR +; +; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source. +; +; Notes : 1) The following C pseudo-code describes the operations being performed in the code below. +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; SP = OSISRStkPtr; /* Use the ISR stack from now on */ +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; DISABLE general interrupts; /* Must DI before calling OSIntExit() */ +; OSIntExit(); +; if (OSIntNesting == 0) { +; SP = OSTCBHighRdy->OSTCBStkPtr; /* Restore the current task's stack */ +; } +; Restore the CPU registers +; Return from interrupt. +; +; 2) ALL ISRs should be written like this! +; +; 3) You MUST disable general interrupts BEFORE you call OSIntExit() because an interrupt +; COULD occur just as OSIntExit() returns and thus, the new ISR would save the SP of +; the ISR stack and NOT the SP of the task stack. This of course will most likely cause +; the code to crash. By disabling interrupts BEFORE OSIntExit(), interrupts would be +; disabled when OSIntExit() would return. This assumes that you are using OS_CRITICAL_METHOD +; #3 (which is the prefered method). +; +; 4) If you DON'T use a separate ISR stack then you don't need to disable general interrupts +; just before calling OSIntExit(). The pseudo-code for an ISR would thus look like this: +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; OSIntExit(); +; Restore the CPU registers +; Return from interrupt. +;******************************************************************************************************** + + .sect ".text:_isr" ; place this function in the ISR section + .asmfunc +OSTickISR: ; wd timer ISR + PUSHM.A #12, R15 + + BIC.W #0x01, &SFRIE1 ; disable wd timer interrupt + + CMP.B #0, &OSIntNesting ; if (OSIntNesting == 0) + JNE OSTickISR1 + + MOVX.A &OSTCBCur, R13 ; save task stack + MOVX.A SP, 0(R13) + + MOVX.A &OSISRStkPtr, SP ; load interrupt stack + +OSTickISR1: + INC.B &OSIntNesting ; increase OSIntNesting + + BIS.W #0x01, &SFRIE1 ; enable wd timer interrupt + NOP + + EINT ; enable general interrupt to allow for interrupt nesting + NOP + + CALLA #OSTimeTick ; call ticks routine + + DINT ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit() + NOP + + CALLA #OSIntExit + + CMP.B #0, &OSIntNesting ; if (OSIntNesting == 0) + JNE OSTickISR2 + + MOVX.A &OSTCBHighRdy, R13 ; restore task stack SP + MOVX.A @R13, SP + +OSTickISR2: + POPM.A #12, R15 + + RETI ; return from interrupt + .endasmfunc + + +;******************************************************************************************************** +; WD TIMER INTERRUPT VECTOR ENTRY +; +; Interrupt vectors +;******************************************************************************************************** + + .sect WDT_VECTOR + .short OSTickISR ; interrupt vector. Watchdog/Timer, Timer mode + + .end diff --git a/Ports/MSP430X/CCS/MSP430x5xx/os_cpu_c.c b/Ports/MSP430X/CCS/MSP430x5xx/os_cpu_c.c new file mode 100644 index 0000000..9111f66 --- /dev/null +++ b/Ports/MSP430X/CCS/MSP430x5xx/os_cpu_c.c @@ -0,0 +1,280 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI MSP430X +* MSP430x5xx +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR System Embedded Workbench for TI MSP430 V4.11B +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if 0 + LPM0; /* Enter low power mode */ +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : The register passing convention for the IAR compiler is that the LEFTMOST two parameters +* are passed in registers: +* 1st parameter: R12 for a 16-bit value or, R13:R12 for a 32-bit value +* 2nd parameter: R14 for a 16-bit value or, R15:R14 for a 32-bit value +* +* OSTaskStkInit() thus needs to place 'p_arg' in R12 since when the task is started, 'p_arg' +* is the FIRST argument of the task declaration: +* +* void Task (void *p_arg) +* { +* } +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U tmp; + INT16U *top; + + + opt = opt; + top = (INT16U *)ptos; + top--; + *top-- = (INT16U) ((INT32U)task & 0xFFFF); /* Interrupt return pointer */ + tmp = (INT32U)(((INT32U)task & 0xF0000) >> 4); + *top-- = (INT16U)0x0008 | tmp; /* Status register */ + *top-- = (INT16U)0x0015; + *top-- = (INT16U)0x1515; + *top-- = (INT16U)0x0014; + *top-- = (INT16U)0x1414; + *top-- = (INT16U)0x0013; + *top-- = (INT16U)0x1313; + *top-- = (INT16U)((INT32U)p_arg >> 16); /* Pass 'p_arg' through register R12 */ + *top-- = (INT16U)((INT32U)p_arg && 0xFFFF); /* Pass 'p_arg' through register R12 */ + *top-- = (INT16U)0x0011; + *top-- = (INT16U)0x1111; + *top-- = (INT16U)0x0010; + *top-- = (INT16U)0x1010; + *top-- = (INT16U)0x0009; + *top-- = (INT16U)0x0909; + *top-- = (INT16U)0x0008; + *top-- = (INT16U)0x0808; + *top-- = (INT16U)0x0007; + *top-- = (INT16U)0x0707; + *top-- = (INT16U)0x0006; + *top-- = (INT16U)0x0606; + *top-- = (INT16U)0x0005; + *top-- = (INT16U)0x0505; + *top-- = (INT16U)0x0004; + *top = (INT16U)0x0404; + return ((OS_STK *)top); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/MSP430X/CCS/MSP430x5xx/os_dbg.c b/Ports/MSP430X/CCS/MSP430x5xx/os_dbg.c new file mode 100644 index 0000000..58861bd --- /dev/null +++ b/Ports/MSP430X/CCS/MSP430x5xx/os_dbg.c @@ -0,0 +1,315 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/MSP430X/IAR/MSP430x5xx/os_cpu.h b/Ports/MSP430X/IAR/MSP430x5xx/os_cpu.h new file mode 100644 index 0000000..271e59c --- /dev/null +++ b/Ports/MSP430X/IAR/MSP430x5xx/os_cpu.h @@ -0,0 +1,128 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI MSP430X +* MSP430x5xx +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of CPU status register (SR = 16 bits) */ + +/* +********************************************************************************************************* +* TI MSP430 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED! +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() _DINT() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() _EINT() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() /* Disable interrupts */ +#define OS_EXIT_CRITICAL() /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() (cpu_sr = OS_CPU_SR_Save()) /* Disable interrupts */ +#define OS_EXIT_CRITICAL() (OS_CPU_SR_Restore(cpu_sr)) /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* MSP430 +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on MSP430 */ + +#define OS_TASK_SW() OSCtxSw() /* Task level context switch routine */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_CPU_EXT OS_STK *OSISRStkPtr; /* Pointer to top-of ISR stack */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S85 */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +#endif \ No newline at end of file diff --git a/Ports/MSP430X/IAR/MSP430x5xx/os_cpu_a.s43 b/Ports/MSP430X/IAR/MSP430x5xx/os_cpu_a.s43 new file mode 100644 index 0000000..d8ff996 --- /dev/null +++ b/Ports/MSP430X/IAR/MSP430x5xx/os_cpu_a.s43 @@ -0,0 +1,304 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; TI MSP430X +; MSP430x5xx +; +; Filename : os_cpu_a.s43 +; Version : V2.93.00 +;******************************************************************************************************** + +#include + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSIntExit + EXTERN OSIntNesting + + EXTERN OSISRStkPtr + + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + + EXTERN OSRunning + + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + + EXTERN OSTaskSwHook + EXTERN OSTimeTick + + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSStartHighRdy + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC WDT_ISR + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE ; Program code + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;*********************************************************************************************************************************************************************************************************** + +OS_CPU_SR_Save + MOV.W SR, R12 + DINT + RETA + + +OS_CPU_SR_Restore + MOV.W R12, SR + RETA + +;******************************************************************************************************** +; START HIGHEST PRIORITY READY TASK +; +; Description: This function is called by OSStart() to start the highest priority task that is ready to run. +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy + CALLA #OSTaskSwHook + + MOV.B #1, &OSRunning ; kernel running + + MOVX.A SP, &OSISRStkPtr ; save interrupt stack + + MOVX.A &OSTCBHighRdy, R13 ; load highest ready task stack + MOVX.A @R13, SP + + POPM.A #12, R15 + + RETI ; emulate return from interrupt + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description: This function is called by OS_Sched() to perform a task level context switch. +; +; Note : OSCtxSw() MUST: +; a) Save the current task's registers onto the current task stack +; b) Save the SP into the current task's OS_TCB +; c) Call OSTaskSwHook() +; d) Copy OSPrioHighRdy to OSPrioCur +; e) Copy OSTCBHighRdy to OSTCBCur +; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; g) Restore all the registers from the high priority task stack +; h) Perform a return from interrupt +;******************************************************************************************************** + +OSCtxSw + POP.W R12 ; Pop lower 16 bits of PC. + POP.W R13 ; Pop upper 4 bits of PC. + + PUSH.W R12 ; Save lower 16 bits of PC. + + RLAM.A #4, R13 ; Save SR + upper 4 bits of PC. + RLAM.A #4, R13 + RLAM.A #4, R13 + MOVX.W SR, R12 + ADDX.A R13, R12 + PUSH.W R12 + + PUSHM.A #12, R15 ; Save R4-R15. + + MOVX.A &OSTCBCur, R13 ; OSTCBCur->OSTCBStkPtr = SP + MOVX.A SP, 0(R13) + + CALLA #OSTaskSwHook + + MOV.B &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy + MOV.B R13, &OSPrioCur + + MOVX.A &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy + MOVX.A R13, &OSTCBCur + + MOVX.A @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr + + POPM.A #12, R15 ; Restore R4-R15. + + RETI ; Return from interrupt. + + +;******************************************************************************************************** +; ISR LEVEL CONTEXT SWITCH +; +; Description: This function is called by OSIntExit() to perform an ISR level context switch. +; +; Note : OSIntCtxSw() MUST: +; a) Call OSTaskSwHook() +; b) Copy OSPrioHighRdy to OSPrioCur +; c) Copy OSTCBHighRdy to OSTCBCur +; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; e) Restore all the registers from the high priority task stack +; f) Perform a return from interrupt +;******************************************************************************************************** + +OSIntCtxSw + CALLA #OSTaskSwHook + + MOV.B &OSPrioHighRdy, R13 ; OSPrioCur = OSPrioHighRdy + MOV.B R13, &OSPrioCur + + MOVX.A &OSTCBHighRdy, R13 ; OSTCBCur = OSTCBHighRdy + MOVX.A R13, &OSTCBCur + + MOVX.A @R13, SP ; SP = OSTCBHighRdy->OSTCBStkPtr + + POPM.A #12, R15 + + RETI ; return from interrup + + +;******************************************************************************************************** +; TICK ISR +; +; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source. +; +; Notes : 1) The following C pseudo-code describes the operations being performed in the code below. +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; SP = OSISRStkPtr; /* Use the ISR stack from now on */ +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; DISABLE general interrupts; /* Must DI before calling OSIntExit() */ +; OSIntExit(); +; if (OSIntNesting == 0) { +; SP = OSTCBHighRdy->OSTCBStkPtr; /* Restore the current task's stack */ +; } +; Restore the CPU registers +; Return from interrupt. +; +; 2) ALL ISRs should be written like this! +; +; 3) You MUST disable general interrupts BEFORE you call OSIntExit() because an interrupt +; COULD occur just as OSIntExit() returns and thus, the new ISR would save the SP of +; the ISR stack and NOT the SP of the task stack. This of course will most likely cause +; the code to crash. By disabling interrupts BEFORE OSIntExit(), interrupts would be +; disabled when OSIntExit() would return. This assumes that you are using OS_CRITICAL_METHOD +; #3 (which is the prefered method). +; +; 4) If you DON'T use a separate ISR stack then you don't need to disable general interrupts +; just before calling OSIntExit(). The pseudo-code for an ISR would thus look like this: +; +; Save all the CPU registers +; if (OSIntNesting == 0) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; OSIntNesting++; +; Enable interrupt nesting; /* Allow nesting of interrupts (if needed) */ +; Clear the interrupt source; +; OSTimeTick(); /* Call uC/OS-II's tick handler */ +; OSIntExit(); +; Restore the CPU registers +; Return from interrupt. +;******************************************************************************************************** + +WDT_ISR ; wd timer ISR + PUSHM.A #12, R15 + + BIC.W #0x01, SFRIE1 ; disable wd timer interrupt + + CMP.B #0, &OSIntNesting ; if (OSIntNesting == 0) + JNE WDT_ISR_1 + + MOVX.A &OSTCBCur, R13 ; save task stack + MOVX.A SP, 0(R13) + + MOVX.A &OSISRStkPtr, SP ; load interrupt stack + +WDT_ISR_1 + INC.B &OSIntNesting ; increase OSIntNesting + + BIS.W #0x01, SFRIE1 ; enable wd timer interrupt + + EINT ; enable general interrupt to allow for interrupt nesting + + CALLA #OSTimeTick ; call ticks routine + + DINT ; IMPORTANT: disable general interrupt BEFORE calling OSIntExit() + + CALLA #OSIntExit + + CMP.B #0, &OSIntNesting ; if (OSIntNesting == 0) + JNE WDT_ISR_2 + + MOVX.A &OSTCBHighRdy, R13 ; restore task stack SP + MOVX.A @R13, SP + +WDT_ISR_2 + POPM.A #12, R15 + + RETI ; return from interrupt + +;******************************************************************************************************** +; WD TIMER INTERRUPT VECTOR ENTRY +; +; Interrupt vectors +;******************************************************************************************************** + COMMON INTVEC + + ORG WDT_VECTOR +WDT_VEC DW WDT_ISR ; interrupt vector. Watchdog/Timer, Timer mode + + END diff --git a/Ports/MSP430X/IAR/MSP430x5xx/os_cpu_c.c b/Ports/MSP430X/IAR/MSP430x5xx/os_cpu_c.c new file mode 100644 index 0000000..9111f66 --- /dev/null +++ b/Ports/MSP430X/IAR/MSP430x5xx/os_cpu_c.c @@ -0,0 +1,280 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TI MSP430X +* MSP430x5xx +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* Compiler : IAR System Embedded Workbench for TI MSP430 V4.11B +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if 0 + LPM0; /* Enter low power mode */ +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : The register passing convention for the IAR compiler is that the LEFTMOST two parameters +* are passed in registers: +* 1st parameter: R12 for a 16-bit value or, R13:R12 for a 32-bit value +* 2nd parameter: R14 for a 16-bit value or, R15:R14 for a 32-bit value +* +* OSTaskStkInit() thus needs to place 'p_arg' in R12 since when the task is started, 'p_arg' +* is the FIRST argument of the task declaration: +* +* void Task (void *p_arg) +* { +* } +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U tmp; + INT16U *top; + + + opt = opt; + top = (INT16U *)ptos; + top--; + *top-- = (INT16U) ((INT32U)task & 0xFFFF); /* Interrupt return pointer */ + tmp = (INT32U)(((INT32U)task & 0xF0000) >> 4); + *top-- = (INT16U)0x0008 | tmp; /* Status register */ + *top-- = (INT16U)0x0015; + *top-- = (INT16U)0x1515; + *top-- = (INT16U)0x0014; + *top-- = (INT16U)0x1414; + *top-- = (INT16U)0x0013; + *top-- = (INT16U)0x1313; + *top-- = (INT16U)((INT32U)p_arg >> 16); /* Pass 'p_arg' through register R12 */ + *top-- = (INT16U)((INT32U)p_arg && 0xFFFF); /* Pass 'p_arg' through register R12 */ + *top-- = (INT16U)0x0011; + *top-- = (INT16U)0x1111; + *top-- = (INT16U)0x0010; + *top-- = (INT16U)0x1010; + *top-- = (INT16U)0x0009; + *top-- = (INT16U)0x0909; + *top-- = (INT16U)0x0008; + *top-- = (INT16U)0x0808; + *top-- = (INT16U)0x0007; + *top-- = (INT16U)0x0707; + *top-- = (INT16U)0x0006; + *top-- = (INT16U)0x0606; + *top-- = (INT16U)0x0005; + *top-- = (INT16U)0x0505; + *top-- = (INT16U)0x0004; + *top = (INT16U)0x0404; + return ((OS_STK *)top); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTimeTickHook (void) +{ +} +#endif diff --git a/Ports/MSP430X/IAR/MSP430x5xx/os_dbg.c b/Ports/MSP430X/IAR/MSP430x5xx/os_dbg.c new file mode 100644 index 0000000..0d7000e --- /dev/null +++ b/Ports/MSP430X/IAR/MSP430x5xx/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/MicroBlaze/EDK/Code/includes.h b/Ports/MicroBlaze/EDK/Code/includes.h new file mode 100644 index 0000000..a85aa3b --- /dev/null +++ b/Ports/MicroBlaze/EDK/Code/includes.h @@ -0,0 +1,32 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MASTER INCLUDE FILE +* +* Filename : includes.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include +#include +#include + +#include diff --git a/Ports/MicroBlaze/EDK/Code/os_cfg.h b/Ports/MicroBlaze/EDK/Code/os_cfg.h new file mode 100644 index 0000000..7112297 --- /dev/null +++ b/Ports/MicroBlaze/EDK/Code/os_cfg.h @@ -0,0 +1,130 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* uC/OS-II Configuration File for V2.9x +* +* Filename : os_cfg.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CFG_H +#define OS_CFG_H + + /* ---------------------- MISCELLANEOUS ----------------------- */ +#define OS_ARG_CHK_EN 1 /* Enable (1) or Disable (0) argument checking */ +#define OS_CPU_HOOKS_EN 1 /* uC/OS-II hooks are found in the processor port files */ + +#define OS_DEBUG_EN 1 /* Enable(1) debug variables */ + +#define OS_EVENT_NAME_SIZE 32 /* Determine the size of the name of a Sem, Mutex, Mbox or Q */ + +#define OS_LOWEST_PRIO 63 /* Defines the lowest priority that can be assigned ... */ + /* ... MUST NEVER be higher than 63! */ + +#define OS_MAX_EVENTS 10 /* Max. number of event control blocks in your application */ +#define OS_MAX_FLAGS 5 /* Max. number of Event Flag Groups in your application */ +#define OS_MAX_MEM_PART 5 /* Max. number of memory partitions */ +#define OS_MAX_QS 4 /* Max. number of queue control blocks in your application */ +#define OS_MAX_TASKS 20 /* Max. number of tasks in your application, MUST be >= 2 */ + +#define OS_SCHED_LOCK_EN 1 /* Include code for OSSchedLock() and OSSchedUnlock() */ + +#define OS_TASK_IDLE_STK_SIZE 128 /* Idle task stack size (# of OS_STK wide entries) */ + +#define OS_TASK_STAT_EN 1 /* Enable (1) or Disable(0) the statistics task */ +#define OS_TASK_STAT_STK_SIZE 128 /* Statistics task stack size (# of OS_STK wide entries) */ +#define OS_TASK_STAT_STK_CHK_EN 1 /* Check task stacks from statistic task */ + +#define OS_TICK_STEP_EN 1 /* Enable tick stepping feature for uC/OS-View */ +#define OS_TICKS_PER_SEC 20 /* Set the number of ticks in one second */ + + + /* ----------------------- EVENT FLAGS ------------------------ */ +#define OS_FLAG_EN 1 /* Enable (1) or Disable (0) code generation for EVENT FLAGS */ +#define OS_FLAG_WAIT_CLR_EN 1 /* Include code for Wait on Clear EVENT FLAGS */ +#define OS_FLAG_ACCEPT_EN 1 /* Include code for OSFlagAccept() */ +#define OS_FLAG_DEL_EN 1 /* Include code for OSFlagDel() */ +#define OS_FLAG_NAME_SIZE 32 /* Determine the size of the name of an event flag group */ +#define OS_FLAG_QUERY_EN 1 /* Include code for OSFlagQuery() */ + + + /* -------------------- MESSAGE MAILBOXES --------------------- */ +#define OS_MBOX_EN 1 /* Enable (1) or Disable (0) code generation for MAILBOXES */ +#define OS_MBOX_ACCEPT_EN 1 /* Include code for OSMboxAccept() */ +#define OS_MBOX_DEL_EN 1 /* Include code for OSMboxDel() */ +#define OS_MBOX_POST_EN 1 /* Include code for OSMboxPost() */ +#define OS_MBOX_POST_OPT_EN 1 /* Include code for OSMboxPostOpt() */ +#define OS_MBOX_QUERY_EN 1 /* Include code for OSMboxQuery() */ + + + /* --------------------- MEMORY MANAGEMENT -------------------- */ +#define OS_MEM_EN 1 /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */ +#define OS_MEM_QUERY_EN 1 /* Include code for OSMemQuery() */ +#define OS_MEM_NAME_SIZE 32 /* Determine the size of a memory partition name */ + + + /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */ +#define OS_MUTEX_EN 1 /* Enable (1) or Disable (0) code generation for MUTEX */ +#define OS_MUTEX_ACCEPT_EN 1 /* Include code for OSMutexAccept() */ +#define OS_MUTEX_DEL_EN 1 /* Include code for OSMutexDel() */ +#define OS_MUTEX_QUERY_EN 1 /* Include code for OSMutexQuery() */ + + + /* ---------------------- MESSAGE QUEUES ---------------------- */ +#define OS_Q_EN 1 /* Enable (1) or Disable (0) code generation for QUEUES */ +#define OS_Q_ACCEPT_EN 1 /* Include code for OSQAccept() */ +#define OS_Q_DEL_EN 1 /* Include code for OSQDel() */ +#define OS_Q_FLUSH_EN 1 /* Include code for OSQFlush() */ +#define OS_Q_POST_EN 1 /* Include code for OSQPost() */ +#define OS_Q_POST_FRONT_EN 1 /* Include code for OSQPostFront() */ +#define OS_Q_POST_OPT_EN 1 /* Include code for OSQPostOpt() */ +#define OS_Q_QUERY_EN 1 /* Include code for OSQQuery() */ + + + /* ------------------------ SEMAPHORES ------------------------ */ +#define OS_SEM_EN 1 /* Enable (1) or Disable (0) code generation for SEMAPHORES */ +#define OS_SEM_ACCEPT_EN 1 /* Include code for OSSemAccept() */ +#define OS_SEM_DEL_EN 1 /* Include code for OSSemDel() */ +#define OS_SEM_QUERY_EN 1 /* Include code for OSSemQuery() */ + + + /* --------------------- TASK MANAGEMENT ---------------------- */ +#define OS_TASK_CHANGE_PRIO_EN 1 /* Include code for OSTaskChangePrio() */ +#define OS_TASK_CREATE_EN 1 /* Include code for OSTaskCreate() */ +#define OS_TASK_CREATE_EXT_EN 1 /* Include code for OSTaskCreateExt() */ +#define OS_TASK_DEL_EN 1 /* Include code for OSTaskDel() */ +#define OS_TASK_NAME_SIZE 32 /* Determine the size of a task name */ +#define OS_TASK_PROFILE_EN 1 /* Include variables in OS_TCB for profiling */ +#define OS_TASK_QUERY_EN 1 /* Include code for OSTaskQuery() */ +#define OS_TASK_SUSPEND_EN 1 /* Include code for OSTaskSuspend() and OSTaskResume() */ +#define OS_TASK_SW_HOOK_EN 1 /* Include code for OSTaskSwHook() */ + + + /* --------------------- TIME MANAGEMENT ---------------------- */ +#define OS_TIME_DLY_HMSM_EN 1 /* Include code for OSTimeDlyHMSM() */ +#define OS_TIME_DLY_RESUME_EN 1 /* Include code for OSTimeDlyResume() */ +#define OS_TIME_GET_SET_EN 1 /* Include code for OSTimeGet() and OSTimeSet() */ +#define OS_TIME_TICK_HOOK_EN 1 /* Include code for OSTimeTickHook() */ + + +typedef INT16U OS_FLAGS; /* Date type for event flag bits (8, 16 or 32 bits) */ + +#endif diff --git a/Ports/MicroBlaze/EDK/Code/system.c b/Ports/MicroBlaze/EDK/Code/system.c new file mode 100644 index 0000000..6e9c78c --- /dev/null +++ b/Ports/MicroBlaze/EDK/Code/system.c @@ -0,0 +1,131 @@ +/****************************************************************************** +* Function name : system.c +* returns : +* Created by : Nasser Poureh +* Date Created : 6/17/03 +* Company : Insight Electronics +* Description : Main Program +* Notes : +******************************************************************************/ + +#include "xuartlite_l.h" +#include "xtmrctr_l.h" +#include "xgpio_l.h" +#include "xparameters.h" +#include + + + +unsigned int count_1 = 0; +unsigned int count_2 = 0; +unsigned int timer_count = 1; +static char display_data[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6}; + + + + + +void timer1_int_handler(void * baseaddr_p) { + int baseaddr = *(int *)baseaddr_p; + unsigned int csr; + + /* Read timer 0 CSR to see if it raised the interrupt */ + csr = XTmrCtr_mGetControlStatusReg(XPAR_MYTIMER1_BASEADDR, 0); + + if (csr & XTC_CSR_INT_OCCURED_MASK) { + + XGpio_mSetDataReg(XPAR_MYGPIO_A_BASEADDR, display_data[count_1]); + + + /* Clear the timer interrupt */ + XTmrCtr_mSetControlStatusReg(XPAR_MYTIMER1_BASEADDR, 0, csr); + + } + + count_1 = count_1 + 1; + + if (count_1 == 10) { + count_1 = 0; + } + +} + + + + + +void timer2_int_handler(void * baseaddr_p) { + int baseaddr = *(int *)baseaddr_p; + unsigned int csr; + + /* Read timer 0 CSR to see if it raised the interrupt */ + csr = XTmrCtr_mGetControlStatusReg(XPAR_MYTIMER2_BASEADDR, 0); + + if (csr & XTC_CSR_INT_OCCURED_MASK) { + + XGpio_mSetDataReg(XPAR_MYGPIO_B_BASEADDR, display_data[count_2]); + + + /* Clear the timer interrupt */ + XTmrCtr_mSetControlStatusReg(XPAR_MYTIMER2_BASEADDR, 0, csr); + + } + count_2 = count_2 + 1; + + if (count_2 == 10) { + count_2 = 0; + } + +} + + + + + + + +main() { + + + print(" ####################################################\n\r"); + print(" # #\n\r"); + print(" # Memec Design MB1000 #\n\r"); + print(" # MicroBlaze Development Board #\n\r"); + print(" # #\n\r"); + print(" ####################################################\n\r"); + print("\n\r"); + print("\n\r"); + + + + /* Enable microblaze interrupts */ + microblaze_enable_interrupts(); + + /* Start the interrupt controller */ + XIntc_mMasterEnable(XPAR_MYINTC_BASEADDR); + + /* Set the direction of the GPIO ports to outputs to drive the 7-seg LEDs*/ + XGpio_mSetDataDirection(XPAR_MYGPIO_A_BASEADDR, 0x00); + XGpio_mSetDataDirection(XPAR_MYGPIO_B_BASEADDR, 0x00); + + /* set the number of cycles each timer counts before generating an interrupt */ + XTmrCtr_mSetLoadReg(XPAR_MYTIMER1_BASEADDR, 0, 50000000); + XTmrCtr_mSetLoadReg(XPAR_MYTIMER2_BASEADDR, 0, 100000000); + + /* reset the timers, and clear interrupts */ + XTmrCtr_mSetControlStatusReg(XPAR_MYTIMER1_BASEADDR, 0, XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK ); + XTmrCtr_mSetControlStatusReg(XPAR_MYTIMER2_BASEADDR, 0, XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK ); + + /* Enable timer1 and timer2 interrupts in the interrupt controller */ + XIntc_mEnableIntr(XPAR_MYINTC_BASEADDR, XPAR_MYTIMER1_INTERRUPT_MASK | XPAR_MYTIMER2_INTERRUPT_MASK); + + /* start the timers */ + XTmrCtr_mSetControlStatusReg(XPAR_MYTIMER1_BASEADDR, 0, XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK); + XTmrCtr_mSetControlStatusReg(XPAR_MYTIMER2_BASEADDR, 0, XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK | XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK); + + /* Wait for interrupts to occur */ + while (1) + ; + +} + diff --git a/Ports/MicroBlaze/GNU/USE_MSR_INSTR/os_cpu_a.S b/Ports/MicroBlaze/GNU/USE_MSR_INSTR/os_cpu_a.S new file mode 100644 index 0000000..73560f8 --- /dev/null +++ b/Ports/MicroBlaze/GNU/USE_MSR_INSTR/os_cpu_a.S @@ -0,0 +1,730 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Xilinx MicroBlaze +* GNU C/C++ Compiler +* +* Filename : os_cpu_a.S +* Version : V2.93.00 +********************************************************************************************************* +*/ +#define _ASMLANGUAGE + +/* +********************************************************************************************************* +* CONSTANTS USED TO ACCESS TASK CONTEXT STACK +********************************************************************************************************* +*/ +.equ STK_OFFSET_RMSR, 0x00 +.equ STK_OFFSET_R02, 0x04 +.equ STK_OFFSET_R03, 0x08 +.equ STK_OFFSET_R04, 0x0C +.equ STK_OFFSET_R05, 0x10 +.equ STK_OFFSET_R06, 0x14 +.equ STK_OFFSET_R07, 0x18 +.equ STK_OFFSET_R08, 0x1C +.equ STK_OFFSET_R09, 0x20 +.equ STK_OFFSET_R10, 0x24 +.equ STK_OFFSET_R11, 0x28 +.equ STK_OFFSET_R12, 0x2C +.equ STK_OFFSET_R13, 0x30 +.equ STK_OFFSET_R14, 0x34 +.equ STK_OFFSET_R15, 0x38 +.equ STK_OFFSET_R17, 0x3C +.equ STK_OFFSET_R18, 0x40 +.equ STK_OFFSET_R19, 0x44 +.equ STK_OFFSET_R20, 0x48 +.equ STK_OFFSET_R21, 0x4C +.equ STK_OFFSET_R22, 0x50 +.equ STK_OFFSET_R23, 0x54 +.equ STK_OFFSET_R24, 0x58 +.equ STK_OFFSET_R25, 0x5C +.equ STK_OFFSET_R26, 0x60 +.equ STK_OFFSET_R27, 0x64 +.equ STK_OFFSET_R28, 0x68 +.equ STK_OFFSET_R29, 0x6C +.equ STK_OFFSET_R30, 0x70 +.equ STK_OFFSET_R31, 0x74 + +.equ STK_CTX_SIZE, 0x78 + +.equ CPU_IE_BIT, 0x02 + + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + .globl OSStartHighRdy + .globl OSCtxSw + .globl OSIntCtxSw + + .globl _interrupt_handler + .globl OS_CPU_ISR + .globl OS_CPU_SR_Save + .globl OS_CPU_SR_Restore + +/* +********************************************************************************************************* +* EXTERNAL FUNCTIONS +********************************************************************************************************* +*/ + .extern OSIntEnter + .extern OSIntExit + .extern OS_CPU_IntHandler +/* +********************************************************************************************************* +* EXTERNAL VARIABLES +********************************************************************************************************* +*/ + .extern OSRunning + .extern OSIntNesting + .extern OSTaskSwHook + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSPrioCur + .extern OSPrioHighRdy + +.text +/* +********************************************************************************************************* +* DISABLE INTERRUPTS +* OS_CPU_SR OS_CPU_SR_Save(void); +* +* Description : Disables the interrupts and returns the RMSR contents. This allows the IE state to be +* restored at a subsequent time. +* +* The variable in the calling routine which the return is set to MUST be declared 'volatile' +* for proper operation. There is no guarantee that the proper register will be scheduled +* for the subsequent 'OS_CPU_SR_Save()' function call if the variable is not declared +* 'volatile'. +* +* Arguments : None +* +* Returns : Current RMSR contents in R3 +* +* Note(s) : None +********************************************************************************************************* +*/ + +OS_CPU_SR_Save: + RTSD r15, 8 + MSRCLR r3, CPU_IE_BIT /* Save MSR in r3 and disable interrupts */ + +/* +********************************************************************************************************* +* ENABLE INTERRUPTS +* void OS_CPU_SR_Restore(OS_CPU_SR sr); +* +* Description: Enables the interrupts using the provided data. If the IE bit is set in the argument, the +* RTID opcode is used to return. If the IE bis is clear, the standard RTSD is used leaving +* the interrupts disabled. +* +* The argument from the calling routine MUST be declared 'volatile' for proper operation. +* There is no guarantee that the proper register will be scheduled for the 'OS_CPU_SR_Restore()' +* function call if the variable is not declared 'volatile'. +* +* Arguments : Saved RMSR contents in R5 +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +OS_CPU_SR_Restore: + RTSD r15, 8 + MTS rMSR, r5 /* Move the saved status from r5 into rMSR */ + + +/* +********************************************************************************************************* +* OSStartHighRdy() +* +* Description: Starts the highest priority task that is available to run. OSStartHighRdy() MUST: +* +* a) Call OSTaskSwHook() +* b) Set OSRunning to TRUE +* c) Switch to the highest priority task. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (IE=1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +********************************************************************************************************* +*/ + +OSStartHighRdy: + + BRLID r15, OSTaskSwHook /* Call OSTaskSwHook() */ + AND r0, r0, r0 /* NO-OP */ + + OR r3, r3, r0 /* OSRunning = TRUE */ + ADDIK r3, r0, 1 + SBI r3, r0, OSRunning + + LWI r3, r0, OSTCBHighRdy /* SP = OSTCBHighRdy->OSTCBStkPtr */ + LW r1, r0, r3 + + LWI r31, r1, STK_OFFSET_R31 /* *************** RESTORE TASK'S CONTEXT *************** */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear the IE bit (It will be set by the return from INT.) */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (i.e. de-allocate storage) */ + + RTID r14, 0 /* Branch to task level code enabling interrupts, IE=1 */ + AND r0, r0, r0 /* NO-OP */ + +/* +********************************************************************************************************* +* OSCtxSw() +* +* Description: Performs the Context switch from a task. This function is ALWAYS called with interrupts +* DISABLED. +* +* OSCtxSw() must implement the following pseudo-code: +* +* Save ALL CPU registers; +* OSTCBCur->OSTCBStkPtr = SP; +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore ALL the CPU registers; +* if (IE bit of saved RMSR is 0) { +* Return from function call; +* } else { +* Set IE bit of RMSR to 0; +* Return from interrupt whcih sets IE back to 1; +* } +* +* +* The stack frame of the task to suspend will look as follows when OSCtxSw() is done: +* +* OSTCBCur->OSTCBStkPtr + 0x00 RMSR (See Note 1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* The stack frame of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (See Note 2) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* Note(s) : 1) OSCtxSw() is ALWAYS called with IE set to 0 (i.e. interrupts disabled). +* 2) If the task frame was saved by OSCtxSw(), IE would be set to 0. +* If the task frame was saved by an ISR, IE would be set to 1. +********************************************************************************************************* +*/ + +OSCtxSw: + /* *************** SAVE CURRENT TASK'S CONTEXT *************** */ + ADDIK r1, r1, -STK_CTX_SIZE /* Allocate storage for saving registers onto stack */ + + SWI r2, r1, STK_OFFSET_R02 /* Save the remaining registers onto the task's stack */ + SWI r3, r1, STK_OFFSET_R03 + SWI r4, r1, STK_OFFSET_R04 + SWI r5, r1, STK_OFFSET_R05 + SWI r6, r1, STK_OFFSET_R06 + SWI r7, r1, STK_OFFSET_R07 + SWI r8, r1, STK_OFFSET_R08 + SWI r9, r1, STK_OFFSET_R09 + SWI r10, r1, STK_OFFSET_R10 + SWI r11, r1, STK_OFFSET_R11 + SWI r12, r1, STK_OFFSET_R12 + SWI r13, r1, STK_OFFSET_R13 + SWI r14, r1, STK_OFFSET_R14 + SWI r15, r1, STK_OFFSET_R15 + SWI r17, r1, STK_OFFSET_R17 + SWI r18, r1, STK_OFFSET_R18 + SWI r19, r1, STK_OFFSET_R19 + SWI r20, r1, STK_OFFSET_R20 + SWI r21, r1, STK_OFFSET_R21 + SWI r22, r1, STK_OFFSET_R22 + SWI r23, r1, STK_OFFSET_R23 + SWI r24, r1, STK_OFFSET_R24 + SWI r25, r1, STK_OFFSET_R25 + SWI r26, r1, STK_OFFSET_R26 + SWI r27, r1, STK_OFFSET_R27 + SWI r28, r1, STK_OFFSET_R28 + SWI r29, r1, STK_OFFSET_R29 + SWI r30, r1, STK_OFFSET_R30 + SWI r31, r1, STK_OFFSET_R31 + + MFS r3, RMSR /* save the MSR (See Note 1) */ + SWI r3, r1, STK_OFFSET_RMSR + + LWI r3, r0, OSTCBCur /* OSTCBCur->OSTCBStkPtr = SP */ + SW r1, r0, r3 + + BRLID r15, OSTaskSwHook /* Call OSTaskSwHook() */ + AND r0, r0, r0 /* NO-OP */ + + LBUI r3, r0, OSPrioHighRdy /* OSPrioCur = OSPrioHighRdy */ + SBI r3, r0, OSPrioCur + + LWI r3, r0, OSTCBHighRdy /* OSTCBCur = OSTCBHighRdy */ + SWI r3, r0, OSTCBCur + + LW r1, r0, r3 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + LWI r31, r1, STK_OFFSET_R31 /* **************** RESTORE NEW TASK'S CONTEXT *************** */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDI r3, r3, CPU_IE_BIT /* See if IE is 0 (Saved by OSCtxSw()) or 1 (Saved by ISR) */ + BNEI r3, OSCtxSw_SavedByISR /* Branch if ISR saved context */ + + /* *********** The context was saved by OSCtxSw() ************ */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTSD r15, 8 /* Context was saved by OSCtxSw() */ + AND r0, r0, r0 /* NO-OP */ + +OSCtxSw_SavedByISR: + /* ************ The context was saved by an ISR ************** */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear the IE bit (It will be set by the return from INT.) */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTID r14, 0 /* Context was saved by ISR, return address is in R14, Set IE */ + AND r0, r0, r0 /* NO-OP */ + +/* +********************************************************************************************************* +* OSIntCtxSw() +* +* Description: Performs the Context Switch from an ISR. +* +* OSIntCtxSw() must implement the following pseudo-code: +* +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore ALL the CPU registers; +* if (IE bit of saved RMSR is 0) { +* Return from function call; +* } else { +* Set IE bit of RMSR to 0; +* Return from interrupt; +* } +* +* Upon entry, the registers of the task being suspended have already been saved onto that +* task's stack and the SP for the task has been saved in its OS_TCB by the ISR. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (See Note 1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* Note(s) : 1) If the task frame was saved by OSCtxSw(), IE would be set to 0. +* If the task frame was saved by an ISR, IE would be set to 1. +********************************************************************************************************* +*/ + +OSIntCtxSw: + + BRLID r15, OSTaskSwHook /* Call OSTaskSwHook() */ + AND r0, r0, r0 /* NO-OP */ + + LBUI r3, r0, OSPrioHighRdy /* OSPrioCur = OSPrioHighRdy */ + SBI r3, r0, OSPrioCur + + LWI r3, r0, OSTCBHighRdy /* OSTCBCur = OSTCBHighRdy */ + SWI r3, r0, OSTCBCur + + LW r1, r0, r3 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + LWI r31, r1, STK_OFFSET_R31 /* **************** RESTORE NEW TASK'S CONTEXT *************** */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDI r3, r3, CPU_IE_BIT /* See if IE is 0 (Saved by OSCtxSw()) or 1 (Saved by ISR) */ + BNEI r3, OSIntCtxSw_SavedByISR /* Branch if ISR saved context */ + + /* *********** The context was saved by OSCtxSw() ************ */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTSD r15, 8 /* Context was saved by OSCtxSw() */ + AND r0, r0, r0 /* NO-OP */ + +OSIntCtxSw_SavedByISR: /* ************ The context was saved by an ISR ************** */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear the IE bit (It will be set by the return from INT.) */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTID r14, 0 /* Context was saved by ISR, return address is in R14 */ + AND r0, r0, r0 /* NO-OP */ + +/* +********************************************************************************************************* +* OS_CPU_ISR() +* +* Description: This routine is intended to be the target of the Interrupt processing functionality that +* occurs when the MicroBlaze is interrupted. The address, 'XOSExternalInterruptHandler', is +* used as the branch destination in the code that is executed at addresses 0x10 and 0x14 in +* the MicroBlaze vector table assuming that the vector table is in RAM +* +* The XPS interrupt vector is replaced by OS_CPU_ISR() by executing the code from a C function: +* +* *(INT32U *)0x00000010 = 0xB0000000 | ((INT32U)OS_CPU_ISR >> 16); +* *(INT32U *)0x00000014 = 0xB8080000 | ((INT32U)OS_CPU_ISR & 0x0000FFFF); +* +* The interrupted task context is saved onto its stack as follows: +* +* OSTCBCur->OSTCBStkPtr + 0x00 RMSR (See Note 1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* Note(s) : 1) The IE bit is saved onto the stack 'set' since the code must return to the interrupted +* task with interrupts enabled. +********************************************************************************************************* +*/ + +_interrupt_handler: +OS_CPU_ISR: + /* ********** SAVE INTERRUPTED TASK'S CONTEXT *********** */ + ADDIK r1, r1, -STK_CTX_SIZE /* Allocate storage for saving registers onto stack */ + + SWI r2, r1, STK_OFFSET_R02 + SWI r3, r1, STK_OFFSET_R03 + SWI r4, r1, STK_OFFSET_R04 + SWI r5, r1, STK_OFFSET_R05 + SWI r6, r1, STK_OFFSET_R06 + SWI r7, r1, STK_OFFSET_R07 + SWI r8, r1, STK_OFFSET_R08 + SWI r9, r1, STK_OFFSET_R09 + SWI r10, r1, STK_OFFSET_R10 + SWI r11, r1, STK_OFFSET_R11 + SWI r12, r1, STK_OFFSET_R12 + SWI r13, r1, STK_OFFSET_R13 + SWI r14, r1, STK_OFFSET_R14 + SWI r15, r1, STK_OFFSET_R15 + SWI r17, r1, STK_OFFSET_R17 + SWI r18, r1, STK_OFFSET_R18 + SWI r19, r1, STK_OFFSET_R19 + SWI r20, r1, STK_OFFSET_R20 + SWI r21, r1, STK_OFFSET_R21 + SWI r22, r1, STK_OFFSET_R22 + SWI r23, r1, STK_OFFSET_R23 + SWI r24, r1, STK_OFFSET_R24 + SWI r25, r1, STK_OFFSET_R25 + SWI r26, r1, STK_OFFSET_R26 + SWI r27, r1, STK_OFFSET_R27 + SWI r28, r1, STK_OFFSET_R28 + SWI r29, r1, STK_OFFSET_R29 + SWI r30, r1, STK_OFFSET_R30 + SWI r31, r1, STK_OFFSET_R31 + + MFS r3, RMSR /* save the MSR */ + ORI r3, r3, CPU_IE_BIT /* Set IE to 1 to return to interrupted task with INT en. */ + SWI r3, r1, STK_OFFSET_RMSR /* MSR is at top of frame */ + + LBUI r3, r0, OSIntNesting /* if (OSIntNesting == 0) { */ + BNEI r3, OS_CPU_ISR_1 + + LWI r3, r0, OSTCBCur /* OSTCBCur->OSTCBStkPtr = SP */ + SW r1, r0, r3 /* } */ + +OS_CPU_ISR_1: + LBUI r3, r0, OSIntNesting + ADDIK r3, r3, 1 /* OSIntNesting++; */ + SBI r3, r0, OSIntNesting + + BRLID r15, BSP_IntHandler /* Call the provided C level interrupt handler */ + AND r0, r0, r0 /* NO-OP */ + + BRLID r15, OSIntExit /* OSIntExit() */ + AND r0, r0, r0 /* NO-OP */ + + LWI r31, r1, STK_OFFSET_R31 /* ********* RESTORE INTERRUPTED TASK'S CONTEXT ********* */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear IE to prevent interrupts until stack is cleaned */ + MTS RMSR,r3 + + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack */ + + RTID r14, 0 /* Return from interrupt with interrupts enabled */ + AND r0, r0, r0 /* NO-OP */ diff --git a/Ports/MicroBlaze/GNU/os_cpu.h b/Ports/MicroBlaze/GNU/os_cpu.h new file mode 100644 index 0000000..8d5c667 --- /dev/null +++ b/Ports/MicroBlaze/GNU/os_cpu.h @@ -0,0 +1,108 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Xilinx MicroBlaze +* GNU C/C++ Compiler +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; +typedef double FP64; + +typedef unsigned int OS_STK; /* Each stack entry is 32-bits wide */ +typedef unsigned int volatile OS_CPU_SR; /* The CPU Status Word is 32-bits wide. This variable */ + /* MUST be volatile for proper operation. Refer to */ + /* os_cpu_a.s for more details */ + +/* +********************************************************************************************************* +* CRITICAL SECTIONS MANAGEMENT +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save(); +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr); + + +/* +********************************************************************************************************* +* Xilinx Microblaze +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ + +#define OS_TASK_SW() OSCtxSw() + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + /* See OS_CPU_A.ASM */ +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore(OS_CPU_SR); + +void OS_CPU_ISR (void); + + diff --git a/Ports/MicroBlaze/GNU/os_cpu_a.S b/Ports/MicroBlaze/GNU/os_cpu_a.S new file mode 100644 index 0000000..e734a9b --- /dev/null +++ b/Ports/MicroBlaze/GNU/os_cpu_a.S @@ -0,0 +1,744 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Xilinx MicroBlaze +* GNU C/C++ Compiler +* +* Filename : os_cpu_a.S +* Version : V2.93.00 +********************************************************************************************************* +*/ +#define _ASMLANGUAGE + +/* +********************************************************************************************************* +* CONSTANTS USED TO ACCESS TASK CONTEXT STACK +********************************************************************************************************* +*/ +.equ STK_OFFSET_RMSR, 0x00 +.equ STK_OFFSET_R02, 0x04 +.equ STK_OFFSET_R03, 0x08 +.equ STK_OFFSET_R04, 0x0C +.equ STK_OFFSET_R05, 0x10 +.equ STK_OFFSET_R06, 0x14 +.equ STK_OFFSET_R07, 0x18 +.equ STK_OFFSET_R08, 0x1C +.equ STK_OFFSET_R09, 0x20 +.equ STK_OFFSET_R10, 0x24 +.equ STK_OFFSET_R11, 0x28 +.equ STK_OFFSET_R12, 0x2C +.equ STK_OFFSET_R13, 0x30 +.equ STK_OFFSET_R14, 0x34 +.equ STK_OFFSET_R15, 0x38 +.equ STK_OFFSET_R17, 0x3C +.equ STK_OFFSET_R18, 0x40 +.equ STK_OFFSET_R19, 0x44 +.equ STK_OFFSET_R20, 0x48 +.equ STK_OFFSET_R21, 0x4C +.equ STK_OFFSET_R22, 0x50 +.equ STK_OFFSET_R23, 0x54 +.equ STK_OFFSET_R24, 0x58 +.equ STK_OFFSET_R25, 0x5C +.equ STK_OFFSET_R26, 0x60 +.equ STK_OFFSET_R27, 0x64 +.equ STK_OFFSET_R28, 0x68 +.equ STK_OFFSET_R29, 0x6C +.equ STK_OFFSET_R30, 0x70 +.equ STK_OFFSET_R31, 0x74 + +.equ STK_CTX_SIZE, 0x78 + +.equ CPU_IE_BIT, 0x02 + + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + .globl OSStartHighRdy + .globl OSCtxSw + .globl OSIntCtxSw + + .globl _interrupt_handler + .globl OS_CPU_ISR + .globl OS_CPU_SR_Save + .globl OS_CPU_SR_Restore + +/* +********************************************************************************************************* +* EXTERNAL FUNCTIONS +********************************************************************************************************* +*/ + .extern OSIntEnter + .extern OSIntExit + .extern OS_CPU_IntHandler +/* +********************************************************************************************************* +* EXTERNAL VARIABLES +********************************************************************************************************* +*/ + .extern OSRunning + .extern OSIntNesting + .extern OSTaskSwHook + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSPrioCur + .extern OSPrioHighRdy + +.text +/* +********************************************************************************************************* +* DISABLE INTERRUPTS +* OS_CPU_SR OS_CPU_SR_Save(void); +* +* Description : Disables the interrupts and returns the RMSR contents. This allows the IE state to be +* restored at a subsequent time. +* +* The variable in the calling routine which the return is set to MUST be declared 'volatile' +* for proper operation. There is no guarantee that the proper register will be scheduled +* for the subsequent 'OS_CPU_SR_Save()' function call if the variable is not declared +* 'volatile'. +* +* Arguments : None +* +* Returns : Current RMSR contents in R3 +* +* Note(s) : None +********************************************************************************************************* +*/ + +OS_CPU_SR_Save: + ADDIK r1, r1, -4 /* Save R4 since it's used as a scratchpad register */ + SW r4, r1, r0 + + MFS r3, RMSR /* Read the MSR. r3 is used as the return value */ + ANDNI r4, r3, CPU_IE_BIT /* Mask off the IE bit */ + MTS RMSR, r4 /* Store the MSR */ + + LW r4, r1, r0 /* Restore R4 */ + ADDIK r1, r1, 4 + + AND r0, r0, r0 /* NO-OP - pipeline flush */ + AND r0, r0, r0 /* NO-OP - pipeline flush */ + AND r0, r0, r0 /* NO-OP - pipeline flush */ + + RTSD r15, 8 /* Return to caller with R3 containing original RMSR */ + AND r0, r0, r0 /* NO-OP */ + +/* +********************************************************************************************************* +* ENABLE INTERRUPTS +* void OS_CPU_SR_Restore(OS_CPU_SR sr); +* +* Description: Enables the interrupts using the provided data. If the IE bit is set in the argument, the +* RTID opcode is used to return. If the IE bis is clear, the standard RTSD is used leaving +* the interrupts disabled. +* +* The argument from the calling routine MUST be declared 'volatile' for proper operation. +* There is no guarantee that the proper register will be scheduled for the 'OS_CPU_SR_Restore()' +* function call if the variable is not declared 'volatile'. +* +* Arguments : Saved RMSR contents in R5 +* +* Returns : None +* +* Note(s) : None +********************************************************************************************************* +*/ + +OS_CPU_SR_Restore: + RTSD r15, 8 + MTS rMSR, r5 /* Move the saved status from r5 into rMSR */ + + +/* +********************************************************************************************************* +* OSStartHighRdy() +* +* Description: Starts the highest priority task that is available to run. OSStartHighRdy() MUST: +* +* a) Call OSTaskSwHook() +* b) Set OSRunning to TRUE +* c) Switch to the highest priority task. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (IE=1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +********************************************************************************************************* +*/ + +OSStartHighRdy: + + BRLID r15, OSTaskSwHook /* Call OSTaskSwHook() */ + AND r0, r0, r0 /* NO-OP */ + + OR r3, r3, r0 /* OSRunning = TRUE */ + ADDIK r3, r0, 1 + SBI r3, r0, OSRunning + + LWI r3, r0, OSTCBHighRdy /* SP = OSTCBHighRdy->OSTCBStkPtr */ + LW r1, r0, r3 + + LWI r31, r1, STK_OFFSET_R31 /* *************** RESTORE TASK'S CONTEXT *************** */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear the IE bit (It will be set by the return from INT.) */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (i.e. de-allocate storage) */ + + RTID r14, 0 /* Branch to task level code enabling interrupts, IE=1 */ + AND r0, r0, r0 /* NO-OP */ + +/* +********************************************************************************************************* +* OSCtxSw() +* +* Description: Performs the Context switch from a task. This function is ALWAYS called with interrupts +* DISABLED. +* +* OSCtxSw() must implement the following pseudo-code: +* +* Save ALL CPU registers; +* OSTCBCur->OSTCBStkPtr = SP; +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore ALL the CPU registers; +* if (IE bit of saved RMSR is 0) { +* Return from function call; +* } else { +* Set IE bit of RMSR to 0; +* Return from interrupt whcih sets IE back to 1; +* } +* +* +* The stack frame of the task to suspend will look as follows when OSCtxSw() is done: +* +* OSTCBCur->OSTCBStkPtr + 0x00 RMSR (See Note 1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* The stack frame of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (See Note 2) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* Note(s) : 1) OSCtxSw() is ALWAYS called with IE set to 0 (i.e. interrupts disabled). +* 2) If the task frame was saved by OSCtxSw(), IE would be set to 0. +* If the task frame was saved by an ISR, IE would be set to 1. +********************************************************************************************************* +*/ + +OSCtxSw: + /* *************** SAVE CURRENT TASK'S CONTEXT *************** */ + ADDIK r1, r1, -STK_CTX_SIZE /* Allocate storage for saving registers onto stack */ + + SWI r2, r1, STK_OFFSET_R02 /* Save the remaining registers onto the task's stack */ + SWI r3, r1, STK_OFFSET_R03 + SWI r4, r1, STK_OFFSET_R04 + SWI r5, r1, STK_OFFSET_R05 + SWI r6, r1, STK_OFFSET_R06 + SWI r7, r1, STK_OFFSET_R07 + SWI r8, r1, STK_OFFSET_R08 + SWI r9, r1, STK_OFFSET_R09 + SWI r10, r1, STK_OFFSET_R10 + SWI r11, r1, STK_OFFSET_R11 + SWI r12, r1, STK_OFFSET_R12 + SWI r13, r1, STK_OFFSET_R13 + SWI r14, r1, STK_OFFSET_R14 + SWI r15, r1, STK_OFFSET_R15 + SWI r17, r1, STK_OFFSET_R17 + SWI r18, r1, STK_OFFSET_R18 + SWI r19, r1, STK_OFFSET_R19 + SWI r20, r1, STK_OFFSET_R20 + SWI r21, r1, STK_OFFSET_R21 + SWI r22, r1, STK_OFFSET_R22 + SWI r23, r1, STK_OFFSET_R23 + SWI r24, r1, STK_OFFSET_R24 + SWI r25, r1, STK_OFFSET_R25 + SWI r26, r1, STK_OFFSET_R26 + SWI r27, r1, STK_OFFSET_R27 + SWI r28, r1, STK_OFFSET_R28 + SWI r29, r1, STK_OFFSET_R29 + SWI r30, r1, STK_OFFSET_R30 + SWI r31, r1, STK_OFFSET_R31 + + MFS r3, RMSR /* save the MSR (See Note 1) */ + SWI r3, r1, STK_OFFSET_RMSR + + LWI r3, r0, OSTCBCur /* OSTCBCur->OSTCBStkPtr = SP */ + SW r1, r0, r3 + + BRLID r15, OSTaskSwHook /* Call OSTaskSwHook() */ + AND r0, r0, r0 /* NO-OP */ + + LBUI r3, r0, OSPrioHighRdy /* OSPrioCur = OSPrioHighRdy */ + SBI r3, r0, OSPrioCur + + LWI r3, r0, OSTCBHighRdy /* OSTCBCur = OSTCBHighRdy */ + SWI r3, r0, OSTCBCur + + LW r1, r0, r3 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + LWI r31, r1, STK_OFFSET_R31 /* **************** RESTORE NEW TASK'S CONTEXT *************** */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDI r3, r3, CPU_IE_BIT /* See if IE is 0 (Saved by OSCtxSw()) or 1 (Saved by ISR) */ + BNEI r3, OSCtxSw_SavedByISR /* Branch if ISR saved context */ + + /* *********** The context was saved by OSCtxSw() ************ */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTSD r15, 8 /* Context was saved by OSCtxSw() */ + AND r0, r0, r0 /* NO-OP */ + +OSCtxSw_SavedByISR: + /* ************ The context was saved by an ISR ************** */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear the IE bit (It will be set by the return from INT.) */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTID r14, 0 /* Context was saved by ISR, return address is in R14, Set IE */ + AND r0, r0, r0 /* NO-OP */ + +/* +********************************************************************************************************* +* OSIntCtxSw() +* +* Description: Performs the Context Switch from an ISR. +* +* OSIntCtxSw() must implement the following pseudo-code: +* +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore ALL the CPU registers; +* if (IE bit of saved RMSR is 0) { +* Return from function call; +* } else { +* Set IE bit of RMSR to 0; +* Return from interrupt; +* } +* +* Upon entry, the registers of the task being suspended have already been saved onto that +* task's stack and the SP for the task has been saved in its OS_TCB by the ISR. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (See Note 1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* Note(s) : 1) If the task frame was saved by OSCtxSw(), IE would be set to 0. +* If the task frame was saved by an ISR, IE would be set to 1. +********************************************************************************************************* +*/ + +OSIntCtxSw: + + BRLID r15, OSTaskSwHook /* Call OSTaskSwHook() */ + AND r0, r0, r0 /* NO-OP */ + + LBUI r3, r0, OSPrioHighRdy /* OSPrioCur = OSPrioHighRdy */ + SBI r3, r0, OSPrioCur + + LWI r3, r0, OSTCBHighRdy /* OSTCBCur = OSTCBHighRdy */ + SWI r3, r0, OSTCBCur + + LW r1, r0, r3 /* SP = OSTCBHighRdy->OSTCBStkPtr */ + + LWI r31, r1, STK_OFFSET_R31 /* **************** RESTORE NEW TASK'S CONTEXT *************** */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDI r3, r3, CPU_IE_BIT /* See if IE is 0 (Saved by OSCtxSw()) or 1 (Saved by ISR) */ + BNEI r3, OSIntCtxSw_SavedByISR /* Branch if ISR saved context */ + + /* *********** The context was saved by OSCtxSw() ************ */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTSD r15, 8 /* Context was saved by OSCtxSw() */ + AND r0, r0, r0 /* NO-OP */ + +OSIntCtxSw_SavedByISR: /* ************ The context was saved by an ISR ************** */ + LWI r3, r1, STK_OFFSET_RMSR /* Get the saved RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear the IE bit (It will be set by the return from INT.) */ + MTS RMSR,r3 + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack (deallocate storage) */ + + RTID r14, 0 /* Context was saved by ISR, return address is in R14 */ + AND r0, r0, r0 /* NO-OP */ + +/* +********************************************************************************************************* +* OS_CPU_ISR() +* +* Description: This routine is intended to be the target of the Interrupt processing functionality that +* occurs when the MicroBlaze is interrupted. The address, 'XOSExternalInterruptHandler', is +* used as the branch destination in the code that is executed at addresses 0x10 and 0x14 in +* the MicroBlaze vector table assuming that the vector table is in RAM +* +* The XPS interrupt vector is replaced by OS_CPU_ISR() by executing the code from a C function: +* +* *(INT32U *)0x00000010 = 0xB0000000 | ((INT32U)OS_CPU_ISR >> 16); +* *(INT32U *)0x00000014 = 0xB8080000 | ((INT32U)OS_CPU_ISR & 0x0000FFFF); +* +* The interrupted task context is saved onto its stack as follows: +* +* OSTCBCur->OSTCBStkPtr + 0x00 RMSR (See Note 1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH MEMORY) +* +* Note(s) : 1) The IE bit is saved onto the stack 'set' since the code must return to the interrupted +* task with interrupts enabled. +********************************************************************************************************* +*/ + +_interrupt_handler: +OS_CPU_ISR: + /* ********** SAVE INTERRUPTED TASK'S CONTEXT *********** */ + ADDIK r1, r1, -STK_CTX_SIZE /* Allocate storage for saving registers onto stack */ + + SWI r2, r1, STK_OFFSET_R02 + SWI r3, r1, STK_OFFSET_R03 + SWI r4, r1, STK_OFFSET_R04 + SWI r5, r1, STK_OFFSET_R05 + SWI r6, r1, STK_OFFSET_R06 + SWI r7, r1, STK_OFFSET_R07 + SWI r8, r1, STK_OFFSET_R08 + SWI r9, r1, STK_OFFSET_R09 + SWI r10, r1, STK_OFFSET_R10 + SWI r11, r1, STK_OFFSET_R11 + SWI r12, r1, STK_OFFSET_R12 + SWI r13, r1, STK_OFFSET_R13 + SWI r14, r1, STK_OFFSET_R14 + SWI r15, r1, STK_OFFSET_R15 + SWI r17, r1, STK_OFFSET_R17 + SWI r18, r1, STK_OFFSET_R18 + SWI r19, r1, STK_OFFSET_R19 + SWI r20, r1, STK_OFFSET_R20 + SWI r21, r1, STK_OFFSET_R21 + SWI r22, r1, STK_OFFSET_R22 + SWI r23, r1, STK_OFFSET_R23 + SWI r24, r1, STK_OFFSET_R24 + SWI r25, r1, STK_OFFSET_R25 + SWI r26, r1, STK_OFFSET_R26 + SWI r27, r1, STK_OFFSET_R27 + SWI r28, r1, STK_OFFSET_R28 + SWI r29, r1, STK_OFFSET_R29 + SWI r30, r1, STK_OFFSET_R30 + SWI r31, r1, STK_OFFSET_R31 + + MFS r3, RMSR /* save the MSR */ + ORI r3, r3, CPU_IE_BIT /* Set IE to 1 to return to interrupted task with INT en. */ + SWI r3, r1, STK_OFFSET_RMSR /* MSR is at top of frame */ + + LBUI r3, r0, OSIntNesting /* if (OSIntNesting == 0) { */ + BNEI r3, OS_CPU_ISR_1 + + LWI r3, r0, OSTCBCur /* OSTCBCur->OSTCBStkPtr = SP */ + SW r1, r0, r3 /* } */ + +OS_CPU_ISR_1: + LBUI r3, r0, OSIntNesting + ADDIK r3, r3, 1 /* OSIntNesting++; */ + SBI r3, r0, OSIntNesting + + BRLID r15, BSP_IntHandler /* Call the provided C level interrupt handler */ + AND r0, r0, r0 /* NO-OP */ + + BRLID r15, OSIntExit /* OSIntExit() */ + AND r0, r0, r0 /* NO-OP */ + + LWI r31, r1, STK_OFFSET_R31 /* ********* RESTORE INTERRUPTED TASK'S CONTEXT ********* */ + LWI r30, r1, STK_OFFSET_R30 + LWI r29, r1, STK_OFFSET_R29 + LWI r28, r1, STK_OFFSET_R28 + LWI r27, r1, STK_OFFSET_R27 + LWI r26, r1, STK_OFFSET_R26 + LWI r25, r1, STK_OFFSET_R25 + LWI r24, r1, STK_OFFSET_R24 + LWI r23, r1, STK_OFFSET_R23 + LWI r22, r1, STK_OFFSET_R22 + LWI r21, r1, STK_OFFSET_R21 + LWI r20, r1, STK_OFFSET_R20 + LWI r19, r1, STK_OFFSET_R19 + LWI r18, r1, STK_OFFSET_R18 + LWI r17, r1, STK_OFFSET_R17 + LWI r15, r1, STK_OFFSET_R15 + LWI r14, r1, STK_OFFSET_R14 + LWI r13, r1, STK_OFFSET_R13 + LWI r12, r1, STK_OFFSET_R12 + LWI r11, r1, STK_OFFSET_R11 + LWI r10, r1, STK_OFFSET_R10 + LWI r9, r1, STK_OFFSET_R09 + LWI r8, r1, STK_OFFSET_R08 + LWI r7, r1, STK_OFFSET_R07 + LWI r6, r1, STK_OFFSET_R06 + LWI r5, r1, STK_OFFSET_R05 + LWI r4, r1, STK_OFFSET_R04 + LWI r2, r1, STK_OFFSET_R02 + + LWI r3, r1, STK_OFFSET_RMSR /* Get RMSR */ + ANDNI r3, r3, CPU_IE_BIT /* Clear IE to prevent interrupts until stack is cleaned */ + MTS RMSR,r3 + + LWI r3, r1, STK_OFFSET_R03 /* Restore R3 (was used a scratchpad register for RMSR) */ + + ADDIK r1, r1, STK_CTX_SIZE /* Clean up the stack */ + + RTID r14, 0 /* Return from interrupt with interrupts enabled */ + AND r0, r0, r0 /* NO-OP */ diff --git a/Ports/MicroBlaze/GNU/os_cpu_c.c b/Ports/MicroBlaze/GNU/os_cpu_c.c new file mode 100644 index 0000000..1f54d17 --- /dev/null +++ b/Ports/MicroBlaze/GNU/os_cpu_c.c @@ -0,0 +1,340 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Xilinx MicroBlaze +* GNU C/C++ Compiler +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +extern void *_SDA_BASE_; +extern void *_SDA2_BASE_; + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE >0 + OSView_TaskCreateHook(ptcb); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called when a task returns without being properly deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task that was accidently returned. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskReturnHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (IE=1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH Memory) +* + 0x78 Empty +* ptos ---------> + 0x7C Empty +* +* 2) R16 is not saved as part of the task context since it is used by the debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + INT32U msr_val; + + + __asm__ __volatile__ ("mfs\t%0,rmsr\n" : "=r"(msr_val)); + + msr_val &= 0x000000A0; /* Ensure that the status of the caches is not changed */ + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT32U *)ptos; /* Load stack pointer */ + pstk--; /* Make sure we point to free entry ... */ + pstk--; /* ... compiler uses top-of-stack so free an extra one. */ + *pstk-- = (INT32U)0x31313131; /* R31 */ + *pstk-- = (INT32U)0x30303030; /* R30 */ + *pstk-- = (INT32U)0x29292929; /* R29 */ + *pstk-- = (INT32U)0x28282828; /* R28 */ + *pstk-- = (INT32U)0x27272727; /* R27 */ + *pstk-- = (INT32U)0x26262626; /* R26 */ + *pstk-- = (INT32U)0x25252525; /* R25 */ + *pstk-- = (INT32U)0x24242424; /* R24 */ + *pstk-- = (INT32U)0x23232323; /* R23 */ + *pstk-- = (INT32U)0x22222222; /* R22 */ + *pstk-- = (INT32U)0x21212121; /* R21 */ + *pstk-- = (INT32U)0x20202020; /* R20 */ + *pstk-- = (INT32U)0x19191919; /* R19 */ + *pstk-- = (INT32U)0x18181818; /* R18 */ + *pstk-- = (INT32U)0x17171717; /* R17 */ + *pstk-- = (INT32U)task - 8; /* R15 = task return address (assuming function call) */ + *pstk-- = (INT32U)task; /* R14 = task (Interrupt return address) */ + *pstk-- = (INT32U)&_SDA_BASE_; /* R13 */ + *pstk-- = (INT32U)0x12121212; /* R12 */ + *pstk-- = (INT32U)0x11111111; /* R11 */ + *pstk-- = (INT32U)0x10101010; /* R10 */ + *pstk-- = (INT32U)0x09090909; /* R09 */ + *pstk-- = (INT32U)0x08080808; /* R08 */ + *pstk-- = (INT32U)0x07070707; /* R07 */ + *pstk-- = (INT32U)0x06060606; /* R06 */ + *pstk-- = (INT32U)p_arg; /* R05 */ + *pstk-- = (INT32U)0x04040404; /* R04 */ + *pstk-- = (INT32U)0x03030303; /* R03 */ + *pstk-- = (INT32U)&_SDA2_BASE_; /* R02 */ + *pstk = msr_val | 0x00000002; /* MSR with interrupts enabled */ + + return ((OS_STK *)pstk); /* Return new top of stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif +} +#endif diff --git a/Ports/MicroBlaze/GNU/os_dbg.c b/Ports/MicroBlaze/GNU/os_dbg.c new file mode 100644 index 0000000..abb433a --- /dev/null +++ b/Ports/MicroBlaze/GNU/os_dbg.c @@ -0,0 +1,266 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/Microchip/PIC24FJ128/C30/os_cpu.h b/Ports/Microchip/PIC24FJ128/C30/os_cpu.h new file mode 100644 index 0000000..85e5752 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/C30/os_cpu.h @@ -0,0 +1,94 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PIC24 MPLab Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +/* +********************************************************************************************************* +* APPLICATION INDEPENDENT DATA TYPES +* +* Notes : These data types are chosen based upon the C30 compiler datatype specifications +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; +typedef signed char INT8S; +typedef unsigned int INT16U; +typedef signed int INT16S; +typedef unsigned long INT32U; +typedef signed long INT32S; +typedef float FP32; +typedef long double FP64; + +/* +********************************************************************************************************* +* OTHER DATA TYPES +********************************************************************************************************* +*/ + +typedef INT16U OS_STK; /* Define the size of each stack entry */ +typedef INT16U OS_CPU_SR; /* Define the size of CPU status register */ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 /* Use type 3 critical sections */ +#define OS_STK_GROWTH 0 /* Stack grows from low to high memory */ + +#define OS_TASK_SW() {__asm__ volatile("call _OSCtxSw");} /* Macro for defining a high level context switch */ + +#if OS_CRITICAL_METHOD == 1 /* Support critical method type 1 */ +#define OS_ENTER_CRITICAL() SRbits.IPL = 6 /* Disable interrupts (all but 7) */ +#define OS_EXIT_CRITICAL() SRbits.IPL = 0 /* Eenable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 /* Support critical method type 3 */ +#define OS_ENTER_CRITICAL() {cpu_sr = SR; SRbits.IPL = 6;} /* Disable interrupts (all but 7) */ +#define OS_EXIT_CRITICAL() {SR = cpu_sr;} /* Enable interrupts */ +#endif + + diff --git a/Ports/Microchip/PIC24FJ128/C30/os_cpu_a.s b/Ports/Microchip/PIC24FJ128/C30/os_cpu_a.s new file mode 100644 index 0000000..8067c3a --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/C30/os_cpu_a.s @@ -0,0 +1,150 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PIC24 MPLab Port +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** +; + .equ __24FJ128GA010, 1 ; Inform the p24FJ128GA010 header file that we are using a p24FJ128GA010 + +; +;******************************************************************************************************** +; INCLUDES +;******************************************************************************************************** +; + + .include "p24FJ128GA010.inc" ; Include assembly equates for various CPU registers and bit masks + .include "os_cpu_util_a.s" ; Include an assembly utility files with macros for saving and restoring the CPU registers + +; +;******************************************************************************************************** +; LINKER SPECIFICS +;******************************************************************************************************** +; + + .text ; Locate this file in the text region of the build + +; +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** +; + + .global _OSStartHighRdy + .global _OSCtxSw + .global _OSIntCtxSw + +; +;******************************************************************************************************** +; OSStartHighRdy +; +; Description : This function determines the highest priority task that is ready to run after +; OSInit() is called. +;******************************************************************************************************** +; + +_OSStartHighRdy: + call _OSTaskSwHook ; Call user defined task switch hook + + mov #0x0001, w0 ; Set OSRunning to TRUE + mov #_OSRunning, w1 + mov.b w0, [w1] ; Set OSRunning to TRUE + + ; Get stack pointer of the task to resume + mov _OSTCBHighRdy, w0 ; Get the pointer to the stack to resume + mov [w0], w15 ; Dereference the pointer and store the data (the new stack address) W15, the stack pointer register + + OS_REGS_RESTORE ; Restore all of this tasks registers from the stack + + retfie ; Return from the interrupt, the task is now ready to run + +; +;******************************************************************************************************** +; OSCtxSw +; +; Description : TThe code to perform a 'task level' context switch. OSCtxSw() is called +; when a higher priority task is made ready to run by another task or, +; when the current task can no longer execute (e.g. it calls OSTimeDly(), +; OSSemPend() and the semaphore is not available, etc.). +;******************************************************************************************************** +; + +_OSCtxSw: + ; TRAP (interrupt) should bring us here, not 'call'. + ; Since the PIC24 has no TRAP, it is necessary to correct the stack to simulate an interrupt + ; In other words, this function must also save SR and IPL3 to the stack, not just the PC. + + mov.b SRL, wreg ; Load SRL + sl w0, #8, w0 ; Shift left by 8 + btsc CORCON, #IPL3 ; Test IPL3 bit, skip if clear + bset w0, #7; ; Copy IPL3 to bit7 of w0 + + ior w0, [--w15], w0 ; Merge bits + mov w0, [w15++] ; Write back + + OS_REGS_SAVE ; Save processor registers + + ; Save current task's stack pointer into the currect tasks TCB + mov _OSTCBCur, w0 ; Get the address of the location in this tasks TCB to store the stack pointer + mov w15, [w0] ; Store the stack pointer in this tasks TCB + + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + +; +;******************************************************************************************************** +; OSIntCtxSw +; +; Description : When an ISR (Interrupt Service Routine) completes, OSIntExit() is called to +; determine whether a more important task than the interrupted task needs to +; execute. If that's the case, OSIntExit() determines which task to run next +; and calls OSIntCtxSw() to perform the actual context switch to that task. +;******************************************************************************************************** +; + +_OSIntCtxSw: + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + diff --git a/Ports/Microchip/PIC24FJ128/C30/os_cpu_c.c b/Ports/Microchip/PIC24FJ128/C30/os_cpu_c.c new file mode 100644 index 0000000..0f04c66 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/C30/os_cpu_c.c @@ -0,0 +1,349 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PIC24 MPLab Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) You may pass a task creation parameters through the opt variable. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* +* 2) Registers are initialized to make them easy to differentiate with a debugger. +* +* 3) Setup the stack frame of the task: +* +* ptos - 0 -> +* ptos - 2 -> CORCON +* ptos - 4 -> SR (initialized to 0) +* ptos - 8 -> RCOUNT +* ptos - 10 -> PSVPAG +* ptos - 12 -> TBLPAG +* ptos - 14 -> W14 +* ptos - 16 -> W13 +* ptos - 18 -> W12 +* ptos - 20 -> W11 +* ptos - 22 -> W10 +* ptos - 24 -> W9 +* ptos - 26 -> W8 +* ptos - 28 -> W7 +* ptos - 30 -> W6 +* ptos - 32 -> W5 +* ptos - 34 -> W4 +* ptos - 36 -> W3 +* ptos - 38 -> W2 +* ptos - 40 -> W1 +* ptos - 44 -> p_arg +* ptos - 46 -> 0 (15..8) | CORCON.7 | PC (22..16) Simulate ISR +* ptos - 48 -> PC (15..0) +* ptos - 50 -> PC (22..16) Simulate function call +* ptos - 52 -> PC (15..0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit( void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) { + INT16U x; + INT8U pc_high; + + + pc_high = 0; /* Upper byte of PC always 0. Pointers are 16 bit unsigned */ + + *ptos++ = (OS_STK)task; /* Simulate a call to the task by putting 32 bits of data */ + *ptos++ = (OS_STK)pc_high; /* data on the stack. */ + + /* Simulate an interrupt */ + *ptos++ = (OS_STK)task; /* Put the address of this task on the stack (PC) */ + + x = 0; /* Set the SR to enable ALL interrupts */ + if (CORCONbits.IPL3) { /* Check the CPU's current interrupt level 3 bit */ + x |= 0x0080; /* If set, then save the priority level bit in x bit [7] */ + } + *ptos++ = (OS_STK)(x | (INT16U)pc_high); /* Push the SR Low, CORCON IPL3 and PC (22..16) */ + + *ptos++ = (OS_STK)p_arg; /* Initialize register W0 */ + *ptos++ = 0x1111; /* Initialize register W1 */ + *ptos++ = 0x2222; /* Initialize register W2 */ + *ptos++ = 0x3333; /* Initialize register W3 */ + *ptos++ = 0x4444; /* Initialize register W4 */ + *ptos++ = 0x5555; /* Initialize register W5 */ + *ptos++ = 0x6666; /* Initialize register W6 */ + *ptos++ = 0x7777; /* Initialize register W7 */ + *ptos++ = 0x8888; /* Initialize register W8 */ + *ptos++ = 0x9999; /* Initialize register W9 */ + *ptos++ = 0xAAAA; /* Initialize register W10 */ + *ptos++ = 0xBBBB; /* Initialize register W11 */ + *ptos++ = 0xCCCC; /* Initialize register W12 */ + *ptos++ = 0xDDDD; /* Initialize register W13 */ + *ptos++ = 0xEEEE; /* Initialize register W14 */ + + *ptos++ = TBLPAG; /* Push the Data Table Page Address on to the stack */ + *ptos++ = PSVPAG; /* Push the Program Space Visability Register on the stack */ + *ptos++ = RCOUNT; /* Push the Repeat Loop Counter Register on to the stack */ + + *ptos++ = 0; /* Force the SR to enable all interrupt, clear flags */ + *ptos++ = CORCON; /* Push the Core Control Register on to the stack */ + + return (ptos); /* Return the stack pointer to the new tasks stack */ +} + + diff --git a/Ports/Microchip/PIC24FJ128/C30/os_cpu_util_a.s b/Ports/Microchip/PIC24FJ128/C30/os_cpu_util_a.s new file mode 100644 index 0000000..1c1020f --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/C30/os_cpu_util_a.s @@ -0,0 +1,80 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PIC24 MPLab Port +; +; Filename : os_cpu_util_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; MACRO OS_REGS_SAVE +; +; Description : This macro saves the current state of the CPU onto the current tasks stack +; +; Notes : W15 is the CPU stack pointer. It should never be pushed from the stack during +; a context save. +;******************************************************************************************************** +; + +.macro OS_REGS_SAVE ; Start of Macro + push.d w0 ; Push W0 and W1 on to the stack + push.d w2 ; Push W2 and W3 on to the stack + push.d w4 ; Push W4 and W5 on to the stack + push.d w6 ; Push W6 and W7 on to the stack + push.d w8 ; Push W8 and W9 on to the stack + push.d w10 ; Push W10 and W11 on to the stack + push.d w12 ; Push W12 and W13 on to the stack + push w14 ; Push W14 **ONLY** on to the stack + + push TBLPAG ; Push the Table Page Register on to the stack + push PSVPAG ; Push the Program Space Visability Register on the stack + push RCOUNT ; Push the Repeat Loop Counter Register on to the stack + + push SR ; Push the CPU Status Register on to the stack + push CORCON ; Push the Core Control Register on to the stack +.endm ; End of Macro + +; +;******************************************************************************************************** +; MACRO OS_REGS_RESTORE +; +; Description : This macro restores the current state of the CPU from the current tasks stack +; +; Notes : 1) W15 is the CPU stack pointer. It should never be popped from the stack during +; a context restore. +; 2) Registers are always popped in the reverse order from which they were pushed +;******************************************************************************************************** +; + +.macro OS_REGS_RESTORE ; Start of Macro + pop CORCON ; Pull the Core Control Register from the stack + pop SR ; Pull the CPU Status Register from the stack + + pop RCOUNT ; Pull the Repeat Loop Counter Register from the stack + pop PSVPAG ; Pull the Program Space Visability Register on the stack + pop TBLPAG ; Pull the Table Page Register from the stack + + pop w14 ; Pull W14 **ONLY** from the stack + pop.d w12 ; Pull W12 and W13 from the stack + pop.d w10 ; Pull W10 and W11 from the stack + pop.d w8 ; Pull W8 and W9 from the stack + pop.d w6 ; Pull W6 and W7 from the stack + pop.d w4 ; Pull W4 and W5 from the stack + pop.d w2 ; Pull W2 and W3 from the stack + pop.d w0 ; Pull W0 and W1 from the stack +.endm ; End of Macro diff --git a/Ports/Microchip/PIC24FJ128/C30/os_dbg.c b/Ports/Microchip/PIC24FJ128/C30/os_dbg.c new file mode 100644 index 0000000..71d5d43 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/C30/os_dbg.c @@ -0,0 +1,296 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu.h b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu.h new file mode 100644 index 0000000..efb2021 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu.h @@ -0,0 +1,96 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PIC24 MPLab Port +* For the Hi-Tech dsPICC Compiler +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); /* See os_cpu_a.s */ +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +/* +********************************************************************************************************* +* APPLICATION INDEPENDENT DATA TYPES +* +* Notes : These data types are chosen based upon the C30 compiler datatype specifications +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; +typedef signed char INT8S; +typedef unsigned int INT16U; +typedef signed int INT16S; +typedef unsigned long INT32U; +typedef signed long INT32S; +typedef float FP32; +typedef long double FP64; + +/* +********************************************************************************************************* +* OTHER DATA TYPES +********************************************************************************************************* +*/ + +typedef INT16U OS_STK; /* Define the size of each stack entry */ +typedef INT16U OS_CPU_SR; /* Define the size of CPU status register */ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 /* Use type 3 critical sections */ +#define OS_STK_GROWTH 0 /* Stack grows from low to high memory */ + +#define OS_TASK_SW() OSCtxSw() /* Macro for defining a high level context switch */ + /* This function call adds 4 bytes to the stack */ + +#if OS_CRITICAL_METHOD == 1 /* Support critical method type 1 */ +#define OS_ENTER_CRITICAL() SRbits.IPL = 7 /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() SRbits.IPL = 0 /* Eenable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 /* Support critical method type 3 */ +#define OS_ENTER_CRITICAL() {cpu_sr = SR; SRbits.IPL = 7;} /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() {SR = cpu_sr;} /* Enable interrupts */ +#endif + + diff --git a/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_a.as b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_a.as new file mode 100644 index 0000000..1e69df2 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_a.as @@ -0,0 +1,163 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PIC24 MPLab Port +; For the Hi-Tech dsPICC Compiler +; +; Filename : os_cpu_a.as +; Version : V2.93.00 +;******************************************************************************************************** + + +; +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** +; + +; +;******************************************************************************************************** +; INCLUDES +;******************************************************************************************************** +; + + #include ; Include assembly equates for various CPU registers and bit masks + #include "os_cpu_util_a.as" ; Include an assembly utility files with macros for saving and restoring the CPU registers + +; +;******************************************************************************************************** +; LINKER SPECIFICS +;******************************************************************************************************** +; + + psect text,global,reloc=4,class=CODE,delta=2 ; Locate this file in the text region of the build + +; +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** +; + IPL3 EQU 0x0003 +; +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** +; + + GLOBAL _OSStartHighRdy + GLOBAL _OSCtxSw + GLOBAL _OSIntCtxSw + GLOBAL _OSTaskSwHook + GLOBAL _OSRunning + GLOBAL _OSTCBHighRdy + GLOBAL _OSPrioHighRdy + GLOBAL _OSPrioCur + +; +;******************************************************************************************************** +; OSStartHighRdy +; +; Description : This function determines the highest priority task that is ready to run after +; OSInit() is called. +;******************************************************************************************************** +; + +_OSStartHighRdy: + call _OSTaskSwHook ; Call user defined task switch hook + + mov #0x0001, w0 ; Set OSRunning to TRUE + mov #_OSRunning, w1 + mov.b w0, [w1] ; Set OSRunning to TRUE + + ; Get stack pointer of the task to resume + mov _OSTCBHighRdy, w0 ; Get the pointer to the stack to resume + mov [w0], w15 ; Dereference the pointer and store the data (the new stack address) W15, the stack pointer register + + OS_REGS_RESTORE ; Restore all of this tasks registers from the stack + + retfie ; Return from the interrupt, the task is now ready to run + +; +;******************************************************************************************************** +; OSCtxSw +; +; Description : TThe code to perform a 'task level' context switch. OSCtxSw() is called +; when a higher priority task is made ready to run by another task or, +; when the current task can no longer execute (e.g. it calls OSTimeDly(), +; OSSemPend() and the semaphore is not available, etc.). +;******************************************************************************************************** +; + +_OSCtxSw: + ; Ideally, a TRAP (interrupt) would bring us here, not 'call' (see os_cpu.h). + ; Since the PIC24 has no software TRAP instruction, it is necessary to correct the stack + ; to simulate an interrupt. In other words, this function must also save SR and IPL3 to + ; the stack, not just the PC. + + mov.b SR, wreg ; Load SRL + sl w0, #8, w0 ; Shift left by 8 + btsc CORCON, #IPL3 ; Test IPL3 bit, skip if clear + bset w0, #7; ; Copy IPL3 to bit7 of w0 + + ior w0, [--w15], w0 ; Merge IPL3 bit with last byte pushed + mov w0, [w15++] ; Readjust stack pointer so there is no net change due to previous write + + OS_REGS_SAVE ; Save processor registers + + ; Save current task's stack pointer into the currect tasks TCB + mov _OSTCBCur, w0 ; Get the address of the location in this tasks TCB to store the stack pointer + mov w15, [w0] ; Store the stack pointer in this tasks TCB + + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + +; +;******************************************************************************************************** +; OSIntCtxSw +; +; Description : When an ISR (Interrupt Service Routine) completes, OSIntExit() is called to +; determine whether a more important task than the interrupted task needs to +; execute. If that's the case, OSIntExit() determines which task to run next +; and calls OSIntCtxSw() to perform the actual context switch to that task. +;******************************************************************************************************** +; + +_OSIntCtxSw: + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + diff --git a/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_c.c b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_c.c new file mode 100644 index 0000000..0fef3e9 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_c.c @@ -0,0 +1,350 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PIC24 MPLab Port +* For the Hi-Tech dsPICC Compiler +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) You may pass a task creation parameters through the opt variable. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* +* 2) Registers are initialized to make them easy to differentiate with a debugger. +* +* 3) Setup the stack frame of the task: +* +* ptos - 0 -> +* ptos - 2 -> CORCON +* ptos - 4 -> SR (initialized to 0) +* ptos - 8 -> RCOUNT +* ptos - 10 -> PSVPAG +* ptos - 12 -> TBLPAG +* ptos - 14 -> W14 +* ptos - 16 -> W13 +* ptos - 18 -> W12 +* ptos - 20 -> W11 +* ptos - 22 -> W10 +* ptos - 24 -> W9 +* ptos - 26 -> W8 +* ptos - 28 -> W7 +* ptos - 30 -> W6 +* ptos - 32 -> W5 +* ptos - 34 -> W4 +* ptos - 36 -> W3 +* ptos - 38 -> W2 +* ptos - 40 -> W1 +* ptos - 44 -> p_arg +* ptos - 46 -> 0 (15..8) | CORCON.7 | PC (22..16) Simulate ISR +* ptos - 48 -> PC (15..0) +* ptos - 50 -> PC (22..16) Simulate function call +* ptos - 52 -> PC (15..0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit( void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) { + INT16U x; + INT8U pc_high; + + + pc_high = 0; /* Upper byte of PC always 0. Pointers are 16 bit unsigned */ + + *ptos++ = (OS_STK)task; /* Simulate a call to the task by putting 32 bits of data */ + *ptos++ = (OS_STK)pc_high; /* data on the stack. */ + + /* Simulate an interrupt */ + *ptos++ = (OS_STK)task; /* Put the address of this task on the stack (PC) */ + + x = 0; /* Set the SR to enable ALL interrupts */ + if (CORCONbits.IPL3) { /* Check the CPU's current interrupt level 3 bit */ + x |= 0x0080; /* If set, then save the priority level bit in x bit [7] */ + } + *ptos++ = (OS_STK)(x | (INT16U)pc_high); /* Push the SR Low, CORCON IPL3 and PC (22..16) */ + + *ptos++ = (OS_STK)p_arg; /* Initialize register W0 */ + *ptos++ = 0x1111; /* Initialize register W1 */ + *ptos++ = 0x2222; /* Initialize register W2 */ + *ptos++ = 0x3333; /* Initialize register W3 */ + *ptos++ = 0x4444; /* Initialize register W4 */ + *ptos++ = 0x5555; /* Initialize register W5 */ + *ptos++ = 0x6666; /* Initialize register W6 */ + *ptos++ = 0x7777; /* Initialize register W7 */ + *ptos++ = 0x8888; /* Initialize register W8 */ + *ptos++ = 0x9999; /* Initialize register W9 */ + *ptos++ = 0xAAAA; /* Initialize register W10 */ + *ptos++ = 0xBBBB; /* Initialize register W11 */ + *ptos++ = 0xCCCC; /* Initialize register W12 */ + *ptos++ = 0xDDDD; /* Initialize register W13 */ + *ptos++ = 0xEEEE; /* Initialize register W14 */ + + *ptos++ = TBLPAG; /* Push the Data Table Page Address on to the stack */ + *ptos++ = PSVPAG; /* Push the Program Space Visability Register on the stack */ + *ptos++ = RCOUNT; /* Push the Repeat Loop Counter Register on to the stack */ + + *ptos++ = 0; /* Force the SR to enable all interrupt, clear flags */ + *ptos++ = CORCON; /* Push the Core Control Register on to the stack */ + + return (ptos); /* Return the stack pointer to the new tasks stack */ +} + + diff --git a/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_util_a.as b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_util_a.as new file mode 100644 index 0000000..7e97bbc --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/DSPICC/os_cpu_util_a.as @@ -0,0 +1,93 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; PIC24 MPLab Port +; For the Hi-Tech dsPICC Compiler +; +; Filename : os_cpu_util_a.as +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** +; + + GLOBAL _OSIntNesting + GLOBAL _OSTCBCur + GLOBAL _OSIntExit + +; +;******************************************************************************************************** +; MACRO OS_REGS_SAVE +; +; Description : This macro saves the current state of the CPU onto the current tasks stack +; +; Notes : W15 is the CPU stack pointer. It should never be pushed from the stack during +; a context save. +;******************************************************************************************************** +; + +OS_REGS_SAVE MACRO ; Start of Macro + push.d w0 ; Push W0 and W1 onto the stack + push.d w2 ; Push W2 and W3 onto the stack + push.d w4 ; Push W4 and W5 onto the stack + push.d w6 ; Push W6 and W7 onto the stack + push.d w8 ; Push W8 and W9 onto the stack + push.d w10 ; Push W10 and W11 onto the stack + push.d w12 ; Push W12 and W13 onto the stack + push w14 ; Push W14 **ONLY** onto the stack + + push TBLPAG ; Push the Table Page Register onto the stack + push PSVPAG ; Push the Program Space Visibility Register onto the stack + push RCOUNT ; Push the Repeat Loop Counter Register onto the stack + + push SR ; Push the CPU Status Register onto the stack + push CORCON ; Push the Core Control Register onto the stack +ENDM ; End of Macro + +; +;******************************************************************************************************** +; MACRO OS_REGS_RESTORE +; +; Description : This macro restores the current state of the CPU from the current tasks stack +; +; Notes : 1) W15 is the CPU stack pointer. It should never be popped from the stack during +; a context restore. +; 2) Registers are always popped in the reverse order from which they were pushed +;******************************************************************************************************** +; + +OS_REGS_RESTORE MACRO ; Start of Macro + pop CORCON ; Pull the Core Control Register from the stack + pop SR ; Pull the CPU Status Register from the stack + + pop RCOUNT ; Pull the Repeat Loop Counter Register from the stack + pop PSVPAG ; Pull the Program Space Visibility Register from the stack + pop TBLPAG ; Pull the Table Page Register from the stack + + pop w14 ; Pull W14 **ONLY** from the stack + pop.d w12 ; Pull W12 and W13 from the stack + pop.d w10 ; Pull W10 and W11 from the stack + pop.d w8 ; Pull W8 and W9 from the stack + pop.d w6 ; Pull W6 and W7 from the stack + pop.d w4 ; Pull W4 and W5 from the stack + pop.d w2 ; Pull W2 and W3 from the stack + pop.d w0 ; Pull W0 and W1 from the stack +ENDM ; End of Macro + + diff --git a/Ports/Microchip/PIC24FJ128/DSPICC/os_dbg.c b/Ports/Microchip/PIC24FJ128/DSPICC/os_dbg.c new file mode 100644 index 0000000..71d5d43 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/DSPICC/os_dbg.c @@ -0,0 +1,296 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu.h b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu.h new file mode 100644 index 0000000..af219be --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu.h @@ -0,0 +1,95 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Microchip PIC24 +* ICCDSPIC +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +/* +********************************************************************************************************* +* APPLICATION INDEPENDENT DATA TYPES +* +* Notes : These data types are chosen based upon the C30 compiler datatype specifications +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; +typedef signed char INT8S; +typedef unsigned int INT16U; +typedef signed int INT16S; +typedef unsigned long INT32U; +typedef signed long INT32S; +typedef float FP32; + +/* +********************************************************************************************************* +* OTHER DATA TYPES +********************************************************************************************************* +*/ + +typedef INT16U OS_STK; /* Define the size of each stack entry */ +typedef INT16U OS_CPU_SR; /* Define the size of CPU status register */ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 /* Use type 3 critical sections */ +#define OS_STK_GROWTH 0 /* Stack grows from low to high memory */ + +#define OS_TASK_SW() OSCtxSw() /* Macro for defining a high level context switch */ + /* This function call adds 4 bytes to the stack */ + +#if OS_CRITICAL_METHOD == 1 /* Support critical method type 1 */ +#define OS_ENTER_CRITICAL() IPL = 7; /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() IPL = 0; /* Eenable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 /* Support critical method type 3 */ +#define OS_ENTER_CRITICAL() {cpu_sr = SR; IPL = 7;} /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() {SR = cpu_sr;} /* Enable interrupts */ +#endif + + diff --git a/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_a.s b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_a.s new file mode 100644 index 0000000..9f24b68 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_a.s @@ -0,0 +1,152 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Microchip PIC24 +; ICCDSPIC +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; INCLUDES +;******************************************************************************************************** + +#include "io24fj128ga010.h" +#include "os_cpu_util_a.s59" + +;******************************************************************************************************** +; LINKER SPECIFICS +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** + +IPL3 EQU 0x0003 + +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + +;******************************************************************************************************** +; EXTERNALS +;******************************************************************************************************** + + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + +;******************************************************************************************************** +; OSStartHighRdy +; +; Description : This function determines the highest priority task that is ready to run after +; OSInit() is called. +;******************************************************************************************************** + +OSStartHighRdy: + call OSTaskSwHook ; Call user defined task switch hook + + mov #0x0001, w0 ; Set OSRunning to TRUE + mov #OSRunning, w1 + mov.b w0, [w1] ; Set OSRunning to TRUE + + ; Get stack pointer of the task to resume + mov OSTCBHighRdy, w0 ; Get the pointer to the stack to resume + mov [w0], w15 ; Dereference the pointer and store the data (the new stack address) W15, the stack pointer register + + OS_REGS_RESTORE ; Restore all of this tasks registers from the stack + + retfie ; Return from the interrupt, the task is now ready to run + +;******************************************************************************************************** +; OSCtxSw +; +; Description : TThe code to perform a 'task level' context switch. OSCtxSw() is called +; when a higher priority task is made ready to run by another task or, +; when the current task can no longer execute (e.g. it calls OSTimeDly(), +; OSSemPend() and the semaphore is not available, etc.). +;******************************************************************************************************** + +OSCtxSw: + ; TRAP (interrupt) should bring us here, not 'call'. + ; Since dsPIC has no TRAP, it is necessary to correct the stack to simulate an interrupt + ; In other words, this function must also save SR and IPL3 to the stack, not just the PC. + + mov.b SR, wreg ; Load SRL + sl w0, #8, w0 ; Shift left by 8 + btsc.b CORCON, #IPL3 ; Test IPL3 bit, skip if clear + bset w0, #7; ; Copy IPL3 to bit7 of w0 + + ior w0, [--w15], w0 ; Merge bits + mov w0, [w15++] ; Write back + + OS_REGS_SAVE ; Save processor registers + + ; Save current task's stack pointer into the currect tasks TCB + mov OSTCBCur, w0 ; Get the address of the location in this tasks TCB to store the stack pointer + mov w15, [w0] ; Store the stack pointer in this tasks TCB + + call OSTaskSwHook ; Call the user defined task switch hook + + mov OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, OSTCBCur + mov #OSPrioHighRdy, w0 + mov #OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + +;******************************************************************************************************** +; OSIntCtxSw +; +; Description : When an ISR (Interrupt Service Routine) completes, OSIntExit() is called to +; determine whether a more important task than the interrupted task needs to +; execute. If that's the case, OSIntExit() determines which task to run next +; and calls OSIntCtxSw() to perform the actual context switch to that task. +;******************************************************************************************************** + +OSIntCtxSw: + call OSTaskSwHook ; Call the user defined task switch hook + + mov OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, OSTCBCur + mov #OSPrioHighRdy, w0 + mov #OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + + END + + diff --git a/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_c.c b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_c.c new file mode 100644 index 0000000..531282b --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_c.c @@ -0,0 +1,353 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Microchip PIC24 +* ICCDSPIC +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif + + SPLIM = 0xFFFE; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) You may pass a task creation parameters through the opt variable. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* +* 2) Registers are initialized to make them easy to differentiate with a debugger. +* +* 3) Setup the stack frame of the task: +* +* ptos - 0 -> +* ptos - 2 -> CORCON +* ptos - 4 -> SR (initialized to 0) +* ptos - 8 -> RCOUNT +* ptos - 10 -> PSVPAG +* ptos - 12 -> TBLPAG +* ptos - 14 -> W14 +* ptos - 16 -> W13 +* ptos - 18 -> W12 +* ptos - 20 -> W11 +* ptos - 22 -> W10 +* ptos - 24 -> W9 +* ptos - 26 -> W8 +* ptos - 28 -> W7 +* ptos - 30 -> W6 +* ptos - 32 -> W5 +* ptos - 34 -> W4 +* ptos - 36 -> W3 +* ptos - 38 -> W2 +* ptos - 40 -> W1 +* ptos - 44 -> p_arg +* ptos - 46 -> 0 (15..8) | CORCON.7 | PC (22..16) Simulate ISR +* ptos - 48 -> PC (15..0) +* ptos - 50 -> PC (22..16) Simulate function call +* ptos - 52 -> PC (15..0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit( void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) { + INT16U x; + INT8U pc_high; + + + pc_high = 0; /* Upper byte of PC always 0. Pointers are 16 bit unsigned */ + + *ptos++ = (OS_STK)task; /* Simulate a call to the task by putting 32 bits of data */ + *ptos++ = (OS_STK)pc_high; /* data on the stack. */ + + /* Simulate an interrupt */ + *ptos++ = (OS_STK)task; /* Put the address of this task on the stack (PC) */ + + x = 0; /* Set the SR to enable ALL interrupts */ + if (CORCONbits.IPL3) { /* Check the CPU's current interrupt level 3 bit */ + x |= 0x0080; /* If set, then save the priority level bit in x bit [7] */ + } + *ptos++ = (OS_STK)(x | (INT16U)pc_high); /* Push the SR Low, CORCON IPL3 and PC (22..16) */ + + *ptos++ = (OS_STK)p_arg; /* Initialize register W0 */ + *ptos++ = 0x1111; /* Initialize register W1 */ + *ptos++ = 0x2222; /* Initialize register W2 */ + *ptos++ = 0x3333; /* Initialize register W3 */ + *ptos++ = 0x4444; /* Initialize register W4 */ + *ptos++ = 0x5555; /* Initialize register W5 */ + *ptos++ = 0x6666; /* Initialize register W6 */ + *ptos++ = 0x7777; /* Initialize register W7 */ + *ptos++ = 0x8888; /* Initialize register W8 */ + *ptos++ = 0x9999; /* Initialize register W9 */ + *ptos++ = 0xAAAA; /* Initialize register W10 */ + *ptos++ = 0xBBBB; /* Initialize register W11 */ + *ptos++ = 0xCCCC; /* Initialize register W12 */ + *ptos++ = 0xDDDD; /* Initialize register W13 */ + *ptos++ = 0xEEEE; /* Initialize register W14 */ + + *ptos++ = TBLPAG; /* Push the Data Table Page Address on to the stack */ + *ptos++ = PSVPAG; /* Push the Program Space Visability Register on the stack */ + *ptos++ = RCOUNT; /* Push the Repeat Loop Counter Register on to the stack */ + + *ptos++ = 0; /* Force the SR to enable all interrupt, clear flags */ + *ptos++ = CORCON; /* Push the Core Control Register on to the stack */ + + return (ptos); /* Return the stack pointer to the new tasks stack */ +} + + diff --git a/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_util_a.s b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_util_a.s new file mode 100644 index 0000000..c2678ad --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_cpu_util_a.s @@ -0,0 +1,81 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Microchip PIC24 +; ICCDSPIC +; +; Filename : os_cpu_util_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; MACRO OS_REGS_SAVE +; +; Description : This macro saves the current state of the CPU onto the current tasks stack +; +; Notes : W15 is the CPU stack pointer. It should never be pushed from the stack during +; a context save. +;******************************************************************************************************** +; + +.macro OS_REGS_SAVE ; Start of Macro + push.d w0 ; Push W0 and W1 on to the stack + push.d w2 ; Push W2 and W3 on to the stack + push.d w4 ; Push W4 and W5 on to the stack + push.d w6 ; Push W6 and W7 on to the stack + push.d w8 ; Push W8 and W9 on to the stack + push.d w10 ; Push W10 and W11 on to the stack + push.d w12 ; Push W12 and W13 on to the stack + push w14 ; Push W14 **ONLY** on to the stack + + push TBLPAG ; Push the Table Page Register on to the stack + push PSVPAG ; Push the Program Space Visability Register on the stack + push RCOUNT ; Push the Repeat Loop Counter Register on to the stack + + push SR ; Push the CPU Status Register on to the stack + push CORCON ; Push the Core Control Register on to the stack +.endm ; End of Macro + +; +;******************************************************************************************************** +; MACRO OS_REGS_RESTORE +; +; Description : This macro restores the current state of the CPU from the current tasks stack +; +; Notes : 1) W15 is the CPU stack pointer. It should never be popped from the stack during +; a context restore. +; 2) Registers are always popped in the reverse order from which they were pushed +;******************************************************************************************************** +; + +.macro OS_REGS_RESTORE ; Start of Macro + pop CORCON ; Pull the Core Control Register from the stack + pop SR ; Pull the CPU Status Register from the stack + + pop RCOUNT ; Pull the Repeat Loop Counter Register from the stack + pop PSVPAG ; Pull the Program Space Visability Register on the stack + pop TBLPAG ; Pull the Table Page Register from the stack + + pop w14 ; Pull W14 **ONLY** from the stack + pop.d w12 ; Pull W12 and W13 from the stack + pop.d w10 ; Pull W10 and W11 from the stack + pop.d w8 ; Pull W8 and W9 from the stack + pop.d w6 ; Pull W6 and W7 from the stack + pop.d w4 ; Pull W4 and W5 from the stack + pop.d w2 ; Pull W2 and W3 from the stack + pop.d w0 ; Pull W0 and W1 from the stack +.endm ; End of Macro diff --git a/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_dbg.c b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_dbg.c new file mode 100644 index 0000000..71d5d43 --- /dev/null +++ b/Ports/Microchip/PIC24FJ128/ICCDSPIC/os_dbg.c @@ -0,0 +1,296 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/Microchip/PIC30F6014/C30/os_cpu.h b/Ports/Microchip/PIC30F6014/C30/os_cpu.h new file mode 100644 index 0000000..4689539 --- /dev/null +++ b/Ports/Microchip/PIC30F6014/C30/os_cpu.h @@ -0,0 +1,99 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 MPLab Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H_ +#define OS_CPU_H_ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); /* See os_cpu_a.s */ +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +/* +********************************************************************************************************* +* APPLICATION INDEPENDENT DATA TYPES +* +* Notes : These data types are chosen based upon the C30 compiler datatype specifications +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; +typedef signed char INT8S; +typedef unsigned int INT16U; +typedef signed int INT16S; +typedef unsigned long INT32U; +typedef signed long INT32S; +typedef float FP32; +typedef long double FP64; + +/* +********************************************************************************************************* +* OTHER DATA TYPES +********************************************************************************************************* +*/ + +typedef INT16U OS_STK; /* Define the size of each stack entry */ +typedef INT16U OS_CPU_SR; /* Define the size of CPU status register */ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 /* Use type 3 critical sections */ +#define OS_STK_GROWTH 0 /* Stack grows from low to high memory */ + +#define OS_TASK_SW() OSCtxSw() /* Macro for defining a high level context switch */ + /* This function call adds 4 bytes to the stack */ + +#if OS_CRITICAL_METHOD == 1 /* Support critical method type 1 */ +#define OS_ENTER_CRITICAL() SRbits.IPL = 7 /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() SRbits.IPL = 0 /* Eenable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 /* Support critical method type 3 */ +#define OS_ENTER_CRITICAL() {cpu_sr = SR; SRbits.IPL = 7;} /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() {SR = cpu_sr;} /* Enable interrupts */ +#endif + +#endif + diff --git a/Ports/Microchip/PIC30F6014/C30/os_cpu_a.s b/Ports/Microchip/PIC30F6014/C30/os_cpu_a.s new file mode 100644 index 0000000..25a59ea --- /dev/null +++ b/Ports/Microchip/PIC30F6014/C30/os_cpu_a.s @@ -0,0 +1,150 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 MPLab Port +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** +; + .equ __30F6014A, 1 ; Inform the p33FG256GP710 header file that we are using a dsPIC33FJ256GP710 + +; +;******************************************************************************************************** +; INCLUDES +;******************************************************************************************************** +; + + .include "p30f6014A.inc" ; Include assembly equates for various CPU registers and bit masks + .include "os_cpu_util_a.s" ; Include an assembly utility files with macros for saving and restoring the CPU registers + +; +;******************************************************************************************************** +; LINKER SPECIFICS +;******************************************************************************************************** +; + + .text ; Locate this file in the text region of the build + +; +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** +; + + .global _OSStartHighRdy + .global _OSCtxSw + .global _OSIntCtxSw + +; +;******************************************************************************************************** +; OSStartHighRdy +; +; Description : This function determines the highest priority task that is ready to run after +; OSInit() is called. +;******************************************************************************************************** +; + +_OSStartHighRdy: + call _OSTaskSwHook ; Call user defined task switch hook + + mov #0x0001, w0 ; Set OSRunning to TRUE + mov #_OSRunning, w1 + mov.b w0, [w1] ; Set OSRunning to TRUE + + ; Get stack pointer of the task to resume + mov _OSTCBHighRdy, w0 ; Get the pointer to the stack to resume + mov [w0], w15 ; Dereference the pointer and store the data (the new stack address) W15, the stack pointer register + + OS_REGS_RESTORE ; Restore all of this tasks registers from the stack + + retfie ; Return from the interrupt, the task is now ready to run + +; +;******************************************************************************************************** +; OSCtxSw +; +; Description : TThe code to perform a 'task level' context switch. OSCtxSw() is called +; when a higher priority task is made ready to run by another task or, +; when the current task can no longer execute (e.g. it calls OSTimeDly(), +; OSSemPend() and the semaphore is not available, etc.). +;******************************************************************************************************** +; + +_OSCtxSw: + ; TRAP (interrupt) should bring us here, not 'call'. + ; Since dsPIC has no TRAP, it is necessary to correct the stack to simulate an interrupt + ; In other words, this function must also save SR and IPL3 to the stack, not just the PC. + + mov.b SRL, wreg ; Load SRL + sl w0, #8, w0 ; Shift left by 8 + btsc CORCON, #IPL3 ; Test IPL3 bit, skip if clear + bset w0, #7; ; Copy IPL3 to bit7 of w0 + + ior w0, [--w15], w0 ; Merge bits + mov w0, [w15++] ; Write back + + OS_REGS_SAVE ; Save processor registers + + ; Save current task's stack pointer into the currect tasks TCB + mov _OSTCBCur, w0 ; Get the address of the location in this tasks TCB to store the stack pointer + mov w15, [w0] ; Store the stack pointer in this tasks TCB + + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + +; +;******************************************************************************************************** +; OSIntCtxSw +; +; Description : When an ISR (Interrupt Service Routine) completes, OSIntExit() is called to +; determine whether a more important task than the interrupted task needs to +; execute. If that's the case, OSIntExit() determines which task to run next +; and calls OSIntCtxSw() to perform the actual context switch to that task. +;******************************************************************************************************** +; + +_OSIntCtxSw: + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + diff --git a/Ports/Microchip/PIC30F6014/C30/os_cpu_c.c b/Ports/Microchip/PIC30F6014/C30/os_cpu_c.c new file mode 100644 index 0000000..54c2260 --- /dev/null +++ b/Ports/Microchip/PIC30F6014/C30/os_cpu_c.c @@ -0,0 +1,462 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 MPLab Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include +#include +#include + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif + + SPLIM = 0xFFFE; /* Initialize the stack pointer limit register to a maximum */ +} /* address thus effectively disabling stack checking */ +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) You may pass a task creation parameters through the opt variable. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 2) Registers are initialized to make them easy to differentiate with a debugger. +* +* 3) Setup the stack frame of the task: +* +* ptos - 0 -> +* ptos - 2 -> CORCON +* ptos - 4 -> SR (initialized to 0) +* ptos - 6 -> DOENDH +* ptos - 8 -> DOENDL +* ptos - 10 -> DOSTARTH +* ptos - 12 -> DOSTARTL +* ptos - 14 -> DCOUNT +* ptos - 16 -> RCOUNT +* ptos - 18 -> PSVPAG +* ptos - 20 -> TBLPAG +* ptos - 22 -> ACCBU +* ptos - 24 -> ACCBH +* ptos - 26 -> ACCBL +* ptos - 28 -> ACCAU +* ptos - 30 -> ACCAH +* ptos - 32 -> ACCAL +* ptos - 34 -> W14 +* ptos - 36 -> W13 +* ptos - 38 -> W12 +* ptos - 40 -> W11 +* ptos - 42 -> W10 +* ptos - 44 -> W9 +* ptos - 46 -> W8 +* ptos - 48 -> W7 +* ptos - 50 -> W6 +* ptos - 52 -> W5 +* ptos - 54 -> W4 +* ptos - 56 -> W3 +* ptos - 58 -> W2 +* ptos - 60 -> W1 +* ptos - 62 -> p_arg +* ptos - 64 -> 0 (15..8) | CORCON.7 | PC (22..16) Simulate ISR +* ptos - 66 -> PC (15..0) +* ptos - 68 -> PC (22..16) Simulate function call +* ptos - 70 -> PC (15..0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U x; + +#if 1 + INT16U pc_high; + + + pc_high = 0; /* Upper byte of PC always 0. Pointers are 16 bit unsigned */ + + *ptos++ = (OS_STK)task; /* Simulate a call to the task by putting 32 bits of data */ + *ptos++ = (OS_STK)pc_high; /* data on the stack. */ + + /* Simulate an interrupt */ + *ptos++ = (OS_STK)task; /* Put the address of this task on the stack (PC) */ + + x = 0; /* Set the SR to enable ALL interrupts */ + if (CORCONbits.IPL3) { /* Check the CPU's current interrupt level 3 bit */ + x |= 0x0080; /* If set, then save the priority level bit in x bit [7] */ + } + *ptos++ = (OS_STK)(x | (INT16U)pc_high); /* Push the SR Low, CORCON IPL3 and PC (22..16) */ +#else + /* simulate a call to my task... put dummy address on the stack (32 bits) */ + *ptos++ = (OS_STK)task; + *ptos++ = 0; + + /* simulate interrupt */ + *ptos++ = (OS_STK)task; + x = (SR << 8); + x &= 0xFF00; + if (CORCONbits.IPL3) { + x |= 0x0080; + } + *ptos++ = x; +#endif + /* Push all of the registers to stack */ + *ptos++ = (OS_STK)p_arg; /* Register W0 holds data passed to the task when started */ + *ptos++ = 0x1111; /* Initialize register W1 */ + *ptos++ = 0x2222; /* Initialize register W2 */ + *ptos++ = 0x3333; /* Initialize register W3 */ + *ptos++ = 0x4444; /* Initialize register W4 */ + *ptos++ = 0x5555; /* Initialize register W5 */ + *ptos++ = 0x6666; /* Initialize register W6 */ + *ptos++ = 0x7777; /* Initialize register W7 */ + *ptos++ = 0x8888; /* Initialize register W8 */ + *ptos++ = 0x9999; /* Initialize register W9 */ + *ptos++ = 0xAAAA; /* Initialize register W10 */ + *ptos++ = 0xBBBB; /* Initialize register W11 */ + *ptos++ = 0xCCCC; /* Initialize register W12 */ + *ptos++ = 0xDDDD; /* Initialize register W13 */ + *ptos++ = 0xEEEE; /* Initialize register W14 */ + + *ptos++ = ACCAL; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAH; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAU; /* Push Accumulator A onto the stack */ + *ptos++ = ACCBL; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBH; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBU; /* Push Accumulator B onto the stack */ + *ptos++ = TBLPAG; /* Push the Data Table Page Address onto the stack */ + *ptos++ = PSVPAG; /* Push the Program Space Visability Register on the stack */ + *ptos++ = RCOUNT; /* Push the Repeat Loop Counter Register onto the stack */ + *ptos++ = DCOUNT; /* Push the Do Loop Counter Register onto the stack */ + *ptos++ = DOSTARTL; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOSTARTH; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOENDL; /* Push the Do Loop End Address Register onto the stack */ + *ptos++ = DOENDH; /* Push the Do Loop End Address Register onto the stack */ + + *ptos++ = 0; /* Force the SR to enable all interrupt, clear flags */ + *ptos++ = CORCON; /* Push the Core Control Register on to the stack */ + + return (ptos); /* Return the stack pointer to the new tasks stack */ +} diff --git a/Ports/Microchip/PIC30F6014/C30/os_cpu_util_a.s b/Ports/Microchip/PIC30F6014/C30/os_cpu_util_a.s new file mode 100644 index 0000000..2715d52 --- /dev/null +++ b/Ports/Microchip/PIC30F6014/C30/os_cpu_util_a.s @@ -0,0 +1,102 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 MPLab Port +; +; Filename : os_cpu_util_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; MACRO OS_REGS_SAVE +; +; Description : This macro saves the current state of the CPU onto the current tasks stack +; +; Notes : W15 is the CPU stack pointer. It should never be pushed from the stack during +; a context save. +;******************************************************************************************************** +; + +.macro OS_REGS_SAVE ; Start of Macro + push.d w0 ; Push W0 and W1 onto the stack + push.d w2 ; Push W2 and W3 onto the stack + push.d w4 ; Push W4 and W5 onto the stack + push.d w6 ; Push W6 and W7 onto the stack + push.d w8 ; Push W8 and W9 onto the stack + push.d w10 ; Push W10 and W11 onto the stack + push.d w12 ; Push W12 and W13 onto the stack + push w14 ; Push W14 **ONLY** onto the stack + + push ACCAL ; Push Accumulator A onto the stack + push ACCAH ; Push Accumulator A onto the stack + push ACCAU ; Push Accumulator A onto the stack + push ACCBL ; Push Accumulator B onto the stack + push ACCBH ; Push Accumulator B onto the stack + push ACCBU ; Push Accumulator B onto the stack + push TBLPAG ; Push the Table Page Register onto the stack + push PSVPAG ; Push the Program Space Visibility Register onto the stack + push RCOUNT ; Push the Repeat Loop Counter Register onto the stack + push DCOUNT ; Push the Do Loop Counter Register onto the stack + push DOSTARTL ; Push the Do Loop Start Address Register onto the stack + push DOSTARTH ; Push the Do Loop Start Address Register onto the stack + push DOENDL ; Push the Do Loop End Address Register onto the stack + push DOENDH ; Push the Do Loop End Address Register onto the stack + + push SR ; Push the CPU Status Register onto the stack + push CORCON ; Push the Core Control Register onto the stack +.endm ; End of Macro + +; +;******************************************************************************************************** +; MACRO OS_REGS_RESTORE +; +; Description : This macro restores the current state of the CPU from the current tasks stack +; +; Notes : 1) W15 is the CPU stack pointer. It should never be popped from the stack during +; a context restore. +; 2) Registers are always popped in the reverse order from which they were pushed +;******************************************************************************************************** +; + +.macro OS_REGS_RESTORE ; Start of Macro + pop CORCON ; Pull the Core Control Register from the stack + pop SR ; Pull the CPU Status Register from the stack + + pop DOENDH ; Pull the Do Loop End Address Register from the stack + pop DOENDL ; Pull the Do Loop End Address Register from the stack + pop DOSTARTH ; Pull the Do Loop Start Address Register from the stack + pop DOSTARTL ; Pull the Do Loop Start Address Register from the stack + pop DCOUNT ; Pull the Do Loop Counter Register from the stack + pop RCOUNT ; Pull the Repeat Loop Counter Register from the stack + pop PSVPAG ; Pull the Program Space Visibility Register from the stack + pop TBLPAG ; Pull the Table Page Register from the stack + pop ACCBU ; Pull Accumulator B from the stack + pop ACCBH ; Pull Accumulator B from the stack + pop ACCBL ; Pull Accumulator B from the stack + pop ACCAU ; Pull Accumulator A from the stack + pop ACCAH ; Pull Accumulator A from the stack + pop ACCAL ; Pull Accumulator A from the stack + + pop w14 ; Pull W14 **ONLY** from the stack + pop.d w12 ; Pull W12 and W13 from the stack + pop.d w10 ; Pull W10 and W11 from the stack + pop.d w8 ; Pull W8 and W9 from the stack + pop.d w6 ; Pull W6 and W7 from the stack + pop.d w4 ; Pull W4 and W5 from the stack + pop.d w2 ; Pull W2 and W3 from the stack + pop.d w0 ; Pull W0 and W1 from the stack +.endm ; End of Macro diff --git a/Ports/Microchip/PIC33FJ256/C30/os_cpu.h b/Ports/Microchip/PIC33FJ256/C30/os_cpu.h new file mode 100644 index 0000000..1c2c101 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/C30/os_cpu.h @@ -0,0 +1,95 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 MPLab Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); /* See os_cpu_a.s */ +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +/* +********************************************************************************************************* +* APPLICATION INDEPENDENT DATA TYPES +* +* Notes : These data types are chosen based upon the C30 compiler datatype specifications +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; +typedef signed char INT8S; +typedef unsigned int INT16U; +typedef signed int INT16S; +typedef unsigned long INT32U; +typedef signed long INT32S; +typedef float FP32; +typedef long double FP64; + +/* +********************************************************************************************************* +* OTHER DATA TYPES +********************************************************************************************************* +*/ + +typedef INT16U OS_STK; /* Define the size of each stack entry */ +typedef INT16U OS_CPU_SR; /* Define the size of CPU status register */ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 /* Use type 3 critical sections */ +#define OS_STK_GROWTH 0 /* Stack grows from low to high memory */ + +#define OS_TASK_SW() OSCtxSw() /* Macro for defining a high level context switch */ + /* This function call adds 4 bytes to the stack */ + +#if OS_CRITICAL_METHOD == 1 /* Support critical method type 1 */ +#define OS_ENTER_CRITICAL() SRbits.IPL = 7 /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() SRbits.IPL = 0 /* Eenable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 /* Support critical method type 3 */ +#define OS_ENTER_CRITICAL() {cpu_sr = SR; SRbits.IPL = 7;} /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() {SR = cpu_sr;} /* Enable interrupts */ +#endif + + diff --git a/Ports/Microchip/PIC33FJ256/C30/os_cpu_a.s b/Ports/Microchip/PIC33FJ256/C30/os_cpu_a.s new file mode 100644 index 0000000..8b05f53 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/C30/os_cpu_a.s @@ -0,0 +1,150 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 MPLab Port +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** +; + .equ __33FJ256GP710, 1 ; Inform the p33FG256GP710 header file that we are using a dsPIC33FJ256GP710 + +; +;******************************************************************************************************** +; INCLUDES +;******************************************************************************************************** +; + + .include "p33FJ256GP710.inc" ; Include assembly equates for various CPU registers and bit masks + .include "os_cpu_util_a.s" ; Include an assembly utility files with macros for saving and restoring the CPU registers + +; +;******************************************************************************************************** +; LINKER SPECIFICS +;******************************************************************************************************** +; + + .text ; Locate this file in the text region of the build + +; +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** +; + + .global _OSStartHighRdy + .global _OSCtxSw + .global _OSIntCtxSw + +; +;******************************************************************************************************** +; OSStartHighRdy +; +; Description : This function determines the highest priority task that is ready to run after +; OSInit() is called. +;******************************************************************************************************** +; + +_OSStartHighRdy: + call _OSTaskSwHook ; Call user defined task switch hook + + mov #0x0001, w0 ; Set OSRunning to TRUE + mov #_OSRunning, w1 + mov.b w0, [w1] ; Set OSRunning to TRUE + + ; Get stack pointer of the task to resume + mov _OSTCBHighRdy, w0 ; Get the pointer to the stack to resume + mov [w0], w15 ; Dereference the pointer and store the data (the new stack address) W15, the stack pointer register + + OS_REGS_RESTORE ; Restore all of this tasks registers from the stack + + retfie ; Return from the interrupt, the task is now ready to run + +; +;******************************************************************************************************** +; OSCtxSw +; +; Description : TThe code to perform a 'task level' context switch. OSCtxSw() is called +; when a higher priority task is made ready to run by another task or, +; when the current task can no longer execute (e.g. it calls OSTimeDly(), +; OSSemPend() and the semaphore is not available, etc.). +;******************************************************************************************************** +; + +_OSCtxSw: + ; TRAP (interrupt) should bring us here, not 'call'. + ; Since dsPIC has no TRAP, it is necessary to correct the stack to simulate an interrupt + ; In other words, this function must also save SR and IPL3 to the stack, not just the PC. + + mov.b SRL, wreg ; Load SRL + sl w0, #8, w0 ; Shift left by 8 + btsc CORCON, #IPL3 ; Test IPL3 bit, skip if clear + bset w0, #7; ; Copy IPL3 to bit7 of w0 + + ior w0, [--w15], w0 ; Merge bits + mov w0, [w15++] ; Write back + + OS_REGS_SAVE ; Save processor registers + + ; Save current task's stack pointer into the currect tasks TCB + mov _OSTCBCur, w0 ; Get the address of the location in this tasks TCB to store the stack pointer + mov w15, [w0] ; Store the stack pointer in this tasks TCB + + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + +; +;******************************************************************************************************** +; OSIntCtxSw +; +; Description : When an ISR (Interrupt Service Routine) completes, OSIntExit() is called to +; determine whether a more important task than the interrupted task needs to +; execute. If that's the case, OSIntExit() determines which task to run next +; and calls OSIntCtxSw() to perform the actual context switch to that task. +;******************************************************************************************************** +; + +_OSIntCtxSw: + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + diff --git a/Ports/Microchip/PIC33FJ256/C30/os_cpu_c.c b/Ports/Microchip/PIC33FJ256/C30/os_cpu_c.c new file mode 100644 index 0000000..7740313 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/C30/os_cpu_c.c @@ -0,0 +1,445 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 MPLab Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif + + SPLIM = 0xFFFE; /* Initialize the stack pointer limit register to a maximum */ +} /* address thus effectively disabling stack checking */ +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + +/* +********************************************************************************************************* +* INTERRUPT DISABLE TIME MEASUREMENT, START +********************************************************************************************************* +*/ + +#if OS_CPU_INT_DIS_MEAS_EN > 0u +void OS_CPU_IntDisMeasInit (void) +{ + OS_CPU_IntDisMeasNestingCtr = 0u; + OS_CPU_IntDisMeasCntsEnter = 0u; + OS_CPU_IntDisMeasCntsExit = 0u; + OS_CPU_IntDisMeasCntsMax = 0u; + OS_CPU_IntDisMeasCntsDelta = 0u; + OS_CPU_IntDisMeasCntsOvrhd = 0u; + OS_CPU_IntDisMeasStart(); /* Measure the overhead of the functions */ + OS_CPU_IntDisMeasStop(); + OS_CPU_IntDisMeasCntsOvrhd = OS_CPU_IntDisMeasCntsDelta; +} + + +void OS_CPU_IntDisMeasStart (void) +{ + OS_CPU_IntDisMeasNestingCtr++; + if (OS_CPU_IntDisMeasNestingCtr == 1u) { /* Only measure at the first nested level */ + OS_CPU_IntDisMeasCntsEnter = OS_CPU_IntDisMeasTmrRd(); + } +} + + +void OS_CPU_IntDisMeasStop (void) +{ + OS_CPU_IntDisMeasNestingCtr--; /* Decrement nesting ctr */ + if (OS_CPU_IntDisMeasNestingCtr == 0u) { + OS_CPU_IntDisMeasCntsExit = OS_CPU_IntDisMeasTmrRd(); + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsExit - OS_CPU_IntDisMeasCntsEnter; + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsOvrhd) { /* Ensure overhead < delta */ + OS_CPU_IntDisMeasCntsDelta -= OS_CPU_IntDisMeasCntsOvrhd; + } else { + OS_CPU_IntDisMeasCntsDelta = OS_CPU_IntDisMeasCntsOvrhd; + } + if (OS_CPU_IntDisMeasCntsDelta > OS_CPU_IntDisMeasCntsMax) { /* Track MAXIMUM */ + OS_CPU_IntDisMeasCntsMax = OS_CPU_IntDisMeasCntsDelta; + } + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) You may pass a task creation parameters through the opt variable. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 2) Registers are initialized to make them easy to differentiate with a debugger. +* +* 3) Setup the stack frame of the task: +* +* ptos - 0 -> +* ptos - 2 -> CORCON +* ptos - 4 -> SR (initialized to 0) +* ptos - 6 -> DOENDH +* ptos - 8 -> DOENDL +* ptos - 10 -> DOSTARTH +* ptos - 12 -> DOSTARTL +* ptos - 14 -> DCOUNT +* ptos - 16 -> RCOUNT +* ptos - 18 -> PSVPAG +* ptos - 20 -> TBLPAG +* ptos - 22 -> ACCBU +* ptos - 24 -> ACCBH +* ptos - 26 -> ACCBL +* ptos - 28 -> ACCAU +* ptos - 30 -> ACCAH +* ptos - 32 -> ACCAL +* ptos - 34 -> W14 +* ptos - 36 -> W13 +* ptos - 38 -> W12 +* ptos - 40 -> W11 +* ptos - 42 -> W10 +* ptos - 44 -> W9 +* ptos - 46 -> W8 +* ptos - 48 -> W7 +* ptos - 50 -> W6 +* ptos - 52 -> W5 +* ptos - 54 -> W4 +* ptos - 56 -> W3 +* ptos - 58 -> W2 +* ptos - 60 -> W1 +* ptos - 62 -> p_arg +* ptos - 64 -> 0 (15..8) | CORCON.7 | PC (22..16) Simulate ISR +* ptos - 66 -> PC (15..0) +* ptos - 68 -> PC (22..16) Simulate function call +* ptos - 70 -> PC (15..0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U x; + INT16U pc_high; + + + pc_high = 0; /* Upper byte of PC always 0. Pointers are 16 bit unsigned */ + + *ptos++ = (OS_STK)task; /* Simulate a call to the task by putting 32 bits of data */ + *ptos++ = (OS_STK)pc_high; /* data on the stack. */ + + /* Simulate an interrupt */ + *ptos++ = (OS_STK)task; /* Put the address of this task on the stack (PC) */ + + x = 0; /* Set the SR to enable ALL interrupts */ + if (CORCONbits.IPL3) { /* Check the CPU's current interrupt level 3 bit */ + x |= 0x0080; /* If set, then save the priority level bit in x bit [7] */ + } + *ptos++ = (OS_STK)(x | (INT16U)pc_high); /* Push the SR Low, CORCON IPL3 and PC (22..16) */ + + /* Push all of the registers to stack */ + *ptos++ = (OS_STK)p_arg; /* Register W0 holds data passed to the task when started */ + *ptos++ = 0x1111; /* Initialize register W1 */ + *ptos++ = 0x2222; /* Initialize register W2 */ + *ptos++ = 0x3333; /* Initialize register W3 */ + *ptos++ = 0x4444; /* Initialize register W4 */ + *ptos++ = 0x5555; /* Initialize register W5 */ + *ptos++ = 0x6666; /* Initialize register W6 */ + *ptos++ = 0x7777; /* Initialize register W7 */ + *ptos++ = 0x8888; /* Initialize register W8 */ + *ptos++ = 0x9999; /* Initialize register W9 */ + *ptos++ = 0xAAAA; /* Initialize register W10 */ + *ptos++ = 0xBBBB; /* Initialize register W11 */ + *ptos++ = 0xCCCC; /* Initialize register W12 */ + *ptos++ = 0xDDDD; /* Initialize register W13 */ + *ptos++ = 0xEEEE; /* Initialize register W14 */ + + *ptos++ = ACCAL; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAH; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAU; /* Push Accumulator A onto the stack */ + *ptos++ = ACCBL; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBH; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBU; /* Push Accumulator B onto the stack */ + *ptos++ = TBLPAG; /* Push the Data Table Page Address onto the stack */ + *ptos++ = PSVPAG; /* Push the Program Space Visability Register on the stack */ + *ptos++ = RCOUNT; /* Push the Repeat Loop Counter Register onto the stack */ + *ptos++ = DCOUNT; /* Push the Do Loop Counter Register onto the stack */ + *ptos++ = DOSTARTL; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOSTARTH; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOENDL; /* Push the Do Loop End Address Register onto the stack */ + *ptos++ = DOENDH; /* Push the Do Loop End Address Register onto the stack */ + + *ptos++ = 0; /* Force the SR to enable all interrupt, clear flags */ + *ptos++ = CORCON; /* Push the Core Control Register on to the stack */ + + return (ptos); /* Return the stack pointer to the new tasks stack */ +} diff --git a/Ports/Microchip/PIC33FJ256/C30/os_cpu_util_a.s b/Ports/Microchip/PIC33FJ256/C30/os_cpu_util_a.s new file mode 100644 index 0000000..c339d56 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/C30/os_cpu_util_a.s @@ -0,0 +1,103 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 MPLab Port +; +; Filename : os_cpu_util_a.s +; Version : V2.93.00 +;******************************************************************************************************** + + +; +;******************************************************************************************************** +; MACRO OS_REGS_SAVE +; +; Description : This macro saves the current state of the CPU onto the current tasks stack +; +; Notes : W15 is the CPU stack pointer. It should never be pushed from the stack during +; a context save. +;******************************************************************************************************** +; + +.macro OS_REGS_SAVE ; Start of Macro + push.d w0 ; Push W0 and W1 onto the stack + push.d w2 ; Push W2 and W3 onto the stack + push.d w4 ; Push W4 and W5 onto the stack + push.d w6 ; Push W6 and W7 onto the stack + push.d w8 ; Push W8 and W9 onto the stack + push.d w10 ; Push W10 and W11 onto the stack + push.d w12 ; Push W12 and W13 onto the stack + push w14 ; Push W14 **ONLY** onto the stack + + push ACCAL ; Push Accumulator A onto the stack + push ACCAH ; Push Accumulator A onto the stack + push ACCAU ; Push Accumulator A onto the stack + push ACCBL ; Push Accumulator B onto the stack + push ACCBH ; Push Accumulator B onto the stack + push ACCBU ; Push Accumulator B onto the stack + push TBLPAG ; Push the Table Page Register onto the stack + push PSVPAG ; Push the Program Space Visibility Register onto the stack + push RCOUNT ; Push the Repeat Loop Counter Register onto the stack + push DCOUNT ; Push the Do Loop Counter Register onto the stack + push DOSTARTL ; Push the Do Loop Start Address Register onto the stack + push DOSTARTH ; Push the Do Loop Start Address Register onto the stack + push DOENDL ; Push the Do Loop End Address Register onto the stack + push DOENDH ; Push the Do Loop End Address Register onto the stack + + push SR ; Push the CPU Status Register onto the stack + push CORCON ; Push the Core Control Register onto the stack +.endm ; End of Macro + +; +;******************************************************************************************************** +; MACRO OS_REGS_RESTORE +; +; Description : This macro restores the current state of the CPU from the current tasks stack +; +; Notes : 1) W15 is the CPU stack pointer. It should never be popped from the stack during +; a context restore. +; 2) Registers are always popped in the reverse order from which they were pushed +;******************************************************************************************************** +; + +.macro OS_REGS_RESTORE ; Start of Macro + pop CORCON ; Pull the Core Control Register from the stack + pop SR ; Pull the CPU Status Register from the stack + + pop DOENDH ; Pull the Do Loop End Address Register from the stack + pop DOENDL ; Pull the Do Loop End Address Register from the stack + pop DOSTARTH ; Pull the Do Loop Start Address Register from the stack + pop DOSTARTL ; Pull the Do Loop Start Address Register from the stack + pop DCOUNT ; Pull the Do Loop Counter Register from the stack + pop RCOUNT ; Pull the Repeat Loop Counter Register from the stack + pop PSVPAG ; Pull the Program Space Visibility Register from the stack + pop TBLPAG ; Pull the Table Page Register from the stack + pop ACCBU ; Pull Accumulator B from the stack + pop ACCBH ; Pull Accumulator B from the stack + pop ACCBL ; Pull Accumulator B from the stack + pop ACCAU ; Pull Accumulator A from the stack + pop ACCAH ; Pull Accumulator A from the stack + pop ACCAL ; Pull Accumulator A from the stack + + pop w14 ; Pull W14 **ONLY** from the stack + pop.d w12 ; Pull W12 and W13 from the stack + pop.d w10 ; Pull W10 and W11 from the stack + pop.d w8 ; Pull W8 and W9 from the stack + pop.d w6 ; Pull W6 and W7 from the stack + pop.d w4 ; Pull W4 and W5 from the stack + pop.d w2 ; Pull W2 and W3 from the stack + pop.d w0 ; Pull W0 and W1 from the stack +.endm ; End of Macro diff --git a/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu.h b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu.h new file mode 100644 index 0000000..901e534 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu.h @@ -0,0 +1,95 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 MPLab Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); /* See os_cpu_a.s */ +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +/* +********************************************************************************************************* +* APPLICATION INDEPENDENT DATA TYPES +* +* Notes : These data types are chosen based upon the C30 compiler datatype specifications +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; +typedef signed char INT8S; +typedef unsigned int INT16U; +typedef signed int INT16S; +typedef unsigned long INT32U; +typedef signed long INT32S; +typedef float FP32; +typedef long double FP64; + +/* +********************************************************************************************************* +* OTHER DATA TYPES +********************************************************************************************************* +*/ + +typedef INT16U OS_STK; /* Define the size of each stack entry */ +typedef INT16U OS_CPU_SR; /* Define the size of CPU status register */ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 /* Use type 3 critical sections */ +#define OS_STK_GROWTH 0 /* Stack grows from low to high memory */ + +#define OS_TASK_SW() OSCtxSw() /* Macro for defining a high level context switch */ + /* This function call adds 4 bytes to the stack */ + +#if OS_CRITICAL_METHOD == 1 /* Support critical method type 1 */ +#define OS_ENTER_CRITICAL() SRbits.IPL = 7 /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() SRbits.IPL = 0 /* Eenable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 /* Support critical method type 3 */ +#define OS_ENTER_CRITICAL() {cpu_sr = SR; SRbits.IPL = 7;} /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() {SR = cpu_sr;} /* Enable interrupts */ +#endif + + diff --git a/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_a.as b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_a.as new file mode 100644 index 0000000..54d60c6 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_a.as @@ -0,0 +1,161 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 MPLab Port +; +; Filename : os_cpu_a.as +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** +; + +; +;******************************************************************************************************** +; INCLUDES +;******************************************************************************************************** +; + + #include ; Include assembly equates for various CPU registers and bit masks + #include "os_cpu_util_a.as" ; Include an assembly utility files with macros for saving and restoring the CPU registers + +; +;******************************************************************************************************** +; LINKER SPECIFICS +;******************************************************************************************************** +; + + psect text,global,reloc=4,class=CODE,delta=2 ; Locate this file in the text region of the build + +; +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** +; + IPL3 EQU 0x0003 +; +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** +; + + GLOBAL _OSStartHighRdy + GLOBAL _OSCtxSw + GLOBAL _OSIntCtxSw + GLOBAL _OSTaskSwHook + GLOBAL _OSRunning + GLOBAL _OSTCBHighRdy + GLOBAL _OSPrioHighRdy + GLOBAL _OSPrioCur + +; +;******************************************************************************************************** +; OSStartHighRdy +; +; Description : This function determines the highest priority task that is ready to run after +; OSInit() is called. +;******************************************************************************************************** +; + +_OSStartHighRdy: + call _OSTaskSwHook ; Call user defined task switch hook + + mov #0x0001, w0 ; Set OSRunning to TRUE + mov #_OSRunning, w1 + mov.b w0, [w1] ; Set OSRunning to TRUE + + ; Get stack pointer of the task to resume + mov _OSTCBHighRdy, w0 ; Get the pointer to the stack to resume + mov [w0], w15 ; Dereference the pointer and store the data (the new stack address) W15, the stack pointer register + + OS_REGS_RESTORE ; Restore all of this tasks registers from the stack + + retfie ; Return from the interrupt, the task is now ready to run + +; +;******************************************************************************************************** +; OSCtxSw +; +; Description : TThe code to perform a 'task level' context switch. OSCtxSw() is called +; when a higher priority task is made ready to run by another task or, +; when the current task can no longer execute (e.g. it calls OSTimeDly(), +; OSSemPend() and the semaphore is not available, etc.). +;******************************************************************************************************** +; + +_OSCtxSw: + ; Ideally, a TRAP (interrupt) would bring us here, not 'call' (see os_cpu.h). + ; Since the dsPIC has no software TRAP instruction, it is necessary to correct the stack + ; to simulate an interrupt. In other words, this function must also save SR and IPL3 to + ; the stack, not just the PC. + + mov.b SR, wreg ; Load SRL + sl w0, #8, w0 ; Shift left by 8 + btsc CORCON, #IPL3 ; Test IPL3 bit, skip if clear + bset w0, #7; ; Copy IPL3 to bit7 of w0 + + ior w0, [--w15], w0 ; Merge IPL3 bit with last byte pushed + mov w0, [w15++] ; Readjust stack pointer so there is no net change due to previous write + + OS_REGS_SAVE ; Save processor registers + + ; Save current task's stack pointer into the currect tasks TCB + mov _OSTCBCur, w0 ; Get the address of the location in this tasks TCB to store the stack pointer + mov w15, [w0] ; Store the stack pointer in this tasks TCB + + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + +; +;******************************************************************************************************** +; OSIntCtxSw +; +; Description : When an ISR (Interrupt Service Routine) completes, OSIntExit() is called to +; determine whether a more important task than the interrupted task needs to +; execute. If that's the case, OSIntExit() determines which task to run next +; and calls OSIntCtxSw() to perform the actual context switch to that task. +;******************************************************************************************************** +; + +_OSIntCtxSw: + call _OSTaskSwHook ; Call the user defined task switch hook + + mov _OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, _OSTCBCur + mov #_OSPrioHighRdy, w0 + mov #_OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + diff --git a/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_c.c b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_c.c new file mode 100644 index 0000000..adc9c46 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_c.c @@ -0,0 +1,373 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 MPLab Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif + + SPLIM = 0xFFFE; /* Initialize the stack pointer limit register to a maximum */ +} /* address thus effectively disabling stack checking */ +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) You may pass a task creation parameters through the opt variable. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 2) Registers are initialized to make them easy to differentiate with a debugger. +* +* 3) Setup the stack frame of the task: +* +* ptos - 0 -> +* ptos - 2 -> CORCON +* ptos - 4 -> SR (initialized to 0) +* ptos - 6 -> DOENDH +* ptos - 8 -> DOENDL +* ptos - 10 -> DOSTARTH +* ptos - 12 -> DOSTARTL +* ptos - 14 -> DCOUNT +* ptos - 16 -> RCOUNT +* ptos - 18 -> PSVPAG +* ptos - 20 -> TBLPAG +* ptos - 22 -> ACCBU +* ptos - 24 -> ACCBH +* ptos - 26 -> ACCBL +* ptos - 28 -> ACCAU +* ptos - 30 -> ACCAH +* ptos - 32 -> ACCAL +* ptos - 34 -> W14 +* ptos - 36 -> W13 +* ptos - 38 -> W12 +* ptos - 40 -> W11 +* ptos - 42 -> W10 +* ptos - 44 -> W9 +* ptos - 46 -> W8 +* ptos - 48 -> W7 +* ptos - 50 -> W6 +* ptos - 52 -> W5 +* ptos - 54 -> W4 +* ptos - 56 -> W3 +* ptos - 58 -> W2 +* ptos - 60 -> W1 +* ptos - 62 -> p_arg +* ptos - 64 -> 0 (15..8) | CORCON.7 | PC (22..16) Simulate ISR +* ptos - 66 -> PC (15..0) +* ptos - 68 -> PC (22..16) Simulate function call +* ptos - 70 -> PC (15..0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U x; + INT16U pc_high; + + + pc_high = 0; /* Upper byte of PC always 0. Pointers are 16 bit unsigned */ + + *ptos++ = (OS_STK)task; /* Simulate a call to the task by putting 32 bits of data */ + *ptos++ = (OS_STK)pc_high; /* data on the stack. */ + + /* Simulate an interrupt */ + *ptos++ = (OS_STK)task; /* Put the address of this task on the stack (PC) */ + + x = 0; /* Set the SR to enable ALL interrupts */ + if (CORCONbits.IPL3) { /* Check the CPU's current interrupt level 3 bit */ + x |= 0x0080; /* If set, then save the priority level bit in x bit [7] */ + } + *ptos++ = (OS_STK)(x | (INT16U)pc_high); /* Push the SR Low, CORCON IPL3 and PC (22..16) */ + + /* Push all of the registers to stack */ + *ptos++ = (OS_STK)p_arg; /* Register W0 holds data passed to the task when started */ + *ptos++ = 0x1111; /* Initialize register W1 */ + *ptos++ = 0x2222; /* Initialize register W2 */ + *ptos++ = 0x3333; /* Initialize register W3 */ + *ptos++ = 0x4444; /* Initialize register W4 */ + *ptos++ = 0x5555; /* Initialize register W5 */ + *ptos++ = 0x6666; /* Initialize register W6 */ + *ptos++ = 0x7777; /* Initialize register W7 */ + *ptos++ = 0x8888; /* Initialize register W8 */ + *ptos++ = 0x9999; /* Initialize register W9 */ + *ptos++ = 0xAAAA; /* Initialize register W10 */ + *ptos++ = 0xBBBB; /* Initialize register W11 */ + *ptos++ = 0xCCCC; /* Initialize register W12 */ + *ptos++ = 0xDDDD; /* Initialize register W13 */ + *ptos++ = 0xEEEE; /* Initialize register W14 */ + + *ptos++ = ACCAL; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAH; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAU; /* Push Accumulator A onto the stack */ + *ptos++ = ACCBL; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBH; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBU; /* Push Accumulator B onto the stack */ + *ptos++ = TBLPAG; /* Push the Data Table Page Address onto the stack */ + *ptos++ = PSVPAG; /* Push the Program Space Visability Register on the stack */ + *ptos++ = RCOUNT; /* Push the Repeat Loop Counter Register onto the stack */ + *ptos++ = DCOUNT; /* Push the Do Loop Counter Register onto the stack */ + *ptos++ = DOSTARTL; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOSTARTH; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOENDL; /* Push the Do Loop End Address Register onto the stack */ + *ptos++ = DOENDH; /* Push the Do Loop End Address Register onto the stack */ + + *ptos++ = 0; /* Force the SR to enable all interrupt, clear flags */ + *ptos++ = CORCON; /* Push the Core Control Register on to the stack */ + + return (ptos); /* Return the stack pointer to the new tasks stack */ +} diff --git a/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_util_a.as b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_util_a.as new file mode 100644 index 0000000..032a853 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/DSPICC/os_cpu_util_a.as @@ -0,0 +1,112 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 MPLab Port +; +; Filename : os_cpu_util_a.as +; Version : V2.93.00 +;******************************************************************************************************** + +; +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** +; + + GLOBAL _OSIntNesting + GLOBAL _OSTCBCur + GLOBAL _OSIntExit + +; +;******************************************************************************************************** +; MACRO OS_REGS_SAVE +; +; Description : This macro saves the current state of the CPU onto the current tasks stack +; +; Notes : W15 is the CPU stack pointer. It should never be pushed from the stack during +; a context save. +;******************************************************************************************************** +; + +OS_REGS_SAVE MACRO ; Start of Macro + push.d w0 ; Push W0 and W1 onto the stack + push.d w2 ; Push W2 and W3 onto the stack + push.d w4 ; Push W4 and W5 onto the stack + push.d w6 ; Push W6 and W7 onto the stack + push.d w8 ; Push W8 and W9 onto the stack + push.d w10 ; Push W10 and W11 onto the stack + push.d w12 ; Push W12 and W13 onto the stack + push w14 ; Push W14 **ONLY** onto the stack + + push ACCAL ; Push Accumulator A onto the stack + push ACCAH ; Push Accumulator A onto the stack + push ACCAU ; Push Accumulator A onto the stack + push ACCBL ; Push Accumulator B onto the stack + push ACCBH ; Push Accumulator B onto the stack + push ACCBU ; Push Accumulator B onto the stack + push TBLPAG ; Push the Table Page Register onto the stack + push PSVPAG ; Push the Program Space Visibility Register onto the stack + push RCOUNT ; Push the Repeat Loop Counter Register onto the stack + push DCOUNT ; Push the Do Loop Counter Register onto the stack + push DOSTARTL ; Push the Do Loop Start Address Register onto the stack + push DOSTARTH ; Push the Do Loop Start Address Register onto the stack + push DOENDL ; Push the Do Loop End Address Register onto the stack + push DOENDH ; Push the Do Loop End Address Register onto the stack + + push SR ; Push the CPU Status Register onto the stack + push CORCON ; Push the Core Control Register onto the stack +ENDM ; End of Macro + +; +;******************************************************************************************************** +; MACRO OS_REGS_RESTORE +; +; Description : This macro restores the current state of the CPU from the current tasks stack +; +; Notes : 1) W15 is the CPU stack pointer. It should never be popped from the stack during +; a context restore. +; 2) Registers are always popped in the reverse order from which they were pushed +;******************************************************************************************************** +; + +OS_REGS_RESTORE MACRO ; Start of Macro + pop CORCON ; Pull the Core Control Register from the stack + pop SR ; Pull the CPU Status Register from the stack + + pop DOENDH ; Pull the Do Loop End Address Register from the stack + pop DOENDL ; Pull the Do Loop End Address Register from the stack + pop DOSTARTH ; Pull the Do Loop Start Address Register from the stack + pop DOSTARTL ; Pull the Do Loop Start Address Register from the stack + pop DCOUNT ; Pull the Do Loop Counter Register from the stack + pop RCOUNT ; Pull the Repeat Loop Counter Register from the stack + pop PSVPAG ; Pull the Program Space Visibility Register from the stack + pop TBLPAG ; Pull the Table Page Register from the stack + pop ACCBU ; Pull Accumulator B from the stack + pop ACCBH ; Pull Accumulator B from the stack + pop ACCBL ; Pull Accumulator B from the stack + pop ACCAU ; Pull Accumulator A from the stack + pop ACCAH ; Pull Accumulator A from the stack + pop ACCAL ; Pull Accumulator A from the stack + + pop w14 ; Pull W14 **ONLY** from the stack + pop.d w12 ; Pull W12 and W13 from the stack + pop.d w10 ; Pull W10 and W11 from the stack + pop.d w8 ; Pull W8 and W9 from the stack + pop.d w6 ; Pull W6 and W7 from the stack + pop.d w4 ; Pull W4 and W5 from the stack + pop.d w2 ; Pull W2 and W3 from the stack + pop.d w0 ; Pull W0 and W1 from the stack +ENDM ; End of Macro diff --git a/Ports/Microchip/PIC33FJ256/DSPICC/os_dbg.c b/Ports/Microchip/PIC33FJ256/DSPICC/os_dbg.c new file mode 100644 index 0000000..71d5d43 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/DSPICC/os_dbg.c @@ -0,0 +1,296 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu.h b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu.h new file mode 100644 index 0000000..3d439a0 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu.h @@ -0,0 +1,95 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 IAR Compiler +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw(void); /* See os_cpu_a.s */ +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +/* +********************************************************************************************************* +* APPLICATION INDEPENDENT DATA TYPES +* +* Notes : These data types are chosen based upon the C30 compiler datatype specifications +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; +typedef signed char INT8S; +typedef unsigned int INT16U; +typedef signed int INT16S; +typedef unsigned long INT32U; +typedef signed long INT32S; +typedef float FP32; +typedef long double FP64; + +/* +********************************************************************************************************* +* OTHER DATA TYPES +********************************************************************************************************* +*/ + +typedef INT16U OS_STK; /* Define the size of each stack entry */ +typedef INT16U OS_CPU_SR; /* Define the size of CPU status register */ + +/* +********************************************************************************************************* +* PROCESSOR SPECIFICS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 /* Use type 3 critical sections */ +#define OS_STK_GROWTH 0 /* Stack grows from low to high memory */ + +#define OS_TASK_SW() OSCtxSw() /* Macro for defining a high level context switch */ + /* This function call adds 4 bytes to the stack */ + +#if OS_CRITICAL_METHOD == 1 /* Support critical method type 1 */ +#define OS_ENTER_CRITICAL() IPL = 7; /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() IPL = 0; /* Eenable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 /* Support critical method type 3 */ +#define OS_ENTER_CRITICAL() {cpu_sr = SR; IPL = 7;} /* Disable all interrupts */ +#define OS_EXIT_CRITICAL() {SR = cpu_sr;} /* Enable interrupts */ +#endif + + diff --git a/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_a.s59 b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_a.s59 new file mode 100644 index 0000000..b85538e --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_a.s59 @@ -0,0 +1,151 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 IAR Compiler +; +; Filename : os_cpu_a.s59 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; INCLUDES +;******************************************************************************************************** + +#include "io33fj256gp710.h" +#include "os_cpu_util_a.s59" + +;******************************************************************************************************** +; LINKER SPECIFICS +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + +;******************************************************************************************************** +; CONSTANTS +;******************************************************************************************************** + +IPL3 EQU 0x0003 + +;******************************************************************************************************** +; GLOBALS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + +;******************************************************************************************************** +; EXTERNALS +;******************************************************************************************************** + + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSRunning + EXTERN OSTaskSwHook + +;******************************************************************************************************** +; OSStartHighRdy +; +; Description : This function determines the highest priority task that is ready to run after +; OSInit() is called. +;******************************************************************************************************** + +OSStartHighRdy: + call OSTaskSwHook ; Call user defined task switch hook + + mov #0x0001, w0 ; Set OSRunning to TRUE + mov #OSRunning, w1 + mov.b w0, [w1] ; Set OSRunning to TRUE + + ; Get stack pointer of the task to resume + mov OSTCBHighRdy, w0 ; Get the pointer to the stack to resume + mov [w0], w15 ; Dereference the pointer and store the data (the new stack address) W15, the stack pointer register + + OS_REGS_RESTORE ; Restore all of this tasks registers from the stack + + retfie ; Return from the interrupt, the task is now ready to run + +;******************************************************************************************************** +; OSCtxSw +; +; Description : TThe code to perform a 'task level' context switch. OSCtxSw() is called +; when a higher priority task is made ready to run by another task or, +; when the current task can no longer execute (e.g. it calls OSTimeDly(), +; OSSemPend() and the semaphore is not available, etc.). +;******************************************************************************************************** + +OSCtxSw: + ; TRAP (interrupt) should bring us here, not 'call'. + ; Since dsPIC has no TRAP, it is necessary to correct the stack to simulate an interrupt + ; In other words, this function must also save SR and IPL3 to the stack, not just the PC. + + mov.b SR, wreg ; Load SRL + sl w0, #8, w0 ; Shift left by 8 + btsc.b CORCON, #IPL3 ; Test IPL3 bit, skip if clear + bset w0, #7; ; Copy IPL3 to bit7 of w0 + + ior w0, [--w15], w0 ; Merge bits + mov w0, [w15++] ; Write back + + OS_REGS_SAVE ; Save processor registers + + ; Save current task's stack pointer into the currect tasks TCB + mov OSTCBCur, w0 ; Get the address of the location in this tasks TCB to store the stack pointer + mov w15, [w0] ; Store the stack pointer in this tasks TCB + + call OSTaskSwHook ; Call the user defined task switch hook + + mov OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, OSTCBCur + mov #OSPrioHighRdy, w0 + mov #OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + +;******************************************************************************************************** +; OSIntCtxSw +; +; Description : When an ISR (Interrupt Service Routine) completes, OSIntExit() is called to +; determine whether a more important task than the interrupted task needs to +; execute. If that's the case, OSIntExit() determines which task to run next +; and calls OSIntCtxSw() to perform the actual context switch to that task. +;******************************************************************************************************** + +OSIntCtxSw: + call OSTaskSwHook ; Call the user defined task switch hook + + mov OSTCBHighRdy, w1 ; Set the current running TCB to the TCB of the highest priority task ready to run + mov w1, OSTCBCur + mov #OSPrioHighRdy, w0 + mov #OSPrioCur, w2 + mov.b [w0], [w2] + + mov [w1], w15 ; Load W15 with the stack pointer from the task that is ready to run + + OS_REGS_RESTORE ; Restore registers + + retfie ; Return from interrupt + + END + + diff --git a/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_c.c b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_c.c new file mode 100644 index 0000000..4b9b65e --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_c.c @@ -0,0 +1,373 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* dsPIC33 IAR Compiler +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "uCOS_II.H" + +/* +********************************************************************************************************* +* LOCALS +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0 + OSTmrCtr = 0; +#endif + + SPLIM = 0xFFFE; +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +#if OS_CPU_INT_DIS_MEAS_EN > 0 + OS_CPU_IntDisMeasInit(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) You may pass a task creation parameters through the opt variable. You MUST only use the +* upper 8 bits of 'opt' because the lower bits are reserved by uC/OS-II. If you make +* changes to the code below, you will need to ensure that it doesn't affect the behaviour +* of OSTaskIdle() and OSTaskStat(). +* 2) Registers are initialized to make them easy to differentiate with a debugger. +* +* 3) Setup the stack frame of the task: +* +* ptos - 0 -> +* ptos - 2 -> CORCON +* ptos - 4 -> SR (initialized to 0) +* ptos - 6 -> DOENDH +* ptos - 8 -> DOENDL +* ptos - 10 -> DOSTARTH +* ptos - 12 -> DOSTARTL +* ptos - 14 -> DCOUNT +* ptos - 16 -> RCOUNT +* ptos - 18 -> PSVPAG +* ptos - 20 -> TBLPAG +* ptos - 22 -> ACCBU +* ptos - 24 -> ACCBH +* ptos - 26 -> ACCBL +* ptos - 28 -> ACCAU +* ptos - 30 -> ACCAH +* ptos - 32 -> ACCAL +* ptos - 34 -> W14 +* ptos - 36 -> W13 +* ptos - 38 -> W12 +* ptos - 40 -> W11 +* ptos - 42 -> W10 +* ptos - 44 -> W9 +* ptos - 46 -> W8 +* ptos - 48 -> W7 +* ptos - 50 -> W6 +* ptos - 52 -> W5 +* ptos - 54 -> W4 +* ptos - 56 -> W3 +* ptos - 58 -> W2 +* ptos - 60 -> W1 +* ptos - 62 -> p_arg +* ptos - 64 -> 0 (15..8) | CORCON.7 | PC (22..16) Simulate ISR +* ptos - 66 -> PC (15..0) +* ptos - 68 -> PC (22..16) Simulate function call +* ptos - 70 -> PC (15..0) +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT16U x; + INT16U pc_high; + + + pc_high = 0; /* Upper byte of PC always 0. Pointers are 16 bit unsigned */ + + *ptos++ = (OS_STK)task; /* Simulate a call to the task by putting 32 bits of data */ + *ptos++ = (OS_STK)pc_high; /* data on the stack. */ + + /* Simulate an interrupt */ + *ptos++ = (OS_STK)task; /* Put the address of this task on the stack (PC) */ + + x = 0; /* Set the SR to enable ALL interrupts */ + if (CORCON & 0x0008) { /* Check the CPU's current interrupt level. Bit 3 in CORCON */ + x |= 0x0080; /* If set, then save the priority level bit in x bit [7] */ + } + *ptos++ = (OS_STK)(x | (INT16U)pc_high); /* Push the SR Low, CORCON IPL3 and PC (22..16) */ + + /* Push all of the registers to stack */ + *ptos++ = (OS_STK)p_arg; /* Register W0 holds data passed to the task when started */ + *ptos++ = 0x1111; /* Initialize register W1 */ + *ptos++ = 0x2222; /* Initialize register W2 */ + *ptos++ = 0x3333; /* Initialize register W3 */ + *ptos++ = 0x4444; /* Initialize register W4 */ + *ptos++ = 0x5555; /* Initialize register W5 */ + *ptos++ = 0x6666; /* Initialize register W6 */ + *ptos++ = 0x7777; /* Initialize register W7 */ + *ptos++ = 0x8888; /* Initialize register W8 */ + *ptos++ = 0x9999; /* Initialize register W9 */ + *ptos++ = 0xAAAA; /* Initialize register W10 */ + *ptos++ = 0xBBBB; /* Initialize register W11 */ + *ptos++ = 0xCCCC; /* Initialize register W12 */ + *ptos++ = 0xDDDD; /* Initialize register W13 */ + *ptos++ = 0xEEEE; /* Initialize register W14 */ + + *ptos++ = ACCAL; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAH; /* Push Accumulator A onto the stack */ + *ptos++ = ACCAU; /* Push Accumulator A onto the stack */ + *ptos++ = ACCBL; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBH; /* Push Accumulator B onto the stack */ + *ptos++ = ACCBU; /* Push Accumulator B onto the stack */ + *ptos++ = TBLPAG; /* Push the Data Table Page Address onto the stack */ + *ptos++ = PSVPAG; /* Push the Program Space Visability Register on the stack */ + *ptos++ = RCOUNT; /* Push the Repeat Loop Counter Register onto the stack */ + *ptos++ = DCOUNT; /* Push the Do Loop Counter Register onto the stack */ + *ptos++ = DOSTARTL; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOSTARTH; /* Push the Do Loop Start Address Register onto the stack */ + *ptos++ = DOENDL; /* Push the Do Loop End Address Register onto the stack */ + *ptos++ = DOENDH; /* Push the Do Loop End Address Register onto the stack */ + + *ptos++ = 0; /* Force the SR to enable all interrupt, clear flags */ + *ptos++ = CORCON; /* Push the Core Control Register on to the stack */ + + return (ptos); /* Return the stack pointer to the new tasks stack */ +} diff --git a/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_util_a.s59 b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_util_a.s59 new file mode 100644 index 0000000..68e9a18 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_cpu_util_a.s59 @@ -0,0 +1,107 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; dsPIC33 IAR Compiler +; +; Filename : os_cpu_util_a.s59 +; Version : V2.93.00 +;******************************************************************************************************** + +;******************************************************************************************************** +; MACRO OS_REGS_SAVE +; +; Description : This macro saves the current state of the CPU onto the current tasks stack +; +; Notes : W15 is the CPU stack pointer. It should never be pushed from the stack during +; a context save. +;******************************************************************************************************** + +OS_REGS_SAVE MACRO + push.d w0 ; Push W0 and W1 onto the stack + push.d w2 ; Push W2 and W3 onto the stack + push.d w4 ; Push W4 and W5 onto the stack + push.d w6 ; Push W6 and W7 onto the stack + push.d w8 ; Push W8 and W9 onto the stack + push.d w10 ; Push W10 and W11 onto the stack + push.d w12 ; Push W12 and W13 onto the stack + push w14 ; Push W14 **ONLY** onto the stack + + push ACCAL ; Push Accumulator A onto the stack + push ACCAH ; Push Accumulator A onto the stack + push ACCAU ; Push Accumulator A onto the stack + push ACCBL ; Push Accumulator B onto the stack + push ACCBH ; Push Accumulator B onto the stack + push ACCBU ; Push Accumulator B onto the stack + push TBLPAG ; Push the Table Page Register onto the stack + push PSVPAG ; Push the Program Space Visibility Register onto the stack + push RCOUNT ; Push the Repeat Loop Counter Register onto the stack + push DCOUNT ; Push the Do Loop Counter Register onto the stack + push DOSTARTL ; Push the Do Loop Start Address Register onto the stack + push DOSTARTH ; Push the Do Loop Start Address Register onto the stack + push DOENDL ; Push the Do Loop End Address Register onto the stack + push DOENDH ; Push the Do Loop End Address Register onto the stack + + push SR ; Push the CPU Status Register onto the stack + push CORCON ; Push the Core Control Register onto the stack + ENDM + +;******************************************************************************************************** +; MACRO OS_REGS_RESTORE +; +; Description : This macro restores the current state of the CPU from the current tasks stack +; +; Notes : 1) W15 is the CPU stack pointer. It should never be popped from the stack during +; a context restore. +; 2) Registers are always popped in the reverse order from which they were pushed +;******************************************************************************************************** + +OS_REGS_RESTORE MACRO + pop CORCON ; Pull the Core Control Register from the stack + pop SR ; Pull the CPU Status Register from the stack + + pop DOENDH ; Pull the Do Loop End Address Register from the stack + pop DOENDL ; Pull the Do Loop End Address Register from the stack + pop DOSTARTH ; Pull the Do Loop Start Address Register from the stack + pop DOSTARTL ; Pull the Do Loop Start Address Register from the stack + pop DCOUNT ; Pull the Do Loop Counter Register from the stack + pop RCOUNT ; Pull the Repeat Loop Counter Register from the stack + pop PSVPAG ; Pull the Program Space Visibility Register from the stack + pop TBLPAG ; Pull the Table Page Register from the stack + pop ACCBU ; Pull Accumulator B from the stack + pop ACCBH ; Pull Accumulator B from the stack + pop ACCBL ; Pull Accumulator B from the stack + pop ACCAU ; Pull Accumulator A from the stack + pop ACCAH ; Pull Accumulator A from the stack + pop ACCAL ; Pull Accumulator A from the stack + + pop w14 ; Pull W14 **ONLY** from the stack + pop.d w12 ; Pull W12 and W13 from the stack + pop.d w10 ; Pull W10 and W11 from the stack + pop.d w8 ; Pull W8 and W9 from the stack + pop.d w6 ; Pull W6 and W7 from the stack + pop.d w4 ; Pull W4 and W5 from the stack + pop.d w2 ; Pull W2 and W3 from the stack + pop.d w0 ; Pull W0 and W1 from the stack + ENDM + + + + + + + + + diff --git a/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_dbg.c b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_dbg.c new file mode 100644 index 0000000..71d5d43 --- /dev/null +++ b/Ports/Microchip/PIC33FJ256/ICCDSPIC/os_dbg.c @@ -0,0 +1,296 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PPC405/GNU/os_cpu.h b/Ports/PPC405/GNU/os_cpu.h new file mode 100644 index 0000000..47557b2 --- /dev/null +++ b/Ports/PPC405/GNU/os_cpu.h @@ -0,0 +1,104 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PowerPC405 +* GNU C/C++ Compiler +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include "xparameters.h" +#include + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; +typedef double FP64; + +typedef unsigned int OS_STK; /* Each stack entry is 32-bits wide */ +typedef unsigned int volatile OS_CPU_SR; /* The CPU Status Word is 32-bits wide. This variable */ + /* MUST be volatile for proper operation. Refer to */ + /* os_cpu_a.s for more details */ + +/* +********************************************************************************************************* +* CRITICAL SECTIONS MANAGEMENT +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save(); +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr); + + +/* +********************************************************************************************************* +* PowerPC405 +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PowerPC */ + +#define OS_TASK_SW() __asm__ __volatile__("sc\n") + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Save(void); /* See OS_CPU_A.S */ +void OS_CPU_SR_Restore(OS_CPU_SR); /* See OS_CPU_A.S */ + diff --git a/Ports/PPC405/GNU/os_cpu_a.S b/Ports/PPC405/GNU/os_cpu_a.S new file mode 100644 index 0000000..af81252 --- /dev/null +++ b/Ports/PPC405/GNU/os_cpu_a.S @@ -0,0 +1,1004 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PowerPC405 +* GNU C/C++ Compiler +* +* Filename : os_cpu_a.S +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include "xreg405.h" + + .file "os_cpu_a.S" + + .section ".vectors","ax" + +#ifdef __DCC__ +#define // ; +#define MACRO0(name)name: .macro +#define MACRO1(name, param1)name: .macro param1 +#define MACRO2(name, param1, param2)name: .macro param1, param2 +#define CONCAT(left, right) left##&&##right +#define CONCAT3(left, parammiddle, right) left##&&##parammiddle##right +#define PARAM(param) param +#else +#include +#define r1 1 +#define r2 2 +#define MACRO0(name) .macro name +#define MACRO1(name, param1) .macro name param1 +#define MACRO2(name, param1, param2) .macro name param1 param2 +#define CONCAT(left,right) left##right +#define PARAM(param) param +#endif + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + + .global OSStartHighRdy + .global OSIntCtxSw + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + +/* +********************************************************************************************************* +* EXTERNAL FUNCTIONS +********************************************************************************************************* +*/ + + .extern OSIntEnter + .extern OSIntExit + .extern BSP_IntHandler + .extern OSTaskSwHook + +/* +********************************************************************************************************* +* EXTERNAL VARIABLES +********************************************************************************************************* +*/ + + .extern OSRunning + .extern OSIntNesting + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSPrioCur + .extern OSPrioHighRdy + +/* +********************************************************************************************************* +* CONSTANTS USED TO ACCESS TASK CONTEXT STACK +********************************************************************************************************* +*/ + + .set STK_OFFSET_BC, 0 + .set STK_OFFSET_NEW_LR, STK_OFFSET_BC + 4 + .set STK_OFFSET_MSR, STK_OFFSET_NEW_LR + 4 + .set STK_OFFSET_PC, STK_OFFSET_MSR + 4 + .set STK_OFFSET_LR, STK_OFFSET_PC + 4 + .set STK_OFFSET_CTR, STK_OFFSET_LR + 4 + .set STK_OFFSET_XER, STK_OFFSET_CTR + 4 + .set STK_OFFSET_CR, STK_OFFSET_XER + 4 + .set STK_OFFSET_USPRG0, STK_OFFSET_CR + 4 + .set STK_OFFSET_R0, STK_OFFSET_USPRG0 + 4 + .set STK_OFFSET_R2, STK_OFFSET_R0 + 4 + .set STK_OFFSET_R3R31, STK_OFFSET_R2 + 4 + .set STK_CTX_SIZE, STK_OFFSET_R3R31 + ( ( 31 - 3 ) + 1 ) * 4 + +/* +********************************************************************************************************* +* OS_CPU_ISR_CRITICAL +* +* Description: This macro is placed at offset 0x0100 in the interrupt-handler table, so it is executed +* whenever the external critical interrupt signal is asserted. This code saves the +* current task's context before calling BSP_IntHandler(), which provides further, +* application-specific processing of the interrupt. +* +* The interrupted task's context is saved onto its stack as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \./ +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OS_CPU_ISR_CRITICAL) + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu XREG_GPR1,-STK_CTX_SIZE(XREG_GPR1) /* Adjust the stack pointer */ + + stw XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Save General-Purpose Registers 0 and 2 */ + stw XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + stmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Save General-Purpose Registers 3-31 */ + + mflr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Save the Link Register */ + + mfctr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Save the Count Register */ + + mfxer XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Save the Fixed-Point Exception Register */ + + mfcr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Save the Condition Register */ + + mfspr XREG_GPR0, 0x100 + stw XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Save User SPR General-Purpose Register 0 */ + + mfsrr3 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Save the Machine-State Register */ + + mfsrr2 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Save the return address */ + + lis XREG_GPR4, OSIntNesting@h /* See if OSIntNesting == 0 */ + ori XREG_GPR4, XREG_GPR4, OSIntNesting@l + lwz XREG_GPR5, 0(XREG_GPR4) + addic. XREG_GPR5, XREG_GPR5, 0 + bc 0x04, 0x02, OS_CPU_ISR_CRITICAL_1 + + lis XREG_GPR6, OSTCBCur@h /* Save the current task's stack pointer */ + ori XREG_GPR6, XREG_GPR6, OSTCBCur@l + lwz XREG_GPR7, 0(XREG_GPR6) + stw XREG_GPR1, 0(XREG_GPR7) + +OS_CPU_ISR_CRITICAL_1: + + addi XREG_GPR5, XREG_GPR5, 1 /* Increment OSIntNesting */ + stb XREG_GPR5, 0(XREG_GPR4) + + lis XREG_GPR0, BSP_IntHandler@h /* Call the interrupt controller's handler */ + ori XREG_GPR0, XREG_GPR0, BSP_IntHandler@l + mtlr XREG_GPR0 + blrl + + lis XREG_GPR0, OSIntExit@h /* Call OSIntExit() */ + ori XREG_GPR0, XREG_GPR0, OSIntExit@l + mtlr XREG_GPR0 + blrl + + /* *** RESTORE INTERRUPTED TASK'S CONTEXT **** */ + + lwz XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Restore the Machine-State Register to SRR3 */ + mtsrr3 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Restore the Machine-State Register to SRR2 */ + mtsrr2 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Restore the Condition Register */ + mtcr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Restore the Fixed-Point Exception Register */ + mtxer XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Restore the Count Register */ + mtctr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Restore the Link Register */ + mtlr XREG_GPR0 + + lmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Restore General-Purpose Registers 3-31 */ + + lwz XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Restore General-Purpose Registers 0 and 2 */ + lwz XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + addi XREG_GPR1, XREG_GPR1,STK_CTX_SIZE /* Adjust the stack pointer */ + + rfci /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OS_CPU_ISR_NON_CRITICAL +* +* Description: This macro is placed at offset 0x0500 in the interrupt-handler table, so it is executed +* whenever the external non-critical interrupt signal is asserted. This code saves the +* current task's context before calling BSP_IntHandler(), which provides further, +* application-specific processing of the interrupt. +* +* The interrupted task's context is saved onto its stack as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \./ +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OS_CPU_ISR_NON_CRITICAL) + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu XREG_GPR1,-STK_CTX_SIZE(XREG_GPR1) /* Adjust the stack pointer */ + + stw XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Save General-Purpose Registers 0 and 2 */ + stw XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + stmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Save General-Purpose Registers 3-31 */ + + mflr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Save the Link Register */ + + mfctr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Save the Count Register */ + + mfxer XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Save the Fixed-Point Exception Register */ + + mfcr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Save the Condition Register */ + + mfspr XREG_GPR0, 0x100 + stw XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Save User SPR General-Purpose Register 0 */ + + mfsrr1 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Save the Machine-State Register */ + + mfsrr0 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Save the return address */ + + lis XREG_GPR4, OSIntNesting@h /* See if OSIntNesting == 0 */ + ori XREG_GPR4, XREG_GPR4, OSIntNesting@l + lwz XREG_GPR5, 0(XREG_GPR4) + addic. XREG_GPR5, XREG_GPR5, 0 + bc 0x04, 0x02, OS_CPU_ISR_NON_CRITICAL_1 + + lis XREG_GPR6, OSTCBCur@h /* Save the current task's stack pointer */ + ori XREG_GPR6, XREG_GPR6, OSTCBCur@l + lwz XREG_GPR7, 0(XREG_GPR6) + stw XREG_GPR1, 0(XREG_GPR7) + +OS_CPU_ISR_NON_CRITICAL_1: + + addi XREG_GPR5, XREG_GPR5, 1 /* Increment OSIntNesting */ + stb XREG_GPR5, 0(XREG_GPR4) + + lis XREG_GPR0, BSP_IntHandler@h /* Call the interrupt controller's handler */ + ori XREG_GPR0, XREG_GPR0, BSP_IntHandler@l + mtlr XREG_GPR0 + blrl + + lis XREG_GPR0, OSIntExit@h /* Call OSIntExit() */ + ori XREG_GPR0, XREG_GPR0, OSIntExit@l + mtlr XREG_GPR0 + blrl + + /* *** RESTORE INTERRUPTED TASK'S CONTEXT **** */ + + lwz XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Restore the return address to SRR0 */ + mtsrr0 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Restore the Condition Register */ + mtcr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Restore the Fixed-Point Exception Register */ + mtxer XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Restore the Count Register */ + mtctr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Restore the Link Register */ + mtlr XREG_GPR0 + + lmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Restore General-Purpose Registers 3-31 */ + + lwz XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Restore General-Purpose Registers 0 and 2 */ + lwz XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + addi XREG_GPR1, XREG_GPR1,STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OSCtxSw +* +* Description: Performs a Context switch from a task. This function is ALWAYS called with interrupts +* DISABLED. +* +* OSCtxSw() implements the following pseudo-code: +* +* Save CPU registers; +* OSTCBCur->OSTCBStkPtr = SP; +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore CPU registers +* Execute the return-from-interrupt instruction; +* +* +* The stack frame of the task to suspend will look as follows when OSCtxSw() is done: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \./ +* + 0x9C GPR31 (HIGH MEMORY) +* +* The stack frame of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \./ +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OSCtxSw) + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu XREG_GPR1,-STK_CTX_SIZE(XREG_GPR1) /* Adjust the stack pointer */ + + stw XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Save General-Purpose Registers 0 and 2 */ + stw XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + stmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Save General-Purpose Registers 3-31 */ + + mflr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Save the Link Register */ + + mfctr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Save the Count Register */ + + mfxer XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Save the Fixed-Point Exception Register */ + + mfcr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Save the Condition Register */ + + mfspr XREG_GPR0, 0x100 + stw XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Save User SPR General-Purpose Register 0 */ + + mfsrr1 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Save the Machine-State Register */ + + mfsrr0 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Save the return address */ + + lis XREG_GPR4, OSTCBCur@h /* Save the current task's stack pointer */ + ori XREG_GPR4, XREG_GPR4, OSTCBCur@l + lwz XREG_GPR5, 0(XREG_GPR4) + stw XREG_GPR1, 0(XREG_GPR5) + + lis XREG_GPR0, OSTaskSwHook@h /* Call OSTaskSwHook() */ + ori XREG_GPR0, XREG_GPR0, OSTaskSwHook@l + mtlr XREG_GPR0 + blrl + + lis XREG_GPR4, OSPrioHighRdy@h /* Update the current priority */ + ori XREG_GPR4, XREG_GPR4, OSPrioHighRdy@l + lbz XREG_GPR5, 0(XREG_GPR4) + lis XREG_GPR6, OSPrioCur@h + ori XREG_GPR6, XREG_GPR6, OSPrioCur@l + stb XREG_GPR5, 0(XREG_GPR6) + + lis XREG_GPR4, OSTCBHighRdy@h /* Update the current TCB */ + ori XREG_GPR4, XREG_GPR4, OSTCBHighRdy@l + lwz XREG_GPR5, 0(XREG_GPR4) + lis XREG_GPR6, OSTCBCur@h + ori XREG_GPR6, XREG_GPR6, OSTCBCur@l + stw XREG_GPR5, 0(XREG_GPR6) + + lwz XREG_GPR1, 0(XREG_GPR5) /* Load the new task's stack pointer */ + + /* ******** RESTORE NEW TASK'S CONTEXT ******* */ + + lwz XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Restore the return address to SRR0 */ + mtsrr0 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Restore the Condition Register */ + mtcr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Restore the Fixed-Point Exception Register */ + mtxer XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Restore the Count Register */ + mtctr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Restore the Link Register */ + mtlr XREG_GPR0 + + lmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Restore General-Purpose Registers 3-31 */ + + lwz XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Restore General-Purpose Registers 0 and 2 */ + lwz XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + addi XREG_GPR1, XREG_GPR1,STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OSTickISR +* +* Description: This macro is used to process uC/OS-II tick interrupts, which are produced by the +* programmable interval timer. This code saves the current task's context before calling +* OSTimeTick(), uC/OS-II's CPU-independent routine for processing these interrupts. +* +* The interrupted task's context is saved onto its stack as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \./ +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OSTickISR) + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu XREG_GPR1,-STK_CTX_SIZE(XREG_GPR1) /* Adjust the stack pointer */ + + stw XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Save General-Purpose Registers 0 and 2 */ + stw XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + stmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Save General-Purpose Registers 3-31 */ + + mflr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Save the Link Register */ + + mfctr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Save the Count Register */ + + mfxer XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Save the Fixed-Point Exception Register */ + + mfcr XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Save the Condition Register */ + + mfspr XREG_GPR0, 0x100 + stw XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Save User SPR General-Purpose Register 0 */ + + mfsrr1 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Save the Machine-State Register */ + + mfsrr0 XREG_GPR0 + stw XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Save the return address */ + + lis XREG_GPR4, OSIntNesting@h /* See if OSIntNesting == 0 */ + ori XREG_GPR4, XREG_GPR4, OSIntNesting@l + lbz XREG_GPR5, 0(XREG_GPR4) + addic. XREG_GPR5, XREG_GPR5, 0 + bc 0x04, 0x02, OSTickISR_1 + + lis XREG_GPR6, OSTCBCur@h /* Save the current task's stack pointer */ + ori XREG_GPR6, XREG_GPR6, OSTCBCur@l + lwz XREG_GPR7, 0(XREG_GPR6) + stw XREG_GPR1, 0(XREG_GPR7) + +OSTickISR_1: + + addi XREG_GPR5, XREG_GPR5, 1 /* Increment OSIntNesting */ + stb XREG_GPR5, 0(XREG_GPR4) + + lis XREG_GPR0, 0x0800 /* Clear the PIT interrupt */ + mttsr XREG_GPR0 + + lis XREG_GPR0, OSTimeTick@h /* Call OSTimeTick() */ + ori XREG_GPR0, XREG_GPR0, OSTimeTick@l + mtlr XREG_GPR0 + blrl + + lis XREG_GPR0, OSIntExit@h /* Call OSIntExit() */ + ori XREG_GPR0, XREG_GPR0, OSIntExit@l + mtlr XREG_GPR0 + blrl + + /* **** RESTORE INTERRUPTED TASK'S CONTEXT *** */ + + lwz XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Restore the return address to SRR0 */ + mtsrr0 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Restore the Condition Register */ + mtcr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Restore the Fixed-Point Exception Register */ + mtxer XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Restore the Count Register */ + mtctr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Restore the Link Register */ + mtlr XREG_GPR0 + + lmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Restore General-Purpose Registers 3-31 */ + + lwz XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Restore General-Purpose Registers 0 and 2 */ + lwz XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + addi XREG_GPR1, XREG_GPR1,STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OS_NULL_NON_CRITICAL +* +* Description : This exception handler simply returns to the interrupted code. +********************************************************************************************************* +*/ + + MACRO0(OS_NULL_NON_CRITICAL) + + rfi + + .endm + +/* +********************************************************************************************************* +* OS_NULL_CRITICAL +* +* Description : This exception handler simply returns to the interrupted code. +********************************************************************************************************* +*/ + + MACRO0(OS_NULL_CRITICAL) + + rfci + + .endm + +/* +********************************************************************************************************* +* PowerPC405 Interrupt-Handler Table +* +* This is the interrupt-handler table used by the PowerPC to appropriately invoke handlers for various +* types of interrupts. The interrupts are the results of exceptions, each of which corresponds to an +* offset into this table. When the interrupt associated with a given expection occurs, the PowerPC adds +* the offset for that exception to this table's base address, which is stored in the Exception-Vector +* Prefix Register (EVPR) by OSStartHighRdy(). The code at the resulting address should represent the +* handler for the exception. +* +* The table entries for the critical input exception (offset 0x0100) and the external input exception +* (offset 0x0500) span 256 (0x100) bytes each, which is enough room to accomodate uC/OS-II's handlers +* for those interrupts, OS_CPU_ISR_CRITICAL() and OS_CPU_ISR_NON_CRITICAL(), respectively. The entry +* for the programmable-interval timer exception, however, only covers 16 bytes, so OSTickISR(), +* uC/OS-II's handler for timer exceptions, must be placed at another location. Since the entries at +* offsets 0x1300 and 0x1400 don't correspond to any exceptions, OSTickISR() is placed there, and a +* branch to that location is inserted at offset 0x1000, the actual offset corresponding to the +* programmable-interval timer exception. +* +* All table entries that are not currently used by uC/OS-II contain null routines that simply return +* from the interrupt without performing any actions. These routines can be replaced if an application +* requires support for additional types of exceptions. +********************************************************************************************************* +*/ + +_vectorbase: + + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x0100 /* Offset 0x0100 -> Critical Input Exception */ + OS_CPU_ISR_CRITICAL + + + .org _vectorbase + 0x0200 /* Offset 0x0200 -> Machine Check Exception */ + OS_NULL_CRITICAL + + + .org _vectorbase + 0x0300 /* Offset 0x0300 -> Data Storage Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x0400 /* Offset 0x0400 -> Instruction Storage Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x0500 /* Offset 0x0500 -> External Input Exception */ + OS_CPU_ISR_NON_CRITICAL + + + .org _vectorbase + 0x0600 /* Offset 0x0600 -> Alignment Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x0700 /* Offset 0x0700 -> Program Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x0800 /* Offset 0x0800 -> FPU Unavailable Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x0C00 /* Offset 0x0C00 -> System Call Exception */ + OSCtxSw + + + .org _vectorbase + 0x0F20 /* Offset 0x0F20 -> APU Unavailable Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x1000 /* Offset 0x1000 -> Programmable-Interval Timer Exception */ + b PITISR + + + .org _vectorbase + 0x1010 /* Offset 0x1010 -> Fixed-Interval Timer Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x1020 /* Offset 0x1020 -> Watchdog Timer Exception */ + OS_NULL_CRITICAL + + + .org _vectorbase + 0x1100 /* Offset 0x1100 -> Data TLB Miss Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x1200 /* Offset 0x1200 -> Instruction TLB Miss Exception */ + OS_NULL_NON_CRITICAL + + + .org _vectorbase + 0x1300 /* Offset 0x1300 -> Excess code from other entries */ +PITISR: + OSTickISR + + .org _vectorbase + 0x2000 /* Offset 0x2000 -> Debug Exceptions */ + OS_NULL_CRITICAL + + + + .section ".text" + +/* +********************************************************************************************************* +* OSIntCtxSw() +* +* Description: Performs the Context Switch from an ISR. +* +* OSIntCtxSw() implements the following pseudo-code: +* +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* if (Context saved by Critical ISR) { +* Restore MSR and PC to SRR3 and SRR2, respectively; +* Restore all other registers; +* Execute the return-from-critical-interrupt instruction; +* } else { +* Restore MSR and PC to SRR1 and SRR0, respectively; +* Restore all other registers; +* Execute the return-from-interrupt instruction; +* } +* +* Upon entry, the registers of the task being suspended have already been saved onto that +* task's stack and the SP for the task has been saved in its OS_TCB by the ISR. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 Interrupt type +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \./ +* + 0x9C GPR31 (HIGH MEMORY) +* +* Note(s) : 1) If the task frame was saved by a critical ISR, the stack entry at offset 0x20 will be +* set to 1. +* If the task frame was saved by a non-critical ISR, the stack entry at offset 0x20 will +* be set to 0. +********************************************************************************************************* +*/ + +OSIntCtxSw: + + lis XREG_GPR0, OSTaskSwHook@h /* Call OSTaskSwHook() */ + ori XREG_GPR0, XREG_GPR0, OSTaskSwHook@l + mtlr XREG_GPR0 + blrl + + lis XREG_GPR4, OSPrioHighRdy@h /* Update the current priority */ + ori XREG_GPR4, XREG_GPR4, OSPrioHighRdy@l + lbz XREG_GPR5, 0(XREG_GPR4) + lis XREG_GPR6, OSPrioCur@h + ori XREG_GPR6, XREG_GPR6, OSPrioCur@l + stb XREG_GPR5, 0(XREG_GPR6) + + lis XREG_GPR4, OSTCBHighRdy@h /* Update the current TCB */ + ori XREG_GPR4, XREG_GPR4, OSTCBHighRdy@l + lwz XREG_GPR5, 0(XREG_GPR4) + lis XREG_GPR6, OSTCBCur@h + ori XREG_GPR6, XREG_GPR6, OSTCBCur@l + stw XREG_GPR5, 0(XREG_GPR6) + + lwz XREG_GPR1, 0(XREG_GPR5) /* Load the new task's stack pointer */ + + /* ******** RESTORE NEW TASK'S CONTEXT ******* */ + + lwz XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Restore the return address to SRR0 */ + mtsrr0 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Restore the Condition Register */ + mtcr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Restore the Fixed-Point Exception Register */ + mtxer XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Restore the Count Register */ + mtctr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Restore the Link Register */ + mtlr XREG_GPR0 + + lmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Restore General-Purpose Registers 3-31 */ + + lwz XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Restore General-Purpose Registers 0 and 2 */ + lwz XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + addi XREG_GPR1, XREG_GPR1,STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + +/* +********************************************************************************************************* +* OSStartHighRdy() +* +* Description: Starts the highest priority task that is available to run. OSStartHighRdy() MUST: +* +* a) Call OSTaskSwHook() +* b) Set OSRunning to TRUE +* c) Switch to the highest priority task. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 Interrupt type (initialized to 0x00000000) +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \./ +* + 0x9C GPR31 (HIGH MEMORY) +* +* Note(s) : 1) The MSR entry in the stack is initialized so that interrupts will be enabled when the +* task begins to run. In order to allow the interrupts to be properly serviced, +* OSStartHighRdy() initializes the Exception-Vector Prefix Register (EVPR) so that it +* contains the address of the interrupt-handler table defined above. +********************************************************************************************************* +*/ + +OSStartHighRdy: + + lis XREG_GPR0, OSTaskSwHook@h /* Call OSTaskSwHook() */ + ori XREG_GPR0, XREG_GPR0, OSTaskSwHook@l + mtlr XREG_GPR0 + blrl + + li XREG_GPR0, 1 /* Indicate that the OS is running */ + lis XREG_GPR4, OSRunning@h + ori XREG_GPR4, XREG_GPR4, OSRunning@l + stb XREG_GPR0, 0(XREG_GPR4) + + lis XREG_GPR4, OSTCBHighRdy@h /* Load the first task's stack pointer */ + ori XREG_GPR4, XREG_GPR4, OSTCBHighRdy@l + lwz XREG_GPR5, 0(XREG_GPR4) + lwz XREG_GPR1, 0(XREG_GPR5) + + lis XREG_GPR0, _vectorbase@h /* Initialize the EVPR */ + mtevpr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_MSR(XREG_GPR1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_PC(XREG_GPR1) /* Restore the return address to SRR0 */ + mtsrr0 XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_USPRG0(XREG_GPR1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CR(XREG_GPR1) /* Restore the Condition Register */ + mtcr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_XER(XREG_GPR1) /* Restore the Fixed-Point Exception Register */ + mtxer XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_CTR(XREG_GPR1) /* Restore the Count Register */ + mtctr XREG_GPR0 + + lwz XREG_GPR0, STK_OFFSET_LR(XREG_GPR1) /* Restore the Link Register */ + mtlr XREG_GPR0 + + lmw XREG_GPR3, STK_OFFSET_R3R31(XREG_GPR1) /* Restore General-Purpose Registers 3-31 */ + + lwz XREG_GPR0, STK_OFFSET_R0(XREG_GPR1) /* Restore General-Purpose Registers 0 and 2 */ + lwz XREG_GPR2, STK_OFFSET_R2(XREG_GPR1) + + addi XREG_GPR1, XREG_GPR1,STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Start the task */ + +/* +********************************************************************************************************* +* DISABLE INTERRUPTS +* OS_CPU_SR OS_CPU_SR_Save(void); +* +* Description : Sets the MSR, disabling interrupts, and returns the previous MSR contents. This allows +* the machine state to be restored at a subsequent time. +* +* Arguments : None +* +* Returns : Current MSR contents in GPR3 +* +* Note(s) : 1) The variable in the calling routine that will hold the return value MUST be declared +* volatile for proper operation. There is no guarantee that the proper register will +* be scheduled for the subsequent 'OS_CPU_SR_Save()' function call if the variable is +* not declared volatile. +********************************************************************************************************* +*/ + +OS_CPU_SR_Save: + + addis XREG_GPR4, 0, 0xFFFD + ori XREG_GPR4, XREG_GPR4, 0x7FFF + mfmsr XREG_GPR3 + and XREG_GPR4, XREG_GPR4, XREG_GPR3 /* Clear bits 14 and 16, corresponding to... */ + mtmsr XREG_GPR4 /* ...critical and non-critical interrupts */ + blr + +/* +********************************************************************************************************* +* ENABLE INTERRUPTS +* void OS_CPU_SR_Restore(OS_CPU_SR sr); +* +* Description : Sets the MSR, possibly enabling interrupts, using the value passed in GPR3. +* +* Arguments : Saved MSR contents in GPR3 +* +* Returns : None +* +* Note(s) : 1) The argument from the calling routine MUST be declared volatile for proper operation. +* There is no guarantee that the proper register will be scheduled for the call to +* OS_CPU_SR_Restore() if the variable is not declared 'volatile'. +********************************************************************************************************* +*/ + +OS_CPU_SR_Restore: + + mtmsr XREG_GPR3 /* Restore the saved MSR */ + blr + + + diff --git a/Ports/PPC405/GNU/os_cpu_c.c b/Ports/PPC405/GNU/os_cpu_c.c new file mode 100644 index 0000000..ccd3b5a --- /dev/null +++ b/Ports/PPC405/GNU/os_cpu_c.c @@ -0,0 +1,328 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PowerPC405 +* GNU C/C++ Compiler +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +extern void *_SDA_BASE_; +extern void *_SDA2_BASE_; + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_VIEW_MODULE >0 + OSView_TaskCreateHook(ptcb); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (IE=1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH Memory) +* + 0x78 Empty +* ptos ---------> + 0x7C Empty +* +* 2) R16 is not saved as part of the task context since it is used by the debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT32U *)ptos; /* Load stack pointer */ + pstk--; /* Make sure we point to free entry ... */ + pstk--; /* ... compiler uses top-of-stack so free an extra one. */ + *pstk-- = (INT32U)0x31313131; /* r31 */ + *pstk-- = (INT32U)0x30303030; /* r30 */ + *pstk-- = (INT32U)0x29292929; /* r29 */ + *pstk-- = (INT32U)0x28282828; /* r28 */ + *pstk-- = (INT32U)0x27272727; /* r27 */ + *pstk-- = (INT32U)0x26262626; /* r26 */ + *pstk-- = (INT32U)0x25252525; /* r25 */ + *pstk-- = (INT32U)0x24242424; /* r24 */ + *pstk-- = (INT32U)0x23232323; /* r23 */ + *pstk-- = (INT32U)0x22222222; /* r22 */ + *pstk-- = (INT32U)0x21212121; /* r21 */ + *pstk-- = (INT32U)0x20202020; /* r20 */ + *pstk-- = (INT32U)0x19191919; /* r19 */ + *pstk-- = (INT32U)0x18181818; /* r18 */ + *pstk-- = (INT32U)0x17171717; /* r17 */ + *pstk-- = (INT32U)0x16161616; /* r16 */ + *pstk-- = (INT32U)0x15151515; /* r15 */ + *pstk-- = (INT32U)0x14141414; /* r14 */ + *pstk-- = (INT32U)_SDA_BASE_; /* r13 */ + *pstk-- = (INT32U)0x12121212; /* r12 */ + *pstk-- = (INT32U)0x11111111; /* r11 */ + *pstk-- = (INT32U)0x10101010; /* r10 */ + *pstk-- = (INT32U)0x09090909; /* r09 */ + *pstk-- = (INT32U)0x08080808; /* r08 */ + *pstk-- = (INT32U)0x07070707; /* r07 */ + *pstk-- = (INT32U)0x06060606; /* r06 */ + *pstk-- = (INT32U)0x05050505; /* r05 */ + *pstk-- = (INT32U)0x04040404; /* r04 */ + *pstk-- = (INT32U)p_arg; /* r03 */ + *pstk-- = (INT32U)_SDA2_BASE_; /* r02 */ + *pstk-- = (INT32U)0x00000000; /* r00 */ + *pstk-- = (INT32U)0x00000000; /* Indicates how the task's context should be restored */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Condition Register */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Fixed-Point Exception Register */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Count Register */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Link Register */ + *pstk-- = (INT32U)task; /* Return address */ + *pstk-- = (INT32U)0x00028000; /* Machine-State Register; interrupts are enabled */ + pstk--; + + return ((OS_STK *)pstk); /* Return new top of stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ + +#if OS_VIEW_MODULE > 0 + OSView_TaskSwHook(); +#endif + +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_VIEW_MODULE > 0 + OSView_TickHook(); +#endif +} +#endif diff --git a/Ports/PPC405/GNU/os_dbg.c b/Ports/PPC405/GNU/os_dbg.c new file mode 100644 index 0000000..abb433a --- /dev/null +++ b/Ports/PPC405/GNU/os_dbg.c @@ -0,0 +1,266 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PPC440/GNU/os_cpu.h b/Ports/PPC440/GNU/os_cpu.h new file mode 100644 index 0000000..dbca8b1 --- /dev/null +++ b/Ports/PPC440/GNU/os_cpu.h @@ -0,0 +1,101 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PowerPC440 +* GNU C/C++ Compiler +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; +typedef double FP64; + +typedef unsigned int OS_STK; /* Each stack entry is 32-bits wide */ +typedef unsigned int volatile OS_CPU_SR; /* The CPU Status Word is 32-bits wide. This variable */ + /* MUST be volatile for proper operation. Refer to */ + /* os_cpu_a.s for more details */ + +/* +********************************************************************************************************* +* CRITICAL SECTIONS MANAGEMENT +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#define OS_ENTER_CRITICAL() cpu_sr = OS_CPU_SR_Save(); +#define OS_EXIT_CRITICAL() OS_CPU_SR_Restore(cpu_sr); + + +/* +********************************************************************************************************* +* PowerPC440 +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PowerPC */ + +#define OS_TASK_SW() __asm__ __volatile__("sc\n") + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Save(void); /* See OS_CPU_A.S */ +void OS_CPU_SR_Restore(OS_CPU_SR); /* See OS_CPU_A.S */ + diff --git a/Ports/PPC440/GNU/os_cpu_a.S b/Ports/PPC440/GNU/os_cpu_a.S new file mode 100644 index 0000000..1400beb --- /dev/null +++ b/Ports/PPC440/GNU/os_cpu_a.S @@ -0,0 +1,1090 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PowerPC440 +* GNU C/C++ Compiler +* +* Filename : os_cpu_a.S +* Version : V2.93.00 +********************************************************************************************************* +*/ + + .file "os_cpu_a.S" + + .section ".vectors","ax" + +#define MACRO0(name) .macro name +#define MACRO1(name, param1) .macro name param1 +#define MACRO2(name, param1, param2) .macro name param1 param2 +#define CONCAT(left,right) left##right +#define PARAM(param) param + +/* +********************************************************************************************************* +* PUBLIC FUNCTIONS +********************************************************************************************************* +*/ + + .global OSStartHighRdy + .global OSIntCtxSw + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + + +/* +********************************************************************************************************* +* EXTERNAL FUNCTIONS +********************************************************************************************************* +*/ + + .extern OSIntEnter + .extern OSIntExit + .extern BSP_CriticalIntHandler + .extern BSP_NonCriticalIntHandler + .extern OSTaskSwHook + +/* +********************************************************************************************************* +* EXTERNAL VARIABLES +********************************************************************************************************* +*/ + + .extern OSRunning + .extern OSIntNesting + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSPrioCur + .extern OSPrioHighRdy + + +/* +********************************************************************************************************* +* CONSTANTS USED TO ACCESS TASK CONTEXT STACK +********************************************************************************************************* +*/ + + .set STK_OFFSET_BC, 0 + .set STK_OFFSET_NEW_LR, STK_OFFSET_BC + 4 + .set STK_OFFSET_MSR, STK_OFFSET_NEW_LR + 4 + .set STK_OFFSET_PC, STK_OFFSET_MSR + 4 + .set STK_OFFSET_LR, STK_OFFSET_PC + 4 + .set STK_OFFSET_CTR, STK_OFFSET_LR + 4 + .set STK_OFFSET_XER, STK_OFFSET_CTR + 4 + .set STK_OFFSET_CR, STK_OFFSET_XER + 4 + .set STK_OFFSET_USPRG0, STK_OFFSET_CR + 4 + .set STK_OFFSET_R0, STK_OFFSET_USPRG0 + 4 + .set STK_OFFSET_R2R31, STK_OFFSET_R0 + 4 + .set STK_CTX_SIZE, STK_OFFSET_R2R31 + ( ( 31 - 2 ) + 1 ) * 4 + .set SIXTEEN_BYTES, 16 + .set IVOR0_VAL , 0 + .set IVOR1_VAL, IVOR0_VAL + SIXTEEN_BYTES + .set IVOR2_VAL, IVOR1_VAL + SIXTEEN_BYTES + .set IVOR3_VAL, IVOR2_VAL + SIXTEEN_BYTES + .set IVOR4_VAL, IVOR3_VAL + SIXTEEN_BYTES + .set IVOR5_VAL, IVOR4_VAL + SIXTEEN_BYTES + .set IVOR6_VAL, IVOR5_VAL + SIXTEEN_BYTES + .set IVOR7_VAL, IVOR6_VAL + SIXTEEN_BYTES + .set IVOR8_VAL, IVOR7_VAL + SIXTEEN_BYTES + .set IVOR9_VAL, IVOR8_VAL + SIXTEEN_BYTES + .set IVOR10_VAL, IVOR9_VAL + SIXTEEN_BYTES + .set IVOR11_VAL, IVOR10_VAL + SIXTEEN_BYTES + .set IVOR12_VAL, IVOR11_VAL + SIXTEEN_BYTES + .set IVOR13_VAL, IVOR12_VAL + SIXTEEN_BYTES + .set IVOR14_VAL, IVOR13_VAL + SIXTEEN_BYTES + .set IVOR15_VAL, IVOR14_VAL + SIXTEEN_BYTES + +/* +********************************************************************************************************* +* OS_CPU_ISR_CRITICAL +* +* Description: This macro is placed at offset 0x0400 in the interrupt-handler table, so it is executed +* whenever critical interrupts are enabled and the external critical interrupt signal is +* asserted. The macro's code saves the current task's context before calling +* BSP_CriticalIntHandler(), which provides further, application-specific processing of the +* interrupt. +* +* Critical interrupts are disabled while this routine executes. However, critical interupts +* are not disabled when non-critical interrupts occur. Therefore, this routine checks the +* return address saved in CSSR0 to determine if one of the non-critical ISRs residing in the +* interrupt-handler table was interrupted. If the return address indeed corresponds to one +* of these ISRs, OSIntNesting is not manipulated and the scheduler is not invoked. These +* precautions are necessary when a non-critical ISR is interrupted because the interrupt +* may have occurred before that ISR incremented OSIntNesting, which could result in the +* ensuing critical ISR prematurely invoking the scheduler. Whether or not a non-critical +* ISR was interrupted, though, context is saved and the interrupt is serviced by +* BSP_CriticalIntHandler(). +* +* The interrupted task's context is saved onto its stack as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \ / +* V +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OS_CPU_ISR_CRITICAL) + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu 1,-STK_CTX_SIZE(1) /* Adjust the stack pointer */ + + stw 0, STK_OFFSET_R0(1) /* Save General-Purpose Register 0 */ + + stmw 2, STK_OFFSET_R2R31(1) /* Save General-Purpose Registers 2-31 */ + + mflr 0 + stw 0, STK_OFFSET_LR(1) /* Save the Link Register */ + + mfctr 0 + stw 0, STK_OFFSET_CTR(1) /* Save the Count Register */ + + mfxer 0 + stw 0, STK_OFFSET_XER(1) /* Save the Fixed-Point Exception Register */ + + mfcr 0 + stw 0, STK_OFFSET_CR(1) /* Save the Condition Register */ + + mfspr 0, 0x100 + stw 0, STK_OFFSET_USPRG0(1) /* Save User SPR General-Purpose Register 0 */ + + mfcsrr1 0 + stw 0, STK_OFFSET_MSR(1) /* Save the Machine-State Register */ + + mfcsrr0 0 + stw 0, STK_OFFSET_PC(1) /* Save the return address */ + + /* See if a non-critical ISR was interrupted */ + mfevpr 4 + subf 5, 4, 0 /* Subtract the EVPR from the return address */ + cmpli 1, 0, 5, DEBUG_ISR@l /* Compare the result to the last offset */ + lis 0, BSP_CriticalIntHandler@h /* Load the address of BSP_CriticalIntHandler */ + ori 0, 0, BSP_CriticalIntHandler@l + mtlr 0 + bc 0x05, 0x04, CRITICAL_CHECK_NESTING /* Branch if the return address is not in... */ + /* ...the interrupt-handler table */ + blrl + b CRITICAL_RESTORE_CTX + + +CRITICAL_CHECK_NESTING: + + lis 4, OSIntNesting@h /* See if OSIntNesting == 0 */ + ori 4, 4, OSIntNesting@l + lwz 5, 0(4) + addic. 5, 5, 0 + bc 0x04, 0x02, CRITICAL_INC_NESTING + + lis 6, OSTCBCur@h /* Save the current task's stack pointer */ + ori 6, 6, OSTCBCur@l + lwz 7, 0(6) + stw 1, 0(7) + +CRITICAL_INC_NESTING: + + addi 5, 5, 1 /* Increment OSIntNesting */ + stb 5, 0(4) + + blrl /* Call the interrupt controller's handler */ + + lis 0, OSIntExit@h /* Call OSIntExit() */ + ori 0, 0, OSIntExit@l + mtlr 0 + blrl + + /* *** RESTORE INTERRUPTED TASK'S CONTEXT **** */ +CRITICAL_RESTORE_CTX: + lwz 0, STK_OFFSET_MSR(1) /* Restore the Machine-State Register to CSRR1 */ + mtcsrr1 0 + + lwz 0, STK_OFFSET_PC(1) /* Restore the Machine-State Register to CSRR0 */ + mtcsrr0 0 + + lwz 0, STK_OFFSET_USPRG0(1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, 0 + + lwz 0, STK_OFFSET_CR(1) /* Restore the Condition Register */ + mtcr 0 + + lwz 0, STK_OFFSET_XER(1) /* Restore the Fixed-Point Exception Register */ + mtxer 0 + + lwz 0, STK_OFFSET_CTR(1) /* Restore the Count Register */ + mtctr 0 + + lwz 0, STK_OFFSET_LR(1) /* Restore the Link Register */ + mtlr 0 + + lmw 2, STK_OFFSET_R2R31(1) /* Restore General-Purpose Registers 2-31 */ + + lwz 0, STK_OFFSET_R0(1) /* Restore General-Purpose Register 0 */ + + addi 1, 1,STK_CTX_SIZE /* Adjust the stack pointer */ + + rfci /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OS_CPU_ISR_NON_CRITICAL +* +* Description: This macro is placed at offset 0x0300 in the interrupt-handler table, so it is executed +* whenever the external non-critical interrupt signal is asserted. This code saves the +* current task's context before calling BSP_NonCriticalIntHandler(), which provides further, +* application-specific processing of the interrupt. +* +* The interrupted task's context is saved onto its stack as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \ / +* V +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OS_CPU_ISR_NON_CRITICAL) + + + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu 1, -STK_CTX_SIZE(1) /* Adjust the stack pointer */ + + stw 0, STK_OFFSET_R0(1) /* Save General-Purpose Register 0 */ + + stmw 2, STK_OFFSET_R2R31(1) /* Save General-Purpose Registers 2-31 */ + + mflr 0 + stw 0, STK_OFFSET_LR(1) /* Save the Link Register */ + + mfctr 0 + stw 0, STK_OFFSET_CTR(1) /* Save the Count Register */ + + mfxer 0 + stw 0, STK_OFFSET_XER(1) /* Save the Fixed-Point Exception Register */ + + mfcr 0 + stw 0, STK_OFFSET_CR(1) /* Save the Condition Register */ + + mfspr 0, 0x100 + stw 0, STK_OFFSET_USPRG0(1) /* Save User SPR General-Purpose Register 0 */ + + mfsrr1 0 + stw 0, STK_OFFSET_MSR(1) /* Save the Machine-State Register */ + + mfsrr0 0 + stw 0, STK_OFFSET_PC(1) /* Save the return address */ + + lis 4, OSIntNesting@h /* See if OSIntNesting == 0 */ + ori 4, 4, OSIntNesting@l + lwz 5, 0(4) + addic. 5, 5, 0 + bc 0x04, 0x02, NON_CRITICAL_INC_NESTING + + lis 6, OSTCBCur@h /* Save the current task's stack pointer */ + ori 6, 6, OSTCBCur@l + lwz 7, 0(6) + stw 1, 0(7) + +NON_CRITICAL_INC_NESTING: + + addi 5, 5, 1 /* Increment OSIntNesting */ + stb 5, 0(4) + + lis 0, BSP_NonCriticalIntHandler@h /* Call the interrupt controller's handler */ + ori 0, 0, BSP_NonCriticalIntHandler@l + mtlr 0 + blrl + + lis 0, OSIntExit@h /* Call OSIntExit() */ + ori 0, 0, OSIntExit@l + mtlr 0 + blrl + + /* *** RESTORE INTERRUPTED TASK'S CONTEXT **** */ + + lwz 0, STK_OFFSET_MSR(1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 0 + + lwz 0, STK_OFFSET_PC(1) /* Restore the return address to SRR0 */ + mtsrr0 0 + + lwz 0, STK_OFFSET_USPRG0(1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, 0 + + lwz 0, STK_OFFSET_CR(1) /* Restore the Condition Register */ + mtcr 0 + + lwz 0, STK_OFFSET_XER(1) /* Restore the Fixed-Point Exception Register */ + mtxer 0 + + lwz 0, STK_OFFSET_CTR(1) /* Restore the Count Register */ + mtctr 0 + + lwz 0, STK_OFFSET_LR(1) /* Restore the Link Register */ + mtlr 0 + + lmw 2, STK_OFFSET_R2R31(1) /* Restore General-Purpose Registers 2-31 */ + + lwz 0, STK_OFFSET_R0(1) /* Restore General-Purpose Register 0 */ + + addi 1, 1, STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OSCtxSw +* +* Description: Performs a Context switch from a task. This function is ALWAYS called with interrupts +* DISABLED. +* +* OSCtxSw() implements the following pseudo-code: +* +* Save CPU registers; +* OSTCBCur->OSTCBStkPtr = SP; +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* Restore CPU registers +* Execute the return-from-interrupt instruction; +* +* +* The stack frame of the task to suspend will look as follows when OSCtxSw() is done: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \ / +* V +* + 0x9C GPR31 (HIGH MEMORY) +* +* The stack frame of the task to resume looks as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register 0 +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \ / +* V +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OSCtxSw) + + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu 1,-STK_CTX_SIZE(1) /* Adjust the stack pointer */ + + stw 0, STK_OFFSET_R0(1) /* Save General-Purpose Register 0 */ + + stmw 2, STK_OFFSET_R2R31(1) /* Save General-Purpose Registers 2-31 */ + + mflr 0 + stw 0, STK_OFFSET_LR(1) /* Save the Link Register */ + + mfctr 0 + stw 0, STK_OFFSET_CTR(1) /* Save the Count Register */ + + mfxer 0 + stw 0, STK_OFFSET_XER(1) /* Save the Fixed-Point Exception Register */ + + mfcr 0 + stw 0, STK_OFFSET_CR(1) /* Save the Condition Register */ + + mfspr 0, 0x100 + stw 0, STK_OFFSET_USPRG0(1) /* Save User SPR General-Purpose Register 0 */ + + mfsrr1 0 + stw 0, STK_OFFSET_MSR(1) /* Save the Machine-State Register */ + + mfsrr0 0 + stw 0, STK_OFFSET_PC(1) /* Save the return address */ + + lis 4, OSTCBCur@h /* Save the current task's stack pointer */ + ori 4, 4, OSTCBCur@l + lwz 5, 0(4) + stw 1, 0(5) + + lis 0, OSTaskSwHook@h /* Call OSTaskSwHook() */ + ori 0, 0, OSTaskSwHook@l + mtlr 0 + blrl + + lis 4, OSPrioHighRdy@h /* Update the current priority */ + ori 4, 4, OSPrioHighRdy@l + lbz 5, 0(4) + lis 6, OSPrioCur@h + ori 6, 6, OSPrioCur@l + stb 5, 0(6) + + lis 4, OSTCBHighRdy@h /* Update the current TCB */ + ori 4, 4, OSTCBHighRdy@l + lwz 5, 0(4) + lis 6, OSTCBCur@h + ori 6, 6, OSTCBCur@l + stw 5, 0(6) + + lwz 1, 0(5) /* Load the new task's stack pointer */ + + /* ******** RESTORE NEW TASK'S CONTEXT ******* */ + + lwz 0, STK_OFFSET_MSR(1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 0 + + lwz 0, STK_OFFSET_PC(1) /* Restore the return address to SRR0 */ + mtsrr0 0 + + lwz 0, STK_OFFSET_USPRG0(1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, 0 + + lwz 0, STK_OFFSET_CR(1) /* Restore the Condition Register */ + mtcr 0 + + lwz 0, STK_OFFSET_XER(1) /* Restore the Fixed-Point Exception Register */ + mtxer 0 + + lwz 0, STK_OFFSET_CTR(1) /* Restore the Count Register */ + mtctr 0 + + lwz 0, STK_OFFSET_LR(1) /* Restore the Link Register */ + mtlr 0 + + lmw 2, STK_OFFSET_R2R31(1) /* Restore General-Purpose Registers 2-31 */ + + lwz 0, STK_OFFSET_R0(1) /* Restore General-Purpose Register 0 */ + + addi 1, 1, STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OSTickISR +* +* Description: This macro is used to process uC/OS-II tick interrupts, which are produced by the +* CPU's Decrementer. This code saves the current task's context before calling +* OSTimeTick(), uC/OS-II's CPU-independent routine for processing these interrupts. +* +* The interrupted task's context is saved onto its stack as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 User SPR General-Purpose Register +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \ / +* V +* + 0x9C GPR31 (HIGH MEMORY) +* +********************************************************************************************************* +*/ + + MACRO0(OSTickISR) + + /* ******* SAVE CURRENT TASK'S CONTEXT ******* */ + stwu 1, -STK_CTX_SIZE(1) /* Adjust the stack pointer */ + + stw 0, STK_OFFSET_R0(1) /* Save General-Purpose Register 0 */ + + stmw 2, STK_OFFSET_R2R31(1) /* Save General-Purpose Registers 2-31 */ + + mflr 0 + stw 0, STK_OFFSET_LR(1) /* Save the Link Register */ + + mfctr 0 + stw 0, STK_OFFSET_CTR(1) /* Save the Count Register */ + + mfxer 0 + stw 0, STK_OFFSET_XER(1) /* Save the Fixed-Point Exception Register */ + + mfcr 0 + stw 0, STK_OFFSET_CR(1) /* Save the Condition Register */ + + mfspr 0, 0x100 + stw 0, STK_OFFSET_USPRG0(1) /* Save User SPR General-Purpose Register 0 */ + + mfsrr1 0 + stw 0, STK_OFFSET_MSR(1) /* Save the Machine-State Register */ + + mfsrr0 0 + stw 0, STK_OFFSET_PC(1) /* Save the return address */ + + lis 4, OSIntNesting@h /* See if OSIntNesting == 0 */ + ori 4, 4, OSIntNesting@l + lbz 5, 0(4) + addic. 5, 5, 0 + bc 0x04, 0x02, TICK_INC_NESTING + + lis 6, OSTCBCur@h /* Save the current task's stack pointer */ + ori 6, 6, OSTCBCur@l + lwz 7, 0(6) + stw 1, 0(7) + +TICK_INC_NESTING: + + addi 5, 5, 1 /* Increment OSIntNesting */ + stb 5, 0(4) + + lis 0, 0x0800 /* Clear the Decrementer interrupt */ + mttsr 0 + + lis 0, OSTimeTick@h /* Call OSTimeTick() */ + ori 0, 0, OSTimeTick@l + mtlr 0 + blrl + + lis 0, OSIntExit@h /* Call OSIntExit() */ + ori 0, 0, OSIntExit@l + mtlr 0 + blrl + + /* **** RESTORE INTERRUPTED TASK'S CONTEXT *** */ + + lwz 0, STK_OFFSET_MSR(1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 0 + + lwz 0, STK_OFFSET_PC(1) /* Restore the return address to SRR0 */ + mtsrr0 0 + + lwz 0, STK_OFFSET_USPRG0(1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, 0 + + lwz 0, STK_OFFSET_CR(1) /* Restore the Condition Register */ + mtcr 0 + + lwz 0, STK_OFFSET_XER(1) /* Restore the Fixed-Point Exception Register */ + mtxer 0 + + lwz 0, STK_OFFSET_CTR(1) /* Restore the Count Register */ + mtctr 0 + + lwz 0, STK_OFFSET_LR(1) /* Restore the Link Register */ + mtlr 0 + + lmw 2, STK_OFFSET_R2R31(1) /* Restore General-Purpose Registers 2-31 */ + + lwz 0, STK_OFFSET_R0(1) /* Restore General-Purpose Register 0 */ + + addi 1, 1, STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + + .endm + +/* +********************************************************************************************************* +* OS_NULL_NON_CRITICAL +* +* Description : This exception handler simply returns to the interrupted code. +********************************************************************************************************* +*/ + + MACRO0(OS_NULL_NON_CRITICAL) + + rfi + + .endm + +/* +********************************************************************************************************* +* OS_NULL_CRITICAL +* +* Description : This exception handler simply returns to the interrupted code. +********************************************************************************************************* +*/ + + MACRO0(OS_NULL_CRITICAL) + + rfci + + .endm + +/* +********************************************************************************************************* +* PowerPC440 Interrupt-Handler Table +* +* This is the interrupt-handler table used by the PowerPC 440 to appropriately invoke handlers for various +* types of interrupts. The entry points listed below are set accordingly to the IOVRs registers which are +* initialized in OSStartHighRdy routine. +* +* +* All table entries that are not currently used by uC/OS-II contain null routines that simply return +* from the interrupt without performing any actions. These routines can be replaced if an application +* requires support for additional types of exceptions. +********************************************************************************************************* +*/ +.globl _vectorbase +.align 4 /* 16 bytes alignment to ensure the IVORs are aligned correctly */ + +_vectorbase: + +.org _vectorbase + IVOR0_VAL /* "Vector 0x00", Critical interrupt. */ + IVOR0: b CRITICAL + +.org _vectorbase + IVOR1_VAL /* "Vector 0x10", Machine Check interrupt. */ + IVOR1: b NULL_CRITICAL + + +.org _vectorbase + IVOR2_VAL /* "Vector 0x20", Data Storage interrupt. */ + IVOR2: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR3_VAL /* "Vector 0x30", Instruct. Storage interrupt. */ + IVOR3: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR4_VAL /* "Vector 0x40", External interrupt. */ + IVOR4: b NONCRITICAL + + +.org _vectorbase + IVOR5_VAL /* "Vector 0x50", Alignment interrupt. */ + IVOR5: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR6_VAL /* "Vector 0x60", Program interrupt. */ + IVOR6: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR7_VAL /* " Vector 0x70", FPU Unavailable interrupt. */ + IVOR7: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR8_VAL /* "Vector 0x80", System Call interrupt. */ + IVOR8: b SYSTEM_CALL_ISR + + +.org _vectorbase + IVOR9_VAL /* "Vector 0x90", APU Available interrupt. */ + IVOR9: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR10_VAL /* "Vector 0xA0", Decrementer interrupt. */ + IVOR10: b DEC_ISR + + +.org _vectorbase + IVOR11_VAL /* "Vector 0xB0", FIT interrupt. */ + IVOR11: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR12_VAL /* "Vector 0xC0", Watchdog Timer interrupt. */ + IVOR12: b NULL_CRITICAL + + +.org _vectorbase + IVOR13_VAL /* "Vector 0xD0", Data TLB Miss interrupt. */ + IVOR13: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR14_VAL /* "Vector 0xE0", Instruct. TLB Miss interr. */ + IVOR14: b NULL_NONCRITICAL + + +.org _vectorbase + IVOR15_VAL /* "Vector 0xF0", Debug interrupt. */ + IVOR15: b NULL_CRITICAL + + +.org _vectorbase + 0x0300 +NONCRITICAL: OS_CPU_ISR_NON_CRITICAL + +.org _vectorbase + 0x0400 +CRITICAL: OS_CPU_ISR_CRITICAL + +.org _vectorbase + 0x0500 +MACHINE: OS_NULL_CRITICAL + +.org _vectorbase + 0x0600 +SYSTEM_CALL_ISR: OSCtxSw + +.org _vectorbase + 0x0700 +DEC_ISR: OSTickISR + +.org _vectorbase + 0x0800 +NULL_NONCRITICAL: OS_NULL_NON_CRITICAL + +.org _vectorbase + 0x0900 +NULL_CRITICAL: OS_NULL_CRITICAL + +.org _vectorbase + 0x0a00 +DEBUG_ISR: OS_NULL_CRITICAL + + + .section ".text" + +/* +********************************************************************************************************* +* OSIntCtxSw() +* +* Description: Performs the Context Switch from an ISR. +* +* OSIntCtxSw() implements the following pseudo-code: +* +* OSTaskSwHook(); +* OSPrioCur = OSPrioHighRdy; +* OSTCBCur = OSTCBHighRdy; +* SP = OSTCBHighRdy->OSTCBStkPtr; +* if (Context saved by Critical ISR) { +* Restore MSR and PC to CSRR1 and CSRR0, respectively; +* Restore all other registers; +* Execute the return-from-critical-interrupt instruction; +* } else { +* Restore MSR and PC to SRR1 and SRR0, respectively; +* Restore all other registers; +* Execute the return-from-interrupt instruction; +* } +* +* Upon entry, the registers of the task being suspended have already been saved onto that +* task's stack and the SP for the task has been saved in its OS_TCB by the ISR. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 Interrupt type +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \ / +* V +* + 0x9C GPR31 (HIGH MEMORY) +* +* Note(s) : 1) If the task frame was saved by a critical ISR, the stack entry at offset 0x20 will be +* set to 1. +* If the task frame was saved by a non-critical ISR, the stack entry at offset 0x20 will +* be set to 0. +********************************************************************************************************* +*/ + +OSIntCtxSw: + + lis 0, OSTaskSwHook@h /* Call OSTaskSwHook() */ + ori 0, 0, OSTaskSwHook@l + mtlr 0 + blrl + + lis 4, OSPrioHighRdy@h /* Update the current priority */ + ori 4, 4, OSPrioHighRdy@l + lbz 5, 0(4) + lis 6, OSPrioCur@h + ori 6, 6, OSPrioCur@l + stb 5, 0(6) + + lis 4, OSTCBHighRdy@h /* Update the current TCB */ + ori 4, 4, OSTCBHighRdy@l + lwz 5, 0(4) + lis 6, OSTCBCur@h + ori 6, 6, OSTCBCur@l + stw 5, 0(6) + + lwz 1, 0(5) /* Load the new task's stack pointer */ + + /* ******** RESTORE NEW TASK'S CONTEXT ******* */ + + lwz 0, STK_OFFSET_MSR(1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 0 + + lwz 0, STK_OFFSET_PC(1) /* Restore the return address to SRR0 */ + mtsrr0 0 + + lwz 0, STK_OFFSET_USPRG0(1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, 0 + + lwz 0, STK_OFFSET_CR(1) /* Restore the Condition Register */ + mtcr 0 + + lwz 0, STK_OFFSET_XER(1) /* Restore the Fixed-Point Exception Register */ + mtxer 0 + + lwz 0, STK_OFFSET_CTR(1) /* Restore the Count Register */ + mtctr 0 + + lwz 0, STK_OFFSET_LR(1) /* Restore the Link Register */ + mtlr 0 + + lmw 2, STK_OFFSET_R2R31(1) /* Restore General-Purpose Registers 2-31 */ + + lwz 0, STK_OFFSET_R0(1) /* Restore General-Purpose Register 0 */ + + addi 1, 1, STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Return to the interrupted task */ + +/* +********************************************************************************************************* +* OSStartHighRdy() +* +* Description: Starts the highest priority task that is available to run. OSStartHighRdy() MUST: +* +* a) Call OSTaskSwHook() +* b) Set OSRunning to TRUE +* c) Switch to the highest priority task. +* +* The stack frame of the task to resume is assumed to look as follows: +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 Back chain (LOW Memory) +* + 0x04 New Link Register +* + 0x08 Machine-State Register +* + 0x0C Return Address +* + 0x10 Link Register +* + 0x14 Count Register +* + 0x18 Fixed-Point Exception Register +* + 0x1C Condition Register +* + 0x20 Interrupt type (initialized to 0x00000000) +* + 0x24 GPR0 +* + 0x28 GPR2 +* + 0x2C GPR3 +* + 0x30 GPR4 +* | +* | +* \ / +* V +* + 0x9C GPR31 (HIGH MEMORY) +* +* Note(s) : 1) The MSR entry in the stack is initialized so that interrupts will be enabled when the +* task begins to run. In order to allow the interrupts to be properly serviced, +* OSStartHighRdy() initializes IVPR and IOVRs registers. +********************************************************************************************************* +*/ + +OSStartHighRdy: + + lis 0, OSTaskSwHook@h /* Call OSTaskSwHook() */ + ori 0, 0, OSTaskSwHook@l + mtlr 0 + blrl + + li 0, 1 /* Indicate that the OS is running */ + lis 4, OSRunning@h + ori 4, 4, OSRunning@l + stb 0, 0(4) + + lis 4, OSTCBHighRdy@h /* Load the first task's stack pointer */ + ori 4, 4, OSTCBHighRdy@l + lwz 5, 0(4) + lwz 1, 0(5) + + lis 4, _vectorbase@h /* Initialize the IVPR register */ + ori 4, 4, _vectorbase@l + mtivpr 4 + + + /* Initialize the IVORs registers */ + mtivor0 4 + + addi 4, 4, IVOR1_VAL + mtivor1 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor2 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor3 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor4 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor5 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor6 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor7 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor8 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor9 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor10 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor11 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor12 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor13 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor14 4 + + addi 4, 4, SIXTEEN_BYTES + mtivor15 4 + + + lwz 0, STK_OFFSET_MSR(1) /* Restore the Machine-State Register to SRR1 */ + mtsrr1 0 + + lwz 0, STK_OFFSET_PC(1) /* Restore the return address to SRR0 */ + mtsrr0 0 + + lwz 0, STK_OFFSET_USPRG0(1) /* Restore User SPR General-Purpose Register 0 */ + mtspr 0x100, 0 + + lwz 0, STK_OFFSET_CR(1) /* Restore the Condition Register */ + mtcr 0 + + lwz 0, STK_OFFSET_XER(1) /* Restore the Fixed-Point Exception Register */ + mtxer 0 + + lwz 0, STK_OFFSET_CTR(1) /* Restore the Count Register */ + mtctr 0 + + lwz 0, STK_OFFSET_LR(1) /* Restore the Link Register */ + mtlr 0 + + lmw 2, STK_OFFSET_R2R31(1) /* Restore General-Purpose Registers 2-31 */ + + lwz 0, STK_OFFSET_R0(1) /* Restore General-Purpose Register 0 */ + + addi 1, 1, STK_CTX_SIZE /* Adjust the stack pointer */ + + rfi /* Start the task */ + +/* +********************************************************************************************************* +* DISABLE INTERRUPTS +* OS_CPU_SR OS_CPU_SR_Save(void); +* +* Description : Sets the MSR, disabling interrupts, and returns the previous MSR contents. This allows +* the machine state to be restored at a subsequent time. +* +* Arguments : None +* +* Returns : Current MSR contents in GPR3 +* +* Note(s) : 1) The variable in the calling routine that will hold the return value MUST be declared +* volatile for proper operation. There is no guarantee that the proper register will +* be scheduled for the subsequent 'OS_CPU_SR_Save()' function call if the variable is +* not declared volatile. +********************************************************************************************************* +*/ + +OS_CPU_SR_Save: + + addis 4, 0, 0xFFFD + ori 4, 4, 0x7FFF + mfmsr 3 + and 4, 4, 3 /* Clear bits 14 and 16, corresponding to... */ + mtmsr 4 /* ...critical and non-critical interrupts */ + blr + +/* +********************************************************************************************************* +* ENABLE INTERRUPTS +* void OS_CPU_SR_Restore(OS_CPU_SR sr); +* +* Description : Sets the MSR, possibly enabling interrupts, using the value passed in GPR3. +* +* Arguments : Saved MSR contents in GPR3 +* +* Returns : None +* +* Note(s) : 1) The argument from the calling routine MUST be declared volatile for proper operation. +* There is no guarantee that the proper register will be scheduled for the call to +* OS_CPU_SR_Restore() if the variable is not declared 'volatile'. +********************************************************************************************************* +*/ + +OS_CPU_SR_Restore: + + mtmsr 3 /* Restore the saved MSR */ + blr + + + diff --git a/Ports/PPC440/GNU/os_cpu_c.c b/Ports/PPC440/GNU/os_cpu_c.c new file mode 100644 index 0000000..5ef4d19 --- /dev/null +++ b/Ports/PPC440/GNU/os_cpu_c.c @@ -0,0 +1,345 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* PowerPC440 +* GNU C/C++ Compiler +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +extern void *_SDA_BASE_; +extern void *_SDA2_BASE_; + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ + +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; +#endif + +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* OSTCBHighRdy->OSTCBStkPtr + 0x00 RMSR (IE=1) (LOW Memory) +* + 0x04 R2 +* + 0x08 R3 +* + 0x0C R4 +* + 0x10 R5 (p_arg passed to task) +* + 0x14 R6 +* + 0x18 R7 +* + 0x1C R8 +* + 0x20 R9 +* + 0x24 R10 +* + 0x28 R11 +* + 0x2C R12 +* + 0x30 R13 +* + 0x34 R14 +* + 0x38 R15 +* + 0x3C R17 +* + 0x40 R18 +* + 0x44 R19 +* + 0x48 R20 +* + 0x4C R21 +* + 0x50 R22 +* + 0x54 R23 +* + 0x58 R24 +* + 0x5C R25 +* + 0x60 R26 +* + 0x64 R27 +* + 0x68 R28 +* + 0x6C R29 +* + 0x70 R30 +* + 0x74 R31 (HIGH Memory) +* + 0x78 Empty +* ptos ---------> + 0x7C Empty +* +* 2) R16 is not saved as part of the task context since it is used by the debugger. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk; + INT32U msr; + + + /* Obtain the current value of the MSR */ + __asm__ __volatile__("mfmsr %0\n" : "=r" (msr)); + /* Interrupts will be enabled when the task is started */ + msr |= 0x00028000; + + opt = opt; /* 'opt' is not used, prevent warning */ + pstk = (INT32U *)ptos; /* Load stack pointer */ + pstk--; /* Make sure we point to free entry ... */ + pstk--; /* ... compiler uses top-of-stack so free an extra one. */ + *pstk-- = (INT32U)0x31313131; /* r31 */ + *pstk-- = (INT32U)0x30303030; /* r30 */ + *pstk-- = (INT32U)0x29292929; /* r29 */ + *pstk-- = (INT32U)0x28282828; /* r28 */ + *pstk-- = (INT32U)0x27272727; /* r27 */ + *pstk-- = (INT32U)0x26262626; /* r26 */ + *pstk-- = (INT32U)0x25252525; /* r25 */ + *pstk-- = (INT32U)0x24242424; /* r24 */ + *pstk-- = (INT32U)0x23232323; /* r23 */ + *pstk-- = (INT32U)0x22222222; /* r22 */ + *pstk-- = (INT32U)0x21212121; /* r21 */ + *pstk-- = (INT32U)0x20202020; /* r20 */ + *pstk-- = (INT32U)0x19191919; /* r19 */ + *pstk-- = (INT32U)0x18181818; /* r18 */ + *pstk-- = (INT32U)0x17171717; /* r17 */ + *pstk-- = (INT32U)0x16161616; /* r16 */ + *pstk-- = (INT32U)0x15151515; /* r15 */ + *pstk-- = (INT32U)0x14141414; /* r14 */ + *pstk-- = (INT32U)_SDA_BASE_; /* r13 */ + *pstk-- = (INT32U)0x12121212; /* r12 */ + *pstk-- = (INT32U)0x11111111; /* r11 */ + *pstk-- = (INT32U)0x10101010; /* r10 */ + *pstk-- = (INT32U)0x09090909; /* r09 */ + *pstk-- = (INT32U)0x08080808; /* r08 */ + *pstk-- = (INT32U)0x07070707; /* r07 */ + *pstk-- = (INT32U)0x06060606; /* r06 */ + *pstk-- = (INT32U)0x05050505; /* r05 */ + *pstk-- = (INT32U)0x04040404; /* r04 */ + *pstk-- = (INT32U)p_arg; /* r03 */ + *pstk-- = (INT32U)_SDA2_BASE_; /* r02 */ + *pstk-- = (INT32U)0x00000000; /* r00 */ + *pstk-- = (INT32U)0x0F0F0F0F; /* User SPR General-Purpose Register 0 */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Condition Register */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Fixed-Point Exception Register */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Count Register */ + *pstk-- = (INT32U)0x0F0F0F0F; /* Link Register */ + *pstk-- = (INT32U)task; /* Return address */ + *pstk-- = msr; /* Machine-State Register; interrupts are enabled */ + pstk--; + + return ((OS_STK *)pstk); /* Return new top of stack */ +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif + +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0 + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PPC440/GNU/os_dbg.c b/Ports/PPC440/GNU/os_dbg.c new file mode 100644 index 0000000..b95232b --- /dev/null +++ b/Ports/PPC440/GNU/os_dbg.c @@ -0,0 +1,315 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +#define OS_COMPILER_OPT __root + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0u; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0u; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0u; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0u; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0u; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0u; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +OS_COMPILER_OPT INT16U const OSTmrEn = OS_TMR_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +OS_COMPILER_OPT INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +OS_COMPILER_OPT INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +OS_COMPILER_OPT INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +OS_COMPILER_OPT INT16U const OSTmrSize = sizeof(OS_TMR); +OS_COMPILER_OPT INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +OS_COMPILER_OPT INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +OS_COMPILER_OPT INT16U const OSTmrSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrTblSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelSize = 0u; +OS_COMPILER_OPT INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0u) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTbl) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu.h b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..5b9b3a3 --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu.h @@ -0,0 +1,129 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef __OS_CPU_H__ /* test for multiple inclusion */ +#define __OS_CPU_H__ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_STK_RSVD_SIZE 10 /* EABI Buffer above the stack */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PPC */ + + +/* +********************************************************************************************************* +* FLOATING POINT +* +* Note: also enable or disable "OS_SAVE_CONTEXT_WITH_FPRS .equ 1" in os_cpu_a.h +********************************************************************************************************* +*/ + +#define OS_SAVE_CONTEXT_WITH_FPRS + + +/* +********************************************************************************************************* +* OS Task Swicth +********************************************************************************************************* +*/ + +#if defined __GNUC__ +#define OS_TASK_SW() asm __volatile__ (" se_sc "); +#elif defined __MWERKS__ +#define OS_TASK_SW() asm (" se_sc "); +#else +#error Unknown Compiler Assembler Syntax +#endif + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************* +* Function Prototypes +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +void OSTickISR(void); +void OSExtIntISR(void); + + +#endif /* __OS_CPU_H__ */ diff --git a/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.inc b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.inc new file mode 100644 index 0000000..186d0f9 --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.inc @@ -0,0 +1,335 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ OS_SAVE_CONTEXT_WITH_FPRS, 1 # set to 1 for floating point support; also set in os_cpu.h + + .equ USPRG0, 256 + .equ TCR, 340 + .equ TSR, 336 + .equ SPEFSCR, 512 + .equ HID0, 1008 + .equ L1CSR0, 1010 + + + +#********************************************************************************************************* +#* STACK FRAME DEFINITION +#********************************************************************************************************* + + .equ XR1 ,0 + .equ XBLK ,XR1+4 + + .if OS_SAVE_CONTEXT_WITH_FPRS + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+8 + .equ XR4 ,XR3+8 + .equ XR5 ,XR4+8 + .equ XR6 ,XR5+8 + .equ XR7 ,XR6+8 + .equ XR8 ,XR7+8 + .equ XR9 ,XR8+8 + .equ XR10 ,XR9+8 + .equ XR11 ,XR10+8 + .equ XR12 ,XR11+8 + .equ XR13 ,XR12+8 + .equ XR14 ,XR13+8 + .equ XR15 ,XR14+8 + .equ XR16 ,XR15+8 + .equ XR17 ,XR16+8 + .equ XR18 ,XR17+8 + .equ XR19 ,XR18+8 + .equ XR20 ,XR19+8 + .equ XR21 ,XR20+8 + .equ XR22 ,XR21+8 + .equ XR23 ,XR22+8 + .equ XR24 ,XR23+8 + .equ XR25 ,XR24+8 + .equ XR26 ,XR25+8 + .equ XR27 ,XR26+8 + .equ XR28 ,XR27+8 + .equ XR29 ,XR28+8 + .equ XR30 ,XR29+8 + .equ XR31 ,XR30+8 + .equ XR0 ,XR31+8 + .else + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+4 + .equ XR4 ,XR3+4 + .equ XR5 ,XR4+4 + .equ XR6 ,XR5+4 + .equ XR7 ,XR6+4 + .equ XR8 ,XR7+4 + .equ XR9 ,XR8+4 + .equ XR10 ,XR9+4 + .equ XR11 ,XR10+4 + .equ XR12 ,XR11+4 + .equ XR13 ,XR12+4 + .equ XR14 ,XR13+4 + .equ XR15 ,XR14+4 + .equ XR16 ,XR15+4 + .equ XR17 ,XR16+4 + .equ XR18 ,XR17+4 + .equ XR19 ,XR18+4 + .equ XR20 ,XR19+4 + .equ XR21 ,XR20+4 + .equ XR22 ,XR21+4 + .equ XR23 ,XR22+4 + .equ XR24 ,XR23+4 + .equ XR25 ,XR24+4 + .equ XR26 ,XR25+4 + .equ XR27 ,XR26+4 + .equ XR28 ,XR27+4 + .equ XR29 ,XR28+4 + .equ XR30 ,XR29+4 + .equ XR31 ,XR30+4 + .equ XR0 ,XR31+4 + .endif + + + .equ XSRR0 ,XR0+4 + .equ XSRR1 ,XSRR0+4 + .equ XUSPRG ,XSRR1+4 + .equ XCTR ,XUSPRG+4 + .equ XXER ,XCTR+4 + .equ XCR ,XXER+4 + .equ XLR ,XCR+4 + .equ XSPEFSCR,XLR+4 + .equ XPAD2 ,XSPEFSCR+4 + .equ XPAD3 ,XPAD2+4 + .equ XMSR ,XPAD3+4 + + .equ STACK_FRAME_SIZE ,XMSR+4 + + + +#********************************************************************************************************* +#* PROLOGUE DEFINITION +#********************************************************************************************************* +prologue: .macro + e_add2i. r1, -STACK_FRAME_SIZE + e_stwu r1, 0(r1) + e_stw r0, XR0(r1) + + .if OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 # system call (sc) clears the SPE bit ... + e_or2is r0, 0x0200 # ... therefore set them first + e_or2i r0, 0x0000 + mtmsr r0 + isync + + evstdd r2, XR2(r1) # store GPR as 64bit Register + evstdd r3, XR3(r1) + evstdd r4, XR4(r1) + evstdd r5, XR5(r1) + evstdd r6, XR6(r1) + evstdd r7, XR7(r1) + evstdd r8, XR8(r1) + evstdd r9, XR9(r1) + evstdd r10, XR10(r1) + evstdd r11, XR11(r1) + evstdd r12, XR12(r1) + evstdd r13, XR13(r1) + evstdd r14, XR14(r1) + evstdd r15, XR15(r1) + evstdd r16, XR16(r1) + evstdd r17, XR17(r1) + evstdd r18, XR18(r1) + evstdd r19, XR19(r1) + evstdd r20, XR20(r1) + evstdd r21, XR21(r1) + evstdd r22, XR22(r1) + evstdd r23, XR23(r1) + evstdd r24, XR24(r1) + evstdd r25, XR25(r1) + evstdd r26, XR26(r1) + evstdd r27, XR27(r1) + evstdd r28, XR28(r1) + evstdd r29, XR29(r1) + evstdd r30, XR30(r1) + evstdd r31, XR31(r1) + .else + e_stw r2, XR2(r1) # store GPR as 32bit Register + e_stw r3, XR3(r1) + e_stw r4, XR4(r1) + e_stw r5, XR5(r1) + e_stw r6, XR6(r1) + e_stw r7, XR7(r1) + e_stw r8, XR8(r1) + e_stw r9, XR9(r1) + e_stw r10, XR10(r1) + e_stw r11, XR11(r1) + e_stw r12, XR12(r1) + e_stw r13, XR13(r1) + e_stw r14, XR14(r1) + e_stw r15, XR15(r1) + e_stw r16, XR16(r1) + e_stw r17, XR17(r1) + e_stw r18, XR18(r1) + e_stw r19, XR19(r1) + e_stw r20, XR20(r1) + e_stw r21, XR21(r1) + e_stw r22, XR22(r1) + e_stw r23, XR23(r1) + e_stw r24, XR24(r1) + e_stw r25, XR25(r1) + e_stw r26, XR26(r1) + e_stw r27, XR27(r1) + e_stw r28, XR28(r1) + e_stw r29, XR29(r1) + e_stw r30, XR30(r1) + e_stw r31, XR31(r1) + .endif + + mfmsr r0 + e_stw r0, XMSR(r1) + + mfspr r0, SPEFSCR + e_stw r0, XSPEFSCR(r1) + + mfspr r0, SRR0 + e_stw r0, XSRR0(r1) + + mfspr r0, SRR1 + e_stw r0, XSRR1(r1) + + mfspr r0, USPRG0 + e_stw r0, XUSPRG(r1) + + mflr r0 + e_stw r0, XLR(r1) + + mfctr r0 + e_stw r0, XCTR(r1) + + mfxer r0 + e_stw r0, XXER(r1) + + mfcr r0 + e_stw r0, XCR(r1) + + mfmsr r0 + .endm + + + +#********************************************************************************************************* +#* EPILOGUE DEFINITION +#********************************************************************************************************* +epilogue: .macro + wrteei 0 + + .if OS_SAVE_CONTEXT_WITH_FPRS + evldd r2, XR2(r1) # load GPR as 64bit Register + evldd r3, XR3(r1) + evldd r4, XR4(r1) + evldd r5, XR5(r1) + evldd r6, XR6(r1) + evldd r7, XR7(r1) + evldd r8, XR8(r1) + evldd r9, XR9(r1) + evldd r10, XR10(r1) + evldd r11, XR11(r1) + evldd r12, XR12(r1) + evldd r13, XR13(r1) + evldd r14, XR14(r1) + evldd r15, XR15(r1) + evldd r16, XR16(r1) + evldd r17, XR17(r1) + evldd r18, XR18(r1) + evldd r19, XR19(r1) + evldd r20, XR20(r1) + evldd r21, XR21(r1) + evldd r22, XR22(r1) + evldd r23, XR23(r1) + evldd r24, XR24(r1) + evldd r25, XR25(r1) + evldd r26, XR26(r1) + evldd r27, XR27(r1) + evldd r28, XR28(r1) + evldd r29, XR29(r1) + evldd r30, XR30(r1) + evldd r31, XR31(r1) + .else + e_lwz r2, XR2(r1) # load GPR as 32bit Register + e_lwz r3, XR3(r1) + e_lwz r4, XR4(r1) + e_lwz r5, XR5(r1) + e_lwz r6, XR6(r1) + e_lwz r7, XR7(r1) + e_lwz r8, XR8(r1) + e_lwz r9, XR9(r1) + e_lwz r10, XR10(r1) + e_lwz r11, XR11(r1) + e_lwz r12, XR12(r1) + e_lwz r13, XR13(r1) + e_lwz r14, XR14(r1) + e_lwz r15, XR15(r1) + e_lwz r16, XR16(r1) + e_lwz r17, XR17(r1) + e_lwz r18, XR18(r1) + e_lwz r19, XR19(r1) + e_lwz r20, XR20(r1) + e_lwz r21, XR21(r1) + e_lwz r22, XR22(r1) + e_lwz r23, XR23(r1) + e_lwz r24, XR24(r1) + e_lwz r25, XR25(r1) + e_lwz r26, XR26(r1) + e_lwz r27, XR27(r1) + e_lwz r28, XR28(r1) + e_lwz r29, XR29(r1) + e_lwz r30, XR30(r1) + e_lwz r31, XR31(r1) + .endif + + e_lwz r0, XCR(r1) + mtcrf 0xff,r0 + e_lwz r0, XXER(r1) + mtxer r0 + e_lwz r0, XCTR(r1) + mtctr r0 + e_lwz r0, XLR(r1) + mtlr r0 + + e_lwz r0, XSRR1(r1) + mtspr SRR1,r0 + e_lwz r0, XSRR0(r1) + mtspr SRR0,r0 + + e_lwz r0, XUSPRG(r1) + mtspr USPRG0,r0 + + e_lwz r0, XSPEFSCR(r1) + mtspr SPEFSCR,r0 + + e_lwz r0, XR0(r1) + e_add2i. r1, STACK_FRAME_SIZE + .endm + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT INCLUDE FILE END +#********************************************************************************************************* diff --git a/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.s b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.s new file mode 100644 index 0000000..7a49d0b --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_a.s @@ -0,0 +1,266 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# CodeWarrior Compiler +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* ASM HEADER +#********************************************************************************************************* + + .include "os_cpu_a.inc" + + .section .xcptn_vle, text_vle + + .extern BSP_TmrTickISR + + .extern OSTaskSwHook + .extern OSIntEnter + .extern OSIntExit + + .extern OSTCBCur # pointer to current tasks TCB + .extern OSTCBHighRdy # pointer to highest priority ready task + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSRunning + .extern OSIntNesting + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ INTC_IACKR, 0xfff48010 # Interrupt Acknowledge Register address + .equ INTC_EOIR, 0xfff48018 # End of Interrupt Register address + + +#********************************************************************************************************* +#* PUBLIC DECLARATIONS +#********************************************************************************************************* + + .global OSCtxSw + .global OSStartHighRdy + .global OSIntCtxSw + + .global OSTickISR + .global OSExtIntISR + + + +#********************************************************************************************************* +#* ISR HANDLER FOR SW VECTOR MODE +#* +#* Description : This function is executed when IVOR4 External input interrupt (SPR 404) exception occurs. +#********************************************************************************************************* + .align 16 +OSExtIntISR: + prologue # Save context + + e_lis r11,OSIntNesting@ha # load OSIntNesting + e_lbz r3, OSIntNesting@l(r11) + e_addi r0, r3, 1 + e_stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + e_cmpl16i r0, 1 # if (OSIntNesting != 1) ... + se_bne OSExtIntISR_NotSaveSP # do not save the stackpointer + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + +OSExtIntISR_NotSaveSP: + e_lis r3, INTC_IACKR@h # store address of INTC.IACKR in r3 + e_or2i r3, INTC_IACKR@l + e_lwz r3, 0(r3) # load contents of INTC.IACKR in r3 + e_lwz r12,0(r3) # load the base adress of Vector Table + + mtctr r12 # load Count register + se_bctrl # branch to ISR_Handler + + se_li r0, 0 # load r0 with 0x0000 + e_lis r3, INTC_EOIR@h # get the address of the INTC.EOIR Register ... + e_or2i r3, INTC_EOIR@l + e_stw r0, 0(r3) # and clear the INTC.EOIR register + + e_bl OSIntExit # call to decrement OSIntNesting + + epilogue # restore the context + + se_rfi # return from interrupt + + + +#********************************************************************************************************* +#* SYSTEM TICK ISR +#* +#* Description : This function is the ISR to notify uC/OS-II that a system tick has occurred. +#********************************************************************************************************* + .align 16 +OSTickISR: + prologue + + e_lis r11,OSIntNesting@ha # load OSIntNesting + e_lbz r3, OSIntNesting@l(r11) + e_addi r0, r3, 1 + e_stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + e_cmpl16i r0, 1 # if (OSIntNesting != 1) ... + se_bne OSTickISR_NotSaveSP # do not save the stackpointer + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + +OSTickISR_NotSaveSP: + e_lis r4, 0x0800 # load r4 with TSR[DIS] bit (0x08000000) + mtspr TSR,r4 # clear TSR[DIS] bit + + e_bl BSP_TmrTickISR # call TmrTick handler + e_bl OSIntExit # call to decrement OSIntNesting + + epilogue # Restore context + + se_rfi # run task + + + +#********************************************************************************************************* +#* START HIGHEST PRIORITY TASK READY-TO-RUN +#* +#* Description : This function is called by OSStart() to start the highest priority task that was created +#* by the application before calling OSStart(). +#* +#* Arguments : none +#* +#* Note(s) : 1) OSStartHighRdy() MUST: +#* a) Call OSTaskSwHook() then, +#* b) Set OSRunning to TRUE, +#* c) Switch to the highest priority task by loading the stack pointer of the highest +#* priority task into the SP register and execute an rfi instruction. +#********************************************************************************************************* + .align 16 +OSStartHighRdy: + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_li r0, 1 # Set OSRunning to 1 + e_lis r11,OSRunning@ha + e_stb r0, OSRunning@l(r11) + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + se_rfi # run task + + + +#********************************************************************************************************* +#* TASK LEVEL CONTEXT SWITCH +#* +#* Description : This function is called when a task makes a higher priority task ready-to-run. +#* +#* Arguments : none +#* +#* Note(s) : 1) Upon entry, +#* OSTCBCur points to the OS_TCB of the task to suspend +#* OSTCBHighRdy points to the OS_TCB of the task to resume +#********************************************************************************************************* + .align 16 +OSCtxSw: + prologue # Save context + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority + e_lbz r10,OSPrioHighRdy@l(r12) + + e_lis r12,OSPrioCur@ha # Save as Current Priority + e_stb r10,OSPrioCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer from TCB + + epilogue # Restore context + + se_rfi # run task + + + +#********************************************************************************************************* +#* INTERRUPT LEVEL CONTEXT SWITCH +#* +#* Description : This function is called by OSIntExit() to perform a context switch to a task that has +#* been made ready-to-run by an ISR. +#********************************************************************************************************* + .align 16 +OSIntCtxSw: + mbar 1 + + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority + e_lbz r10,OSPrioHighRdy@l(r12) + + e_lis r12,OSPrioCur@ha # Save as Current Priority + e_stb r10,OSPrioCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + mbar 1 + + se_rfi # run task + + + +#********************************************************************************************************* +#* RETURN FROM INTERRUPT TRAP +#********************************************************************************************************* + .align 16 +RFI_trap: + se_rfi + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT FILE END +#********************************************************************************************************* + .end diff --git a/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_c.c b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_c.c new file mode 100644 index 0000000..4e17b4a --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_cpu_c.c @@ -0,0 +1,453 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* GLOBALS +********************************************************************************************************* +*/ + +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The SRR1 Register holds the original value of the MSR register. This value is copied +* to the MSR register by execute the rfi operation at the end of the ISR. +* +* (2) Ensure any changes to the order of stack initialization is congruent with the Stack +* Frame definitions in OS_CPU_A.s. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stkp; /* Local: Stack pointer */ + OS_CPU_SR msr; /* Local: Initial MSR */ + OS_CPU_SR srr1; /* Local: Initial SRR1 */ + + + (void)opt; /* 'opt' is not used, prevent warning */ + + msr = CPU_SR_Rd(); /* get the MSB reg value */ + srr1 = msr | 0x8000; /* set MSR[EE] bit to enable interrupts */ + + stkp = (OS_STK *)((INT32U)ptos & 0xFFFFFFF0); /* 16-byte align task's stack pointer (EABI) */ + + /* Leave buffer area for locals "above the stack" in ... */ + stkp -= OS_STK_RSVD_SIZE; /* case the compiler prolog puts variables above the stack */ + + /* Stack Frame Initialization */ + *--stkp = (INT32U)msr; /* MSR */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* SPEFSCR */ + *--stkp = (INT32U)task; /* LR */ + *--stkp = 0; /* CR */ + *--stkp = 0; /* XER */ + *--stkp = 0; /* CTR */ + *--stkp = 0; /* USPRG0 */ + *--stkp = (INT32U)srr1; /* SRR1 */ + *--stkp = (INT32U)task; /* SRR0 */ + *--stkp = 0; /* R0 */ + + +#ifdef OS_SAVE_CONTEXT_WITH_FPRS /* Push 64-bit register's initial value to the stack */ + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x3100L; + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x3000L; + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x2900L; + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x2800L; + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x2700L; + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x2600L; + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x2500L; + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x2400L; + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x2300L; + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x2200L; + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x2100L; + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x2000L; + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x1900L; + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x1800L; + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x1700L; + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x1600L; + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x1500L; + *--stkp = 0x14L; /* r14 */ + *--stkp = 0x1400L; + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x0000L; + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x1200L; + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x1100L; + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x1000L; + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x9000L; + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x8000L; + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x7000L; + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x6000L; + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x5000L; + *--stkp = 0x4L; /* r04 */ + *--stkp = 0x4000L; + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = 0x0000L; + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ + *--stkp = 0x0000L; + +#else + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x14L; /* r14 */ + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x4L; /* r04 */ + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ +#endif + *--stkp = 0; /* BLANK for 0xA0 size */ + *--stkp = (INT32U)ptos; /* Stack Ptr */ + + return(stkp); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_dbg.c b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/CodeWarrior/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu.h b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu.h new file mode 100644 index 0000000..5b9b3a3 --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu.h @@ -0,0 +1,129 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef __OS_CPU_H__ /* test for multiple inclusion */ +#define __OS_CPU_H__ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_STK_RSVD_SIZE 10 /* EABI Buffer above the stack */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PPC */ + + +/* +********************************************************************************************************* +* FLOATING POINT +* +* Note: also enable or disable "OS_SAVE_CONTEXT_WITH_FPRS .equ 1" in os_cpu_a.h +********************************************************************************************************* +*/ + +#define OS_SAVE_CONTEXT_WITH_FPRS + + +/* +********************************************************************************************************* +* OS Task Swicth +********************************************************************************************************* +*/ + +#if defined __GNUC__ +#define OS_TASK_SW() asm __volatile__ (" se_sc "); +#elif defined __MWERKS__ +#define OS_TASK_SW() asm (" se_sc "); +#else +#error Unknown Compiler Assembler Syntax +#endif + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************* +* Function Prototypes +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +void OSTickISR(void); +void OSExtIntISR(void); + + +#endif /* __OS_CPU_H__ */ diff --git a/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.inc b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.inc new file mode 100644 index 0000000..186d0f9 --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.inc @@ -0,0 +1,335 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ OS_SAVE_CONTEXT_WITH_FPRS, 1 # set to 1 for floating point support; also set in os_cpu.h + + .equ USPRG0, 256 + .equ TCR, 340 + .equ TSR, 336 + .equ SPEFSCR, 512 + .equ HID0, 1008 + .equ L1CSR0, 1010 + + + +#********************************************************************************************************* +#* STACK FRAME DEFINITION +#********************************************************************************************************* + + .equ XR1 ,0 + .equ XBLK ,XR1+4 + + .if OS_SAVE_CONTEXT_WITH_FPRS + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+8 + .equ XR4 ,XR3+8 + .equ XR5 ,XR4+8 + .equ XR6 ,XR5+8 + .equ XR7 ,XR6+8 + .equ XR8 ,XR7+8 + .equ XR9 ,XR8+8 + .equ XR10 ,XR9+8 + .equ XR11 ,XR10+8 + .equ XR12 ,XR11+8 + .equ XR13 ,XR12+8 + .equ XR14 ,XR13+8 + .equ XR15 ,XR14+8 + .equ XR16 ,XR15+8 + .equ XR17 ,XR16+8 + .equ XR18 ,XR17+8 + .equ XR19 ,XR18+8 + .equ XR20 ,XR19+8 + .equ XR21 ,XR20+8 + .equ XR22 ,XR21+8 + .equ XR23 ,XR22+8 + .equ XR24 ,XR23+8 + .equ XR25 ,XR24+8 + .equ XR26 ,XR25+8 + .equ XR27 ,XR26+8 + .equ XR28 ,XR27+8 + .equ XR29 ,XR28+8 + .equ XR30 ,XR29+8 + .equ XR31 ,XR30+8 + .equ XR0 ,XR31+8 + .else + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+4 + .equ XR4 ,XR3+4 + .equ XR5 ,XR4+4 + .equ XR6 ,XR5+4 + .equ XR7 ,XR6+4 + .equ XR8 ,XR7+4 + .equ XR9 ,XR8+4 + .equ XR10 ,XR9+4 + .equ XR11 ,XR10+4 + .equ XR12 ,XR11+4 + .equ XR13 ,XR12+4 + .equ XR14 ,XR13+4 + .equ XR15 ,XR14+4 + .equ XR16 ,XR15+4 + .equ XR17 ,XR16+4 + .equ XR18 ,XR17+4 + .equ XR19 ,XR18+4 + .equ XR20 ,XR19+4 + .equ XR21 ,XR20+4 + .equ XR22 ,XR21+4 + .equ XR23 ,XR22+4 + .equ XR24 ,XR23+4 + .equ XR25 ,XR24+4 + .equ XR26 ,XR25+4 + .equ XR27 ,XR26+4 + .equ XR28 ,XR27+4 + .equ XR29 ,XR28+4 + .equ XR30 ,XR29+4 + .equ XR31 ,XR30+4 + .equ XR0 ,XR31+4 + .endif + + + .equ XSRR0 ,XR0+4 + .equ XSRR1 ,XSRR0+4 + .equ XUSPRG ,XSRR1+4 + .equ XCTR ,XUSPRG+4 + .equ XXER ,XCTR+4 + .equ XCR ,XXER+4 + .equ XLR ,XCR+4 + .equ XSPEFSCR,XLR+4 + .equ XPAD2 ,XSPEFSCR+4 + .equ XPAD3 ,XPAD2+4 + .equ XMSR ,XPAD3+4 + + .equ STACK_FRAME_SIZE ,XMSR+4 + + + +#********************************************************************************************************* +#* PROLOGUE DEFINITION +#********************************************************************************************************* +prologue: .macro + e_add2i. r1, -STACK_FRAME_SIZE + e_stwu r1, 0(r1) + e_stw r0, XR0(r1) + + .if OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 # system call (sc) clears the SPE bit ... + e_or2is r0, 0x0200 # ... therefore set them first + e_or2i r0, 0x0000 + mtmsr r0 + isync + + evstdd r2, XR2(r1) # store GPR as 64bit Register + evstdd r3, XR3(r1) + evstdd r4, XR4(r1) + evstdd r5, XR5(r1) + evstdd r6, XR6(r1) + evstdd r7, XR7(r1) + evstdd r8, XR8(r1) + evstdd r9, XR9(r1) + evstdd r10, XR10(r1) + evstdd r11, XR11(r1) + evstdd r12, XR12(r1) + evstdd r13, XR13(r1) + evstdd r14, XR14(r1) + evstdd r15, XR15(r1) + evstdd r16, XR16(r1) + evstdd r17, XR17(r1) + evstdd r18, XR18(r1) + evstdd r19, XR19(r1) + evstdd r20, XR20(r1) + evstdd r21, XR21(r1) + evstdd r22, XR22(r1) + evstdd r23, XR23(r1) + evstdd r24, XR24(r1) + evstdd r25, XR25(r1) + evstdd r26, XR26(r1) + evstdd r27, XR27(r1) + evstdd r28, XR28(r1) + evstdd r29, XR29(r1) + evstdd r30, XR30(r1) + evstdd r31, XR31(r1) + .else + e_stw r2, XR2(r1) # store GPR as 32bit Register + e_stw r3, XR3(r1) + e_stw r4, XR4(r1) + e_stw r5, XR5(r1) + e_stw r6, XR6(r1) + e_stw r7, XR7(r1) + e_stw r8, XR8(r1) + e_stw r9, XR9(r1) + e_stw r10, XR10(r1) + e_stw r11, XR11(r1) + e_stw r12, XR12(r1) + e_stw r13, XR13(r1) + e_stw r14, XR14(r1) + e_stw r15, XR15(r1) + e_stw r16, XR16(r1) + e_stw r17, XR17(r1) + e_stw r18, XR18(r1) + e_stw r19, XR19(r1) + e_stw r20, XR20(r1) + e_stw r21, XR21(r1) + e_stw r22, XR22(r1) + e_stw r23, XR23(r1) + e_stw r24, XR24(r1) + e_stw r25, XR25(r1) + e_stw r26, XR26(r1) + e_stw r27, XR27(r1) + e_stw r28, XR28(r1) + e_stw r29, XR29(r1) + e_stw r30, XR30(r1) + e_stw r31, XR31(r1) + .endif + + mfmsr r0 + e_stw r0, XMSR(r1) + + mfspr r0, SPEFSCR + e_stw r0, XSPEFSCR(r1) + + mfspr r0, SRR0 + e_stw r0, XSRR0(r1) + + mfspr r0, SRR1 + e_stw r0, XSRR1(r1) + + mfspr r0, USPRG0 + e_stw r0, XUSPRG(r1) + + mflr r0 + e_stw r0, XLR(r1) + + mfctr r0 + e_stw r0, XCTR(r1) + + mfxer r0 + e_stw r0, XXER(r1) + + mfcr r0 + e_stw r0, XCR(r1) + + mfmsr r0 + .endm + + + +#********************************************************************************************************* +#* EPILOGUE DEFINITION +#********************************************************************************************************* +epilogue: .macro + wrteei 0 + + .if OS_SAVE_CONTEXT_WITH_FPRS + evldd r2, XR2(r1) # load GPR as 64bit Register + evldd r3, XR3(r1) + evldd r4, XR4(r1) + evldd r5, XR5(r1) + evldd r6, XR6(r1) + evldd r7, XR7(r1) + evldd r8, XR8(r1) + evldd r9, XR9(r1) + evldd r10, XR10(r1) + evldd r11, XR11(r1) + evldd r12, XR12(r1) + evldd r13, XR13(r1) + evldd r14, XR14(r1) + evldd r15, XR15(r1) + evldd r16, XR16(r1) + evldd r17, XR17(r1) + evldd r18, XR18(r1) + evldd r19, XR19(r1) + evldd r20, XR20(r1) + evldd r21, XR21(r1) + evldd r22, XR22(r1) + evldd r23, XR23(r1) + evldd r24, XR24(r1) + evldd r25, XR25(r1) + evldd r26, XR26(r1) + evldd r27, XR27(r1) + evldd r28, XR28(r1) + evldd r29, XR29(r1) + evldd r30, XR30(r1) + evldd r31, XR31(r1) + .else + e_lwz r2, XR2(r1) # load GPR as 32bit Register + e_lwz r3, XR3(r1) + e_lwz r4, XR4(r1) + e_lwz r5, XR5(r1) + e_lwz r6, XR6(r1) + e_lwz r7, XR7(r1) + e_lwz r8, XR8(r1) + e_lwz r9, XR9(r1) + e_lwz r10, XR10(r1) + e_lwz r11, XR11(r1) + e_lwz r12, XR12(r1) + e_lwz r13, XR13(r1) + e_lwz r14, XR14(r1) + e_lwz r15, XR15(r1) + e_lwz r16, XR16(r1) + e_lwz r17, XR17(r1) + e_lwz r18, XR18(r1) + e_lwz r19, XR19(r1) + e_lwz r20, XR20(r1) + e_lwz r21, XR21(r1) + e_lwz r22, XR22(r1) + e_lwz r23, XR23(r1) + e_lwz r24, XR24(r1) + e_lwz r25, XR25(r1) + e_lwz r26, XR26(r1) + e_lwz r27, XR27(r1) + e_lwz r28, XR28(r1) + e_lwz r29, XR29(r1) + e_lwz r30, XR30(r1) + e_lwz r31, XR31(r1) + .endif + + e_lwz r0, XCR(r1) + mtcrf 0xff,r0 + e_lwz r0, XXER(r1) + mtxer r0 + e_lwz r0, XCTR(r1) + mtctr r0 + e_lwz r0, XLR(r1) + mtlr r0 + + e_lwz r0, XSRR1(r1) + mtspr SRR1,r0 + e_lwz r0, XSRR0(r1) + mtspr SRR0,r0 + + e_lwz r0, XUSPRG(r1) + mtspr USPRG0,r0 + + e_lwz r0, XSPEFSCR(r1) + mtspr SPEFSCR,r0 + + e_lwz r0, XR0(r1) + e_add2i. r1, STACK_FRAME_SIZE + .endm + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT INCLUDE FILE END +#********************************************************************************************************* diff --git a/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.s b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.s new file mode 100644 index 0000000..acfb792 --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_a.s @@ -0,0 +1,266 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# GNU C Compiler +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* ASM HEADER +#********************************************************************************************************* + + .include "os_cpu_a.inc" + + .section .xcptn_vle, "ax" + + .extern BSP_TmrTickISR + + .extern OSTaskSwHook + .extern OSIntEnter + .extern OSIntExit + + .extern OSTCBCur # pointer to current tasks TCB + .extern OSTCBHighRdy # pointer to highest priority ready task + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSRunning + .extern OSIntNesting + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ INTC_IACKR, 0xfff48010 # Interrupt Acknowledge Register address + .equ INTC_EOIR, 0xfff48018 # End of Interrupt Register address + + +#********************************************************************************************************* +#* PUBLIC DECLARATIONS +#********************************************************************************************************* + + .global OSCtxSw + .global OSStartHighRdy + .global OSIntCtxSw + + .global OSTickISR + .global OSExtIntISR + + + +#********************************************************************************************************* +#* ISR HANDLER FOR SW VECTOR MODE +#* +#* Description : This function is executed when IVOR4 External input interrupt (SPR 404) exception occurs. +#********************************************************************************************************* + .align 4 +OSExtIntISR: + prologue # Save context + + e_lis r11,OSIntNesting@ha # load OSIntNesting + e_lbz r3, OSIntNesting@l(r11) + e_addi r0, r3, 1 + e_stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + e_cmpl16i r0, 1 # if (OSIntNesting != 1) ... + se_bne OSExtIntISR_NotSaveSP # do not save the stackpointer + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + +OSExtIntISR_NotSaveSP: + e_lis r3, INTC_IACKR@h # store address of INTC.IACKR in r3 + e_or2i r3, INTC_IACKR@l + e_lwz r3, 0(r3) # load contents of INTC.IACKR in r3 + e_lwz r12,0(r3) # load the base adress of Vector Table + + mtctr r12 # load Count register + se_bctrl # branch to ISR_Handler + + se_li r0, 0 # load r0 with 0x0000 + e_lis r3, INTC_EOIR@h # get the address of the INTC.EOIR Register ... + e_or2i r3, INTC_EOIR@l + e_stw r0, 0(r3) # and clear the INTC.EOIR register + + e_bl OSIntExit # call to decrement OSIntNesting + + epilogue # restore the context + + se_rfi # return from interrupt + + + +#********************************************************************************************************* +#* SYSTEM TICK ISR +#* +#* Description : This function is the ISR to notify uC/OS-II that a system tick has occurred. +#********************************************************************************************************* + .align 4 +OSTickISR: + prologue + + e_lis r11,OSIntNesting@ha # load OSIntNesting + e_lbz r3, OSIntNesting@l(r11) + e_addi r0, r3, 1 + e_stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + e_cmpl16i r0, 1 # if (OSIntNesting != 1) ... + se_bne OSTickISR_NotSaveSP # do not save the stackpointer + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + +OSTickISR_NotSaveSP: + e_lis r4, 0x0800 # load r4 with TSR[DIS] bit (0x08000000) + mtspr TSR,r4 # clear TSR[DIS] bit + + e_bl BSP_TmrTickISR # call TmrTick handler + e_bl OSIntExit # call to decrement OSIntNesting + + epilogue # Restore context + + se_rfi # run task + + + +#********************************************************************************************************* +#* START HIGHEST PRIORITY TASK READY-TO-RUN +#* +#* Description : This function is called by OSStart() to start the highest priority task that was created +#* by the application before calling OSStart(). +#* +#* Arguments : none +#* +#* Note(s) : 1) OSStartHighRdy() MUST: +#* a) Call OSTaskSwHook() then, +#* b) Set OSRunning to TRUE, +#* c) Switch to the highest priority task by loading the stack pointer of the highest +#* priority task into the SP register and execute an rfi instruction. +#********************************************************************************************************* + .align 4 +OSStartHighRdy: + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_li r0, 1 # Set OSRunning to 1 + e_lis r11,OSRunning@ha + e_stb r0, OSRunning@l(r11) + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + se_rfi # run task + + + +#********************************************************************************************************* +#* TASK LEVEL CONTEXT SWITCH +#* +#* Description : This function is called when a task makes a higher priority task ready-to-run. +#* +#* Arguments : none +#* +#* Note(s) : 1) Upon entry, +#* OSTCBCur points to the OS_TCB of the task to suspend +#* OSTCBHighRdy points to the OS_TCB of the task to resume +#********************************************************************************************************* + .align 4 +OSCtxSw: + prologue # Save context + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority + e_lbz r10,OSPrioHighRdy@l(r12) + + e_lis r12,OSPrioCur@ha # Save as Current Priority + e_stb r10,OSPrioCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer from TCB + + epilogue # Restore context + + se_rfi # run task + + + +#********************************************************************************************************* +#* INTERRUPT LEVEL CONTEXT SWITCH +#* +#* Description : This function is called by OSIntExit() to perform a context switch to a task that has +#* been made ready-to-run by an ISR. +#********************************************************************************************************* + .align 4 +OSIntCtxSw: + mbar 1 + + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority + e_lbz r10,OSPrioHighRdy@l(r12) + + e_lis r12,OSPrioCur@ha # Save as Current Priority + e_stb r10,OSPrioCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + mbar 1 + + se_rfi # run task + + + +#********************************************************************************************************* +#* RETURN FROM INTERRUPT TRAP +#********************************************************************************************************* + .align 4 +RFI_trap: + se_rfi + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT FILE END +#********************************************************************************************************* + .end diff --git a/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_c.c b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_c.c new file mode 100644 index 0000000..72caa23 --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/GNU/os_cpu_c.c @@ -0,0 +1,454 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* GLOBALS +********************************************************************************************************* +*/ + +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The SRR1 Register holds the original value of the MSR register. This value is copied +* to the MSR register by execute the rfi operation at the end of the ISR. +* +* (2) Ensure any changes to the order of stack initialization is congruent with the Stack +* Frame definitions in OS_CPU_A.s. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stkp; /* Local: Stack pointer */ + OS_CPU_SR msr; /* Local: Initial MSR */ + OS_CPU_SR srr1; /* Local: Initial SRR1 */ + + + (void)opt; /* 'opt' is not used, prevent warning */ + + msr = CPU_SR_Rd(); /* get the MSB reg value */ + srr1 = msr | 0x8000; /* set MSR[EE] bit to enable interrupts */ + + stkp = (OS_STK *)((INT32U)ptos & 0xFFFFFFF0); /* 16-byte align task's stack pointer (EABI) */ + + /* Leave buffer area for locals "above the stack" in ... */ + stkp -= OS_STK_RSVD_SIZE; /* case the compiler prolog puts variables above the stack */ + + /* Stack Frame Initialization */ + *--stkp = (INT32U)msr; /* MSR */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* SPEFSCR */ + *--stkp = (INT32U)task; /* LR */ + *--stkp = 0; /* CR */ + *--stkp = 0; /* XER */ + *--stkp = 0; /* CTR */ + *--stkp = 0; /* USPRG0 */ + *--stkp = (INT32U)srr1; /* SRR1 */ + *--stkp = (INT32U)task; /* SRR0 */ + *--stkp = 0; /* R0 */ + + +#ifdef OS_SAVE_CONTEXT_WITH_FPRS /* Push 64-bit register's initial value to the stack */ + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x3100L; + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x3000L; + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x2900L; + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x2800L; + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x2700L; + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x2600L; + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x2500L; + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x2400L; + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x2300L; + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x2200L; + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x2100L; + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x2000L; + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x1900L; + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x1800L; + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x1700L; + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x1600L; + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x1500L; + *--stkp = 0x14L; /* r14 */ + *--stkp = 0x1400L; + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x0000L; + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x1200L; + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x1100L; + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x1000L; + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x9000L; + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x8000L; + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x7000L; + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x6000L; + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x5000L; + *--stkp = 0x4L; /* r04 */ + *--stkp = 0x4000L; + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = 0x0000L; + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ + *--stkp = 0x0000L; + +#else + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x14L; /* r14 */ + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x4L; /* r04 */ + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ +#endif + *--stkp = 0; /* BLANK for 0xA0 size */ + *--stkp = (INT32U)ptos; /* Stack Ptr */ + + return(stkp); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PowerPC/MPC55xx-VLE/GNU/os_dbg.c b/Ports/PowerPC/MPC55xx-VLE/GNU/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/PowerPC/MPC55xx-VLE/GNU/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu.h b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..20bf16c --- /dev/null +++ b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu.h @@ -0,0 +1,129 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef __OS_CPU_H__ /* test for multiple inclusion */ +#define __OS_CPU_H__ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_STK_RSVD_SIZE 10 /* EABI Buffer above the stack */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PPC */ + + +/* +********************************************************************************************************* +* FLOATING POINT +* +* Note: also enable or disable "OS_SAVE_CONTEXT_WITH_FPRS .equ 1" in os_cpu_a.h +********************************************************************************************************* +*/ + +#define OS_SAVE_CONTEXT_WITH_FPRS + + +/* +********************************************************************************************************* +* OS Task Swicth +********************************************************************************************************* +*/ + +#if defined __GNUC__ +#define OS_TASK_SW() asm __volatile__ (" sc "); +#elif defined __MWERKS__ +#define OS_TASK_SW() asm (" sc "); +#else +#error Unknown Compiler Assembler Syntax +#endif + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************* +* Function Prototypes +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +void OSTickISR(void); +void OSExtIntISR(void); + + +#endif /* __OS_CPU_H__ */ diff --git a/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.inc b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.inc new file mode 100644 index 0000000..c4529ed --- /dev/null +++ b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.inc @@ -0,0 +1,334 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ OS_SAVE_CONTEXT_WITH_FPRS, 1 # set to 1 for floating point support; also set in os_cpu.h + + .equ USPRG0, 256 + .equ TCR, 340 + .equ TSR, 336 + .equ SPEFSCR, 512 + .equ HID0, 1008 + .equ L1CSR0, 1010 + + + +#********************************************************************************************************* +#* STACK FRAME DEFINITION +#********************************************************************************************************* + + .equ XR1 ,0 + .equ XBLK ,XR1+4 + + .if OS_SAVE_CONTEXT_WITH_FPRS + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+8 + .equ XR4 ,XR3+8 + .equ XR5 ,XR4+8 + .equ XR6 ,XR5+8 + .equ XR7 ,XR6+8 + .equ XR8 ,XR7+8 + .equ XR9 ,XR8+8 + .equ XR10 ,XR9+8 + .equ XR11 ,XR10+8 + .equ XR12 ,XR11+8 + .equ XR13 ,XR12+8 + .equ XR14 ,XR13+8 + .equ XR15 ,XR14+8 + .equ XR16 ,XR15+8 + .equ XR17 ,XR16+8 + .equ XR18 ,XR17+8 + .equ XR19 ,XR18+8 + .equ XR20 ,XR19+8 + .equ XR21 ,XR20+8 + .equ XR22 ,XR21+8 + .equ XR23 ,XR22+8 + .equ XR24 ,XR23+8 + .equ XR25 ,XR24+8 + .equ XR26 ,XR25+8 + .equ XR27 ,XR26+8 + .equ XR28 ,XR27+8 + .equ XR29 ,XR28+8 + .equ XR30 ,XR29+8 + .equ XR31 ,XR30+8 + .equ XR0 ,XR31+8 + .else + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+4 + .equ XR4 ,XR3+4 + .equ XR5 ,XR4+4 + .equ XR6 ,XR5+4 + .equ XR7 ,XR6+4 + .equ XR8 ,XR7+4 + .equ XR9 ,XR8+4 + .equ XR10 ,XR9+4 + .equ XR11 ,XR10+4 + .equ XR12 ,XR11+4 + .equ XR13 ,XR12+4 + .equ XR14 ,XR13+4 + .equ XR15 ,XR14+4 + .equ XR16 ,XR15+4 + .equ XR17 ,XR16+4 + .equ XR18 ,XR17+4 + .equ XR19 ,XR18+4 + .equ XR20 ,XR19+4 + .equ XR21 ,XR20+4 + .equ XR22 ,XR21+4 + .equ XR23 ,XR22+4 + .equ XR24 ,XR23+4 + .equ XR25 ,XR24+4 + .equ XR26 ,XR25+4 + .equ XR27 ,XR26+4 + .equ XR28 ,XR27+4 + .equ XR29 ,XR28+4 + .equ XR30 ,XR29+4 + .equ XR31 ,XR30+4 + .equ XR0 ,XR31+4 + .endif + + + .equ XSRR0 ,XR0+4 + .equ XSRR1 ,XSRR0+4 + .equ XUSPRG ,XSRR1+4 + .equ XCTR ,XUSPRG+4 + .equ XXER ,XCTR+4 + .equ XCR ,XXER+4 + .equ XLR ,XCR+4 + .equ XSPEFSCR,XLR+4 + .equ XPAD2 ,XSPEFSCR+4 + .equ XPAD3 ,XPAD2+4 + .equ XMSR ,XPAD3+4 + + .equ STACK_FRAME_SIZE ,XMSR+4 + + + +#********************************************************************************************************* +#* PROLOGUE DEFINITION +#********************************************************************************************************* +prologue: .macro + stwu r1, -STACK_FRAME_SIZE(r1) + stw r0, XR0(r1) + + .if OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 # system call (sc) clears the SPE bit ... + oris r0, r0,0x0200 # ... therefore set them first + ori r0, r0,0x0000 + mtmsr r0 + isync + + evstdd r2, XR2(r1) # store GPR as 64bit Register + evstdd r3, XR3(r1) + evstdd r4, XR4(r1) + evstdd r5, XR5(r1) + evstdd r6, XR6(r1) + evstdd r7, XR7(r1) + evstdd r8, XR8(r1) + evstdd r9, XR9(r1) + evstdd r10, XR10(r1) + evstdd r11, XR11(r1) + evstdd r12, XR12(r1) + evstdd r13, XR13(r1) + evstdd r14, XR14(r1) + evstdd r15, XR15(r1) + evstdd r16, XR16(r1) + evstdd r17, XR17(r1) + evstdd r18, XR18(r1) + evstdd r19, XR19(r1) + evstdd r20, XR20(r1) + evstdd r21, XR21(r1) + evstdd r22, XR22(r1) + evstdd r23, XR23(r1) + evstdd r24, XR24(r1) + evstdd r25, XR25(r1) + evstdd r26, XR26(r1) + evstdd r27, XR27(r1) + evstdd r28, XR28(r1) + evstdd r29, XR29(r1) + evstdd r30, XR30(r1) + evstdd r31, XR31(r1) + .else + stw r2, XR2(r1) # store GPR as 32bit Register + stw r3, XR3(r1) + stw r4, XR4(r1) + stw r5, XR5(r1) + stw r6, XR6(r1) + stw r7, XR7(r1) + stw r8, XR8(r1) + stw r9, XR9(r1) + stw r10, XR10(r1) + stw r11, XR11(r1) + stw r12, XR12(r1) + stw r13, XR13(r1) + stw r14, XR14(r1) + stw r15, XR15(r1) + stw r16, XR16(r1) + stw r17, XR17(r1) + stw r18, XR18(r1) + stw r19, XR19(r1) + stw r20, XR20(r1) + stw r21, XR21(r1) + stw r22, XR22(r1) + stw r23, XR23(r1) + stw r24, XR24(r1) + stw r25, XR25(r1) + stw r26, XR26(r1) + stw r27, XR27(r1) + stw r28, XR28(r1) + stw r29, XR29(r1) + stw r30, XR30(r1) + stw r31, XR31(r1) + .endif + + mfmsr r0 + stw r0, XMSR(r1) + + mfspr r0, SPEFSCR + stw r0, XSPEFSCR(r1) + + mfspr r0, SRR0 + stw r0, XSRR0(r1) + + mfspr r0, SRR1 + stw r0, XSRR1(r1) + + mfspr r0, USPRG0 + stw r0, XUSPRG(r1) + + mflr r0 + stw r0, XLR(r1) + + mfctr r0 + stw r0, XCTR(r1) + + mfxer r0 + stw r0, XXER(r1) + + mfcr r0 + stw r0, XCR(r1) + + mfmsr r0 + .endm + + + +#********************************************************************************************************* +#* EPILOGUE DEFINITION +#********************************************************************************************************* +epilogue: .macro + wrteei 0 + + .if OS_SAVE_CONTEXT_WITH_FPRS + evldd r2, XR2(r1) # load GPR as 64bit Register + evldd r3, XR3(r1) + evldd r4, XR4(r1) + evldd r5, XR5(r1) + evldd r6, XR6(r1) + evldd r7, XR7(r1) + evldd r8, XR8(r1) + evldd r9, XR9(r1) + evldd r10, XR10(r1) + evldd r11, XR11(r1) + evldd r12, XR12(r1) + evldd r13, XR13(r1) + evldd r14, XR14(r1) + evldd r15, XR15(r1) + evldd r16, XR16(r1) + evldd r17, XR17(r1) + evldd r18, XR18(r1) + evldd r19, XR19(r1) + evldd r20, XR20(r1) + evldd r21, XR21(r1) + evldd r22, XR22(r1) + evldd r23, XR23(r1) + evldd r24, XR24(r1) + evldd r25, XR25(r1) + evldd r26, XR26(r1) + evldd r27, XR27(r1) + evldd r28, XR28(r1) + evldd r29, XR29(r1) + evldd r30, XR30(r1) + evldd r31, XR31(r1) + .else + lwz r2, XR2(r1) # load GPR as 32bit Register + lwz r3, XR3(r1) + lwz r4, XR4(r1) + lwz r5, XR5(r1) + lwz r6, XR6(r1) + lwz r7, XR7(r1) + lwz r8, XR8(r1) + lwz r9, XR9(r1) + lwz r10, XR10(r1) + lwz r11, XR11(r1) + lwz r12, XR12(r1) + lwz r13, XR13(r1) + lwz r14, XR14(r1) + lwz r15, XR15(r1) + lwz r16, XR16(r1) + lwz r17, XR17(r1) + lwz r18, XR18(r1) + lwz r19, XR19(r1) + lwz r20, XR20(r1) + lwz r21, XR21(r1) + lwz r22, XR22(r1) + lwz r23, XR23(r1) + lwz r24, XR24(r1) + lwz r25, XR25(r1) + lwz r26, XR26(r1) + lwz r27, XR27(r1) + lwz r28, XR28(r1) + lwz r29, XR29(r1) + lwz r30, XR30(r1) + lwz r31, XR31(r1) + .endif + + lwz r0, XCR(r1) + mtcrf 0xff,r0 + lwz r0, XXER(r1) + mtxer r0 + lwz r0, XCTR(r1) + mtctr r0 + lwz r0, XLR(r1) + mtlr r0 + + lwz r0, XSRR1(r1) + mtspr SRR1,r0 + lwz r0, XSRR0(r1) + mtspr SRR0,r0 + + lwz r0, XUSPRG(r1) + mtspr USPRG0,r0 + + lwz r0, XSPEFSCR(r1) + mtspr SPEFSCR,r0 + + lwz r0, XR0(r1) + addi r1, r1, STACK_FRAME_SIZE + .endm + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT INCLUDE FILE END +#********************************************************************************************************* diff --git a/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.s b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.s new file mode 100644 index 0000000..e36e7d6 --- /dev/null +++ b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_a.s @@ -0,0 +1,264 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# CodeWarrior Compiler +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* ASM HEADER +#********************************************************************************************************* + + .include "os_cpu_a.inc" + + .section .xcptn, text + + .extern BSP_TmrTickISR + + .extern OSTaskSwHook + .extern OSIntEnter + .extern OSIntExit + + .extern OSTCBCur # pointer to current tasks TCB + .extern OSTCBHighRdy # pointer to highest priority ready task + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSRunning + .extern OSIntNesting + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ INTC_IACKR, 0xfff48010 # Interrupt Acknowledge Register address + .equ INTC_EOIR, 0xfff48018 # End of Interrupt Register address + + +#********************************************************************************************************* +#* PUBLIC DECLARATIONS +#********************************************************************************************************* + + .global OSCtxSw + .global OSStartHighRdy + .global OSIntCtxSw + + .global OSTickISR + .global OSExtIntISR + + + +#********************************************************************************************************* +#* ISR HANDLER FOR SW VECTOR MODE +#* +#* Description : This function is executed when IVOR4 External input interrupt (SPR 404) exception occurs. +#********************************************************************************************************* + .align 16 +OSExtIntISR: + prologue # Save context + + lis r11,OSIntNesting@ha # load OSIntNesting + lbz r3, OSIntNesting@l(r11) + addi r0, r3, 1 + stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + cmpwi r0, 1 # if (OSIntNesting != 1) ... + bne OSExtIntISR_NotSaveSP # do not save the stackpointer + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + +OSExtIntISR_NotSaveSP: + lis r3, INTC_IACKR@ha # store address of INTC.IACKR in r3 + lwz r3, INTC_IACKR@l(r3) # load contents of INTC.IACKR in r3 + lwz r12,0(r3) # load the base adress of Vector Table + + mtctr r12 # load Count register + bctrl # branch to ISR_Handler + + li r0, 0 # load r0 with 0x0000 + lis r3, INTC_EOIR@ha # get the address of the INTC.EOIR Register ... + stw r0, INTC_EOIR@l(r3) # and clear the INTC.EOIR register + + bl OSIntExit # call to decrement OSIntNesting + + epilogue # restore the context + + rfi # return from interrupt + + + +#********************************************************************************************************* +#* SYSTEM TICK ISR +#* +#* Description : This function is the ISR to notify uC/OS-II that a system tick has occurred. +#********************************************************************************************************* + .align 16 +OSTickISR: + prologue + + lis r11,OSIntNesting@ha # load OSIntNesting + lbz r3, OSIntNesting@l(r11) + addi r0, r3, 1 + stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + cmpwi r0, 1 # if (OSIntNesting != 1) ... + bne OSTickISR_NotSaveSP # do not save the stackpointer + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + +OSTickISR_NotSaveSP: + lis r4, 0x0800 # load r4 with TSR[DIS] bit (0x08000000) + mtspr TSR,r4 # clear TSR[DIS] bit + + bl BSP_TmrTickISR # call TmrTick handler + bl OSIntExit # call to decrement OSIntNesting + + epilogue # Restore context + + rfi # run task + + + +#********************************************************************************************************* +#* START HIGHEST PRIORITY TASK READY-TO-RUN +#* +#* Description : This function is called by OSStart() to start the highest priority task that was created +#* by the application before calling OSStart(). +#* +#* Arguments : none +#* +#* Note(s) : 1) OSStartHighRdy() MUST: +#* a) Call OSTaskSwHook() then, +#* b) Set OSRunning to TRUE, +#* c) Switch to the highest priority task by loading the stack pointer of the highest +#* priority task into the SP register and execute an rfi instruction. +#********************************************************************************************************* + .align 16 +OSStartHighRdy: + bl OSTaskSwHook # Call OSTaskSwHook + + li r0, 1 # Set OSRunning to 1 + lis r11,OSRunning@ha + stb r0, OSRunning@l(r11) + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + rfi # run task + + + +#********************************************************************************************************* +#* TASK LEVEL CONTEXT SWITCH +#* +#* Description : This function is called when a task makes a higher priority task ready-to-run. +#* +#* Arguments : none +#* +#* Note(s) : 1) Upon entry, +#* OSTCBCur points to the OS_TCB of the task to suspend +#* OSTCBHighRdy points to the OS_TCB of the task to resume +#********************************************************************************************************* + .align 16 +OSCtxSw: + prologue # Save context + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer from TCB + + epilogue # Restore context + + rfi # run task + + + +#********************************************************************************************************* +#* INTERRUPT LEVEL CONTEXT SWITCH +#* +#* Description : This function is called by OSIntExit() to perform a context switch to a task that has +#* been made ready-to-run by an ISR. +#********************************************************************************************************* + .align 16 +OSIntCtxSw: + mbar 1 + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + mbar 1 + + rfi # run task + + + +#********************************************************************************************************* +#* RETURN FROM INTERRUPT TRAP +#********************************************************************************************************* + .align 16 +RFI_trap: + rfi + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT FILE END +#********************************************************************************************************* + .end diff --git a/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_c.c b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_c.c new file mode 100644 index 0000000..4e17b4a --- /dev/null +++ b/Ports/PowerPC/MPC55xx/CodeWarrior/os_cpu_c.c @@ -0,0 +1,453 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* GLOBALS +********************************************************************************************************* +*/ + +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The SRR1 Register holds the original value of the MSR register. This value is copied +* to the MSR register by execute the rfi operation at the end of the ISR. +* +* (2) Ensure any changes to the order of stack initialization is congruent with the Stack +* Frame definitions in OS_CPU_A.s. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stkp; /* Local: Stack pointer */ + OS_CPU_SR msr; /* Local: Initial MSR */ + OS_CPU_SR srr1; /* Local: Initial SRR1 */ + + + (void)opt; /* 'opt' is not used, prevent warning */ + + msr = CPU_SR_Rd(); /* get the MSB reg value */ + srr1 = msr | 0x8000; /* set MSR[EE] bit to enable interrupts */ + + stkp = (OS_STK *)((INT32U)ptos & 0xFFFFFFF0); /* 16-byte align task's stack pointer (EABI) */ + + /* Leave buffer area for locals "above the stack" in ... */ + stkp -= OS_STK_RSVD_SIZE; /* case the compiler prolog puts variables above the stack */ + + /* Stack Frame Initialization */ + *--stkp = (INT32U)msr; /* MSR */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* SPEFSCR */ + *--stkp = (INT32U)task; /* LR */ + *--stkp = 0; /* CR */ + *--stkp = 0; /* XER */ + *--stkp = 0; /* CTR */ + *--stkp = 0; /* USPRG0 */ + *--stkp = (INT32U)srr1; /* SRR1 */ + *--stkp = (INT32U)task; /* SRR0 */ + *--stkp = 0; /* R0 */ + + +#ifdef OS_SAVE_CONTEXT_WITH_FPRS /* Push 64-bit register's initial value to the stack */ + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x3100L; + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x3000L; + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x2900L; + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x2800L; + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x2700L; + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x2600L; + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x2500L; + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x2400L; + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x2300L; + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x2200L; + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x2100L; + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x2000L; + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x1900L; + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x1800L; + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x1700L; + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x1600L; + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x1500L; + *--stkp = 0x14L; /* r14 */ + *--stkp = 0x1400L; + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x0000L; + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x1200L; + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x1100L; + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x1000L; + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x9000L; + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x8000L; + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x7000L; + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x6000L; + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x5000L; + *--stkp = 0x4L; /* r04 */ + *--stkp = 0x4000L; + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = 0x0000L; + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ + *--stkp = 0x0000L; + +#else + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x14L; /* r14 */ + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x4L; /* r04 */ + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ +#endif + *--stkp = 0; /* BLANK for 0xA0 size */ + *--stkp = (INT32U)ptos; /* Stack Ptr */ + + return(stkp); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PowerPC/MPC55xx/CodeWarrior/os_dbg.c b/Ports/PowerPC/MPC55xx/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/PowerPC/MPC55xx/CodeWarrior/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PowerPC/MPC55xx/GNU/os_cpu.h b/Ports/PowerPC/MPC55xx/GNU/os_cpu.h new file mode 100644 index 0000000..20bf16c --- /dev/null +++ b/Ports/PowerPC/MPC55xx/GNU/os_cpu.h @@ -0,0 +1,129 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef __OS_CPU_H__ /* test for multiple inclusion */ +#define __OS_CPU_H__ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_STK_RSVD_SIZE 10 /* EABI Buffer above the stack */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PPC */ + + +/* +********************************************************************************************************* +* FLOATING POINT +* +* Note: also enable or disable "OS_SAVE_CONTEXT_WITH_FPRS .equ 1" in os_cpu_a.h +********************************************************************************************************* +*/ + +#define OS_SAVE_CONTEXT_WITH_FPRS + + +/* +********************************************************************************************************* +* OS Task Swicth +********************************************************************************************************* +*/ + +#if defined __GNUC__ +#define OS_TASK_SW() asm __volatile__ (" sc "); +#elif defined __MWERKS__ +#define OS_TASK_SW() asm (" sc "); +#else +#error Unknown Compiler Assembler Syntax +#endif + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************* +* Function Prototypes +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +void OSTickISR(void); +void OSExtIntISR(void); + + +#endif /* __OS_CPU_H__ */ diff --git a/Ports/PowerPC/MPC55xx/GNU/os_cpu_a.inc b/Ports/PowerPC/MPC55xx/GNU/os_cpu_a.inc new file mode 100644 index 0000000..c4529ed --- /dev/null +++ b/Ports/PowerPC/MPC55xx/GNU/os_cpu_a.inc @@ -0,0 +1,334 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ OS_SAVE_CONTEXT_WITH_FPRS, 1 # set to 1 for floating point support; also set in os_cpu.h + + .equ USPRG0, 256 + .equ TCR, 340 + .equ TSR, 336 + .equ SPEFSCR, 512 + .equ HID0, 1008 + .equ L1CSR0, 1010 + + + +#********************************************************************************************************* +#* STACK FRAME DEFINITION +#********************************************************************************************************* + + .equ XR1 ,0 + .equ XBLK ,XR1+4 + + .if OS_SAVE_CONTEXT_WITH_FPRS + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+8 + .equ XR4 ,XR3+8 + .equ XR5 ,XR4+8 + .equ XR6 ,XR5+8 + .equ XR7 ,XR6+8 + .equ XR8 ,XR7+8 + .equ XR9 ,XR8+8 + .equ XR10 ,XR9+8 + .equ XR11 ,XR10+8 + .equ XR12 ,XR11+8 + .equ XR13 ,XR12+8 + .equ XR14 ,XR13+8 + .equ XR15 ,XR14+8 + .equ XR16 ,XR15+8 + .equ XR17 ,XR16+8 + .equ XR18 ,XR17+8 + .equ XR19 ,XR18+8 + .equ XR20 ,XR19+8 + .equ XR21 ,XR20+8 + .equ XR22 ,XR21+8 + .equ XR23 ,XR22+8 + .equ XR24 ,XR23+8 + .equ XR25 ,XR24+8 + .equ XR26 ,XR25+8 + .equ XR27 ,XR26+8 + .equ XR28 ,XR27+8 + .equ XR29 ,XR28+8 + .equ XR30 ,XR29+8 + .equ XR31 ,XR30+8 + .equ XR0 ,XR31+8 + .else + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+4 + .equ XR4 ,XR3+4 + .equ XR5 ,XR4+4 + .equ XR6 ,XR5+4 + .equ XR7 ,XR6+4 + .equ XR8 ,XR7+4 + .equ XR9 ,XR8+4 + .equ XR10 ,XR9+4 + .equ XR11 ,XR10+4 + .equ XR12 ,XR11+4 + .equ XR13 ,XR12+4 + .equ XR14 ,XR13+4 + .equ XR15 ,XR14+4 + .equ XR16 ,XR15+4 + .equ XR17 ,XR16+4 + .equ XR18 ,XR17+4 + .equ XR19 ,XR18+4 + .equ XR20 ,XR19+4 + .equ XR21 ,XR20+4 + .equ XR22 ,XR21+4 + .equ XR23 ,XR22+4 + .equ XR24 ,XR23+4 + .equ XR25 ,XR24+4 + .equ XR26 ,XR25+4 + .equ XR27 ,XR26+4 + .equ XR28 ,XR27+4 + .equ XR29 ,XR28+4 + .equ XR30 ,XR29+4 + .equ XR31 ,XR30+4 + .equ XR0 ,XR31+4 + .endif + + + .equ XSRR0 ,XR0+4 + .equ XSRR1 ,XSRR0+4 + .equ XUSPRG ,XSRR1+4 + .equ XCTR ,XUSPRG+4 + .equ XXER ,XCTR+4 + .equ XCR ,XXER+4 + .equ XLR ,XCR+4 + .equ XSPEFSCR,XLR+4 + .equ XPAD2 ,XSPEFSCR+4 + .equ XPAD3 ,XPAD2+4 + .equ XMSR ,XPAD3+4 + + .equ STACK_FRAME_SIZE ,XMSR+4 + + + +#********************************************************************************************************* +#* PROLOGUE DEFINITION +#********************************************************************************************************* +prologue: .macro + stwu r1, -STACK_FRAME_SIZE(r1) + stw r0, XR0(r1) + + .if OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 # system call (sc) clears the SPE bit ... + oris r0, r0,0x0200 # ... therefore set them first + ori r0, r0,0x0000 + mtmsr r0 + isync + + evstdd r2, XR2(r1) # store GPR as 64bit Register + evstdd r3, XR3(r1) + evstdd r4, XR4(r1) + evstdd r5, XR5(r1) + evstdd r6, XR6(r1) + evstdd r7, XR7(r1) + evstdd r8, XR8(r1) + evstdd r9, XR9(r1) + evstdd r10, XR10(r1) + evstdd r11, XR11(r1) + evstdd r12, XR12(r1) + evstdd r13, XR13(r1) + evstdd r14, XR14(r1) + evstdd r15, XR15(r1) + evstdd r16, XR16(r1) + evstdd r17, XR17(r1) + evstdd r18, XR18(r1) + evstdd r19, XR19(r1) + evstdd r20, XR20(r1) + evstdd r21, XR21(r1) + evstdd r22, XR22(r1) + evstdd r23, XR23(r1) + evstdd r24, XR24(r1) + evstdd r25, XR25(r1) + evstdd r26, XR26(r1) + evstdd r27, XR27(r1) + evstdd r28, XR28(r1) + evstdd r29, XR29(r1) + evstdd r30, XR30(r1) + evstdd r31, XR31(r1) + .else + stw r2, XR2(r1) # store GPR as 32bit Register + stw r3, XR3(r1) + stw r4, XR4(r1) + stw r5, XR5(r1) + stw r6, XR6(r1) + stw r7, XR7(r1) + stw r8, XR8(r1) + stw r9, XR9(r1) + stw r10, XR10(r1) + stw r11, XR11(r1) + stw r12, XR12(r1) + stw r13, XR13(r1) + stw r14, XR14(r1) + stw r15, XR15(r1) + stw r16, XR16(r1) + stw r17, XR17(r1) + stw r18, XR18(r1) + stw r19, XR19(r1) + stw r20, XR20(r1) + stw r21, XR21(r1) + stw r22, XR22(r1) + stw r23, XR23(r1) + stw r24, XR24(r1) + stw r25, XR25(r1) + stw r26, XR26(r1) + stw r27, XR27(r1) + stw r28, XR28(r1) + stw r29, XR29(r1) + stw r30, XR30(r1) + stw r31, XR31(r1) + .endif + + mfmsr r0 + stw r0, XMSR(r1) + + mfspr r0, SPEFSCR + stw r0, XSPEFSCR(r1) + + mfspr r0, SRR0 + stw r0, XSRR0(r1) + + mfspr r0, SRR1 + stw r0, XSRR1(r1) + + mfspr r0, USPRG0 + stw r0, XUSPRG(r1) + + mflr r0 + stw r0, XLR(r1) + + mfctr r0 + stw r0, XCTR(r1) + + mfxer r0 + stw r0, XXER(r1) + + mfcr r0 + stw r0, XCR(r1) + + mfmsr r0 + .endm + + + +#********************************************************************************************************* +#* EPILOGUE DEFINITION +#********************************************************************************************************* +epilogue: .macro + wrteei 0 + + .if OS_SAVE_CONTEXT_WITH_FPRS + evldd r2, XR2(r1) # load GPR as 64bit Register + evldd r3, XR3(r1) + evldd r4, XR4(r1) + evldd r5, XR5(r1) + evldd r6, XR6(r1) + evldd r7, XR7(r1) + evldd r8, XR8(r1) + evldd r9, XR9(r1) + evldd r10, XR10(r1) + evldd r11, XR11(r1) + evldd r12, XR12(r1) + evldd r13, XR13(r1) + evldd r14, XR14(r1) + evldd r15, XR15(r1) + evldd r16, XR16(r1) + evldd r17, XR17(r1) + evldd r18, XR18(r1) + evldd r19, XR19(r1) + evldd r20, XR20(r1) + evldd r21, XR21(r1) + evldd r22, XR22(r1) + evldd r23, XR23(r1) + evldd r24, XR24(r1) + evldd r25, XR25(r1) + evldd r26, XR26(r1) + evldd r27, XR27(r1) + evldd r28, XR28(r1) + evldd r29, XR29(r1) + evldd r30, XR30(r1) + evldd r31, XR31(r1) + .else + lwz r2, XR2(r1) # load GPR as 32bit Register + lwz r3, XR3(r1) + lwz r4, XR4(r1) + lwz r5, XR5(r1) + lwz r6, XR6(r1) + lwz r7, XR7(r1) + lwz r8, XR8(r1) + lwz r9, XR9(r1) + lwz r10, XR10(r1) + lwz r11, XR11(r1) + lwz r12, XR12(r1) + lwz r13, XR13(r1) + lwz r14, XR14(r1) + lwz r15, XR15(r1) + lwz r16, XR16(r1) + lwz r17, XR17(r1) + lwz r18, XR18(r1) + lwz r19, XR19(r1) + lwz r20, XR20(r1) + lwz r21, XR21(r1) + lwz r22, XR22(r1) + lwz r23, XR23(r1) + lwz r24, XR24(r1) + lwz r25, XR25(r1) + lwz r26, XR26(r1) + lwz r27, XR27(r1) + lwz r28, XR28(r1) + lwz r29, XR29(r1) + lwz r30, XR30(r1) + lwz r31, XR31(r1) + .endif + + lwz r0, XCR(r1) + mtcrf 0xff,r0 + lwz r0, XXER(r1) + mtxer r0 + lwz r0, XCTR(r1) + mtctr r0 + lwz r0, XLR(r1) + mtlr r0 + + lwz r0, XSRR1(r1) + mtspr SRR1,r0 + lwz r0, XSRR0(r1) + mtspr SRR0,r0 + + lwz r0, XUSPRG(r1) + mtspr USPRG0,r0 + + lwz r0, XSPEFSCR(r1) + mtspr SPEFSCR,r0 + + lwz r0, XR0(r1) + addi r1, r1, STACK_FRAME_SIZE + .endm + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT INCLUDE FILE END +#********************************************************************************************************* diff --git a/Ports/PowerPC/MPC55xx/GNU/os_cpu_a.s b/Ports/PowerPC/MPC55xx/GNU/os_cpu_a.s new file mode 100644 index 0000000..b16b93f --- /dev/null +++ b/Ports/PowerPC/MPC55xx/GNU/os_cpu_a.s @@ -0,0 +1,264 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC55xx +# GNU C Compiler +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* ASM HEADER +#********************************************************************************************************* + + .include "os_cpu_a.inc" + + .section .xcptn, "ax" + + .extern BSP_TmrTickISR + + .extern OSTaskSwHook + .extern OSIntEnter + .extern OSIntExit + + .extern OSTCBCur # pointer to current tasks TCB + .extern OSTCBHighRdy # pointer to highest priority ready task + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSRunning + .extern OSIntNesting + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ INTC_IACKR, 0xfff48010 # Interrupt Acknowledge Register address + .equ INTC_EOIR, 0xfff48018 # End of Interrupt Register address + + +#********************************************************************************************************* +#* PUBLIC DECLARATIONS +#********************************************************************************************************* + + .global OSCtxSw + .global OSStartHighRdy + .global OSIntCtxSw + + .global OSTickISR + .global OSExtIntISR + + + +#********************************************************************************************************* +#* ISR HANDLER FOR SW VECTOR MODE +#* +#* Description : This function is executed when IVOR4 External input interrupt (SPR 404) exception occurs. +#********************************************************************************************************* + .align 4 +OSExtIntISR: + prologue # Save context + + lis r11,OSIntNesting@ha # load OSIntNesting + lbz r3, OSIntNesting@l(r11) + addi r0, r3, 1 + stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + cmpwi r0, 1 # if (OSIntNesting != 1) ... + bne OSExtIntISR_NotSaveSP # do not save the stackpointer + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + +OSExtIntISR_NotSaveSP: + lis r3, INTC_IACKR@ha # store address of INTC.IACKR in r3 + lwz r3, INTC_IACKR@l(r3) # load contents of INTC.IACKR in r3 + lwz r12,0(r3) # load the base adress of Vector Table + + mtctr r12 # load Count register + bctrl # branch to ISR_Handler + + li r0, 0 # load r0 with 0x0000 + lis r3, INTC_EOIR@ha # get the address of the INTC.EOIR Register ... + stw r0, INTC_EOIR@l(r3) # and clear the INTC.EOIR register + + bl OSIntExit # call to decrement OSIntNesting + + epilogue # restore the context + + rfi # return from interrupt + + + +#********************************************************************************************************* +#* SYSTEM TICK ISR +#* +#* Description : This function is the ISR to notify uC/OS-II that a system tick has occurred. +#********************************************************************************************************* + .align 4 +OSTickISR: + prologue + + lis r11,OSIntNesting@ha # load OSIntNesting + lbz r3, OSIntNesting@l(r11) + addi r0, r3, 1 + stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + cmpwi r0, 1 # if (OSIntNesting != 1) ... + bne OSTickISR_NotSaveSP # do not save the stackpointer + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + +OSTickISR_NotSaveSP: + lis r4, 0x0800 # load r4 with TSR[DIS] bit (0x08000000) + mtspr TSR,r4 # clear TSR[DIS] bit + + bl BSP_TmrTickISR # call TmrTick handler + bl OSIntExit # call to decrement OSIntNesting + + epilogue # Restore context + + rfi # run task + + + +#********************************************************************************************************* +#* START HIGHEST PRIORITY TASK READY-TO-RUN +#* +#* Description : This function is called by OSStart() to start the highest priority task that was created +#* by the application before calling OSStart(). +#* +#* Arguments : none +#* +#* Note(s) : 1) OSStartHighRdy() MUST: +#* a) Call OSTaskSwHook() then, +#* b) Set OSRunning to TRUE, +#* c) Switch to the highest priority task by loading the stack pointer of the highest +#* priority task into the SP register and execute an rfi instruction. +#********************************************************************************************************* + .align 4 +OSStartHighRdy: + bl OSTaskSwHook # Call OSTaskSwHook + + li r0, 1 # Set OSRunning to 1 + lis r11,OSRunning@ha + stb r0, OSRunning@l(r11) + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + rfi # run task + + + +#********************************************************************************************************* +#* TASK LEVEL CONTEXT SWITCH +#* +#* Description : This function is called when a task makes a higher priority task ready-to-run. +#* +#* Arguments : none +#* +#* Note(s) : 1) Upon entry, +#* OSTCBCur points to the OS_TCB of the task to suspend +#* OSTCBHighRdy points to the OS_TCB of the task to resume +#********************************************************************************************************* + .align 4 +OSCtxSw: + prologue # Save context + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer from TCB + + epilogue # Restore context + + rfi # run task + + + +#********************************************************************************************************* +#* INTERRUPT LEVEL CONTEXT SWITCH +#* +#* Description : This function is called by OSIntExit() to perform a context switch to a task that has +#* been made ready-to-run by an ISR. +#********************************************************************************************************* + .align 4 +OSIntCtxSw: + mbar 1 + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + mbar 1 + + rfi # run task + + + +#********************************************************************************************************* +#* RETURN FROM INTERRUPT TRAP +#********************************************************************************************************* + .align 4 +RFI_trap: + rfi + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT FILE END +#********************************************************************************************************* + .end diff --git a/Ports/PowerPC/MPC55xx/GNU/os_cpu_c.c b/Ports/PowerPC/MPC55xx/GNU/os_cpu_c.c new file mode 100644 index 0000000..72caa23 --- /dev/null +++ b/Ports/PowerPC/MPC55xx/GNU/os_cpu_c.c @@ -0,0 +1,454 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC55xx Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* GLOBALS +********************************************************************************************************* +*/ + +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The SRR1 Register holds the original value of the MSR register. This value is copied +* to the MSR register by execute the rfi operation at the end of the ISR. +* +* (2) Ensure any changes to the order of stack initialization is congruent with the Stack +* Frame definitions in OS_CPU_A.s. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stkp; /* Local: Stack pointer */ + OS_CPU_SR msr; /* Local: Initial MSR */ + OS_CPU_SR srr1; /* Local: Initial SRR1 */ + + + (void)opt; /* 'opt' is not used, prevent warning */ + + msr = CPU_SR_Rd(); /* get the MSB reg value */ + srr1 = msr | 0x8000; /* set MSR[EE] bit to enable interrupts */ + + stkp = (OS_STK *)((INT32U)ptos & 0xFFFFFFF0); /* 16-byte align task's stack pointer (EABI) */ + + /* Leave buffer area for locals "above the stack" in ... */ + stkp -= OS_STK_RSVD_SIZE; /* case the compiler prolog puts variables above the stack */ + + /* Stack Frame Initialization */ + *--stkp = (INT32U)msr; /* MSR */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* EABI padding */ + *--stkp = 0; /* SPEFSCR */ + *--stkp = (INT32U)task; /* LR */ + *--stkp = 0; /* CR */ + *--stkp = 0; /* XER */ + *--stkp = 0; /* CTR */ + *--stkp = 0; /* USPRG0 */ + *--stkp = (INT32U)srr1; /* SRR1 */ + *--stkp = (INT32U)task; /* SRR0 */ + *--stkp = 0; /* R0 */ + + +#ifdef OS_SAVE_CONTEXT_WITH_FPRS /* Push 64-bit register's initial value to the stack */ + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x3100L; + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x3000L; + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x2900L; + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x2800L; + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x2700L; + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x2600L; + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x2500L; + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x2400L; + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x2300L; + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x2200L; + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x2100L; + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x2000L; + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x1900L; + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x1800L; + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x1700L; + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x1600L; + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x1500L; + *--stkp = 0x14L; /* r14 */ + *--stkp = 0x1400L; + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x0000L; + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x1200L; + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x1100L; + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x1000L; + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x9000L; + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x8000L; + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x7000L; + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x6000L; + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x5000L; + *--stkp = 0x4L; /* r04 */ + *--stkp = 0x4000L; + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = 0x0000L; + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ + *--stkp = 0x0000L; + +#else + *--stkp = 0x31L; /* r31 */ + *--stkp = 0x30L; /* r30 */ + *--stkp = 0x29L; /* r29 */ + *--stkp = 0x28L; /* r28 */ + *--stkp = 0x27L; /* r27 */ + *--stkp = 0x26L; /* r26 */ + *--stkp = 0x25L; /* r25 */ + *--stkp = 0x24L; /* r24 */ + *--stkp = 0x23L; /* r23 */ + *--stkp = 0x22L; /* r22 */ + *--stkp = 0x21L; /* r21 */ + *--stkp = 0x20L; /* r20 */ + *--stkp = 0x19L; /* r19 */ + *--stkp = 0x18L; /* r18 */ + *--stkp = 0x17L; /* r17 */ + *--stkp = 0x16L; /* r16 */ + *--stkp = 0x15L; /* r15 */ + *--stkp = 0x14L; /* r14 */ + *--stkp = (INT32U)&_SDA_BASE_; /* r13 */ + *--stkp = 0x12L; /* r12 */ + *--stkp = 0x11L; /* r11 */ + *--stkp = 0x10L; /* r10 */ + *--stkp = 0x9L; /* r09 */ + *--stkp = 0x8L; /* r08 */ + *--stkp = 0x7L; /* r07 */ + *--stkp = 0x6L; /* r06 */ + *--stkp = 0x5L; /* r05 */ + *--stkp = 0x4L; /* r04 */ + *--stkp = (INT32U)p_arg; /* r03 */ + *--stkp = (INT32U)&_SDA2_BASE_; /* r02 */ +#endif + *--stkp = 0; /* BLANK for 0xA0 size */ + *--stkp = (INT32U)ptos; /* Stack Ptr */ + + return(stkp); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PowerPC/MPC55xx/GNU/os_dbg.c b/Ports/PowerPC/MPC55xx/GNU/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/PowerPC/MPC55xx/GNU/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu.h b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..6d1816c --- /dev/null +++ b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu.h @@ -0,0 +1,146 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC56xx-VLE Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef __OS_CPU_H__ /* test for multiple inclusion */ +#define __OS_CPU_H__ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Define size of CPU stack entry */ +typedef unsigned long OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_STK_RSVD_SIZE 10 /* EABI Buffer above the stack */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PPC */ + + +/* +********************************************************************************************************* +* FLOATING POINT +* +* Note: also enable or disable "OS_SAVE_CONTEXT_WITH_FPRS .equ 1" in os_cpu_a.h +********************************************************************************************************* +*/ + +#define OS_SAVE_CONTEXT_WITH_FPRS 1 /* Enable Floating Point Capability */ + + +/* +********************************************************************************************************* +* OS Task Swicth +********************************************************************************************************* +*/ + +#if defined __GNUC__ +#define OS_TASK_SW() asm __volatile__ (" se_sc "); +#else +#define OS_TASK_SW() asm (" se_sc "); +#endif + + +/* +********************************************************************************************************* +* MPC56xx +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr); } while (0) + + +/* +********************************************************************************************************* +* Function Prototypes +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Rd (void); + +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +void OSTickISR (void); +void OSExtIntISR (void); + + +#endif /* __OS_CPU_H__ */ diff --git a/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.inc b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.inc new file mode 100644 index 0000000..7e6a36a --- /dev/null +++ b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.inc @@ -0,0 +1,331 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC56xx-VLE +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ OS_SAVE_CONTEXT_WITH_FPRS, 1 # Set to 1 for Floating Point Support; also set in os_cpu.h + + .equ USPRG0, 256 + .equ TCR, 340 + .equ TSR, 336 + .equ SPEFSCR, 512 + .equ HID0, 1008 + .equ L1CSR0, 1010 + + +#********************************************************************************************************* +#* STACK FRAME DEFINITION +#********************************************************************************************************* + + .equ XR1 ,0 + .equ XBLK ,XR1+4 + + .if OS_SAVE_CONTEXT_WITH_FPRS + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+8 + .equ XR4 ,XR3+8 + .equ XR5 ,XR4+8 + .equ XR6 ,XR5+8 + .equ XR7 ,XR6+8 + .equ XR8 ,XR7+8 + .equ XR9 ,XR8+8 + .equ XR10 ,XR9+8 + .equ XR11 ,XR10+8 + .equ XR12 ,XR11+8 + .equ XR13 ,XR12+8 + .equ XR14 ,XR13+8 + .equ XR15 ,XR14+8 + .equ XR16 ,XR15+8 + .equ XR17 ,XR16+8 + .equ XR18 ,XR17+8 + .equ XR19 ,XR18+8 + .equ XR20 ,XR19+8 + .equ XR21 ,XR20+8 + .equ XR22 ,XR21+8 + .equ XR23 ,XR22+8 + .equ XR24 ,XR23+8 + .equ XR25 ,XR24+8 + .equ XR26 ,XR25+8 + .equ XR27 ,XR26+8 + .equ XR28 ,XR27+8 + .equ XR29 ,XR28+8 + .equ XR30 ,XR29+8 + .equ XR31 ,XR30+8 + .equ XR0 ,XR31+8 + .else + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+4 + .equ XR4 ,XR3+4 + .equ XR5 ,XR4+4 + .equ XR6 ,XR5+4 + .equ XR7 ,XR6+4 + .equ XR8 ,XR7+4 + .equ XR9 ,XR8+4 + .equ XR10 ,XR9+4 + .equ XR11 ,XR10+4 + .equ XR12 ,XR11+4 + .equ XR13 ,XR12+4 + .equ XR14 ,XR13+4 + .equ XR15 ,XR14+4 + .equ XR16 ,XR15+4 + .equ XR17 ,XR16+4 + .equ XR18 ,XR17+4 + .equ XR19 ,XR18+4 + .equ XR20 ,XR19+4 + .equ XR21 ,XR20+4 + .equ XR22 ,XR21+4 + .equ XR23 ,XR22+4 + .equ XR24 ,XR23+4 + .equ XR25 ,XR24+4 + .equ XR26 ,XR25+4 + .equ XR27 ,XR26+4 + .equ XR28 ,XR27+4 + .equ XR29 ,XR28+4 + .equ XR30 ,XR29+4 + .equ XR31 ,XR30+4 + .equ XR0 ,XR31+4 + .endif + + .equ XSRR0 ,XR0+4 + .equ XSRR1 ,XSRR0+4 + .equ XUSPRG ,XSRR1+4 + .equ XCTR ,XUSPRG+4 + .equ XXER ,XCTR+4 + .equ XCR ,XXER+4 + .equ XLR ,XCR+4 + .equ XSPEFSCR,XLR+4 + .equ XPAD2 ,XSPEFSCR+4 + .equ XPAD3 ,XPAD2+4 + .equ XMSR ,XPAD3+4 + + .equ STACK_FRAME_SIZE ,XMSR+4 + + +#********************************************************************************************************* +#* PROLOGUE DEFINITION +#********************************************************************************************************* +prologue: .macro + e_add2i. r1, -STACK_FRAME_SIZE + e_stwu r1, 0(r1) + e_stw r0, XR0(r1) + + .if OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 # System Call (sc) clears the SPE bit ... + e_or2is r0, 0x0200 # ... therefore set them first + e_or2i r0, 0x0000 + mtmsr r0 + se_isync + + evstdd r2, XR2(r1) # Store GPR as 64bit Register + evstdd r3, XR3(r1) + evstdd r4, XR4(r1) + evstdd r5, XR5(r1) + evstdd r6, XR6(r1) + evstdd r7, XR7(r1) + evstdd r8, XR8(r1) + evstdd r9, XR9(r1) + evstdd r10, XR10(r1) + evstdd r11, XR11(r1) + evstdd r12, XR12(r1) + evstdd r13, XR13(r1) + evstdd r14, XR14(r1) + evstdd r15, XR15(r1) + evstdd r16, XR16(r1) + evstdd r17, XR17(r1) + evstdd r18, XR18(r1) + evstdd r19, XR19(r1) + evstdd r20, XR20(r1) + evstdd r21, XR21(r1) + evstdd r22, XR22(r1) + evstdd r23, XR23(r1) + evstdd r24, XR24(r1) + evstdd r25, XR25(r1) + evstdd r26, XR26(r1) + evstdd r27, XR27(r1) + evstdd r28, XR28(r1) + evstdd r29, XR29(r1) + evstdd r30, XR30(r1) + evstdd r31, XR31(r1) + .else + e_stw r2, XR2(r1) # Store GPR as 32bit Register + e_stw r3, XR3(r1) + e_stw r4, XR4(r1) + e_stw r5, XR5(r1) + e_stw r6, XR6(r1) + e_stw r7, XR7(r1) + e_stw r8, XR8(r1) + e_stw r9, XR9(r1) + e_stw r10, XR10(r1) + e_stw r11, XR11(r1) + e_stw r12, XR12(r1) + e_stw r13, XR13(r1) + e_stw r14, XR14(r1) + e_stw r15, XR15(r1) + e_stw r16, XR16(r1) + e_stw r17, XR17(r1) + e_stw r18, XR18(r1) + e_stw r19, XR19(r1) + e_stw r20, XR20(r1) + e_stw r21, XR21(r1) + e_stw r22, XR22(r1) + e_stw r23, XR23(r1) + e_stw r24, XR24(r1) + e_stw r25, XR25(r1) + e_stw r26, XR26(r1) + e_stw r27, XR27(r1) + e_stw r28, XR28(r1) + e_stw r29, XR29(r1) + e_stw r30, XR30(r1) + e_stw r31, XR31(r1) + .endif + + mfmsr r0 + e_stw r0, XMSR(r1) + + mfspr r0, SPEFSCR + e_stw r0, XSPEFSCR(r1) + + mfspr r0, SRR0 + e_stw r0, XSRR0(r1) + + mfspr r0, SRR1 + e_stw r0, XSRR1(r1) + + mfspr r0, USPRG0 + e_stw r0, XUSPRG(r1) + + mflr r0 + e_stw r0, XLR(r1) + + mfctr r0 + e_stw r0, XCTR(r1) + + mfxer r0 + e_stw r0, XXER(r1) + + mfcr r0 + e_stw r0, XCR(r1) + + mfmsr r0 + .endm + + +#********************************************************************************************************* +#* EPILOGUE DEFINITION +#********************************************************************************************************* +epilogue: .macro + wrteei 0 + + .if OS_SAVE_CONTEXT_WITH_FPRS + evldd r2, XR2(r1) # Load GPR as 64bit Register + evldd r3, XR3(r1) + evldd r4, XR4(r1) + evldd r5, XR5(r1) + evldd r6, XR6(r1) + evldd r7, XR7(r1) + evldd r8, XR8(r1) + evldd r9, XR9(r1) + evldd r10, XR10(r1) + evldd r11, XR11(r1) + evldd r12, XR12(r1) + evldd r13, XR13(r1) + evldd r14, XR14(r1) + evldd r15, XR15(r1) + evldd r16, XR16(r1) + evldd r17, XR17(r1) + evldd r18, XR18(r1) + evldd r19, XR19(r1) + evldd r20, XR20(r1) + evldd r21, XR21(r1) + evldd r22, XR22(r1) + evldd r23, XR23(r1) + evldd r24, XR24(r1) + evldd r25, XR25(r1) + evldd r26, XR26(r1) + evldd r27, XR27(r1) + evldd r28, XR28(r1) + evldd r29, XR29(r1) + evldd r30, XR30(r1) + evldd r31, XR31(r1) + .else + e_lwz r2, XR2(r1) # Load GPR as 32bit Register + e_lwz r3, XR3(r1) + e_lwz r4, XR4(r1) + e_lwz r5, XR5(r1) + e_lwz r6, XR6(r1) + e_lwz r7, XR7(r1) + e_lwz r8, XR8(r1) + e_lwz r9, XR9(r1) + e_lwz r10, XR10(r1) + e_lwz r11, XR11(r1) + e_lwz r12, XR12(r1) + e_lwz r13, XR13(r1) + e_lwz r14, XR14(r1) + e_lwz r15, XR15(r1) + e_lwz r16, XR16(r1) + e_lwz r17, XR17(r1) + e_lwz r18, XR18(r1) + e_lwz r19, XR19(r1) + e_lwz r20, XR20(r1) + e_lwz r21, XR21(r1) + e_lwz r22, XR22(r1) + e_lwz r23, XR23(r1) + e_lwz r24, XR24(r1) + e_lwz r25, XR25(r1) + e_lwz r26, XR26(r1) + e_lwz r27, XR27(r1) + e_lwz r28, XR28(r1) + e_lwz r29, XR29(r1) + e_lwz r30, XR30(r1) + e_lwz r31, XR31(r1) + .endif + + e_lwz r0, XCR(r1) + mtcrf 0xff,r0 + e_lwz r0, XXER(r1) + mtxer r0 + e_lwz r0, XCTR(r1) + mtctr r0 + e_lwz r0, XLR(r1) + mtlr r0 + + e_lwz r0, XSRR1(r1) + mtspr SRR1,r0 + e_lwz r0, XSRR0(r1) + mtspr SRR0,r0 + + e_lwz r0, XUSPRG(r1) + mtspr USPRG0,r0 + + e_lwz r0, XSPEFSCR(r1) + mtspr SPEFSCR,r0 + + e_lwz r0, XR0(r1) + e_add2i. r1, STACK_FRAME_SIZE + .endm + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT INCLUDE FILE END +#********************************************************************************************************* diff --git a/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.s b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.s new file mode 100644 index 0000000..860d12d --- /dev/null +++ b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_a.s @@ -0,0 +1,306 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC56xx-VLE +# CodeWarrior Compiler +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* ASM HEADER +#********************************************************************************************************* + + .include "os_cpu_a.inc" + + .section .text, text + + .extern BSP_TmrTickISR + + .extern OSTaskSwHook + .extern OSIntEnter + .extern OSIntExit + + .extern OSTCBCur # Pointer to Current Tasks TCB + .extern OSTCBHighRdy # Pointer to Highest Priority Ready Task + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSRunning + .extern OSIntNesting + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ INTC_IACKR, 0xfff48010 # Interrupt Acknowledge Register Address + .equ INTC_EOIR, 0xfff48018 # End of Interrupt Register Address + + +#********************************************************************************************************* +#* PUBLIC DECLARATIONS +#********************************************************************************************************* + + .global OSCtxSw + .global OSStartHighRdy + .global OSIntCtxSw + + .global OSTickISR + .global OSExtIntISR + + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OS_CPU_SR_Rd + + +#********************************************************************************************************* +#* ISR HANDLER FOR SW VECTOR MODE +#* +#* Description : This function is executed when IVOR4 External input interrupt (SPR 404) exception occurs. +#********************************************************************************************************* + .align 16 +OSExtIntISR: + prologue # Save context + + e_lis r11,OSIntNesting@ha # Load OSIntNesting + e_lbz r3, OSIntNesting@l(r11) + e_addi r0, r3, 1 + e_stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + e_cmpl16i r0, 1 # if (OSIntNesting != 1) ... + se_bne OSExtIntISR_NotSaveSP # Do not save the stackpointer + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + +OSExtIntISR_NotSaveSP: + e_lis r3, INTC_IACKR@h # Store address of INTC.IACKR in r3 + e_or2i r3, INTC_IACKR@l + e_lwz r3, 0(r3) # Load contents of INTC.IACKR in r3 + e_lwz r12,0(r3) # Load the base adress of Vector Table + + mtctr r12 # Load Count register + se_bctrl # Branch to ISR_Handler + + se_li r0, 0 # Load r0 with 0x0000 + e_lis r3, INTC_EOIR@h # Get the address of the INTC.EOIR Register ... + e_or2i r3, INTC_EOIR@l + e_stw r0, 0(r3) # And clear the INTC.EOIR register + + e_bl OSIntExit # Call to decrement OSIntNesting + + epilogue # Restore the context + + se_rfi # Return from interrupt + + +#********************************************************************************************************* +#* SYSTEM TICK ISR +#* +#* Description : This function is the ISR to notify uC/OS-II that a system tick has occurred. +#********************************************************************************************************* + .align 16 +OSTickISR: + prologue + + e_lis r11,OSIntNesting@ha # load OSIntNesting + e_lbz r3, OSIntNesting@l(r11) + e_addi r0, r3, 1 + e_stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + e_cmpl16i r0, 1 # if (OSIntNesting != 1) ... + se_bne OSTickISR_NotSaveSP # Do not save the stackpointer + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + +OSTickISR_NotSaveSP: + e_lis r4, 0x0800 # Load r4 with TSR[DIS] bit (0x08000000) + mtspr TSR,r4 # Clear TSR[DIS] bit + + e_bl BSP_TmrTickISR # Call TmrTick handler + e_bl OSIntExit # Call to decrement OSIntNesting + + epilogue # Restore context + + se_rfi # Run task + + +#********************************************************************************************************* +#* CRITICAL SECTION FUNCTIONS +#* +#* Description : These functions are used to enter and exit critical sections using Critical Method #3. +#* +#* OS_CPU_SR OS_CPU_SR_Save (void) +#* Get current global interrupt mask bit value from MSR +#* Disable interrupts +#* Return global interrupt mask bit +#* +#* void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr) +#* Set global interrupt mask bit on MSR according to parameter cpu_sr +#* Return +#* +#* Argument(s) : cpu_sr global interrupt mask status. +#********************************************************************************************************* + +OS_CPU_SR_Save: + mfmsr r3 + wrteei 0 + se_blr + +OS_CPU_SR_Restore: + mtmsr r3 + se_blr + + +#********************************************************************************************************* +#* READ STATUS REGISTER FUNCTION +#* +#* Description : This function is used to retrieve the status register value. +#* +#* OS_CPU_SR OS_CPU_SR_Rd (void) +#* Get current MSR value +#* Return +#********************************************************************************************************* + +OS_CPU_SR_Rd: + mfmsr r3 + se_blr + + +#********************************************************************************************************* +#* START HIGHEST PRIORITY TASK READY-TO-RUN +#* +#* Description : This function is called by OSStart() to start the highest priority task that was created +#* by the application before calling OSStart(). +#* +#* Arguments : none +#* +#* Note(s) : 1) OSStartHighRdy() MUST: +#* a) Call OSTaskSwHook() then, +#* b) Set OSRunning to TRUE, +#* c) Switch to the highest priority task by loading the stack pointer of the highest +#* priority task into the SP register and execute an rfi instruction. +#********************************************************************************************************* + .align 16 +OSStartHighRdy: + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_li r0, 1 # Set OSRunning to 1 + e_lis r11,OSRunning@ha + e_stb r0, OSRunning@l(r11) + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + se_rfi # Run task + + +#********************************************************************************************************* +#* TASK LEVEL CONTEXT SWITCH +#* +#* Description : This function is called when a task makes a higher priority task ready-to-run. +#* +#* Arguments : none +#* +#* Note(s) : 1) Upon entry, +#* OSTCBCur points to the OS_TCB of the task to suspend +#* OSTCBHighRdy points to the OS_TCB of the task to resume +#********************************************************************************************************* + .align 16 +OSCtxSw: + prologue # Save context + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB + e_lwz r11,OSTCBCur@l(r11) + e_stw r1, 0(r11) # Save stack pointer in current TCB + + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority + e_lbz r10,OSPrioHighRdy@l(r12) + + e_lis r12,OSPrioCur@ha # Save as Current Priority + e_stb r10,OSPrioCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer from TCB + + epilogue # Restore context + + se_rfi # Run task + + +#********************************************************************************************************* +#* INTERRUPT LEVEL CONTEXT SWITCH +#* +#* Description : This function is called by OSIntExit() to perform a context switch to a task that has +#* been made ready-to-run by an ISR. +#********************************************************************************************************* + .align 16 +OSIntCtxSw: + mbar 1 + + e_bl OSTaskSwHook # Call OSTaskSwHook + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + e_lwz r11,OSTCBHighRdy@l(r11) + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority + e_lbz r10,OSPrioHighRdy@l(r12) + + e_lis r12,OSPrioCur@ha # Save as Current Priority + e_stb r10,OSPrioCur@l(r12) + + e_lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + mbar 1 + + se_rfi # Run task + + +#********************************************************************************************************* +#* RETURN FROM INTERRUPT TRAP +#********************************************************************************************************* + .align 16 +RFI_trap: + se_rfi + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT FILE END +#********************************************************************************************************* + .end diff --git a/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_c.c b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_c.c new file mode 100644 index 0000000..1da23ac --- /dev/null +++ b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_cpu_c.c @@ -0,0 +1,464 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC56xx Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* GLOBALS +********************************************************************************************************* +*/ + +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 29200u) && (OS_TMR_EN > 0u) +static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 29200) && (OS_TMR_EN > 0) */ + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 29200u) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 29200u) && (OS_TMR_EN > 0u) + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 29200u) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent Compiler Warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent Compiler Warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION >= 29200u) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The SRR1 Register holds the original value of the MSR register. This value is copied +* to the MSR register by execute the rfi operation at the end of the ISR. +* +* (2) Ensure any changes to the order of stack initialization is congruent with the Stack +* Frame definitions in OS_CPU_A.s. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; /* Local: Stack pointer */ + OS_CPU_SR msr; /* Local: Initial MSR */ + OS_CPU_SR srr1; /* Local: Initial SRR1 */ + + + (void)opt; /* 'opt' is not used, prevent warning */ + + msr = OS_CPU_SR_Rd(); /* Get the MSB reg value */ + srr1 = msr | 0x8000u; /* Set MSR[EE] bit to enable interrupts */ + + p_stk = (OS_STK *)((INT32U)ptos & 0xFFFFFFF0u); /* 16-byte align task's stack pointer (EABI) */ + + /* Leave buffer area for locals "above the stack" in ...*/ + p_stk -= OS_STK_RSVD_SIZE; /* Case the compiler prolog puts Var. above the stack */ + + /* Stack Frame Initialization */ + *--p_stk = (INT32U)msr; /* MSR */ + *--p_stk = 0u; /* EABI padding */ + *--p_stk = 0u; /* EABI padding */ + *--p_stk = 0u; /* SPEFSCR */ + *--p_stk = (INT32U)task; /* LR */ + *--p_stk = 0u; /* CR */ + *--p_stk = 0u; /* XER */ + *--p_stk = 0u; /* CTR */ + *--p_stk = 0u; /* USPRG0 */ + *--p_stk = (INT32U)srr1; /* SRR1 */ + *--p_stk = (INT32U)task; /* SRR0 */ + *--p_stk = 0u; /* R0 */ + +#ifdef OS_SAVE_CONTEXT_WITH_FPRS /* Push 64-bit register's initial value to the stack */ + *--p_stk = 0x31uL; /* R31 */ + *--p_stk = 0x3100uL; + *--p_stk = 0x30uL; /* R30 */ + *--p_stk = 0x3000uL; + *--p_stk = 0x29uL; /* R29 */ + *--p_stk = 0x2900uL; + *--p_stk = 0x28uL; /* R28 */ + *--p_stk = 0x2800uL; + *--p_stk = 0x27uL; /* R27 */ + *--p_stk = 0x2700uL; + *--p_stk = 0x26uL; /* R26 */ + *--p_stk = 0x2600uL; + *--p_stk = 0x25uL; /* R25 */ + *--p_stk = 0x2500uL; + *--p_stk = 0x24uL; /* R24 */ + *--p_stk = 0x2400uL; + *--p_stk = 0x23uL; /* R23 */ + *--p_stk = 0x2300uL; + *--p_stk = 0x22uL; /* R22 */ + *--p_stk = 0x2200uL; + *--p_stk = 0x21uL; /* R21 */ + *--p_stk = 0x2100uL; + *--p_stk = 0x20uL; /* R20 */ + *--p_stk = 0x2000uL; + *--p_stk = 0x19uL; /* R19 */ + *--p_stk = 0x1900uL; + *--p_stk = 0x18uL; /* R18 */ + *--p_stk = 0x1800uL; + *--p_stk = 0x17uL; /* R17 */ + *--p_stk = 0x1700uL; + *--p_stk = 0x16uL; /* R16 */ + *--p_stk = 0x1600uL; + *--p_stk = 0x15uL; /* R15 */ + *--p_stk = 0x1500uL; + *--p_stk = 0x14uL; /* R14 */ + *--p_stk = 0x1400uL; + *--p_stk = (INT32U)&_SDA_BASE_; /* R13 */ + *--p_stk = 0x0000uL; + *--p_stk = 0x12uL; /* R12 */ + *--p_stk = 0x1200uL; + *--p_stk = 0x11uL; /* R11 */ + *--p_stk = 0x1100uL; + *--p_stk = 0x10uL; /* R10 */ + *--p_stk = 0x1000uL; + *--p_stk = 0x9uL; /* R09 */ + *--p_stk = 0x9000uL; + *--p_stk = 0x8uL; /* R08 */ + *--p_stk = 0x8000uL; + *--p_stk = 0x7uL; /* R07 */ + *--p_stk = 0x7000uL; + *--p_stk = 0x6uL; /* R06 */ + *--p_stk = 0x6000uL; + *--p_stk = 0x5uL; /* R05 */ + *--p_stk = 0x5000uL; + *--p_stk = 0x4uL; /* R04 */ + *--p_stk = 0x4000uL; + *--p_stk = (INT32U)p_arg; /* R03 */ + *--p_stk = 0x0000uL; + *--p_stk = (INT32U)&_SDA2_BASE_; /* R02 */ + *--p_stk = 0x0000uL; +#else + *--p_stk = 0x31uL; /* R31 */ + *--p_stk = 0x30uL; /* R30 */ + *--p_stk = 0x29uL; /* R29 */ + *--p_stk = 0x28uL; /* R28 */ + *--p_stk = 0x27uL; /* R27 */ + *--p_stk = 0x26uL; /* R26 */ + *--p_stk = 0x25uL; /* R25 */ + *--p_stk = 0x24uL; /* R24 */ + *--p_stk = 0x23uL; /* R23 */ + *--p_stk = 0x22uL; /* R22 */ + *--p_stk = 0x21uL; /* R21 */ + *--p_stk = 0x20uL; /* R20 */ + *--p_stk = 0x19uL; /* R19 */ + *--p_stk = 0x18uL; /* R18 */ + *--p_stk = 0x17uL; /* R17 */ + *--p_stk = 0x16uL; /* R16 */ + *--p_stk = 0x15uL; /* R15 */ + *--p_stk = 0x14uL; /* R14 */ + *--p_stk = (INT32U)&_SDA_BASE_; /* R13 */ + *--p_stk = 0x12uL; /* R12 */ + *--p_stk = 0x11uL; /* R11 */ + *--p_stk = 0x10uL; /* R10 */ + *--p_stk = 0x9uL; /* R09 */ + *--p_stk = 0x8uL; /* R08 */ + *--p_stk = 0x7uL; /* R07 */ + *--p_stk = 0x6uL; /* R06 */ + *--p_stk = 0x5uL; /* R05 */ + *--p_stk = 0x4uL; /* R04 */ + *--p_stk = (INT32U)p_arg; /* R03 */ + *--p_stk = (INT32U)&_SDA2_BASE_; /* R02 */ +#endif + *--p_stk = 0u; /* BLANK for 0xA0 size */ + *--p_stk = (INT32U)ptos; /* Stack Ptr */ + + return(p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 29200u) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent Compiler Warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 29200u) && (OS_TMR_EN > 0u) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_dbg.c b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..a9ec78f --- /dev/null +++ b/Ports/PowerPC/MPC56xx-VLE/CodeWarrior/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu.h b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..94cdb0f --- /dev/null +++ b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu.h @@ -0,0 +1,146 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC56xx Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef __OS_CPU_H__ /* test for multiple inclusion */ +#define __OS_CPU_H__ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Define size of CPU stack entry */ +typedef unsigned long OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_STK_RSVD_SIZE 10 /* EABI Buffer above the stack */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PPC */ + + +/* +********************************************************************************************************* +* FLOATING POINT +* +* Note: also enable or disable "OS_SAVE_CONTEXT_WITH_FPRS .equ 1" in os_cpu_a.h +********************************************************************************************************* +*/ + +#define OS_SAVE_CONTEXT_WITH_FPRS 1 /* Enable Floating Point Capability */ + + +/* +********************************************************************************************************* +* OS Task Switch +********************************************************************************************************* +*/ + +#if defined __GNUC__ +#define OS_TASK_SW() asm __volatile__ (" sc "); +#else +#define OS_TASK_SW() asm (" sc "); +#endif + + +/* +********************************************************************************************************* +* MPC56xx +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save(); } while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr); } while (0) + + +/* +********************************************************************************************************* +* Function Prototypes +********************************************************************************************************* +*/ + +OS_CPU_SR OS_CPU_SR_Rd (void); + +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +void OSTickISR (void); +void OSExtIntISR (void); + + +#endif /* __OS_CPU_H__ */ diff --git a/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.inc b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.inc new file mode 100644 index 0000000..877eae8 --- /dev/null +++ b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.inc @@ -0,0 +1,331 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC56xx +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ OS_SAVE_CONTEXT_WITH_FPRS, 1 # Set to 1 for Floating Point Support; also set in os_cpu.h + + .equ USPRG0, 256 + .equ TCR, 340 + .equ TSR, 336 + .equ SPEFSCR, 512 + .equ HID0, 1008 + .equ L1CSR0, 1010 + + +#********************************************************************************************************* +#* STACK FRAME DEFINITION +#********************************************************************************************************* + + .equ XR1 ,0 + .equ XBLK ,XR1+4 + + .if OS_SAVE_CONTEXT_WITH_FPRS + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+8 + .equ XR4 ,XR3+8 + .equ XR5 ,XR4+8 + .equ XR6 ,XR5+8 + .equ XR7 ,XR6+8 + .equ XR8 ,XR7+8 + .equ XR9 ,XR8+8 + .equ XR10 ,XR9+8 + .equ XR11 ,XR10+8 + .equ XR12 ,XR11+8 + .equ XR13 ,XR12+8 + .equ XR14 ,XR13+8 + .equ XR15 ,XR14+8 + .equ XR16 ,XR15+8 + .equ XR17 ,XR16+8 + .equ XR18 ,XR17+8 + .equ XR19 ,XR18+8 + .equ XR20 ,XR19+8 + .equ XR21 ,XR20+8 + .equ XR22 ,XR21+8 + .equ XR23 ,XR22+8 + .equ XR24 ,XR23+8 + .equ XR25 ,XR24+8 + .equ XR26 ,XR25+8 + .equ XR27 ,XR26+8 + .equ XR28 ,XR27+8 + .equ XR29 ,XR28+8 + .equ XR30 ,XR29+8 + .equ XR31 ,XR30+8 + .equ XR0 ,XR31+8 + .else + .equ XR2 ,XBLK+4 + .equ XR3 ,XR2+4 + .equ XR4 ,XR3+4 + .equ XR5 ,XR4+4 + .equ XR6 ,XR5+4 + .equ XR7 ,XR6+4 + .equ XR8 ,XR7+4 + .equ XR9 ,XR8+4 + .equ XR10 ,XR9+4 + .equ XR11 ,XR10+4 + .equ XR12 ,XR11+4 + .equ XR13 ,XR12+4 + .equ XR14 ,XR13+4 + .equ XR15 ,XR14+4 + .equ XR16 ,XR15+4 + .equ XR17 ,XR16+4 + .equ XR18 ,XR17+4 + .equ XR19 ,XR18+4 + .equ XR20 ,XR19+4 + .equ XR21 ,XR20+4 + .equ XR22 ,XR21+4 + .equ XR23 ,XR22+4 + .equ XR24 ,XR23+4 + .equ XR25 ,XR24+4 + .equ XR26 ,XR25+4 + .equ XR27 ,XR26+4 + .equ XR28 ,XR27+4 + .equ XR29 ,XR28+4 + .equ XR30 ,XR29+4 + .equ XR31 ,XR30+4 + .equ XR0 ,XR31+4 + .endif + + + .equ XSRR0 ,XR0+4 + .equ XSRR1 ,XSRR0+4 + .equ XUSPRG ,XSRR1+4 + .equ XCTR ,XUSPRG+4 + .equ XXER ,XCTR+4 + .equ XCR ,XXER+4 + .equ XLR ,XCR+4 + .equ XSPEFSCR,XLR+4 + .equ XPAD2 ,XSPEFSCR+4 + .equ XPAD3 ,XPAD2+4 + .equ XMSR ,XPAD3+4 + + .equ STACK_FRAME_SIZE ,XMSR+4 + + +#********************************************************************************************************* +#* PROLOGUE DEFINITION +#********************************************************************************************************* +prologue: .macro + stwu r1, -STACK_FRAME_SIZE(r1) + stw r0, XR0(r1) + + .if OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 # System Call (sc) clears the SPE bit ... + oris r0, r0,0x0200 # ... therefore set them first + ori r0, r0,0x0000 + mtmsr r0 + isync + + evstdd r2, XR2(r1) # Store GPR as 64bit Register + evstdd r3, XR3(r1) + evstdd r4, XR4(r1) + evstdd r5, XR5(r1) + evstdd r6, XR6(r1) + evstdd r7, XR7(r1) + evstdd r8, XR8(r1) + evstdd r9, XR9(r1) + evstdd r10, XR10(r1) + evstdd r11, XR11(r1) + evstdd r12, XR12(r1) + evstdd r13, XR13(r1) + evstdd r14, XR14(r1) + evstdd r15, XR15(r1) + evstdd r16, XR16(r1) + evstdd r17, XR17(r1) + evstdd r18, XR18(r1) + evstdd r19, XR19(r1) + evstdd r20, XR20(r1) + evstdd r21, XR21(r1) + evstdd r22, XR22(r1) + evstdd r23, XR23(r1) + evstdd r24, XR24(r1) + evstdd r25, XR25(r1) + evstdd r26, XR26(r1) + evstdd r27, XR27(r1) + evstdd r28, XR28(r1) + evstdd r29, XR29(r1) + evstdd r30, XR30(r1) + evstdd r31, XR31(r1) + .else + stw r2, XR2(r1) # Store GPR as 32bit Register + stw r3, XR3(r1) + stw r4, XR4(r1) + stw r5, XR5(r1) + stw r6, XR6(r1) + stw r7, XR7(r1) + stw r8, XR8(r1) + stw r9, XR9(r1) + stw r10, XR10(r1) + stw r11, XR11(r1) + stw r12, XR12(r1) + stw r13, XR13(r1) + stw r14, XR14(r1) + stw r15, XR15(r1) + stw r16, XR16(r1) + stw r17, XR17(r1) + stw r18, XR18(r1) + stw r19, XR19(r1) + stw r20, XR20(r1) + stw r21, XR21(r1) + stw r22, XR22(r1) + stw r23, XR23(r1) + stw r24, XR24(r1) + stw r25, XR25(r1) + stw r26, XR26(r1) + stw r27, XR27(r1) + stw r28, XR28(r1) + stw r29, XR29(r1) + stw r30, XR30(r1) + stw r31, XR31(r1) + .endif + + mfmsr r0 + stw r0, XMSR(r1) + + mfspr r0, SPEFSCR + stw r0, XSPEFSCR(r1) + + mfspr r0, SRR0 + stw r0, XSRR0(r1) + + mfspr r0, SRR1 + stw r0, XSRR1(r1) + + mfspr r0, USPRG0 + stw r0, XUSPRG(r1) + + mflr r0 + stw r0, XLR(r1) + + mfctr r0 + stw r0, XCTR(r1) + + mfxer r0 + stw r0, XXER(r1) + + mfcr r0 + stw r0, XCR(r1) + + mfmsr r0 + .endm + + +#********************************************************************************************************* +#* EPILOGUE DEFINITION +#********************************************************************************************************* +epilogue: .macro + wrteei 0 + + .if OS_SAVE_CONTEXT_WITH_FPRS + evldd r2, XR2(r1) # Load GPR as 64bit Register + evldd r3, XR3(r1) + evldd r4, XR4(r1) + evldd r5, XR5(r1) + evldd r6, XR6(r1) + evldd r7, XR7(r1) + evldd r8, XR8(r1) + evldd r9, XR9(r1) + evldd r10, XR10(r1) + evldd r11, XR11(r1) + evldd r12, XR12(r1) + evldd r13, XR13(r1) + evldd r14, XR14(r1) + evldd r15, XR15(r1) + evldd r16, XR16(r1) + evldd r17, XR17(r1) + evldd r18, XR18(r1) + evldd r19, XR19(r1) + evldd r20, XR20(r1) + evldd r21, XR21(r1) + evldd r22, XR22(r1) + evldd r23, XR23(r1) + evldd r24, XR24(r1) + evldd r25, XR25(r1) + evldd r26, XR26(r1) + evldd r27, XR27(r1) + evldd r28, XR28(r1) + evldd r29, XR29(r1) + evldd r30, XR30(r1) + evldd r31, XR31(r1) + .else + lwz r2, XR2(r1) # Load GPR as 32bit Register + lwz r3, XR3(r1) + lwz r4, XR4(r1) + lwz r5, XR5(r1) + lwz r6, XR6(r1) + lwz r7, XR7(r1) + lwz r8, XR8(r1) + lwz r9, XR9(r1) + lwz r10, XR10(r1) + lwz r11, XR11(r1) + lwz r12, XR12(r1) + lwz r13, XR13(r1) + lwz r14, XR14(r1) + lwz r15, XR15(r1) + lwz r16, XR16(r1) + lwz r17, XR17(r1) + lwz r18, XR18(r1) + lwz r19, XR19(r1) + lwz r20, XR20(r1) + lwz r21, XR21(r1) + lwz r22, XR22(r1) + lwz r23, XR23(r1) + lwz r24, XR24(r1) + lwz r25, XR25(r1) + lwz r26, XR26(r1) + lwz r27, XR27(r1) + lwz r28, XR28(r1) + lwz r29, XR29(r1) + lwz r30, XR30(r1) + lwz r31, XR31(r1) + .endif + + lwz r0, XCR(r1) + mtcrf 0xff,r0 + lwz r0, XXER(r1) + mtxer r0 + lwz r0, XCTR(r1) + mtctr r0 + lwz r0, XLR(r1) + mtlr r0 + + lwz r0, XSRR1(r1) + mtspr SRR1,r0 + lwz r0, XSRR0(r1) + mtspr SRR0,r0 + + lwz r0, XUSPRG(r1) + mtspr USPRG0,r0 + + lwz r0, XSPEFSCR(r1) + mtspr SPEFSCR,r0 + + lwz r0, XR0(r1) + addi r1, r1, STACK_FRAME_SIZE + .endm + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT INCLUDE FILE END +#********************************************************************************************************* diff --git a/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.s b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.s new file mode 100644 index 0000000..af09653 --- /dev/null +++ b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_a.s @@ -0,0 +1,304 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC56xx +# CodeWarrior Compiler +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* ASM HEADER +#********************************************************************************************************* + + .include "os_cpu_a.inc" + + .section .text, text + + .extern BSP_TmrTickISR + + .extern OSTaskSwHook + .extern OSIntEnter + .extern OSIntExit + + .extern OSTCBCur # Pointer to Current Tasks TCB + .extern OSTCBHighRdy # Pointer to Highest Priority Ready Task + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSRunning + .extern OSIntNesting + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ INTC_IACKR, 0xfff48010 # Interrupt Acknowledge Register Address + .equ INTC_EOIR, 0xfff48018 # End of Interrupt Register Address + + +#********************************************************************************************************* +#* PUBLIC DECLARATIONS +#********************************************************************************************************* + + .global OSCtxSw + .global OSStartHighRdy + .global OSIntCtxSw + + .global OSTickISR + .global OSExtIntISR + + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OS_CPU_SR_Rd + + +#********************************************************************************************************* +#* ISR HANDLER FOR SW VECTOR MODE +#* +#* Description : This function is executed when IVOR4 External input interrupt (SPR 404) exception occurs. +#********************************************************************************************************* + .align 16 +OSExtIntISR: + prologue # Save context + + lis r11,OSIntNesting@ha # Load OSIntNesting + lbz r3, OSIntNesting@l(r11) + addi r0, r3, 1 + stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + cmpwi r0, 1 # if (OSIntNesting != 1) ... + bne OSExtIntISR_NotSaveSP # Do not save the stackpointer + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + +OSExtIntISR_NotSaveSP: + lis r3, INTC_IACKR@ha # Store address of INTC.IACKR in r3 + lwz r3, INTC_IACKR@l(r3) # Load contents of INTC.IACKR in r3 + lwz r12,0(r3) # Load the base adress of Vector Table + + mtctr r12 # Load Count register + bctrl # Branch to ISR_Handler + + li r0, 0 # Load r0 with 0x0000 + lis r3, INTC_EOIR@ha # Get the address of the INTC.EOIR Register ... + stw r0, INTC_EOIR@l(r3) # and clear the INTC.EOIR register + + bl OSIntExit # Call to decrement OSIntNesting + + epilogue # Restore the context + + rfi # Return from interrupt + + +#********************************************************************************************************* +#* SYSTEM TICK ISR +#* +#* Description : This function is the ISR to notify uC/OS-II that a system tick has occurred. +#********************************************************************************************************* + .align 16 +OSTickISR: + prologue + + lis r11,OSIntNesting@ha # Load OSIntNesting + lbz r3, OSIntNesting@l(r11) + addi r0, r3, 1 + stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + cmpwi r0, 1 # if (OSIntNesting != 1) ... + bne OSTickISR_NotSaveSP # do not save the stackpointer + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + +OSTickISR_NotSaveSP: + lis r4, 0x0800 # Load r4 with TSR[DIS] bit (0x08000000) + mtspr TSR,r4 # Clear TSR[DIS] bit + + bl BSP_TmrTickISR # Call TmrTick handler + bl OSIntExit # Call to decrement OSIntNesting + + epilogue # Restore context + + rfi # Run task + + +#********************************************************************************************************* +#* CRITICAL SECTION FUNCTIONS +#* +#* Description : These functions are used to enter and exit critical sections using Critical Method #3. +#* +#* OS_CPU_SR OS_CPU_SR_Save (void) +#* Get current global interrupt mask bit value from MSR +#* Disable interrupts +#* Return global interrupt mask bit +#* +#* void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr) +#* Set global interrupt mask bit on MSR according to parameter cpu_sr +#* Return +#* +#* Argument(s) : cpu_sr global interrupt mask status. +#********************************************************************************************************* + +OS_CPU_SR_Save: + mfmsr r3 + wrteei 0 + blr + +OS_CPU_SR_Restore: + mtmsr r3 + blr + + +#********************************************************************************************************* +#* READ STATUS REGISTER FUNCTION +#* +#* Description : This function is used to retrieve the status register value. +#* +#* OS_CPU_SR OS_CPU_SR_Rd (void) +#* Get current MSR value +#* Return +#********************************************************************************************************* + +OS_CPU_SR_Rd: + mfmsr r3 + blr + + +#********************************************************************************************************* +#* START HIGHEST PRIORITY TASK READY-TO-RUN +#* +#* Description : This function is called by OSStart() to start the highest priority task that was created +#* by the application before calling OSStart(). +#* +#* Arguments : none +#* +#* Note(s) : 1) OSStartHighRdy() MUST: +#* a) Call OSTaskSwHook() then, +#* b) Set OSRunning to TRUE, +#* c) Switch to the highest priority task by loading the stack pointer of the highest +#* priority task into the SP register and execute an rfi instruction. +#********************************************************************************************************* + .align 16 +OSStartHighRdy: + bl OSTaskSwHook # Call OSTaskSwHook + + li r0, 1 # Set OSRunning to 1 + lis r11,OSRunning@ha + stb r0, OSRunning@l(r11) + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + rfi # Run task + + +#********************************************************************************************************* +#* TASK LEVEL CONTEXT SWITCH +#* +#* Description : This function is called when a task makes a higher priority task ready-to-run. +#* +#* Arguments : none +#* +#* Note(s) : 1) Upon entry, +#* OSTCBCur points to the OS_TCB of the task to suspend +#* OSTCBHighRdy points to the OS_TCB of the task to resume +#********************************************************************************************************* + .align 16 +OSCtxSw: + prologue # Save context + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer from TCB + + epilogue # Restore context + + rfi # Run task + + +#********************************************************************************************************* +#* INTERRUPT LEVEL CONTEXT SWITCH +#* +#* Description : This function is called by OSIntExit() to perform a context switch to a task that has +#* been made ready-to-run by an ISR. +#********************************************************************************************************* + .align 16 +OSIntCtxSw: + mbar 1 + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + + mbar 1 + + rfi # Run task + + +#********************************************************************************************************* +#* RETURN FROM INTERRUPT TRAP +#********************************************************************************************************* + .align 16 +RFI_trap: + rfi + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT FILE END +#********************************************************************************************************* + .end diff --git a/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_c.c b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_c.c new file mode 100644 index 0000000..41c9791 --- /dev/null +++ b/Ports/PowerPC/MPC56xx/CodeWarrior/os_cpu_c.c @@ -0,0 +1,464 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC56xx Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* GLOBALS +********************************************************************************************************* +*/ + +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 29200u) && (OS_TMR_EN > 0u) +static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 29200) && (OS_TMR_EN > 0) */ + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 29200u) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 29200u) && (OS_TMR_EN > 0u) + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 29200u) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION >= 29200u) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The SRR1 Register holds the original value of the MSR register. This value is copied +* to the MSR register by execute the rfi operation at the end of the ISR. +* +* (2) Ensure any changes to the order of stack initialization is congruent with the Stack +* Frame definitions in OS_CPU_A.s. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; /* Local: Stack pointer */ + OS_CPU_SR msr; /* Local: Initial MSR */ + OS_CPU_SR srr1; /* Local: Initial SRR1 */ + + + (void)opt; /* 'opt' is not used, prevent warning */ + + msr = OS_CPU_SR_Rd(); /* Get the MSB Reg value */ + srr1 = msr | 0x8000u; /* Set MSR[EE] bit to enable interrupts */ + + p_stk = (OS_STK *)((INT32U)ptos & 0xFFFFFFF0u); /* 16-byte align task's stack pointer (EABI) */ + + /* Leave buffer area for locals "above the stack" in ...*/ + p_stk -= OS_STK_RSVD_SIZE; /* Case the compiler prolog puts Var. above the stack */ + + /* Stack Frame Initialization */ + *--p_stk = (INT32U)msr; /* MSR */ + *--p_stk = 0u; /* EABI padding */ + *--p_stk = 0u; /* EABI padding */ + *--p_stk = 0u; /* SPEFSCR */ + *--p_stk = (INT32U)task; /* LR */ + *--p_stk = 0u; /* CR */ + *--p_stk = 0u; /* XER */ + *--p_stk = 0u; /* CTR */ + *--p_stk = 0u; /* USPRG0 */ + *--p_stk = (INT32U)srr1; /* SRR1 */ + *--p_stk = (INT32U)task; /* SRR0 */ + *--p_stk = 0u; /* R0 */ + +#ifdef OS_SAVE_CONTEXT_WITH_FPRS /* Push 64-bit Register's Initial Value to the Stack */ + *--p_stk = 0x31uL; /* R31 */ + *--p_stk = 0x3100uL; + *--p_stk = 0x30uL; /* R30 */ + *--p_stk = 0x3000uL; + *--p_stk = 0x29uL; /* R29 */ + *--p_stk = 0x2900uL; + *--p_stk = 0x28uL; /* R28 */ + *--p_stk = 0x2800uL; + *--p_stk = 0x27uL; /* R27 */ + *--p_stk = 0x2700uL; + *--p_stk = 0x26uL; /* R26 */ + *--p_stk = 0x2600uL; + *--p_stk = 0x25uL; /* R25 */ + *--p_stk = 0x2500uL; + *--p_stk = 0x24uL; /* R24 */ + *--p_stk = 0x2400uL; + *--p_stk = 0x23uL; /* R23 */ + *--p_stk = 0x2300uL; + *--p_stk = 0x22uL; /* R22 */ + *--p_stk = 0x2200uL; + *--p_stk = 0x21uL; /* R21 */ + *--p_stk = 0x2100uL; + *--p_stk = 0x20uL; /* R20 */ + *--p_stk = 0x2000uL; + *--p_stk = 0x19uL; /* R19 */ + *--p_stk = 0x1900uL; + *--p_stk = 0x18uL; /* R18 */ + *--p_stk = 0x1800uL; + *--p_stk = 0x17uL; /* R17 */ + *--p_stk = 0x1700uL; + *--p_stk = 0x16uL; /* R16 */ + *--p_stk = 0x1600uL; + *--p_stk = 0x15uL; /* R15 */ + *--p_stk = 0x1500uL; + *--p_stk = 0x14uL; /* R14 */ + *--p_stk = 0x1400uL; + *--p_stk = (INT32U)&_SDA_BASE_; /* R13 */ + *--p_stk = 0x0000uL; + *--p_stk = 0x12uL; /* R12 */ + *--p_stk = 0x1200uL; + *--p_stk = 0x11uL; /* R11 */ + *--p_stk = 0x1100uL; + *--p_stk = 0x10uL; /* R10 */ + *--p_stk = 0x1000uL; + *--p_stk = 0x9uL; /* R09 */ + *--p_stk = 0x9000uL; + *--p_stk = 0x8uL; /* R08 */ + *--p_stk = 0x8000uL; + *--p_stk = 0x7uL; /* R07 */ + *--p_stk = 0x7000uL; + *--p_stk = 0x6uL; /* R06 */ + *--p_stk = 0x6000uL; + *--p_stk = 0x5uL; /* R05 */ + *--p_stk = 0x5000uL; + *--p_stk = 0x4uL; /* R04 */ + *--p_stk = 0x4000uL; + *--p_stk = (INT32U)p_arg; /* R03 */ + *--p_stk = 0x0000uL; + *--p_stk = (INT32U)&_SDA2_BASE_; /* R02 */ + *--p_stk = 0x0000uL; +#else + *--p_stk = 0x31uL; /* R31 */ + *--p_stk = 0x30uL; /* R30 */ + *--p_stk = 0x29uL; /* R29 */ + *--p_stk = 0x28uL; /* R28 */ + *--p_stk = 0x27uL; /* R27 */ + *--p_stk = 0x26uL; /* R26 */ + *--p_stk = 0x25uL; /* R25 */ + *--p_stk = 0x24uL; /* R24 */ + *--p_stk = 0x23uL; /* R23 */ + *--p_stk = 0x22uL; /* R22 */ + *--p_stk = 0x21uL; /* R21 */ + *--p_stk = 0x20uL; /* R20 */ + *--p_stk = 0x19uL; /* R19 */ + *--p_stk = 0x18uL; /* R18 */ + *--p_stk = 0x17uL; /* R17 */ + *--p_stk = 0x16uL; /* R16 */ + *--p_stk = 0x15uL; /* R15 */ + *--p_stk = 0x14uL; /* R14 */ + *--p_stk = (INT32U)&_SDA_BASE_; /* R13 */ + *--p_stk = 0x12uL; /* R12 */ + *--p_stk = 0x11uL; /* R11 */ + *--p_stk = 0x10uL; /* R10 */ + *--p_stk = 0x9uL; /* R09 */ + *--p_stk = 0x8uL; /* R08 */ + *--p_stk = 0x7uL; /* R07 */ + *--p_stk = 0x6uL; /* R06 */ + *--p_stk = 0x5uL; /* R05 */ + *--p_stk = 0x4uL; /* R04 */ + *--p_stk = (INT32U)p_arg; /* R03 */ + *--p_stk = (INT32U)&_SDA2_BASE_; /* R02 */ +#endif + *--p_stk = 0u; /* BLANK for 0xA0 size */ + *--p_stk = (INT32U)ptos; /* Stack Ptr */ + + return(p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 29200u) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 29200u) && (OS_TMR_EN > 0u) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PowerPC/MPC56xx/CodeWarrior/os_dbg.c b/Ports/PowerPC/MPC56xx/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..a9ec78f --- /dev/null +++ b/Ports/PowerPC/MPC56xx/CodeWarrior/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu.h b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu.h new file mode 100644 index 0000000..0940b63 --- /dev/null +++ b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu.h @@ -0,0 +1,166 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MPC57xx VLE Port +* GNU Toolchain +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#ifndef OS_CPU_ISR_STK_SIZE +#define OS_CPU_ISR_STK_SIZE 256u /* Default ISR stack size is 256 OS_STK entries */ +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; /* 8-bit boolean or logical */ +typedef unsigned char INT8U; /* 8-bit unsigned integer */ +typedef signed char INT8S; /* 8-bit signed integer */ +typedef unsigned short INT16U; /* 16-bit unsigned integer */ +typedef signed short INT16S; /* 16-bit signed integer */ +typedef unsigned long INT32U; /* 32-bit unsigned integer */ +typedef signed long INT32S; /* 32-bit signed integer */ +typedef float FP32; /* 32-bit floating point */ +typedef double FP64; /* 64-bit floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* MACROS +* +* Note(s): OS_TASK_SW() invokes the task level context switch. +* +* (1) On some processors, this corresponds to a call to OSCtxSw() which is an assembly language +* function that performs the context switch. +* +* (2) On some processors, you need to simulate an interrupt using a 'software interrupt' or a +* TRAP instruction. Some compilers allow you to add in-line assembly language as shown. +********************************************************************************************************* +*/ + +#define OS_TASK_SW() asm __volatile__ (" se_sc "); +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OS_CPU_IntHandler(void); + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.S b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.S new file mode 100644 index 0000000..f13a1b4 --- /dev/null +++ b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.S @@ -0,0 +1,464 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# MPC57xx VLE Port +# GNU Toolchain +# +# Filename : os_cpu_a.S +# Version : V2.93.00 +#******************************************************************************************************** + + + .include "os_cpu_a.inc" + +#******************************************************************************************************** +# PUBLIC FUNCTIONS +#******************************************************************************************************** + + .global OSStartHighRdy + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSCtxSw + .global OSIntCtxSw + + .global OS_ExceptHandler_CriticalInput + .global OS_ExceptHandler_MachineCheck + .global OS_ExceptHandler_DataStorage + .global OS_ExceptHandler_InstructionStorage + .global OS_ExceptHandler_ExternalInput + .global OS_ExceptHandler_Alignment + .global OS_ExceptHandler_Program + .global OS_ExceptHandler_PerformanceMonitor + .global OS_ExceptHandler_SystemCall + .global OS_ExceptHandler_Debug + .global OS_ExceptHandler_EFPUDataException + .global OS_ExceptHandler_EFPURoundException + .global OS_ExceptHandler_EFPUUnavailable + .global OS_ExceptHandler_IVOR13 + .global OS_ExceptHandler_IVOR14 + .global OS_ExceptHandler_IVOR15 + + + .extern OSTCBCur # 4 bytes + .extern OSTCBHighRdy # 4 bytes + .extern OSPrioCur # 1 byte + .extern OSPrioHighRdy # 1 byte + .extern OSTaskSwHook # 4 bytes + .extern OS_CPU_IntHandler # 4 bytes + .extern OSIntNestingCtr # 4 bytes + .extern OS_CPU_ISRStkBase # 4 bytes + .extern OS_CPU_ISRNestingCtr # 1 byte + + +#******************************************************************************************************** +# CODE GENERATION DIRECTIVES +#******************************************************************************************************** + + .section .text + + +#******************************************************************************************************** +# CRITICAL SECTION METHOD 3 FUNCTIONS +# +# Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +# would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +# disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +# disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +# into the CPU's status register. +# +# Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +# void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +# +# +# Note(s) : 1) These functions are used in general like this: +# +# void Task (void *p_arg) +# { +# #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +# OS_CPU_SR cpu_sr; +# #endif +# +# : +# : +# OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +# : +# : +# OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +# : +# : +# } +#******************************************************************************************************* + +OS_CPU_SR_Save: + mfmsr r3 + wrteei 0 + se_blr + +OS_CPU_SR_Restore: + wrtee r3 + se_blr + + +#******************************************************************************************************** +# START MULTITASKING +# +# Description : This function is called by OSStart() to start the highest priority task that was created +# by your application before calling OSStart(). +# +# Arguments : none +# +# Note(s) : 1) See Note #2 of OSTaskStkInit() in os_cpu.h for the stack frame's layout. +# +# 2) OSStartHighRdy() MUST: +# a) Call OSTaskSwHook() then, +# b) Switch to the highest priority task. +#******************************************************************************************************** + +OSStartHighRdy: + e_bl OSTaskSwHook # Call OSTaskSwHook. + + e_li r0, 1 # Set OSRunning to 1. + e_lis r11,OSRunning@ha # ... + e_stb r0,OSRunning@l(r11) # ... + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB. + e_lwz r11,OSTCBHighRdy@l(r11) # ... + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) # ... + + e_lwz r1, 0(r11) # Get new stack pointer. + + epilogue # Restore context. + + se_rfi # Run task. + + +#******************************************************************************************************** +# EXCEPTION VECTORS +#******************************************************************************************************** + +#******************************************************************************************************** +# OS_ExceptHandler_CriticalInput +# IVOR0 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_CriticalInput: + e_b OS_ExceptHandler_CriticalInput + + +#******************************************************************************************************** +# OS_ExceptHandler_MachineCheck +# IVOR1 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_MachineCheck: + e_b OS_ExceptHandler_MachineCheck + + +#******************************************************************************************************** +# OS_ExceptHandler_DataStorage +# IVOR2 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_DataStorage: + e_b OS_ExceptHandler_DataStorage + + +#******************************************************************************************************** +# OS_ExceptHandler_InstructionStorage +# IVOR3 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_InstructionStorage: + e_b OS_ExceptHandler_InstructionStorage + + +#******************************************************************************************************** +# OS_ExceptHandler_ExternalInput +# IVOR4 +# +# Description: Switches to interrupt stack and calls the user-defined function +# void OS_CPU_IntHandler(void). +#******************************************************************************************************** + +OS_ExceptHandler_ExternalInput: + prologue + + e_lis r11,OS_CPU_ISRNestingCtr@ha # Increment the ISR nesting counter to reflect the current nesting level. + e_or2i r11,OS_CPU_ISRNestingCtr@l # ... + e_lwz r12,0(r11) # ... + e_add2i. r12,1 # ... + e_stw r12,0(r11) # ... + + e_cmpl16i r12,1 # Check to see if we are the first interrupt. + e_bgt IntStkInUse # If we are nested the ISR stack is already being used. + # Otherwise, the first interrupt must switch to the ISR stack. + + e_lis r11,OSTCBCur@ha # Get a pointer to current TCB. + e_lwz r11,OSTCBCur@l(r11) # ... + e_stw r1,0(r11) # Save the current stack pointer in the current TCB. + + e_lis r11,OS_CPU_ISRStkBase@ha # Get a pointer to 8-byte aligned base of the ISR stack. + e_lwz r11,OS_CPU_ISRStkBase@l(r11) # ... + mr r1,r11 # Switch to the ISR stack. + + +IntStkInUse: + ### ALLOCATE INITIAL FRAME OF THE ISR CALL STACK ### + e_stwu 0,-4(r1) # Clear the initial frame (Backchain must be null according to EABI) + e_stwu 0,-4(r1) # ... + + e_bl OS_CPU_IntHandler # Unnested kernel-aware interrupts will return through OSIntCtxSw. + + ### NESTED OR FAST ISRS ONLY ### + wrteei 0 # OS_CPU_IntHandler may have enabled interrupts. Make sure they are disabled. + + e_add2i. r1,8 ### DEALLOCATE INITIAL FRAME OF THE ISR CALL STACK ### + + e_lis r11,OS_CPU_ISRNestingCtr@ha # Decrement the ISR nesting counter to reflect the current nesting level. + e_or2i r11,OS_CPU_ISRNestingCtr@l # ... + e_lwz r12,0(r11) # ... + e_add2i. r12,-1 # ... + e_stw r12,0(r11) # ... + + e_cmpl16i r12,0 # Check to see if we are nested. + e_bgt NestedReturn # If we are, the previous frame is in the ISR stack. + # Otherwise, we must switch back to the task stack. + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB. + e_lwz r11,OSTCBCur@l(r11) # ... + e_lwz r1,0(r11) # Load stack pointer from current TCB. + + +NestedReturn: + epilogue # If we are nested or not kernel-aware, pop the previous ISR context and rfi. + + se_rfi + + +#******************************************************************************************************** +# PERFORM A CONTEXT SWITCH (From an ISR) +# +# Description : This routine is called when an ISR makes a higher priority task ready-to-run. +# +# Interrupts should be disabled by the kernel before this point. +#******************************************************************************************************** + +OSIntCtxSw: + e_bl OSTaskSwHook # Call OSTaskSwHook. + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB. + e_lwz r11,OSTCBHighRdy@l(r11) # ... + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) # ... + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority. + e_lbz r10,OSPrioHighRdy@l(r12) # ... + + e_lis r12,OSPrioCur@ha # Save as Current Priority. + e_stb r10,OSPrioCur@l(r12) # ... + + e_lwz r1,0(r11) # Get new stack pointer. + + e_lis r11,OS_CPU_ISRNestingCtr@ha # Decrement the ISR nesting counter to reflect the current nesting level. + e_or2i r11,OS_CPU_ISRNestingCtr@l # ... + e_lwz r12,0(r11) # ... + e_add2i. r12,-1 # ... + e_stw r12,0(r11) # ... + + epilogue # Restore context. + + se_rfi # Run task + + +#******************************************************************************************************** +# OS_ExceptHandler_Alignment +# IVOR5 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_Alignment: + e_b OS_ExceptHandler_Alignment + + +#******************************************************************************************************** +# OS_ExceptHandler_Program +# IVOR6 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_Program: + e_b OS_ExceptHandler_Program + + +#******************************************************************************************************** +# OS_ExceptHandler_PerformanceMonitor +# IVOR7 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_PerformanceMonitor: + e_b OS_ExceptHandler_PerformanceMonitor + + +#******************************************************************************************************** +# OS_ExceptHandler_SystemCall +# IVOR8 +# +# Description: Triggered by the kernel in order to perform a context switch. +#******************************************************************************************************** + +OS_ExceptHandler_SystemCall: + e_b OSCtxSw + + +#******************************************************************************************************** +# TASK LEVEL CONTEXT SWITCH +# +# Description : This routine is called when a task makes a higher priority task ready-to-run. +# The pseudo code is: +# +# OS_CTX_SAVE +# OSTCBCur->OSTCBStkPtr = SP +# OSTaskSwHook() +# OSPrioCur = OSPrioHighRdy +# OSTCBCur = OSTCBHighRdy +# SP = OSTCBCur->OSTCBStkPtr +# OS_CTX_RESTORE +# Return from interrupt/exception +# +# Interrupts should be disabled by the kernel before this point. +#******************************************************************************************************** + +OSCtxSw: + prologue # Save context. + + e_lis r11,OSTCBCur@ha # Get pointer to current TCB. + e_lwz r11,OSTCBCur@l(r11) # ... + e_stw r1, 0(r11) # Save stack pointer in current TCB. + + e_bl OSTaskSwHook # Call OSTaskSwHook. + + e_lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB. + e_lwz r11,OSTCBHighRdy@l(r11) # ... + + e_lis r12,OSTCBCur@ha # Save as current task TCB ptr. + e_stw r11,OSTCBCur@l(r12) # ... + + e_lis r12,OSPrioHighRdy@ha # Get High Ready Priority. + e_lbz r10,OSPrioHighRdy@l(r12) # ... + + e_lis r12,OSPrioCur@ha # Save as Current Priority. + e_stb r10,OSPrioCur@l(r12) # ... + + e_lwz r1,0(r11) # Get new stack pointer from TCB. + + epilogue # Restore context. + + se_rfi # Run task. + + +#******************************************************************************************************** +# OS_ExceptHandler_Debug +# IVOR9 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_Debug: + e_b OS_ExceptHandler_Debug + + +#******************************************************************************************************** +# OS_ExceptHandler_EFPUDataException +# IVOR10 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_EFPUDataException: + e_b OS_ExceptHandler_EFPUDataException + + +#******************************************************************************************************** +# OS_ExceptHandler_EFPURoundException +# IVOR11 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_EFPURoundException: + e_b OS_ExceptHandler_EFPURoundException + + +#******************************************************************************************************** +# OS_ExceptHandler_EFPUUnavailable +# IVOR12 +# +# Description: Unused. +#******************************************************************************************************** + +OS_ExceptHandler_EFPUUnavailable: + e_b OS_ExceptHandler_EFPUUnavailable + + +#******************************************************************************************************** +# OS_ExceptHandler_IVOR13 +# IVOR13 +# +# Description: Reserved. +#******************************************************************************************************** + +OS_ExceptHandler_IVOR13: + e_b OS_ExceptHandler_IVOR13 + + +#******************************************************************************************************** +# OS_ExceptHandler_IVOR14 +# IVOR14 +# +# Description: Reserved. +#******************************************************************************************************** + +OS_ExceptHandler_IVOR14: + e_b OS_ExceptHandler_IVOR14 + + +#******************************************************************************************************** +# OS_ExceptHandler_IVOR15 +# IVOR15 +# +# Description: Reserved. +#******************************************************************************************************** + +OS_ExceptHandler_IVOR15: + e_b OS_ExceptHandler_IVOR15 + + + .end diff --git a/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.inc b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.inc new file mode 100644 index 0000000..4465a10 --- /dev/null +++ b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_a.inc @@ -0,0 +1,215 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# ASSEMBLY LANGUAGE MACROS +# +# MPC57xx VLE Port +# GNU Toolchain +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + +#******************************************************************************************************** +#* DEFINES +#******************************************************************************************************** + + .equ VRSAVE, 256 + .equ SPEFSCR, 512 + + +#******************************************************************************************************** +#* CONTEXT STACK FRAME DEFINITION +#* +#* Description: This stack frame is used to save and restore context. +#******************************************************************************************************** + ### TOP OF STACK FRAME ### + .equ XR1, 0x0 # Backchain + .equ XLR, 0x4 # Link Register + + .equ XMSR, 0x8 + .equ XSRR0, 0xC + .equ XSRR1, 0x10 + .equ XCTR, 0x14 + .equ XXER, 0x18 + .equ XSPEFSCR, 0x1C + + .equ XCR, 0x20 # Condition Register + + ### GENERAL-PURPOSE REGISTERS ### + .equ XR0, 0x24 + .equ XR2, 0x28 + .equ XR3, 0x2C + .equ XR4, 0x30 + .equ XR5, 0x34 + .equ XR6, 0x38 + .equ XR7, 0x3C + .equ XR8, 0x40 + .equ XR9, 0x44 + .equ XR10, 0x48 + .equ XR11, 0x4C + .equ XR12, 0x50 + .equ XR13, 0x54 + .equ XR14, 0x58 + .equ XR15, 0x5C + .equ XR16, 0x60 + .equ XR17, 0x64 + .equ XR18, 0x68 + .equ XR19, 0x6C + .equ XR20, 0x70 + .equ XR21, 0x74 + .equ XR22, 0x78 + .equ XR23, 0x7C + .equ XR24, 0x80 + .equ XR25, 0x84 + .equ XR26, 0x88 + .equ XR27, 0x8C + .equ XR28, 0x90 + .equ XR29, 0x94 + .equ XR30, 0x98 + .equ XR31, 0x9C + ### BOTTOM OF STACK FRAME ### + + .equ STACK_FRAME_SIZE, 0xA0 + + +#******************************************************************************************************** +#* PROLOGUE DEFINITION +#******************************************************************************************************** +prologue: .macro + mtspr VRSAVE,r11 + e_li r11,-STACK_FRAME_SIZE + stwux r1,r1,r11 + mfspr r11,VRSAVE + + e_stw r0,XR0(r1) + e_stw r2,XR2(r1) + e_stw r3,XR3(r1) + e_stw r4,XR4(r1) + e_stw r5,XR5(r1) + e_stw r6,XR6(r1) + e_stw r7,XR7(r1) + e_stw r8,XR8(r1) + e_stw r9,XR9(r1) + e_stw r10,XR10(r1) + e_stw r11,XR11(r1) + e_stw r12,XR12(r1) + e_stw r13,XR13(r1) + e_stw r14,XR14(r1) + e_stw r15,XR15(r1) + e_stw r16,XR16(r1) + e_stw r17,XR17(r1) + e_stw r18,XR18(r1) + e_stw r19,XR19(r1) + e_stw r20,XR20(r1) + e_stw r21,XR21(r1) + e_stw r22,XR22(r1) + e_stw r23,XR23(r1) + e_stw r24,XR24(r1) + e_stw r25,XR25(r1) + e_stw r26,XR26(r1) + e_stw r27,XR27(r1) + e_stw r28,XR28(r1) + e_stw r29,XR29(r1) + e_stw r30,XR30(r1) + e_stw r31,XR31(r1) + + mfmsr r0 + e_stw r0,XMSR(r1) + + mfspr r0,SPEFSCR + e_stw r0,XSPEFSCR(r1) + + mfspr r0,SRR0 + e_stw r0,XSRR0(r1) + + mfspr r0,SRR1 + e_stw r0,XSRR1(r1) + + mflr r0 + e_stw r0,XLR(r1) + + mfctr r0 + e_stw r0,XCTR(r1) + + mfxer r0 + e_stw r0,XXER(r1) + + mfcr r0 + e_stw r0,XCR(r1) + + mfmsr r0 + .endm + + +#******************************************************************************************************** +#* EPILOGUE DEFINITION +#******************************************************************************************************** +epilogue: .macro + e_lwz r2,XR2(r1) + e_lwz r3,XR3(r1) + e_lwz r4,XR4(r1) + e_lwz r5,XR5(r1) + e_lwz r6,XR6(r1) + e_lwz r7,XR7(r1) + e_lwz r8,XR8(r1) + e_lwz r9,XR9(r1) + e_lwz r10,XR10(r1) + e_lwz r11,XR11(r1) + e_lwz r12,XR12(r1) + e_lwz r13,XR13(r1) + e_lwz r14,XR14(r1) + e_lwz r15,XR15(r1) + e_lwz r16,XR16(r1) + e_lwz r17,XR17(r1) + e_lwz r18,XR18(r1) + e_lwz r19,XR19(r1) + e_lwz r20,XR20(r1) + e_lwz r21,XR21(r1) + e_lwz r22,XR22(r1) + e_lwz r23,XR23(r1) + e_lwz r24,XR24(r1) + e_lwz r25,XR25(r1) + e_lwz r26,XR26(r1) + e_lwz r27,XR27(r1) + e_lwz r28,XR28(r1) + e_lwz r29,XR29(r1) + e_lwz r30,XR30(r1) + e_lwz r31,XR31(r1) + + e_lwz r0,XCR(r1) + mtcrf 0xff,r0 + e_lwz r0,XXER(r1) + mtxer r0 + e_lwz r0,XCTR(r1) + mtctr r0 + e_lwz r0,XLR(r1) + mtlr r0 + + e_lwz r0,XSRR1(r1) + mtspr SRR1,r0 + e_lwz r0,XSRR0(r1) + mtspr SRR0,r0 + e_lwz r0,XMSR(r1) + mtmsr r0 + + e_lwz r0,XSPEFSCR(r1) + mtspr SPEFSCR,r0 + + e_lwz r0,XR0(r1) + + e_lwz r1,XR1(r1) + .endm diff --git a/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_c.c b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_c.c new file mode 100644 index 0000000..9e77932 --- /dev/null +++ b/Ports/PowerPC/MPC57xx-VLE/GNU/os_cpu_c.c @@ -0,0 +1,494 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MPC57xx VLE Port +* GNU Toolchain +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include "../../../../Source/os.h" +#include "os_cpu.h" + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* GLOBALS +********************************************************************************************************* +*/ + + OS_STK OS_CPU_ISRStk[OS_CPU_ISR_STK_SIZE]; + OS_STK *OS_CPU_ISRStkBase; /* 8-byte aligned base of the ISR stack. */ + INT32U OS_CPU_ISRNestingCtr; /* Total Nesting Counter: Kernel Aware and Fast IRQs */ + +extern char _SDA_BASE_[]; /* Defined by the linker, as per the PPC System V ABI. */ +extern char _SDA2_BASE_[]; /* Defined by the linker, as per the PPC EABI. */ + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : None. +* +* Note(s) : (1) This function initializes the ISR stack. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ + INT32U i; + OS_STK *p_stk; + + + p_stk = &OS_CPU_ISRStk[0u]; /* Clear the ISR stack */ + for (i = 0u; i < OS_CPU_ISR_STK_SIZE; i++) { + *p_stk++ = (OS_STK)0u; + } + + p_stk = &OS_CPU_ISRStk[OS_CPU_ISR_STK_SIZE-1u]; + p_stk = (OS_STK *)((INT32U)p_stk & 0xFFFFFFF8u); /* Align top of stack to 8-bytes (EABI). */ + + OS_CPU_ISRStkBase = p_stk; + OS_CPU_ISRNestingCtr = 0; + +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ + +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : p_tcb Pointer to the task control block of the task being created. +* +* Note(s) : None. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(p_tcb); +#else + (void)p_tcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : p_tcb Pointer to the task control block of the task being deleted. +* +* Note(s) : None. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(p_tcb); +#else + (void)p_tcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : p_tcb Pointer to the task control block of the task that is returning. +* +* Note(s) : None. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(p_tcb); +#else + (void)p_tcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : None. +* +* Note(s) : None. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : p_task Pointer to the task entry point address. +* +* p_arg Pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* p_tos Pointer to the top of stack. It is assumed that 'p_tos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'p_tos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt Options used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when task starts executing. +* +* 2) The stack frame used to save and restore context is shown below: +* +* Low Address +-----------+ Top of Stack +* | Backchain | +* +-----------+ +* | R1 (LR) | +* +-----------+ +* | MSR | +* +-----------+ +* | SRR0 | +* +-----------+ +* | SRR1 | +* +-----------+ +* | CTR | +* +-----------+ +* | XER | +* +-----------+ +* | SPEFSCR | +* +-----------+ +* | R0 | +* +-----------+ +* | R2 | +* +-----------+ +* | R3 | +* +-----------+ +* ... +* +-----------+ +* | R31 | +* High Address +-----------+ Bottom of Stack +* +* +* +* 3) The back chain always points to the location of the previous frame's back chain. +* The first stack frame shall contain a null back chain, as per the PPC ABI. +* +* Frame 1 +-----------+ +* | Backchain | ------+ +* +-----------+ | +* | | | +* | REGISTERS | | +* | | | +* +-----------+ | +* | +* | +* Frame 0 +-----------+ | +* | NULL | <<----+ +* +-----------+ +* | R1 (LR) | +* +-----------+ +* +********************************************************************************************************** +*/ + +OS_STK *OSTaskStkInit (void (*p_task)(void *p_arg), + void *p_arg, + OS_STK *p_tos, + INT16U opt) +{ + OS_STK *p_stk; + + + (void)opt; /* Prevent compiler warning */ + /* ---------------------------------------------------- */ + /* --------------- INITIAL STACK FRAME ---------------- */ + /* ---------------------------------------------------- */ + p_stk = p_tos - 1u; /* Initial Stack is 2 words: LR and Backchain. */ + + /* Align top of stack to 8-bytes (EABI). */ + p_stk = (OS_STK *)((INT32U)p_stk & 0xFFFFFFF8u); + + *(p_stk+1) = 0x00000000u; /* LR: null for the initial frame. */ + *p_stk-- = 0x00000000u; /* Backchain: null for the initial frame. */ + + /* ---------------------------------------------------- */ + /* ----------------- TASK STACK FRAME ----------------- */ + /* ---------------------------------------------------- */ + *p_stk-- = 0x1F1F1F1Fu; /* R31 */ + *p_stk-- = 0x1E1E1E1Eu; /* R30 */ + *p_stk-- = 0x1D1D1D1Du; /* R29 */ + *p_stk-- = 0x1C1C1C1Cu; /* R28 */ + *p_stk-- = 0x1B1B1B1Bu; /* R27 */ + *p_stk-- = 0x1A1A1A1Au; /* R26 */ + *p_stk-- = 0x19191919u; /* R25 */ + *p_stk-- = 0x18181818u; /* R24 */ + *p_stk-- = 0x17171717u; /* R23 */ + *p_stk-- = 0x16161616u; /* R22 */ + *p_stk-- = 0x15151515u; /* R21 */ + *p_stk-- = 0x14141414u; /* R20 */ + *p_stk-- = 0x13131313u; /* R19 */ + *p_stk-- = 0x12121212u; /* R18 */ + *p_stk-- = 0x11111111u; /* R17 */ + *p_stk-- = 0x10101010u; /* R16 */ + *p_stk-- = 0x0F0F0F0Fu; /* R15 */ + *p_stk-- = 0x0E0E0E0Eu; /* R14 */ + *p_stk-- = (INT32U)_SDA_BASE_; /* R13 */ + *p_stk-- = 0x0C0C0C0Cu; /* R12 */ + *p_stk-- = 0x0B0B0B0Bu; /* R11 */ + *p_stk-- = 0x0A0A0A0Au; /* R10 */ + *p_stk-- = 0x09090909u; /* R9 */ + *p_stk-- = 0x08080808u; /* R8 */ + *p_stk-- = 0x07070707u; /* R7 */ + *p_stk-- = 0x06060606u; /* R6 */ + *p_stk-- = 0x05050505u; /* R5 */ + *p_stk-- = 0x04040404u; /* R4 */ + *p_stk-- = (INT32U)p_arg; /* R3: Task Argument */ + *p_stk-- = (INT32U)_SDA2_BASE_; /* R2 */ + *p_stk-- = 0x00000000u; /* R0 */ + + *p_stk-- = 0x00000000u; /* Condition Register */ + + *p_stk-- = 0x00000000u; /* SPEFSCR */ + *p_stk-- = 0x00000000u; /* XER */ + *p_stk-- = 0x00000000u; /* CTR */ + *p_stk-- = 0x00008000u; /* SRR1: External Interrupts enabled after RFI. */ + *p_stk-- = (INT32U)p_task; /* SRR0: PC after RFI. */ + *p_stk-- = 0x00000000u; /* MSR: Interrupts disabled until RFI. */ + + *p_stk-- = (INT32U)OS_TaskReturn; /* LR used to catch a task return. */ + *p_stk = (INT32U)p_stk + (40u * 4u); /* Backchain */ + + return(p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : None. +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : p_tcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(p_tcb); +#else + (void)p_tcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : None. +* +* Note(s) : 1) This function is assumed to be called from the Tick ISR. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif diff --git a/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu.h b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu.h new file mode 100644 index 0000000..a9da954 --- /dev/null +++ b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu.h @@ -0,0 +1,213 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC8349E Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef __OS_CPU_H__ /* test for multiple inclusion */ +#define __OS_CPU_H__ + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* DATA TYPES +********************************************************************************************************* +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + +#define OS_STK_RSVD_SIZE 8 /* EBI Buffer above the stack CEDRIC : A VOIR */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on PPC */ + + +/* +********************************************************************************************************* +* FLOATING POINT +* +* Note: also enable or disable "OS_SAVE_CONTEXT_WITH_FPRS .equ 1" in os_cpu_a.inc +********************************************************************************************************* +*/ + +#define FPSCR_INIT 0x4L /* Init Value of the FPSCR Register (NI-Bit is set) */ + +#define OS_SAVE_CONTEXT_WITH_FPRS + +/* +********************************************************************************************************* +* STACK FRAME +********************************************************************************************************* +*/ +typedef struct stk_tag { + INT32U R01; + INT32U BLK; + INT32U R00; + INT32U R02; + INT32U R03; + INT32U R04; + INT32U R05; + INT32U R06; + INT32U R07; + INT32U R08; + INT32U R09; + INT32U R10; + INT32U R11; + INT32U R12; + INT32U R13; + INT32U R14; + INT32U R15; + INT32U R16; + INT32U R17; + INT32U R18; + INT32U R19; + INT32U R20; + INT32U R21; + INT32U R22; + INT32U R23; + INT32U R24; + INT32U R25; + INT32U R26; + INT32U R27; + INT32U R28; + INT32U R29; + INT32U R30; + INT32U R31; +#ifdef OS_SAVE_CONTEXT_WITH_FPRS + INT32U _space; /* non packed structure */ + long long F00; + long long F01; + long long F02; + long long F03; + long long F04; + long long F05; + long long F06; + long long F07; + long long F08; + long long F09; + long long F10; + long long F11; + long long F12; + long long F13; + long long F14; + long long F15; + long long F16; + long long F17; + long long F18; + long long F19; + long long F20; + long long F21; + long long F22; + long long F23; + long long F24; + long long F25; + long long F26; + long long F27; + long long F28; + long long F29; + long long F30; + long long F31; + INT32U FPSCR; +#endif + INT32U CSRR0_; + INT32U CSRR1_; + INT32U CR; + INT32U SRR0_; + INT32U SRR1_; + INT32U CTR_; + INT32U XER_; + INT32U LR_; +} STK; + + +/* +********************************************************************************************************* +* OS Task Swicth +********************************************************************************************************* +*/ + +#if defined __MWERKS__ +#define OS_TASK_SW() asm (" sc "); +#else +#error Unknown Compiler Assembler Syntax +#endif + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD CPU_CFG_CRITICAL_METHOD + +#define OS_ENTER_CRITICAL() {CPU_CRITICAL_ENTER();} +#define OS_EXIT_CRITICAL() {CPU_CRITICAL_EXIT();} + + +/* +********************************************************************************************************* +* Function Prototypes +********************************************************************************************************* +*/ + +void OSCtxSw(void); +void OSIntCtxSw(void); +void OSStartHighRdy(void); + +void OSTickISR(void); +void OSExtIntISR(void); + + +#endif /* __OS_CPU_H__ */ diff --git a/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.inc b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.inc new file mode 100644 index 0000000..6ff46a4 --- /dev/null +++ b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.inc @@ -0,0 +1,210 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC8349E +# CodeWarrior Compiler +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + .equ OS_SAVE_CONTEXT_WITH_FPRS, 1 # set to 1 for floating point support; also set in os_cpu.h + + +#********************************************************************************************************* +#* STACK FRAME DEFINITION +#********************************************************************************************************* + + .ifdef OS_SAVE_CONTEXT_WITH_FPRS + .equ STK_FRM_SZ, 424 #/* 32 gpr + 8 spr + sp + 32 fp + fpscr -> (41 * 4 + 32 * 8 + 4 ) */ + .equ XTR_REG_OFFS, 396 #/* (33 * 4) + (32 * 8) + 4 + 4 fill */ + .equ R0_OFFS, 8 + .equ R2_OFFS, 12 + .equ XF0, 136 + .equ XF1, XF0+8 + .equ XF2, XF1+8 + .equ XF3, XF2+8 + .equ XF4, XF3+8 + .equ XF5, XF4+8 + .equ XF6, XF5+8 + .equ XF7, XF6+8 + .equ XF8, XF7+8 + .equ XF9, XF8+8 + .equ XF10, XF9+8 + .equ XF11, XF10+8 + .equ XF12, XF11+8 + .equ XF13, XF12+8 + .equ XF14, XF13+8 + .equ XF15, XF14+8 + .equ XF16, XF15+8 + .equ XF17, XF16+8 + .equ XF18, XF17+8 + .equ XF19, XF18+8 + .equ XF20, XF19+8 + .equ XF21, XF20+8 + .equ XF22, XF21+8 + .equ XF23, XF22+8 + .equ XF24, XF23+8 + .equ XF25, XF24+8 + .equ XF26, XF25+8 + .equ XF27, XF26+8 + .equ XF28, XF27+8 + .equ XF29, XF28+8 + .equ XF30, XF29+8 + .equ XF31, XF30+8 + .equ XFPSCR, XF31+8 + .else + .equ STK_FRM_SZ, 168 #/* 32 gpr + 8 spr + sp -> (41 * 4) */ + .equ XTR_REG_OFFS, 132 #/* (33 * 4) */ + .equ R0_OFFS, 8 + .equ R2_OFFS, 12 + .endif + + + +#********************************************************************************************************* +#* PROLOGUE DEFINITION +#* THIS Stack frame definitions have to be congruent with the +#* Stack Frame usage in OS_CPU_C.c +#********************************************************************************************************* +prologue: .macro + + stwu r1,-STK_FRM_SZ(r1) # create stack frame + stw r0,R0_OFFS(r1) # save r0 + stmw r2,R2_OFFS(r1) # save regs r2 through r31 + + .ifdef OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 + ori r0,r0,0x2000 + mtmsr r0 + isync # wait for FPU availability + stfd f0,XF0(r1) + stfd f1,XF1(r1) + stfd f2,XF2(r1) + stfd f3,XF3(r1) + stfd f4,XF4(r1) + stfd f5,XF5(r1) + stfd f6,XF6(r1) + stfd f7,XF7(r1) + stfd f8,XF8(r1) + stfd f9,XF9(r1) + stfd f10,XF10(r1) + stfd f11,XF11(r1) + stfd f12,XF12(r1) + stfd f13,XF13(r1) + stfd f14,XF14(r1) + stfd f15,XF15(r1) + stfd f16,XF16(r1) + stfd f17,XF17(r1) + stfd f18,XF18(r1) + stfd f19,XF19(r1) + stfd f20,XF20(r1) + stfd f21,XF21(r1) + stfd f22,XF22(r1) + stfd f23,XF23(r1) + stfd f24,XF24(r1) + stfd f25,XF25(r1) + stfd f26,XF26(r1) + stfd f27,XF27(r1) + stfd f28,XF28(r1) + stfd f29,XF29(r1) + stfd f30,XF30(r1) + stfd f31,XF31(r1) + mffs f0 + stfd f0,XFPSCR(r1) + .endif + + mflr r31 # fetch LR + mfxer r30 # fetch XER + mfctr r29 # fetch CTR + mfsrr1 r28 # fetch MSR (from normal interrupt) + mfsrr0 r27 # fetch PC (from normal interrupt) + mfcr r26 # fetch CR + mfspr r25, 59 # fetch CSRR1 (for critical interrupt) + mfspr r24, 58 # fecth CSRR0 + stmw r24,XTR_REG_OFFS(r1) # save regs r24 - r31 + .endm + + + +#********************************************************************************************************* +#* EPILOGUE DEFINITION +#********************************************************************************************************* +epilogue: .macro + lmw r24,XTR_REG_OFFS(r1) + mtspr 58,r24 # restore CSRR1 (for critical interrupt) + mtspr 59,r25 # restore CSRR0 (for critical interrupt) + mtcr r26 # restore CR + mtsrr0 r27 # restore PC + mtsrr1 r28 # restore MSR + mtctr r29 # restore CTR + mtxer r30 # restore XER + mtlr r31 # restore LR + + .ifdef OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 + ori r0,r0,0x2000 + mtmsr r0 + lfd f0,XFPSCR(r1) + mtfsf 0xFF,f0 + lfd f0,XF0(r1) + lfd f1,XF1(r1) + lfd f2,XF2(r1) + lfd f3,XF3(r1) + lfd f4,XF4(r1) + lfd f5,XF5(r1) + lfd f6,XF6(r1) + lfd f7,XF7(r1) + lfd f8,XF8(r1) + lfd f9,XF9(r1) + lfd f10,XF10(r1) + lfd f11,XF11(r1) + lfd f12,XF12(r1) + lfd f13,XF13(r1) + lfd f14,XF14(r1) + lfd f15,XF15(r1) + lfd f16,XF16(r1) + lfd f17,XF17(r1) + lfd f18,XF18(r1) + lfd f19,XF19(r1) + lfd f20,XF20(r1) + lfd f21,XF21(r1) + lfd f22,XF22(r1) + lfd f23,XF23(r1) + lfd f24,XF24(r1) + lfd f25,XF25(r1) + lfd f26,XF26(r1) + lfd f27,XF27(r1) + lfd f28,XF28(r1) + lfd f29,XF29(r1) + lfd f30,XF30(r1) + lfd f31,XF31(r1) + .endif + + lmw r2,R2_OFFS(r1) # restore regs r2 through r31 + lwz r0,R0_OFFS(r1) # restore r0 + lwz r1,0(r1) # restore stack pointer + .endm + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT INCLUDE FILE END +#********************************************************************************************************* diff --git a/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.s b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.s new file mode 100644 index 0000000..66dc8b7 --- /dev/null +++ b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_a.s @@ -0,0 +1,272 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Freescale MPC8349E +# CodeWarrior Compiler +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** + +#********************************************************************************************************* +#* ASM HEADER +#********************************************************************************************************* + + .include "os_cpu_a.inc" + + .extern BSP_TmrTickISR + .extern BSP_ProcessorISR + + .extern OSTaskSwHook + .extern OSIntEnter + .extern OSIntExit + + .extern OSTCBCur # pointer to current tasks TCB + .extern OSTCBHighRdy # pointer to highest priority ready task + .extern OSPrioHighRdy + .extern OSPrioCur + .extern OSRunning + .extern OSIntNesting + + +#********************************************************************************************************* +#* DEFINES +#********************************************************************************************************* + + + +#********************************************************************************************************* +#* PUBLIC DECLARATIONS +#********************************************************************************************************* + + .global OSCtxSw + .global OSStartHighRdy + .global OSIntCtxSw + + .global OSExtIntISR + .global Exception_Epilogue + +#********************************************************************************************************* +#* Section +#********************************************************************************************************* + + .text + +# +#********************************************************************************************************* +#* ISR HANDLER FOR EXCEPTIONS OF THE E300C1 CORE +#* +#* Description : This function is executed to restore registers when an exception occurs. +#* The e300c1 defined the exceptions in a predefined memory space. That is each +#* exceptions have 256 bytes to hold the exception's code. Each exceptions starts +#* at an offset multiple of 256 bytes (e.g 0x100, 0x200, etc.). +#* So the registers restoration is done here because if the epilogue macro is included +#* directly in the memory space of the exceptions, the code size could exceed the 256 +#* bytes size. +#* Except for Reset (0x100), External interrupt (0x500) and System Call (0xC00). +#********************************************************************************************************* +Exception_Epilogue: + mtspr 58,r24 # restore CSRR1 (for critical interrupt) + mtspr 59,r25 # restore CSRR0 (for critical interrupt) + mtcr r26 # restore CR + mtsrr0 r27 # restore PC + mtsrr1 r28 # restore MSR + mtctr r29 # restore CTR + mtxer r30 # restore XER + mtlr r31 # restore LR + + .ifdef OS_SAVE_CONTEXT_WITH_FPRS + mfmsr r0 + ori r0,r0,0x2000 + mtmsr r0 + lfd f0,XFPSCR(r1) + mtfsf 0xFF,f0 + lfd f0,XF0(r1) + lfd f1,XF1(r1) + lfd f2,XF2(r1) + lfd f3,XF3(r1) + lfd f4,XF4(r1) + lfd f5,XF5(r1) + lfd f6,XF6(r1) + lfd f7,XF7(r1) + lfd f8,XF8(r1) + lfd f9,XF9(r1) + lfd f10,XF10(r1) + lfd f11,XF11(r1) + lfd f12,XF12(r1) + lfd f13,XF13(r1) + lfd f14,XF14(r1) + lfd f15,XF15(r1) + lfd f16,XF16(r1) + lfd f17,XF17(r1) + lfd f18,XF18(r1) + lfd f19,XF19(r1) + lfd f20,XF20(r1) + lfd f21,XF21(r1) + lfd f22,XF22(r1) + lfd f23,XF23(r1) + lfd f24,XF24(r1) + lfd f25,XF25(r1) + lfd f26,XF26(r1) + lfd f27,XF27(r1) + lfd f28,XF28(r1) + lfd f29,XF29(r1) + lfd f30,XF30(r1) + lfd f31,XF31(r1) + .endif + + lmw r2,R2_OFFS(r1) # restore regs r2 through r31 + lwz r0,R0_OFFS(r1) # restore r0 + lwz r1,0(r1) # restore stack pointer + rfi # return from interrupt + + + +#********************************************************************************************************* +#* ISR HANDLER FOR EXTERNAL INTERRUPT +#* +#* Description : This function is executed when an External interrupt (0x500) exception occurs. +#********************************************************************************************************* + .align 8 +OSExtIntISR: + prologue # Save context + + lis r11,OSIntNesting@ha # load OSIntNesting + lbz r3, OSIntNesting@l(r11) + addi r0, r3, 1 + stb r0, OSIntNesting@l(r11) # OSIntNesting++ + + cmpwi r0, 1 # if (OSIntNesting != 1) ... + bne OSExtIntISR_NotSaveSP # do not save the stackpointer + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + +OSExtIntISR_NotSaveSP: + bl BSP_ProcessorISR # call processor interrupt handler CEDRIC AJOUT + bl OSIntExit # call to decrement OSIntNesting + + epilogue # Restore context + rfi # return from interrupt + + + +#********************************************************************************************************* +#* START HIGHEST PRIORITY TASK READY-TO-RUN +#* +#* Description : This function is called by OSStart() to start the highest priority task that was created +#* by the application before calling OSStart(). +#* +#* Arguments : none +#* +#* Note(s) : 1) OSStartHighRdy() MUST: +#* a) Call OSTaskSwHook() then, +#* b) Set OSRunning to TRUE, +#* c) Switch to the highest priority task by loading the stack pointer of the highest +#* priority task into the SP register and execute an rfi instruction. +#********************************************************************************************************* + .align 8 +OSStartHighRdy: + bl OSTaskSwHook # Call OSTaskSwHook + + li r0, 1 # Set OSRunning to 1 + lis r11,OSRunning@ha + stb r0, OSRunning@l(r11) + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + rfi # return from interrupt + + + +#********************************************************************************************************* +#* TASK LEVEL CONTEXT SWITCH +#* +#* Description : This function is called when a task makes a higher priority task ready-to-run. +#* +#* Arguments : none +#* +#* Note(s) : 1) Upon entry, +#* OSTCBCur points to the OS_TCB of the task to suspend +#* OSTCBHighRdy points to the OS_TCB of the task to resume +#********************************************************************************************************* + .align 8 +OSCtxSw: + prologue # Save context + + lis r11,OSTCBCur@ha # Get pointer to current TCB + lwz r11,OSTCBCur@l(r11) + stw r1, 0(r11) # Save stack pointer in current TCB + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer from TCB + + epilogue # Restore context + rfi # return from interrupt + + + +#********************************************************************************************************* +#* INTERRUPT LEVEL CONTEXT SWITCH +#* +#* Description : This function is called by OSIntExit() to perform a context switch to a task that has +#* been made ready-to-run by an ISR. +#********************************************************************************************************* + .align 8 +OSIntCtxSw: + + bl OSTaskSwHook # Call OSTaskSwHook + + lis r11,OSTCBHighRdy@ha # Get pointer to ready task TCB + lwz r11,OSTCBHighRdy@l(r11) + + lis r12,OSTCBCur@ha # Save as current task TCB ptr. + stw r11,OSTCBCur@l(r12) + + lis r12,OSPrioHighRdy@ha # Get High Ready Priority + lbz r10,OSPrioHighRdy@l(r12) + + lis r12,OSPrioCur@ha # Save as Current Priority + stb r10,OSPrioCur@l(r12) + + lwz r1, 0(r11) # Get new stack pointer + + epilogue # Restore context + rfi # run task + + +#********************************************************************************************************* +#* CPU ASSEMBLY PORT FILE END +#********************************************************************************************************* + .end diff --git a/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_c.c b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_c.c new file mode 100644 index 0000000..cf98925 --- /dev/null +++ b/Ports/PowerPC/MPC8349E/CodeWarrior/os_cpu_c.c @@ -0,0 +1,402 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Freescale MPC8349E Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDES +********************************************************************************************************* +*/ + +#include + + +/* +********************************************************************************************************* +* GLOBALS CEDRIC : A VERIFIER (EABI) +********************************************************************************************************* +*/ + +extern char _SDA_BASE_[]; +extern char _SDA2_BASE_[]; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION >= 251) +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) The SRR1 Register holds the original value of the MSR register. This value is copied +* to the MSR register by execute the rfi operation at the end of the ISR. +* +* (2) Ensure any changes to the order of stack initialization is congruent with the Stack +* Frame definitions in OS_CPU_A.s. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + STK * stkp; + OS_CPU_SR msr; /* Local: Initial MSR */ + OS_CPU_SR srr1; /* Local: Initial SRR1 */ + + (void)opt; /* 'opt' is not used, prevent warning */ + + msr = CPU_SR_Rd(); /* get the MSB reg value */ + srr1 = (msr | 0x8000); /* set MSR[EE] bit to enable interrupts */ + + /* Leave buffer area for locals "above the stack" in ... */ + ptos -= OS_STK_RSVD_SIZE; /* case the compiler prolog puts variables above the stack */ + stkp = (STK *)((INT32U) ptos & (INT32U) 0xFFFFFFF0); /* 16-byte align task's stack pointer (EABI) */ + + stkp--; /* set structure within stack space */ + + /*****************************************************************/ + /* Ensure any changes to the order of these initializations */ + /* are congruent with the Stack Frame definitions in OS_CPU_A.s */ + /*****************************************************************/ + /* to improve debugging, fill all registers with the name */ + stkp->R31 = 0x31L; /* R31 */ + stkp->R30 = 0x30L; /* R30 */ + stkp->R29 = 0x29L; /* R29 */ + stkp->R28 = 0x28L; /* R28 */ + stkp->R27 = 0x27L; /* R27 */ + stkp->R26 = 0x26L; /* R26 */ + stkp->R25 = 0x25L; /* R25 */ + stkp->R24 = 0x24L; /* R24 */ + stkp->R23 = 0x23L; /* R23 */ + stkp->R22 = 0x22L; /* R22 */ + stkp->R21 = 0x21L; /* R21 */ + stkp->R20 = 0x20L; /* R20 */ + stkp->R19 = 0x19L; /* R19 */ + stkp->R18 = 0x18L; /* R18 */ + stkp->R17 = 0x17L; /* R17 */ + stkp->R16 = 0x16L; /* R16 */ + stkp->R15 = 0x15L; /* R15 */ + stkp->R14 = 0x14L; /* R14 */ + stkp->R13 = (INT32U)&_SDA_BASE_; /* R13 */ + stkp->R12 = 0x12L; /* R12 */ + stkp->R11 = 0x11L; /* R11 */ + stkp->R10 = 0x10L; /* R10 */ + stkp->R09 = 0x09L; /* R9 */ + stkp->R08 = 0x08L; /* R8 */ + stkp->R07 = 0x07L; /* R7 */ + stkp->R06 = 0x06L; /* R6 */ + stkp->R05 = 0x05L; /* R5 */ + stkp->R04 = 0x04L; /* R4 */ + stkp->R03 = (INT32U)p_arg; /* R3 */ + stkp->R02 = (INT32U)&_SDA2_BASE_; /* R2 */ + stkp->R00 = 0x00L; /* R0 */ + + #ifdef OS_SAVE_CONTEXT_WITH_FPRS + stkp->FPSCR = FPSCR_INIT; + stkp->F31 = 0; /* F31 */ + stkp->F30 = 0; /* F30 */ + stkp->F29 = 0; /* F29 */ + stkp->F28 = 0; /* F28 */ + stkp->F27 = 0; /* F27 */ + stkp->F26 = 0; /* F26 */ + stkp->F25 = 0; /* F25 */ + stkp->F24 = 0; /* F24 */ + stkp->F23 = 0; /* F23 */ + stkp->F22 = 0; /* F22 */ + stkp->F21 = 0; /* F21 */ + stkp->F20 = 0; /* F20 */ + stkp->F19 = 0; /* F19 */ + stkp->F18 = 0; /* F18 */ + stkp->F17 = 0; /* F17 */ + stkp->F16 = 0; /* F16 */ + stkp->F15 = 0; /* F15 */ + stkp->F14 = 0; /* F14 */ + stkp->F13 = 0; /* F13 */ + stkp->F12 = 0; /* F12 */ + stkp->F11 = 0; /* F11 */ + stkp->F10 = 0; /* F10 */ + stkp->F09 = 0; /* F9 */ + stkp->F08 = 0; /* F8 */ + stkp->F07 = 0; /* F7 */ + stkp->F06 = 0; /* F6 */ + stkp->F05 = 0; /* F5 */ + stkp->F04 = 0; /* F4 */ + stkp->F03 = 0; /* F3 */ + stkp->F02 = 0; /* F2 */ + stkp->F01 = 0; /* F1 */ + stkp->F00 = 0; /* F0 */ +#endif + stkp->CR = 0; + stkp->CTR_ = 0; + stkp->XER_ = 0; + stkp->CSRR0_ = 0; + stkp->CSRR1_ = 0; + + stkp->LR_ = (INT32U)task; /* LR */ + stkp->BLK = 0; /* BLANK for 0xA8 size */ + stkp->SRR0_ = (INT32U)task; /* SRRO */ + stkp->SRR1_ = (INT32U)srr1; /* SRR1 */ + stkp->R01 = (INT32U)ptos; /* R1 */ + + return (OS_STK *)stkp; +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_VERSION > 203) +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/PowerPC/MPC8349E/CodeWarrior/os_dbg.c b/Ports/PowerPC/MPC8349E/CodeWarrior/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/PowerPC/MPC8349E/CodeWarrior/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/R32C/R32C100/HEW/os_cpu.h b/Ports/R32C/R32C100/HEW/os_cpu.h new file mode 100644 index 0000000..96105c7 --- /dev/null +++ b/Ports/R32C/R32C100/HEW/os_cpu.h @@ -0,0 +1,111 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef INT32U OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M16C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 1 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() asm("STC FLG, $@", cpu_sr);asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("LDC $@, FLG", cpu_sr) /* Enable interrupts */ +#endif +/* +********************************************************************************************************* +* RENESAS M16C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/R32C/R32C100/HEW/os_cpu_a.a30 b/Ports/R32C/R32C100/HEW/os_cpu_a.a30 new file mode 100644 index 0000000..ecdbb6b --- /dev/null +++ b/Ports/R32C/R32C100/HEW/os_cpu_a.a30 @@ -0,0 +1,194 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas R32C Port +; +; Filename : os_cpu_a.a30 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas R32C +; Toolchain : Renesas HEW IDE with the NC100 compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .GLB _OSTCBCur ; Declared as OS_TCB * , 32-bit long + .GLB _OSTCBHighRdy ; Declared as OS_TCB * , 32-bit long + .GLB _OSPrioCur ; Declared as INT8U , 8-bit long + .GLB _OSPrioHighRdy ; Declared as INT8U , 8-bit long + .GLB _OSIntNesting ; Declared as INT8U , 8-bit long + .GLB _OSRunning ; Declared as Boolean (unsigned char), 8-bit long + + .GLB _OSIntExit ; External functions written in C + .GLB _OSTimeTick + .GLB _OSTaskSwHook + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + .SECTION program + .GLB _OSStartHighRdy + +_OSStartHighRdy: + JSR _OSTaskSwHook + + MOV.L _OSTCBHighRdy, A0 ; ISP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + MOV.B #01H, _OSRunning ; OSRunning = TRUE + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB + POPC FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + + .SECTION program + .GLB _OSCtxSw + +_OSCtxSw: + PUSHC FB + PUSHM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB + + MOV.L _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] + + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.L _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB ; Restore all processor registers from the new task's stack + POPC FB + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + + .SECTION program + .GLB _OSIntCtxSw + +_OSIntCtxSw: + JSR _OSTaskSwHook ; OSTaskSwHook() + + MOV.L _OSTCBHighRdy, _OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B _OSPrioHighRdy, _OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L _OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB ; Restore all processor registers from the new task's stack + POPC FB + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + + .SECTION program + .GLB _OSTickISR + +_OSTickISR: + + PUSHC FB + PUSHM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB ; Save current task's registers + + INC.B _OSIntNesting ; OSIntNesting++ + CMP.B #1,_OSIntNesting ; if (OSIntNesting == 1) { + JNE _OSTickISR1 + + MOV.L _OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] ; } + +_OSTickISR1: + JSR _OSTimeTick ; OSTimeTick() + + JSR _OSIntExit ; OSIntExit() + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB ; Restore all processor registers from the new task's stack + POPC FB + + REIT + + + .END diff --git a/Ports/R32C/R32C100/HEW/os_cpu_c.c b/Ports/R32C/R32C100/HEW/os_cpu_c.c new file mode 100644 index 0000000..a0e23c7 --- /dev/null +++ b/Ports/R32C/R32C100/HEW/os_cpu_c.c @@ -0,0 +1,335 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas R32C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas R32C +* Toolchain : Renesas HEW IDE with the NC100 compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 32 bits wide. +* +* +--------+--------+-----------------+ +* SP ----> | FLG | +* +-----------------------------------+ +* | PC | +* +-----------------------------------+ +* | FB | +* +-----------------------------------+ +* | SB | +* +-----------------------------------+ +* | A3 | +* +-----------------------------------+ +* | A2 | +* +-----------------------------------+ +* | A1 | +* +-----------------------------------+ +* | A0 | +* +-----------------------------------+ +* | R7 | R5 | (R7R5) +* +-----------------------------------+ +* | R6 | R4 | (R6R4) +* +-----------------------------------+ +* | R3H | R3L | R1H | R1L | (R3R1) +* +-----------------------------------+ +* PTOS ----> | R2H | R2L | R0H | R0L | (R2R0) +* +-----------------------------------+ +* +********************************************************************************************************* +*/ + + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + INT32U flag; + + + flag = 0x00000040; + pstk32 = (INT32U *)ptos; + + *pstk32-- = (INT32U)pdata; + *pstk32-- = (INT32U)task; + /* Simulate ISR entry */ + /* Save registers onto stack frame */ + *pstk32-- = (INT32U)flag; /* ... Flag register */ + *pstk32-- = (INT32U)task; /* ... PC register */ + *pstk32-- = 0xFBFBFBFB; /* ... FB register */ + *pstk32-- = 0x5B5B5B5B; /* ... SB register */ + *pstk32-- = 0xA3A3A3A3; /* ... A3 register */ + *pstk32-- = 0xA2A2A2A2; /* ... A2 register */ + *pstk32-- = 0xA1A1A1A1; /* ... A1 register */ + *pstk32-- = 0xA0A0A0A0; /* ... A0 register */ + *pstk32-- = 0x77775555; /* ... R7R5 register */ + *pstk32-- = 0x66664444; /* ... R6R4 register */ + *pstk32-- = 0x33331111; /* ... R3R1 register */ + *pstk32 = 0x22220000; /* ... R2R0 register */ + + return ((OS_STK *)pstk32); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/R32C/R32C100/HEW/os_dbg.c b/Ports/R32C/R32C100/HEW/os_dbg.c new file mode 100644 index 0000000..c301ad9 --- /dev/null +++ b/Ports/R32C/R32C100/HEW/os_dbg.c @@ -0,0 +1,273 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas M16C Port +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas M16C +* Toolchain : Renesas HEW IDE with the NC30 compiler +********************************************************************************************************* +*/ + +#include + + /* The following #define tells the IAR compiler to 'not' optimize these ... */ + /* ... 'const' out since they are not used elsewhere. */ +#define OS_COMPILER_OPT + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +OS_COMPILER_OPT INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +OS_COMPILER_OPT INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +OS_COMPILER_OPT INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +OS_COMPILER_OPT INT16U const OSEventEn = OS_EVENT_EN; +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +OS_COMPILER_OPT INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +OS_COMPILER_OPT INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +OS_COMPILER_OPT INT16U const OSEventSize = 0; +OS_COMPILER_OPT INT16U const OSEventTblSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +OS_COMPILER_OPT INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +OS_COMPILER_OPT INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +OS_COMPILER_OPT INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +OS_COMPILER_OPT INT16U const OSFlagGrpSize = 0; +OS_COMPILER_OPT INT16U const OSFlagNodeSize = 0; +OS_COMPILER_OPT INT16U const OSFlagWidth = 0; +#endif +OS_COMPILER_OPT INT16U const OSFlagMax = OS_MAX_FLAGS; +OS_COMPILER_OPT INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +OS_COMPILER_OPT INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +OS_COMPILER_OPT INT16U const OSMboxEn = OS_MBOX_EN; + +OS_COMPILER_OPT INT16U const OSMemEn = OS_MEM_EN; +OS_COMPILER_OPT INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +OS_COMPILER_OPT INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +OS_COMPILER_OPT INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +OS_COMPILER_OPT INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +OS_COMPILER_OPT INT16U const OSMemSize = 0; +OS_COMPILER_OPT INT16U const OSMemTblSize = 0; +#endif +OS_COMPILER_OPT INT16U const OSMutexEn = OS_MUTEX_EN; + +OS_COMPILER_OPT INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +OS_COMPILER_OPT INT16U const OSQEn = OS_Q_EN; +OS_COMPILER_OPT INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +OS_COMPILER_OPT INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +OS_COMPILER_OPT INT16U const OSQSize = 0; +#endif + +OS_COMPILER_OPT INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +OS_COMPILER_OPT INT16U const OSSemEn = OS_SEM_EN; + +OS_COMPILER_OPT INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +OS_COMPILER_OPT INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +OS_COMPILER_OPT INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +OS_COMPILER_OPT INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +OS_COMPILER_OPT INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +OS_COMPILER_OPT INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +OS_COMPILER_OPT INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +OS_COMPILER_OPT INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +OS_COMPILER_OPT INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +OS_COMPILER_OPT INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +OS_COMPILER_OPT INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +OS_COMPILER_OPT INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +OS_COMPILER_OPT INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +OS_COMPILER_OPT INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +OS_COMPILER_OPT INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +OS_COMPILER_OPT INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +OS_COMPILER_OPT INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZAZTION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/R32C/R32C100/IAR/os_cpu.h b/Ports/R32C/R32C100/IAR/os_cpu.h new file mode 100644 index 0000000..f1eb4d8 --- /dev/null +++ b/Ports/R32C/R32C100/IAR/os_cpu.h @@ -0,0 +1,117 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas R32C Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas R32C +* Toolchain : IAR IDE +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Type of CPU status register */ + +/* +********************************************************************************************************* +* RENESAS M16C FAMILY +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("FSET I") /* Enable interrupts */ +#endif + + +#if OS_CRITICAL_METHOD == 2 +#define OS_ENTER_CRITICAL() asm("PUSHC FLG"); asm("FCLR I") /* Disable interrupts */ +#define OS_EXIT_CRITICAL() asm("POPC FLG") /* Enable interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3 +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} /* Disable interrupts */ +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* RENESAS M16C FAMILY MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory */ +#define OS_TASK_SW() asm("INT #0") /* Mapped to the software interrupt 0 */ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S53 */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OSTickISR (void); diff --git a/Ports/R32C/R32C100/IAR/os_cpu_a.s53 b/Ports/R32C/R32C100/IAR/os_cpu_a.s53 new file mode 100644 index 0000000..2c503ae --- /dev/null +++ b/Ports/R32C/R32C100/IAR/os_cpu_a.s53 @@ -0,0 +1,237 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas R32C Port +; +; Filename : os_cpu_a.s53 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas R32C +; Toolchain : IAR For Renesas R32C V1.31 +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy ; Public functions + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + + EXTERN OSIntExit + EXTERN OSTimeTick + EXTERN OSTaskSwHook + + EXTERN OSTCBCur ; External variables (uC/OS-II) + EXTERN OSTCBHighRdy + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntNesting + EXTERN OSRunning + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE32:CODE:NOROOT(4) + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +; +; +; Note(s) : 1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +; OS_CPU_SR cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save + STC FLG, R2R0 ; Set prio int mask to mask all (except faults) + FCLR I + RTS + +OS_CPU_SR_Restore + LDC R2R0, FLG + RTS + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + + +OSStartHighRdy: + JSR OSTaskSwHook + + MOV.L OSTCBHighRdy, A0 ; ISP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], SP + + MOV.B #01H, OSRunning ; OSRunning = TRUE + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB + POPC FB + + REIT + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) OSCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = SP; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +; +; 4) OSCtxSw must be mapped to interrupt #0 in the vector table. +;******************************************************************************************************** + +OSCtxSw: + PUSHC FB + PUSHM SB,A3,A2,A1,A0,R7R5,R6R4,R3R1,R2R0 + + MOV.L OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] + + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.L OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB ; Restore all processor registers from the new task's stack + POPC FB + + REIT + + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) OSIntCtxSw() is called in SVC mode with BOTH FIQ and IRQ interrupts DISABLED. +; +; 2) The pseudo-code for OSCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 3) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw: + JSR OSTaskSwHook ; OSTaskSwHook() + + MOV.L OSTCBHighRdy, OSTCBCur ; OSTCBCur = OSTCBHighRdy + + MOV.B OSPrioHighRdy, OSPrioCur ; OSPrioCur = OSPrioHighRdy + + MOV.L OSTCBHighRdy, A0 ; SP = OSTCBHighRdy->OSTCBStkPtr + LDC [A0], ISP + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB ; Restore all processor registers from the new task's stack + POPC FB + + REIT + +;******************************************************************************************************** +; uC/OS-II TIME TICK ISR +; void OSTickISR(void) +; +; Note(s) : 1) OSTickISR() should be placed on the appropriate interrupt vector. +; +; 2) Pseudo code: +; a) Save all registers +; b) OSIntNesting++ +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP +; } +; d) OSTimeTick(); +; e) OSIntExit(); +; f) Restore all registers +; g) Return from interrupt; +;******************************************************************************************************** + +OSTickISR: + + PUSHC FB + PUSHM SB,A3,A2,A1,A0,R7R5,R6R4,R3R1,R2R0 ; Save current task's registers + + INC.B OSIntNesting ; OSIntNesting++ + CMP.B #1, OSIntNesting ; if (OSIntNesting == 1) { + JNE OSTickISR1 + + MOV.L OSTCBCur, A0 ; OSTCBCur->OSTCBStkPtr = SP + STC ISP, [A0] ; } + +OSTickISR1: + JSR OSTimeTick ; OSTimeTick() + + JSR OSIntExit ; OSIntExit() + + POPM R2R0,R3R1,R6R4,R7R5,A0,A1,A2,A3,SB ; Restore all processor registers from the new task's stack + POPC FB + + REIT + + + END diff --git a/Ports/R32C/R32C100/IAR/os_cpu_c.c b/Ports/R32C/R32C100/IAR/os_cpu_c.c new file mode 100644 index 0000000..b9295bc --- /dev/null +++ b/Ports/R32C/R32C100/IAR/os_cpu_c.c @@ -0,0 +1,335 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas R32C Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas R32C +* Toolchain : IAR IDE +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* last valid entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the LOWEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the HIGHEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Task stack frame is as follows. The stack is 32 bits wide. +* +* +--------+--------+-----------------+ +* SP ----> | FLG | +* +-----------------------------------+ +* | PC | +* +-----------------------------------+ +* | FB | +* +-----------------------------------+ +* | SB | +* +-----------------------------------+ +* | A3 | +* +-----------------------------------+ +* | A2 | +* +-----------------------------------+ +* | A1 | +* +-----------------------------------+ +* | A0 | +* +-----------------------------------+ +* | R7 | R5 | (R7R5) +* +-----------------------------------+ +* | R6 | R4 | (R6R4) +* +-----------------------------------+ +* | R3H | R3L | R1H | R1L | (R3R1) +* +-----------------------------------+ +* PTOS ----> | R2H | R2L | R0H | R0L | (R2R0) +* +-----------------------------------+ +* +********************************************************************************************************* +*/ + + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *pstk32; + INT32U flag; + + + flag = 0x00000040; + pstk32 = (INT32U *)ptos; + + *pstk32-- = (INT32U)pdata; + *pstk32-- = (INT32U)task; + /* Simulate ISR entry */ + /* Save registers onto stack frame */ + *pstk32-- = (INT32U)flag; /* ... Flag register */ + *pstk32-- = (INT32U)task; /* ... PC register */ + *pstk32-- = 0xFBFBFBFB; /* ... FB register */ + *pstk32-- = 0x5B5B5B5B; /* ... SB register */ + *pstk32-- = 0xA3A3A3A3; /* ... A3 register */ + *pstk32-- = 0xA2A2A2A2; /* ... A2 register */ + *pstk32-- = 0xA1A1A1A1; /* ... A1 register */ + *pstk32-- = 0xA0A0A0A0; /* ... A0 register */ + *pstk32-- = 0x77775555; /* ... R7R5 register */ + *pstk32-- = 0x66664444; /* ... R6R4 register */ + *pstk32-- = 0x33331111; /* ... R3R1 register */ + *pstk32 = 0x22220000; /* ... R2R0 register */ + + return ((OS_STK *)pstk32); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/R32C/R32C100/IAR/os_dbg.c b/Ports/R32C/R32C100/IAR/os_dbg.c new file mode 100644 index 0000000..fb52721 --- /dev/null +++ b/Ports/R32C/R32C100/IAR/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/RISC-V/RV32/GCC/os_cpu.h b/Ports/RISC-V/RV32/GCC/os_cpu.h new file mode 100644 index 0000000..89e1220 --- /dev/null +++ b/Ports/RISC-V/RV32/GCC/os_cpu.h @@ -0,0 +1,161 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* RISC-V Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : RISC-V RV32 +* Toolchain : GNU C Compiler +********************************************************************************************************* +* Note(s) : Hardware FP is not supported. +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE +* +* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes & variable/object +* declarations for correct C language linkage. +********************************************************************************************************* +*/ + +#ifdef __cplusplus +extern "C" { /* See Note #1. */ +#endif + + +/* +********************************************************************************************************* +* DEFINES +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; /* Unsigned 8 bit boolean or logical */ +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsigned 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef unsigned long long INT64U; /* 64-bit unsigned integer */ +typedef signed long long INT64S; /* 64-bit signed integer */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned int OS_CPU_SR; /* Define size of Machine status register (32 bits) */ + + +/* +********************************************************************************************************* +* RISC-V +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() do { cpu_sr = OS_CPU_SR_Save();} while (0) +#define OS_EXIT_CRITICAL() do { OS_CPU_SR_Restore(cpu_sr);} while (0) +#endif + + +/* +********************************************************************************************************* +* RISC-V Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory */ + +#define OS_TASK_SW() OSCtxSw() + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + + +/* +********************************************************************************************************* +* EXTERNAL C LANGUAGE LINKAGE END +********************************************************************************************************* +*/ + +#ifdef __cplusplus +} /* End of 'extern'al C lang linkage. */ +#endif + + +/* +********************************************************************************************************* +* MODULE END +********************************************************************************************************* +*/ + +#endif diff --git a/Ports/RISC-V/RV32/GCC/os_cpu_a.S b/Ports/RISC-V/RV32/GCC/os_cpu_a.S new file mode 100644 index 0000000..b3bf258 --- /dev/null +++ b/Ports/RISC-V/RV32/GCC/os_cpu_a.S @@ -0,0 +1,318 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# RISC-V Port +# +# Filename : os_cpu_a.S +# Version : V2.93.00 +#******************************************************************************************************** +# For : RISC-V RV32 +# Toolchain : GNU C Compiler +#******************************************************************************************************** +# Note(s) : Hardware FP is not supported. +#******************************************************************************************************** + +#******************************************************************************************************** +# PUBLIC FUNCTIONS +#******************************************************************************************************** + + .extern OSRunning # External references + .extern OSPrioCur + .extern OSPrioHighRdy + .extern OSTCBCur + .extern OSTCBHighRdy + .extern OSIntExit + .extern OSTaskSwHook + + + .global OSStartHighRdy # Functions declared in this file + .global OS_CPU_SR_Save + .global OS_CPU_SR_Restore + .global OSCtxSw + .global OSIntCtxSw + .global Software_IRQHandler + + +#******************************************************************************************************** +# EQUATES +#******************************************************************************************************** + + .equ RISCV_MSTATUS_MIE, 0x08 + + .equ RISCV_MIE_MSIE, 0x08 # M Soft Interrupt bit + + .equ RISCV_PRCI_BASE_ADDR, 0x44000000 + + +#******************************************************************************************************** +# CODE GENERATION DIRECTIVES +#******************************************************************************************************** + +.section .text + + +#******************************************************************************************************** +# CRITICAL SECTION METHOD 3 FUNCTIONS +# +# Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +# would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +# disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +# disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +# into the CPU's status register. +# +# Prototypes : OS_CPU_SR OS_CPU_SR_Save(void); +# void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr); +# +# +# Note(s) : 1) These functions are used in general like this: +# +# void Task (void *p_arg) +# { +# #if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +# OS_CPU_SR cpu_sr; +# #endif +# +# : +# : +# OS_ENTER_CRITICAL(); /* cpu_sr = OS_CPU_SaveSR(); */ +# : +# : +# OS_EXIT_CRITICAL(); /* OS_CPU_RestoreSR(cpu_sr); */ +# : +# : +# } +#******************************************************************************************************** + +OS_CPU_SR_Save: +# Save the Machine status register + csrr a0, mstatus + +# Disable global interupt + li t0, RISCV_MSTATUS_MIE + csrrc zero, mstatus, t0 + ret + +OS_CPU_SR_Restore: +# Restore the Machine status register previous state + csrw mstatus, a0 + ret + + +#******************************************************************************************************** +# START MULTITASKING +# void OSStartHighRdy(void) +# +# Note(s) : 1) OSStartHighRdy() MUST: +# a) Call OSTaskSwHook() then, +# b) Set OSRunning to TRUE, +# c) Set OSTCBHighRdy->OSTCBStkPtr = SP +# d) Restore x1-x31; There is no need to restore x0 since it is always zero. +# e) Enable interrupts (tasks will run with interrupts enabled). +# f) Switch to highest priority task. +#******************************************************************************************************** + +OSStartHighRdy: +# Disable interrupts + li t0, RISCV_MSTATUS_MIE + csrrc zero, mstatus, t0 + +# Execute OS task switch hook. + jal OSTaskSwHook + +# OSRunning = TRUE; + li t0, 0x01 + la t1, OSRunning + sb t0, 0(t1) + +# SWITCH TO HIGHEST PRIORITY TASK + la t0, OSTCBHighRdy + lw t1, 0(t0) + lw sp, 0(t1) + +# Retrieve the location where to jump + lw t0, 31 * 4(sp) + csrw mepc, t0 + +# Restore x1 to x31 registers + lw ra, 0 * 4(sp) + lw t0, 4 * 4(sp) + lw t1, 5 * 4(sp) + lw t2, 6 * 4(sp) + lw s0, 7 * 4(sp) + lw s1, 8 * 4(sp) + lw a0, 9 * 4(sp) + lw a1, 10 * 4(sp) + lw a2, 11 * 4(sp) + lw a3, 12 * 4(sp) + lw a4, 13 * 4(sp) + lw a5, 14 * 4(sp) + lw a6, 15 * 4(sp) + lw a7, 16 * 4(sp) + lw s2, 17 * 4(sp) + lw s3, 18 * 4(sp) + lw s4, 19 * 4(sp) + lw s5, 20 * 4(sp) + lw s6, 21 * 4(sp) + lw s7, 22 * 4(sp) + lw s8, 23 * 4(sp) + lw s9, 24 * 4(sp) + lw s10, 25 * 4(sp) + lw s11, 26 * 4(sp) + lw t3, 27 * 4(sp) + lw t4, 28 * 4(sp) + lw t5, 29 * 4(sp) + lw t6, 30 * 4(sp) + +# Compensate for the stack pointer + addi sp, sp, 32 * 4 + +# Use register t6 to jump to HIGHEST priority + csrr t6, mepc + +# Enable global interrupts + li t0, RISCV_MSTATUS_MIE + csrrs zero, mstatus, t0 + +# Jump to HIGHEST priority task. + jalr x0, t6, 0 + + +#******************************************************************************************************** +# PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +# PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +# +# Note(s) : 1) OSCtxSw() is called when OS wants to perform a task context switch. This function +# triggers a synchronous software interrupt by writing into the MSIP register +# +# 2) OSIntCtxSw() is called by OSIntExit() when it determines a context switch is needed as +# the result of an interrupt. This function triggers a synchronous software interrupt by +# writing into the MSIP register +#******************************************************************************************************** + +OSCtxSw: +OSIntCtxSw: +# MIE_MSIE -- enable software interrupt bit + li t0, RISCV_MIE_MSIE + csrrs zero, mie, t0 + +# This will trigger a synchronous software interrupt; PRCI->MSIP[0] = 0x01; + li t0, RISCV_PRCI_BASE_ADDR + li t1, 0x1 + sw t1, 0x0(t0) + ret + + +#******************************************************************************************************** +# void Software_IRQHandler (void) +# +# Note(s) : 1) This function is defined with weak linking in 'riscv_hal_stubs.c' so that it can be +# overridden by the kernel port with same prototype. +# +# 2) Pseudo-code is: +# a) Disable global interrupts. +# b) Clear soft interrupt for hart0. +# c) Save the process SP in its TCB, OSTCBCur->OSTCBStkPtr = SP; +# d) Call OSTaskSwHook(); +# e) Get current high priority, OSPrioCur = OSPrioHighRdy; +# f) Get current ready thread TCB, OSTCBCur = OSTCBHighRdy; +# g) Get new process SP from TCB, SP = OSTCBHighRdy->OSTCBStkPtr; +# h) Retrieve the address at which exception happened +# i) Restore x1-x31 from new process stack; x0 is always zero. +# j) Perform exception return which will restore remaining context. +# +# 3) On entry into Software_IRQHandler: +# a) The initial register context save is being done by 'entry.S' +# b) Stack pointer was passed by 'entry.s' in register a2. +# c) OSTCBCur points to the OS_TCB of the task to suspend +# OSTCBHighRdy points to the OS_TCB of the task to resume +#******************************************************************************************************** + +Software_IRQHandler: +# Disable interrupts globally and prevent interruption during context switch + li t0, RISCV_MSTATUS_MIE + csrrc zero, mstatus, t0 + +# Clear soft interrupt for hart0, PRCI->MSIP[0] = 0x00; + li t0, RISCV_PRCI_BASE_ADDR + sw zero, 0x0(t0) + +# Stack pointer was passed by 'entry.s' in register a2. +# OSTCBCur->OSTCBStkPtr = SP; + la t0, OSTCBCur + lw t1, 0(t0) + sw a2, 0(t1) + +# Execute OS task switch hook. + jal OSTaskSwHook + +# OSPrioCur = OSPrioHighRdy; + la t0, OSPrioHighRdy + lb t1, 0(t0) + la t0, OSPrioCur + sb t1, 0(t0) + +# OSTCBCur = OSTCBHighRdy; + la t0, OSTCBHighRdy + lw t1, 0(t0) + la t0, OSTCBCur + sw t1, 0(t0) + +# SP = OSTCBHighRdy->OSTCBStkPtr; + lw sp, 0(t1) + +# Retrieve the address at which exception happened + lw t0, 31 * 4(sp) + csrw mepc, t0 + +# Restore x1 to x31 registers + lw ra, 0 * 4(sp) + lw t0, 4 * 4(sp) + lw t1, 5 * 4(sp) + lw t2, 6 * 4(sp) + lw s0, 7 * 4(sp) + lw s1, 8 * 4(sp) + lw a0, 9 * 4(sp) + lw a1, 10 * 4(sp) + lw a2, 11 * 4(sp) + lw a3, 12 * 4(sp) + lw a4, 13 * 4(sp) + lw a5, 14 * 4(sp) + lw a6, 15 * 4(sp) + lw a7, 16 * 4(sp) + lw s2, 17 * 4(sp) + lw s3, 18 * 4(sp) + lw s4, 19 * 4(sp) + lw s5, 20 * 4(sp) + lw s6, 21 * 4(sp) + lw s7, 22 * 4(sp) + lw s8, 23 * 4(sp) + lw s9, 24 * 4(sp) + lw s10, 25 * 4(sp) + lw s11, 26 * 4(sp) + lw t3, 27 * 4(sp) + lw t4, 28 * 4(sp) + lw t5, 29 * 4(sp) + lw t6, 30 * 4(sp) + + addi sp, sp, 4 * 32 + +# Exception return will restore remaining context + mret + + +#******************************************************************************************************** +# MODULE END +#********************************************************************************************************* diff --git a/Ports/RISC-V/RV32/GCC/os_cpu_c.c b/Ports/RISC-V/RV32/GCC/os_cpu_c.c new file mode 100644 index 0000000..ea8869d --- /dev/null +++ b/Ports/RISC-V/RV32/GCC/os_cpu_c.c @@ -0,0 +1,441 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* RISC-V Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : RISC-V RV32 +* Toolchain : GNU C Compiler +********************************************************************************************************* +* Note(s) : Hardware FP is not supported. +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if OS_TMR_EN > 0u + OSTmrCtr = 0u; +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ + +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskCreateHook(p_tcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskDelHook(p_tcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(p_tcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* p_tos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : (1) Interrupts are enabled when task starts executing. +* +* (2) There is no need to save register x0 since it is a hard-wired zero. +* +* (3) RISC-V calling convention register usage: +* +* +-------------+-------------+----------------------------------+ +* | Register | ABI Name | Description | +* +-------------+-------------+----------------------------------+ +* | x31 - x28 | t6 - t3 | Temporaries | +* +-------------+-------------+----------------------------------+ +* | x27 - x18 | s11 - s2 | Saved registers | +* +-------------+-------------+----------------------------------+ +* | x17 - x12 | a7 - a2 | Function arguments | +* +-------------+-------------+----------------------------------+ +* | x11 - x10 | a1 - a0 | Function arguments/return values | +* +-------------+-------------+----------------------------------+ +* | x9 | s1 | Saved register | +* +-------------+-------------+----------------------------------+ +* | x8 | s0/fp | Saved register/frame pointer | +* +-------------+-------------+----------------------------------+ +* | x7 - x5 | t2 - t0 | Temporaries | +* +-------------+-------------+----------------------------------+ +* | x4 | tp | Thread pointer | +* +-------------+-------------+----------------------------------+ +* | x3 | gp | Global pointer | +* +-------------+-------------+----------------------------------+ +* | x2 | sp | Stack pointer | +* +-------------+-------------+----------------------------------+ +* | x1 | ra | return address | +* +-------------+-------------+----------------------------------+ +* | x0 | zero | Hard-wired zero | +* +-------------+-------------+----------------------------------+ +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *p_tos, + INT16U opt) +{ + OS_STK *p_stk; + + + (void) opt; /* 'opt' is not used, prevent warning */ + + p_stk = p_tos + 1u; /* Load stack pointer and align it to 16-bytes */ + p_stk = (OS_STK *)((OS_STK)(p_stk) & 0xFFFFFFF0u); + + *(--p_stk) = (OS_STK) task; /* Entry Point */ + + *(--p_stk) = (OS_STK) 0x31313131uL; /* t6 */ + *(--p_stk) = (OS_STK) 0x30303030uL; /* t5 */ + *(--p_stk) = (OS_STK) 0x29292929uL; /* t4 */ + *(--p_stk) = (OS_STK) 0x28282828uL; /* t3 */ + /* Saved Registers */ + *(--p_stk) = (OS_STK) 0x27272727uL; /* s11 */ + *(--p_stk) = (OS_STK) 0x26262626uL; /* s10 */ + *(--p_stk) = (OS_STK) 0x25252525uL; /* s9 */ + *(--p_stk) = (OS_STK) 0x24242424uL; /* s8 */ + *(--p_stk) = (OS_STK) 0x23232323uL; /* s7 */ + *(--p_stk) = (OS_STK) 0x22222222uL; /* s6 */ + *(--p_stk) = (OS_STK) 0x21212121uL; /* s5 */ + *(--p_stk) = (OS_STK) 0x20202020uL; /* s4 */ + *(--p_stk) = (OS_STK) 0x19191919uL; /* s3 */ + *(--p_stk) = (OS_STK) 0x18181818uL; /* s2 */ + /* Function Arguments */ + *(--p_stk) = (OS_STK) 0x17171717uL; /* a7 */ + *(--p_stk) = (OS_STK) 0x16161616uL; /* a6 */ + *(--p_stk) = (OS_STK) 0x15151515uL; /* a5 */ + *(--p_stk) = (OS_STK) 0x14141414uL; /* a4 */ + *(--p_stk) = (OS_STK) 0x13131313uL; /* a3 */ + *(--p_stk) = (OS_STK) 0x12121212uL; /* a2 */ + /* Function Arguments/return values */ + *(--p_stk) = (OS_STK) 0x11111111uL; /* a1 */ + *(--p_stk) = (OS_STK) p_arg; /* a0 */ + *(--p_stk) = (OS_STK) 0x09090909uL; /* s1 : Saved register */ + *(--p_stk) = (OS_STK) 0x08080808uL; /* s0/fp: Saved register/Frame pointer */ + /* Temporary registers */ + *(--p_stk) = (OS_STK) 0x07070707uL; /* t2 */ + *(--p_stk) = (OS_STK) 0x06060606uL; /* t1 */ + *(--p_stk) = (OS_STK) 0x05050505uL; /* t0 */ + + *(--p_stk) = (OS_STK) 0x04040404uL; /* tp: Thread pointer */ + *(--p_stk) = (OS_STK) 0x03030303uL; /* gp: Global pointer */ + *(--p_stk) = (OS_STK) 0x02020202uL; /* sp: Stack pointer */ + *(--p_stk) = (OS_STK) OS_TaskReturn; /* ra: return address */ + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif + + OS_TRACE_TASK_SWITCHED_IN(OSTCBHighRdy); +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *p_tcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(p_tcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* SYS TICK HANDLER +* +* Description: Handle the system tick (SysTick) interrupt, which is used to generate the uC/OS-II tick +* interrupt. +* +* Arguments : None. +* +* Note(s) : This function is defined with weak linking in 'riscv_hal_stubs.c' so that it can be +* overridden by the kernel port with same prototype +********************************************************************************************************* +*/ + +void SysTick_Handler (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr; +#endif + + OS_ENTER_CRITICAL(); + OSIntEnter(); /* Tell uC/OS-II that we are starting an ISR */ + OS_EXIT_CRITICAL(); + + OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */ + + OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */ +} diff --git a/Ports/RL78/GNURL78/os_cpu.h b/Ports/RL78/GNURL78/os_cpu.h new file mode 100644 index 0000000..e47cdf3 --- /dev/null +++ b/Ports/RL78/GNURL78/os_cpu.h @@ -0,0 +1,139 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RL78 Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RL78 +* Toolchain : E2Studios v2.x GNURL78 Compiler v1.x +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* + ********************************************************************************************************* + * DATA TYPES + * (Compiler Specific) + ********************************************************************************************************* + */ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short int INT16U; /* Unsigned 16 bit quantity */ +typedef signed short int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* The status register (SR) is 8-bits wide */ + +/* + ********************************************************************************************************* + * RL78 + * + * Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts + * will be enabled even if they were disabled before entering the critical section. + * + * Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if + * interrupts were disabled before entering the critical section, they will be disabled when + * leaving the critical section. + * + * Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you + * would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then + * disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to + * disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' + * into the CPU's status register. + * + ********************************************************************************************************* + */ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + +/* Disable interrupts */ +#define OS_ENTER_CRITICAL() __asm("DI"); +/* Enable interrupts */ +#define OS_EXIT_CRITICAL() __asm("EI"); + +#endif + +#if OS_CRITICAL_METHOD == 2 +/* Disable interrupts Save Intr. State to Status Reg */ +#define OS_ENTER_CRITICAL() __asm("PUSH PSW"); \ + __asm("DI"); + +/* Enable interrupts Recall Intr. State from Status Reg */ +#define OS_EXIT_CRITICAL() __asm("POP PSW"); \ + __asm("EI"); + +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = __get_interrupt_state(); \ + __asm("DI"); + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __set_interrupt_state(cpu_sr); + +#endif + +/* + ********************************************************************************************************* + * RL78 MISCELLANEOUS + ********************************************************************************************************* + */ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on the RL78 */ + +#define OS_TASK_SW() __asm("BRK") /* Issues a break instruction */ + +/* + ********************************************************************************************************* + * GLOBAL VARIABLES + ********************************************************************************************************* + */ + +/* + ********************************************************************************************************* + * PROTOTYPES + ********************************************************************************************************* + */ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +void OSStartHighRdy(void); +void OSIntCtxSw(void); +void OSCtxSw(void); + +void OS_CPU_TickInit(INT32U tick_per_sec); +#endif +#endif diff --git a/Ports/RL78/GNURL78/os_cpu_a.asm b/Ports/RL78/GNURL78/os_cpu_a.asm new file mode 100644 index 0000000..c655123 --- /dev/null +++ b/Ports/RL78/GNURL78/os_cpu_a.asm @@ -0,0 +1,246 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + + +;******************************************************************************************************** +; +; Renesas RL78 Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas RL78 +; Toolchain : E2Studios v2.x GNURL78 Compiler v1.x +;******************************************************************************************************** + +#include "os_cpu_a.inc" + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + .global _OSStartHighRdy + .global _OSCtxSw + .global _OSIntCtxSw + .global _OSTickISR + .global _OSTaskSwHook + .global _OSTCBHighRdy + + .global _OSRunning + .global _OSTCBCur + .global _OSPrioCur + .global _OSPrioHighRdy + .global _OSIntEnter + .global _OSTimeTick + .global _OSIntExit + .global _OSIntNesting + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .text + .section .text + + + +;******************************************************************************************************** +; MACRO DEFINITIONS +;******************************************************************************************************** + +; ASEGN RCODE:CODE, 0x007E +; DW OSCtxSw ; Context Switch vector + +; RSEG CODE ; Program code + +;******************************************************************************************************** +; START HIGHEST PRIORITY READY TASK +; +; Description: This function is called by OSStart() to start the highest priority task that is ready to run. +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +; +; Registers are set as such: +; _______________________________________ +; | Functional Name | Absolute Name | +; | 16-bit | 8-bit | 16-bit | 8-bit | +; --------------------------------------- +; | HL | H | RP3 | R7 | +; | | L | | R6 | +; --------------------------------------- +; | DE | D | RP2 | R5 | +; | | E | | R4 | +; --------------------------------------- +; | BC | B | RP1 | R3 | +; | | C | | R2 | +; --------------------------------------- +; | AX | A | RP0 | R1 | +; | | X | | R0 | +; --------------------------------------- +; +; +;******************************************************************************************************** + +_OSStartHighRdy: + + MOVW BC, #_OSTaskSwHook ; Store location of OSTaskSWHook function + CALL BC ; call OSTaskSwHook() + + MOVW HL, #_OSTCBHighRdy ; HL = OSTCBHighRdy + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy[0] (i.e. OSTCBStkPtr) + MOVW HL, AX + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy->OSTCBStkPtr value + MOVW SP, AX ; SP = OSTCBHighRdy->OSTCBStkPtr + + + MOVW BC, #_OSRunning ; Load OSRunning variable into RP1 + MOV [BC], #1 ; Set OSRunning to TRUE + + OS_CTX_RESTORE ; restore all processor registers from new task's stack + + RETI ; return from interrupt + + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description: This function is called by OS_Sched() to perform a task level context switch. +; +; Note : OSCtxSw() MUST: +; a) Save the current task's registers onto the current task stack +; b) Save the SP into the current task's OS_TCB +; c) Call OSTaskSwHook() +; d) Copy OSPrioHighRdy to OSPrioCur +; e) Copy OSTCBHighRdy to OSTCBCur +; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; g) Restore all the registers from the high priority task stack +; h) Perform a return from interrupt +;******************************************************************************************************** + +_OSCtxSw: + OS_CTX_SAVE ; save processor registers on the stack + + ; Save OSTCBCur->StkPtr as current SP value + MOVW DE, #_OSTCBCur ; Get OSTCBCur + MOVW AX, [DE + 0x0000] ; Store OSTCBCur address in AX + MOVW DE, AX + MOVW AX, SP ; AX->OSTCBCur (AX pointed to OSTCBCur) + MOVW [DE + 0x0000], AX ; OSTCBCur->OSTCBStkPtr = SP + + MOVW BC, #_OSTaskSwHook + CALL BC ; call OSTaskSwHook() + + ; Set OSTCBCur = OSTCBHighRdy + MOVW HL, #_OSTCBHighRdy ; HL = OSTCBHighRdy + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy[0] (i.e. OSTCBStkPtr) + MOVW HL, #_OSTCBCur ; HL = OSTCBCur + MOVW [HL + 0x0000], AX ; OSTCBCur = OSTCBHighRdy[0] (sets equal to one another) + + ; Set OSPrioCur to the next ready priority + MOVW DE, #_OSPrioCur ; DE = OSPrioCur + MOVW HL, #_OSPrioHighRdy ; HL = OSPrioHighRdy + MOV A, [HL + 0x0000] ; AX->OSPrioHighRdy + MOV [DE + 0x0000], A ; OSPrioCur = OSPrioHighRdy + + MOVW HL, #_OSTCBHighRdy ; HL = OSTCBHighRdy + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy[0] (i.e. OSTCBStkPtr) + MOVW HL, AX + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy->OSTCBStkPtr value + MOVW SP, AX ; SP = OSTCBHighRdy->OSTCBStkPtr + + OS_CTX_RESTORE ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; ISR LEVEL CONTEXT SWITCH +; +; Description: This function is called by OSIntExit() to perform an ISR level context switch. +; +; Note : OSIntCtxSw() MUST: +; a) Call OSTaskSwHook() +; b) Copy OSPrioHighRdy to OSPrioCur +; c) Copy OSTCBHighRdy to OSTCBCur +; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; e) Restore all the registers from the high priority task stack +; f) Perform a return from interrupt +;******************************************************************************************************** + +_OSIntCtxSw: + MOVW AX, #_OSTaskSwHook + CALL AX ; call OSTaskSwHook + + ; Set OSTCBCur = OSTCBHighRdy + MOVW HL, #_OSTCBHighRdy ; HL = OSTCBHighRdy + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy[0] (i.e. OSTCBStkPtr) + MOVW HL, #_OSTCBCur ; HL = OSTCBCur + MOVW [HL + 0x0000], AX ; OSTCBCur = OSTCBHighRdy[0] (sets equal to one another) + + MOVW DE, #_OSPrioCur ; DE = OSPrioCur + MOVW HL, #_OSPrioHighRdy ; HL = OSPrioHighRdy + MOVW AX, [HL + 0x0000] ; AX->OSPrioHighRdy + MOVW [DE + 0x0000], AX ; OSPrioCur = OSPrioHighRdy + + MOVW HL, #_OSTCBHighRdy ; HL = OSTCBHighRdy + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy[0] (i.e. OSTCBStkPtr) + MOVW HL, AX + MOVW AX, [HL + 0x0000] ; AX = OSTCBHighRdy->OSTCBStkPtr value + MOVW SP, AX ; SP = OSTCBHighRdy->OSTCBStkPtr + + OS_CTX_RESTORE ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; TICK ISR +; +; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source. +; +; Notes : 1) The following C pseudo-code describes the operations being performed in the code below. +; +; a) Save processor registers; +; b) Increment OSIntNesting; +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; d) Call OSTimeTick(); +; e) Call OSIntExit(); +; f) Restore processosr Registers; +; +; 2) OS_CPU_TickHandler() must be registered in the proper vector address of timer that will be +; used as the tick. +; +; 3) All the other ISRs must have the following implementation to secure proper register saving & +; restoring when servicing an interrupt +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +_OSTickISR: + + OS_ISR_ENTER + + MOVW AX, #_OSTimeTick + CALL AX ; call OSTimeTick() + + OS_ISR_EXIT + + .END diff --git a/Ports/RL78/GNURL78/os_cpu_a.inc b/Ports/RL78/GNURL78/os_cpu_a.inc new file mode 100644 index 0000000..c113101 --- /dev/null +++ b/Ports/RL78/GNURL78/os_cpu_a.inc @@ -0,0 +1,155 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + + +;******************************************************************************************************** +; +; ASSEMBLY LANGUAGE MACROS +; Renesas RL78 Port +; +; Filename : os_cpu_a.inc +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas RL78 +; Toolchain : E2Studios v2.x GNURL78 Compiler v1.x +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + .global _OSTCBCur + .global _OSIntNesting + .global _OSIntExit + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .section .text ; RSEG CODE:CODE:NOROOT(1) + + + +;******************************************************************************************************** +; OS_CTX_SAVE +; +; Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +; the same order as they were saved in OSTaskStkInit(). +; +; Note(s) : None. +;******************************************************************************************************** + +.macro OS_CTX_SAVE + PUSH RP0 ; Register R1 + R0 + PUSH RP1 ; Register R3 + R2 + PUSH RP2 ; Register R5 + R4 + PUSH RP3 ; Register R7 + R6 + MOV A, CS ; Save the CS register value + MOV X, A + MOV A, ES ; Save the ES register value + PUSH RP0 ; Save the ES:CS values in register AX +.endm + + + +;******************************************************************************************************** +; OS_CTX_RESTORE +; +; Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +; reverse order of PUSHALL MACRO (see above) +; +; Note(s) : None. +;******************************************************************************************************** + +.macro OS_CTX_RESTORE + POP RP0 ; Get ES:CS registers from AX + MOV ES, A + MOV A, X + MOV CS, A ; Restore the CS and ES registers + POP RP3 + POP RP2 + POP RP1 + POP RP0 +.endm + + + +;******************************************************************************************************** +; OS_ISR_ENTER +; +; Description : Interrupt service routine prologue for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_ENTER +; OS_CTX_SAVE ; Call the macro: OS_CTX_SAVE +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; +; This MACRO is to be used by your assembly language based ISRs as follows: +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +.macro OS_ISR_ENTER + OS_CTX_SAVE ; Save processor registers on the stack + + MOVW RP0, #_OSIntNesting + INCW RP0 ; increment OSIntNesting + CMPW RP0, #1 ; if (OSIntNesting != 1) + BNZ $branch ; jump out to OSTickISR + + ; else + ; { + MOVW RP2, #_OSTCBCur ; OSTCBCur in RP2 + MOVW RP0, [SP] + MOVW [RP2], RP0 ; OSTCBCur->OSTCBStkPtr = SP + ; } +branch: +.endm + + + +;******************************************************************************************************** +; OS_ISR_EXIT +; +; Description : Interrupt service routine epilog for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_EXIT: +; OSIntExit(); ; Call the C function: OSIntExit(); +; POPALL ; Call the macro: POPALL to restore the registers +; Return from interrupt ; CPU instruction to return from interrupt/exception +;******************************************************************************************************** + +.macro OS_ISR_EXIT + MOVW RP0, #_OSIntExit + CALL RP0 ; call OSIntExit() + + OS_CTX_RESTORE ; restore all processor registers from stack + + RETI ; return from interrupt +.endm + + + +;******************************************************************************************************** +; ASSEMBLY LANGUAGE MACROS FILE END +;******************************************************************************************************** diff --git a/Ports/RL78/GNURL78/os_cpu_c.c b/Ports/RL78/GNURL78/os_cpu_c.c new file mode 100644 index 0000000..664598a --- /dev/null +++ b/Ports/RL78/GNURL78/os_cpu_c.c @@ -0,0 +1,315 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RL78 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RL78 +* Toolchain : E2Studios v2.x GNURL78 Compiler v1.x +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* + ********************************************************************************************************* + * GLOBAL DATA + ********************************************************************************************************* + */ + +/* + ********************************************************************************************************* + * LOCAL VARIABLES + ********************************************************************************************************* + */ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* + ********************************************************************************************************* + * OS INITIALIZATION HOOK + * (BEGINNING) + * + * Description: This function is called by OSInit() at the beginning of OSInit(). + * + * Arguments : none + * + * Note(s) : 1) Interrupts should be disabled during this call. + ********************************************************************************************************* + */ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin(void) { +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* + ********************************************************************************************************* + * OS INITIALIZATION HOOK + * (END) + * + * Description: This function is called by OSInit() at the end of OSInit(). + * + * Arguments : none + * + * Note(s) : 1) Interrupts should be disabled during this call. + ********************************************************************************************************* + */ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd(void) { +} +#endif + +/* + ********************************************************************************************************* + * TASK CREATION HOOK + * + * Description: This function is called when a task is created. + * + * Arguments : ptcb is a pointer to the task control block of the task being created. + * + * Note(s) : 1) Interrupts are disabled during this call. + ********************************************************************************************************* + */ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook(OS_TCB *ptcb) { +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* + ********************************************************************************************************* + * TASK DELETION HOOK + * + * Description: This function is called when a task is deleted. + * + * Arguments : ptcb is a pointer to the task control block of the task being deleted. + * + * Note(s) : 1) Interrupts are disabled during this call. + ********************************************************************************************************* + */ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook(OS_TCB *ptcb) { +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* + ********************************************************************************************************* + * IDLE TASK HOOK + * + * Description: This function is called by the idle task. This hook has been added to allow you to do + * such things as STOP the CPU to conserve power. + * + * Arguments : none + * + * Note(s) : 1) Interrupts are enabled during this call. + ********************************************************************************************************* + */ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook(void) { +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* + ********************************************************************************************************* + * TASK RETURN HOOK + * + * Description: This function is called if a task accidentally returns. In other words, a task should + * either be an infinite loop or delete itself when done. + * + * Arguments : ptcb is a pointer to the task control block of the task that is returning. + * + * Note(s) : none + ********************************************************************************************************* + */ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook(OS_TCB *ptcb) { +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* + ********************************************************************************************************* + * STATISTIC TASK HOOK + * + * Description: This function is called every second by uC/OS-II's statistics task. This allows your + * application to add functionality to the statistics task. + * + * Arguments : none + ********************************************************************************************************* + */ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook(void) { +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* + ********************************************************************************************************* + * INITIALIZE A TASK'S STACK + * + * Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the + * stack frame of the task being created. This function is highly processor specific. + * + * Arguments : task is a pointer to the task code + * + * pdata is a pointer to a user supplied data area that will be passed to the task + * when the task first executes. + * + * ptos is a pointer to the top of stack. It is assumed that 'ptos' points to + * a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then + * 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if + * OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address + * of the stack. + * + * opt specifies options that can be used to alter the behavior of OSTaskStkInit(). + * + * + * Returns : Always returns the location of the new top-of-stack' once the processor registers have + * been placed on the stack in the proper order. + * + ********************************************************************************************************* + */ + +OS_STK *OSTaskStkInit(void (*task)(void *pd), void *pdata, OS_STK *ptos, + INT16U opt) { + OS_STK *p_stk; + + (void) opt; + + p_stk = (INT16U *) ptos; /* Load stack pointer */ + + *(--p_stk) = (INT16U) ((INT32U) pdata >> 16); + *(--p_stk) = (INT16U) pdata; + *(--p_stk) = (INT16U) 0x8600; /* PC bits 16-19 in lower 8 bits, psw in upper 16 bits */ + *(--p_stk) = (INT16U) task; /* PC bits 0-15 */ + *(--p_stk) = 0x1100; /* RP0 = R1 + R0 */ + *(--p_stk) = 0x3322; /* RP1 = R3 + R2 */ + *(--p_stk) = 0x5544; /* RP2 = R5 + R4 */ + *(--p_stk) = 0x7766; /* RP3 = R7 + R6 */ + *(--p_stk) = 0x0F00; /* ES:CS = ES + CS register */ + + return (p_stk); +} + +/* + ********************************************************************************************************* + * TASK SWITCH HOOK + * + * Description: This function is called when a task switch is performed. This allows you to perform other + * operations during a context switch. + * + * Arguments : none + * + * Note(s) : 1) Interrupts are disabled during this call. + * 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that + * will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the + * task being switched out (i.e. the preempted task). + ********************************************************************************************************* + */ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook(void) { +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* + ********************************************************************************************************* + * OS_TCBInit() HOOK + * + * Description: This function is called by OS_TCBInit() after setting up most of the TCB. + * + * Arguments : ptcb is a pointer to the TCB of the task being created. + * + * Note(s) : 1) Interrupts may or may not be ENABLED during this call. + ********************************************************************************************************* + */ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook(OS_TCB *ptcb) { +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* + ********************************************************************************************************* + * TICK HOOK + * + * Description: This function is called every tick. + * + * Arguments : none + * + * Note(s) : 1) Interrupts may or may not be ENABLED during this call. + ********************************************************************************************************* + */ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook(void) { +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/RL78/GNURL78/os_dbg.c b/Ports/RL78/GNURL78/os_dbg.c new file mode 100644 index 0000000..3fdc86d --- /dev/null +++ b/Ports/RL78/GNURL78/os_dbg.c @@ -0,0 +1,315 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/RL78/IAR/os_cpu.h b/Ports/RL78/IAR/os_cpu.h new file mode 100644 index 0000000..efaa853 --- /dev/null +++ b/Ports/RL78/IAR/os_cpu.h @@ -0,0 +1,141 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RL78 Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RL78 +* Toolchain : IAR EWRL78 v1.2x and up +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short int INT16U; /* Unsigned 16 bit quantity */ +typedef signed short int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned short int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned char OS_CPU_SR; /* The status register (SR) is 8-bits wide */ + +/* +********************************************************************************************************* +* RL78 +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() __disable_interrupt() + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __enable_interrupt() + +#endif + +#if OS_CRITICAL_METHOD == 2 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() __asm("PUSH PSW"); \ + __asm("DI"); + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __asm("POP PSW"); \ + __asm("EI"); + +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = __get_interrupt_state(); \ + __disable_interrupt() + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() __set_interrupt_state(cpu_sr) + +#endif + +/* +********************************************************************************************************* +* RL78 MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on the NEC 78K0R */ + +#define OS_TASK_SW() __break() /* Issues a break instruction */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +void OSStartHighRdy (void); +void OSIntCtxSw (void); +void OSCtxSw (void); + +void OS_CPU_TickInit (INT32U tick_per_sec); +#endif +#endif diff --git a/Ports/RL78/IAR/os_cpu_a.asm b/Ports/RL78/IAR/os_cpu_a.asm new file mode 100644 index 0000000..3f3f39c --- /dev/null +++ b/Ports/RL78/IAR/os_cpu_a.asm @@ -0,0 +1,189 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas RL78 Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas RL78 +; Toolchain : IAR EWRL78 v1.2x and up +;******************************************************************************************************** + +#include "os_cpu_a.inc" + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + PUBLIC OSStartHighRdy + PUBLIC OSCtxSw + PUBLIC OSIntCtxSw + PUBLIC OSTickISR + EXTERN OSTaskSwHook + EXTERN OSTCBHighRdy + EXTERN OSRunning + EXTERN OSTCBCur + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSIntEnter + EXTERN OSTimeTick + EXTERN OSIntExit + EXTERN OSIntNesting + + +;******************************************************************************************************** +; MACRO DEFINITIONS +;******************************************************************************************************** + + ASEGN RCODE:CODE, 0x007E + DW OSCtxSw ; Context Switch vector + + RSEG CODE ; Program code + +;******************************************************************************************************** +; START HIGHEST PRIORITY READY TASK +; +; Description: This function is called by OSStart() to start the highest priority task that is ready to run. +; +; Note : OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +;******************************************************************************************************** + +OSStartHighRdy: + + CALL OSTaskSwHook ; call OSTaskSwHook() + MOVW RP1, OSTCBHighRdy ; address of OSTCBHighRdy in RP1 + MOVW RP0, 0x0000[RP1] ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW SP, RP0 ; stack pointer = RP0 + + MOV OSRunning, #0x01 ; OSRunning = True + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; TASK LEVEL CONTEXT SWITCH +; +; Description: This function is called by OS_Sched() to perform a task level context switch. +; +; Note : OSCtxSw() MUST: +; a) Save the current task's registers onto the current task stack +; b) Save the SP into the current task's OS_TCB +; c) Call OSTaskSwHook() +; d) Copy OSPrioHighRdy to OSPrioCur +; e) Copy OSTCBHighRdy to OSTCBCur +; f) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; g) Restore all the registers from the high priority task stack +; h) Perform a return from interrupt +;******************************************************************************************************** + +OSCtxSw: + + PUSHALL ; save processor registers on the stack + + ; save current task's stack pointer into current task's OS_TCB + MOVW RP2, OSTCBCur ; OSTCBCur in RP2 + MOVW RP0, SP + MOVW [RP2], RP0 ; OSTCBCur->OSTCBStkPtr = SP + + CALL OSTaskSwHook ; call OSTaskSwHook + + MOVW RP0, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW OSTCBCur, RP0 ; OSTCBCur = OSTCBHighRdy + + MOV R1, OSPrioHighRdy + MOV OSPrioCur, R1 ; OSPrioCur = OSPrioHighRdy + + MOVW RP1, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW RP0, 0x0000[RP1] ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW SP, RP0 ; stack pointer = RP0 + + POPALL ; restore all processor registers from new task's stack + + RETB ; return from break (software level) + +;******************************************************************************************************** +; ISR LEVEL CONTEXT SWITCH +; +; Description: This function is called by OSIntExit() to perform an ISR level context switch. +; +; Note : OSIntCtxSw() MUST: +; a) Call OSTaskSwHook() +; b) Copy OSPrioHighRdy to OSPrioCur +; c) Copy OSTCBHighRdy to OSTCBCur +; d) Load the SP with OSTCBHighRdy->OSTCBStkPtr +; e) Restore all the registers from the high priority task stack +; f) Perform a return from interrupt +;******************************************************************************************************** + +OSIntCtxSw: + CALL OSTaskSwHook ; call OSTaskSwHook + + MOVW RP0, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW OSTCBCur, RP0 ; OSTCBCur = OSTCBHighRdy + + MOV R1, OSPrioHighRdy + MOV OSPrioCur, R1 ; OSPrioCur = OSPrioHighRdy + + MOVW RP1, OSTCBHighRdy ; get address of OSTCBHighRdy + MOVW RP0, 0x0000[RP1] ; RP0 = OSTCBHighRdy->OSTCBStkPtr + MOVW SP, RP0 ; stack pointer = RP0 + + POPALL ; restore all processor registers from new task's stack + + RETI ; return from interrupt + +;******************************************************************************************************** +; TICK ISR +; +; Description: This ISR handles tick interrupts. This ISR uses the Watchdog timer as the tick source. +; +; Notes : 1) The following C pseudo-code describes the operations being performed in the code below. +; +; a) Save processor registers; +; b) Increment OSIntNesting; +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; d) Call OSTimeTick(); +; e) Call OSIntExit(); +; f) Restore processosr Registers; +; +; 2) OS_CPU_TickHandler() must be registered in the proper vector address of timer that will be +; used as the tick. +; +; 3) All the other ISRs must have the following implementation to secure proper register saving & +; restoring when servicing an interrupt +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OSTickISR: + + OS_ISR_ENTER + + CALL OSTimeTick ; call OSTimeTick() + + OS_ISR_EXIT + + END diff --git a/Ports/RL78/IAR/os_cpu_a.inc b/Ports/RL78/IAR/os_cpu_a.inc new file mode 100644 index 0000000..e5168e7 --- /dev/null +++ b/Ports/RL78/IAR/os_cpu_a.inc @@ -0,0 +1,153 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; ASSEMBLY LANGUAGE MACROS +; Renesas RL78 Port +; +; Filename : os_cpu_a.inc +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas RL78 +; Toolchain : IAR EWRL78 v1.2x and up +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC AND EXTERNAL DECLARATIONS +;******************************************************************************************************** + + EXTERN OSTCBCur + EXTERN OSIntNesting + EXTERN OSIntExit + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(1) + + + +;******************************************************************************************************** +; PUSHALL +; +; Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +; the same order as they were saved in OSTaskStkInit(). +; +; Note(s) : None. +;******************************************************************************************************** + +PUSHALL MACRO + PUSH RP0 ; Register R1 + R0 + PUSH RP1 ; Register R3 + R2 + PUSH RP2 ; Register R5 + R4 + PUSH RP3 ; Register R7 + R6 + MOV A, CS ; Save the CS register value + MOV X, A + MOV A, ES ; Save the ES register value + PUSH RP0 ; Save the ES:CS values in register AX + ENDM + + + +;******************************************************************************************************** +; POPALL +; +; Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +; reverse order of PUSHALL MACRO (see above) +; +; Note(s) : None. +;******************************************************************************************************** + +POPALL MACRO + POP RP0 ; Get ES:CS registers from AX + MOV ES, A + MOV A, X + MOV CS, A ; Restore the CS and ES registers + POP RP3 + POP RP2 + POP RP1 + POP RP0 + ENDM + + + +;******************************************************************************************************** +; OS_ISR_ENTER +; +; Description : Interrupt service routine prologue for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_ENTER +; PUSHALL ; Call the macro: PUSHALL +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; +; This MACRO is to be used by your assembly language based ISRs as follows: +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_ISR_ENTER MACRO + PUSHALL ; Save processor registers on the stack + LOCAL branch + + INC OSIntNesting ; increment OSIntNesting + CMP OSIntNesting, #1 ; if (OSIntNesting != 1) + BNZ branch ; jump out to OSTickISR + + ; else + ; { + MOVW RP2, OSTCBCur ; OSTCBCur in RP2 + MOVW RP0, SP + MOVW [RP2], RP0 ; OSTCBCur->OSTCBStkPtr = SP + ; } +branch: + ENDM + + + +;******************************************************************************************************** +; OS_ISR_EXIT +; +; Description : Interrupt service routine epilog for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_EXIT: +; OSIntExit(); ; Call the C function: OSIntExit(); +; POPALL ; Call the macro: POPALL to restore the registers +; Return from interrupt ; CPU instruction to return from interrupt/exception +;******************************************************************************************************** + +OS_ISR_EXIT MACRO + CALL OSIntExit ; call OSIntExit() + + POPALL ; restore all processor registers from stack + + RETI ; return from interrupt + ENDM + + + +;******************************************************************************************************** +; ASSEMBLY LANGUAGE MACROS FILE END +;******************************************************************************************************** + diff --git a/Ports/RL78/IAR/os_cpu_c.c b/Ports/RL78/IAR/os_cpu_c.c new file mode 100644 index 0000000..ad2f541 --- /dev/null +++ b/Ports/RL78/IAR/os_cpu_c.c @@ -0,0 +1,307 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RL78 Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RL78 +* Toolchain : IAR EWRL78 v1.2x and up +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + OS_STK *p_stk; + + (void)opt; + + p_stk = (INT16U *)ptos; /* Load stack pointer */ + + *(--p_stk) = (INT16U)((INT32U)pdata >> 16); + *(--p_stk) = (INT16U)pdata; + *(--p_stk) = (INT16U)(((INT32U)task >> 16) & 0x000F) | 0x8600; /* PC bits 16-19 in lower 8 bits, psw in upper 16 bits */ + *(--p_stk) = (INT16U)task; /* PC bits 0-15 */ + *(--p_stk) = 0x1100; /* RP0 = R1 + R0 */ + *(--p_stk) = 0x3322; /* RP1 = R3 + R2 */ + *(--p_stk) = 0x5544; /* RP2 = R5 + R4 */ + *(--p_stk) = 0x7766; /* RP3 = R7 + R6 */ + *(--p_stk) = 0x0F00; /* ES:CS = ES + CS register */ + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/RL78/IAR/os_dbg.c b/Ports/RL78/IAR/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/RL78/IAR/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/RX/GNURX/os_cpu.h b/Ports/RX/GNURX/os_cpu.h new file mode 100644 index 0000000..2f9fe01 --- /dev/null +++ b/Ports/RX/GNURX/os_cpu.h @@ -0,0 +1,124 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RX Specific Code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RX +* Toolchain : HEW with GNURX compiler +* E2STUDIO with GNURX compiler +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; /* 8-bit boolean or logical */ +typedef unsigned char INT8U; /* 8-bit unsigned integer */ +typedef signed char INT8S; /* 8-bit signed integer */ +typedef unsigned short INT16U; /* 16-bit unsigned integer */ +typedef signed short INT16S; /* 16-bit signed integer */ +typedef unsigned long INT32U; /* 32-bit unsigned integer */ +typedef signed long INT32S; /* 32-bit signed integer */ +typedef float FP32; /* 32-bit floating point */ +typedef double FP64; /* 64-bit floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() OSCtxSw() /* Context switch through pended call */ + + +/* +********************************************************************************************************* +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#ifdef CPU_CFG_KA_IPL_BOUNDARY +#define OS_ENTER_CRITICAL() do { cpu_sr = get_ipl(); \ + set_ipl(CPU_CFG_KA_IPL_BOUNDARY); } while (0) +#else +#define OS_ENTER_CRITICAL() do { cpu_sr = get_ipl(); \ + set_ipl(12); } while (0) +#endif + /* Restore CPU status word. */ +#define OS_EXIT_CRITICAL() do { set_ipl(cpu_sr); } while (0) +#endif + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +void OSCtxSwISR (void); + +CPU_INT32U OS_KA_IPL_BoundaryGet (void); + +#endif diff --git a/Ports/RX/GNURX/os_cpu_a.S b/Ports/RX/GNURX/os_cpu_a.S new file mode 100644 index 0000000..c931df1 --- /dev/null +++ b/Ports/RX/GNURX/os_cpu_a.S @@ -0,0 +1,282 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas RX Specific Code +; +; Filename : os_cpu_a.S +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas RX +; Toolchain : HEW with GNURX compiler +; E2STUDIO with GNURX compiler +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .global _OSStartHighRdy ; Public functions + .global _OSCtxSwISR ; Perform a context switch + + .global _OSRunning ; External function references + .global _OSTCBCur + .global _OSTCBHighRdy + .global _OSPrioCur ; Declared as INT8U , 8-bit long + .global _OSPrioHighRdy ; Declared as INT8U , 8-bit long + .global _OSTaskSwHook + .global _OS_KA_IPL_BoundaryGet + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .text + .section .text + + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame for the RX100 and RX200 families is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> MACHI +; + 4 MACMI +; + 8 R1 (i.e. p_arg) (32-bit contents of 'p_arg') +; + 12 R2 +; + 16 R3 +; + 20 R4 +; + 24 R5 +; + 28 R6 +; + 32 R7 +; + 36 R8 +; + 40 R9 +; + 44 R10 +; + 48 R11 +; + 52 R12 +; + 56 R12 +; + 60 R14 +; + 64 R15 +; + 68 task (32-bit address of 'task') +; + 72 PSW (Initial value of 0x0000) +; HIGH MEMORY +; +; 2) The stack frame for the RX600 family is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> MACHI +; + 4 MACMI +; + 8 FPSW +; + 12 R1 (i.e. p_arg) (32-bit contents of 'p_arg') +; + 16 R2 +; + 20 R3 +; + 24 R4 +; + 28 R5 +; + 32 R6 +; + 36 R7 +; + 40 R8 +; + 44 R9 +; + 48 R10 +; + 52 R11 +; + 56 R12 +; + 60 R12 +; + 64 R14 +; + 68 R15 +; + 72 task (32-bit address of 'task') +; + 76 PSW (Initial value of 0x0000) +; +; HIGH MEMORY +; +; 3) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy: + MOV.L #_OSTaskSwHook, R5 ; Execute task switch hook + JSR R5 + + MOV.L #_OSRunning, R5 ; Set OSRunning to TRUE + MOV.B #1, [R5] + + SETPSW U + + MOV.L #_OSTCBHighRdy, R5 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L [R5], R2 + MOV.L [R2], R0 + + ; RESTORE CONTEXT OF NEW TASK + POPM R1-R2 ; Pop Accumulator registers + SHLL #16, R2 ; Correct for mid read/low write + MVTACLO R2 ; Write Accumulator + MVTACHI R1 + +#if (defined(__RX_FPU_INSNS__) && (__RX_FPU_INSNS__==1)) + POPC FPSW ; Restore FP status word +#endif + + POPM R1-R15 ; Restore registers + RTE ; Restore PSW and PC + + + +;********************************************************************************************************* +; PENDED CONTEXT SWITCH ISR +; +; Description : This ISR Performs all context switching within the OS. +; +; Arguments : none +; +; Note(s) : 1) Upon entry... +; OSTCBCur Points to the OS_TCB of the task to suspend +; OSTCBHighRdy Contains the pointer from the last scheduling +; +; +; 2) The interrupt stack frame looks as follows. This was caused by the +; execution of SWINT event (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; ISP + 0 ----> 32-bit PC of task +; + 4 32-bit PSW +; + 8 +; HIGH MEMORY +; +; +; 3) The stack frame of the task to resume (for RX100 and RX200 families) looks as follows: +; +; LOW MEMORY +; OSTCBHighRdyPtr->StkPtr + 0 ----> MACHI +; + 4 MACLO +; + 8 R1 (p_arg) +; + 12 R2 +; + 16 R3 +; + 20 R4 +; + 24 R5 +; + 28 R6 +; + 32 R7 +; + 36 R8 +; + 40 R9 +; + 44 R10 +; + 48 R11 +; + 52 R12 +; + 56 R12 +; + 60 R14 +; + 64 R15 +; + 68 task (32-bit address of 'task') +; + 72 PSW +; HIGH MEMORY +; +; +; 4) The stack frame of the task to resume (for the RX600 family) looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->StkPtr + 0 ----> MACHI +; + 4 MACLO +; + 8 FPSW +; + 12 R1 (p_arg) +; + 16 R2 +; + 20 R3 +; + 24 R4 +; + 28 R5 +; + 32 R6 +; + 36 R7 +; + 40 R8 +; + 44 R9 +; + 48 R10 +; + 52 R11 +; + 56 R12 +; + 60 R12 +; + 64 R14 +; + 68 R15 +; + 72 task (32-bit address of 'task') +; + 76 PSW +; HIGH MEMORY +;********************************************************************************************************* + +_OSCtxSwISR: + SETPSW I ; Re-enable higher priority interrupts. + + ; Transfer Interrupt Stack Contents to the current user stack + PUSH.L R15 ; Save R15 to interrupt stack as we'll use for temporary register. + MVFC USP, R15 ; Read the user stack pointer + SUB #12, R15 ; Create space on user stack + MVTC R15, USP ; Update USP + + ; SAVE CONTEXT OF TASK BEING SWITCHED OUT + ; Copy the data across from interrupt stack + MOV.L 8[R0], 8[R15] ; PSW + MOV.L 4[R0], 4[R15] ; PC + MOV.L 0[R0], 0[R15] ; R15 + ADD #12, R0 ; correct ISP for data we are done with using (RTE will be from USP) + SETPSW U ; Switch to user stack for pushing rest of registers + PUSHM R1-R14 ; Save remaining registers + +#if (defined(__RX_FPU_INSNS__) && (__RX_FPU_INSNS__==1)) + PUSHC FPSW ; Save FPSW +#endif + + MVFACHI R1 ; Save special registers + MVFACMI R2 + PUSHM R1-R2 + + ; Context is saved, registers can be used, handle OS requirements + BSR.A _OS_KA_IPL_BoundaryGet ; Set IPL to Kernel Awareness boundary + MVFC PSW, R2 + AND #-0F000001H, R2 + SHLL #24, R1 + OR R1, R2 + MVTC R2, PSW + + MOV.L #_OSTCBCur, R5 ; Save current task's SP into its TCB + MOV.L [R5], R2 + MOV.L R0, [R2] + + MOV.L #_OSTaskSwHook, R5 ; Execute task switch hook + JSR R5 + + MOV.L #_OSPrioCur, R3 ; OSPrioCur = OSPrioHighRdy + MOV.L #_OSPrioHighRdy, R2 + MOV.B [R2], [R3] + + MOV.L #_OSTCBCur, R3 ; OSTCBCur = OSTCBHighRdy + MOV.L #_OSTCBHighRdy, R2 + MOV.L [R2], [R3] + MOV.L [R3], R2 + MOV.L [R2], R0 ; SP = OSTCBCur->StkPtr + + MVTIPL #1 ; Restore IPL to level 1 + + ; RESTORE CONTEXT OF NEW TASK + POPM R1-R2 ; Load ACC registers from stack + SHLL #16, R2 ; Correct for reading mid/writing low + MVTACHI R1 ; Restore special registers + MVTACLO R2 + +#if (defined(__RX_FPU_INSNS__) && (__RX_FPU_INSNS__==1)) + POPC FPSW ; Restore FP status word +#endif + + POPM R1-R15 + RTE + + .END diff --git a/Ports/RX/GNURX/os_cpu_c.c b/Ports/RX/GNURX/os_cpu_c.c new file mode 100644 index 0000000..2b492b5 --- /dev/null +++ b/Ports/RX/GNURX/os_cpu_c.c @@ -0,0 +1,437 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RX Specific Code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RX +* Toolchain : HEW with GNURX compiler +* E2STUDIO with GNURX compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include +#include + + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + +#define PSW_INIT 0x00030000u + + /* ------ SOFTWARE INTERRUPT ACTIVATION REGISTERS ----- */ +#define ICU_BASE_ADDR 0x00087000u +#define ICU_REG_IR027_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x01Bu)) +#define ICU_REG_IER03_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x203u)) +#define ICU_REG_SWINTR (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x2E0u)) +#define ICU_REG_IPR003_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x303u)) + +#define ICU_SWINTR_BIT_SWINT DEF_BIT_00 +#define ICU_IER03_BIT_SWINT DEF_BIT_03 + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif + + ICU_REG_IR027_SWINT = 0u; /* Ensure the software interrupt is clear. */ + ICU_REG_IPR003_SWINT = 1u; /* Pended context switches must be level 1 IPL */ + ICU_REG_IER03_SWINT = ICU_IER03_BIT_SWINT; /* Enable the software interrupt. */ +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + + + (void)opt; /* Prevent compiler warning */ + + p_stk = ptos; /* Load stack pointer */ + *--p_stk = (OS_STK)PSW_INIT; /* PSW */ + *--p_stk = (OS_STK)task; /* PC of task */ + *--p_stk = 0x15151515u; /* R15 */ + *--p_stk = 0x14141414u; /* R14 */ + *--p_stk = 0x13131313u; /* R13 */ + *--p_stk = 0x12121212u; /* R12 */ + *--p_stk = 0x11111111u; /* R11 */ + *--p_stk = 0x10101010u; /* R10 */ + *--p_stk = 0x09090909u; /* R9 */ + *--p_stk = 0x08080808u; /* R8 */ + *--p_stk = 0x07070707u; /* R7 */ + *--p_stk = 0x06060606u; /* R6 */ + *--p_stk = 0x05050505u; /* R5 */ + *--p_stk = 0x04040404u; /* R4 */ + *--p_stk = 0x03030303u; /* R3 */ + *--p_stk = 0x02020202u; /* R2 */ + *--p_stk = (OS_STK)p_arg; /* Pass p_arg in R1 */ + +#if (defined(__RX_FPU_INSNS__) && (__RX_FPU_INSNS__==1)) + *--p_stk = 0x00000100u; /* FPSW */ +#endif + + *--p_stk = 0x00009ABCu; /* ACC (mid, lower word) */ + *--p_stk = 0x12345678u; /* ACC (high) */ + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif + OS_TRACE_TASK_SWITCHED_IN(OSTCBHighRdy); +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* Context Switch +* +* Description: This function is called to switch task context (called from task) +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OSCtxSw (void) +{ + ICU_REG_SWINTR = ICU_SWINTR_BIT_SWINT; /* Trigger the pended interrupt request */ +} + + +/* +********************************************************************************************************* +* Context Switch from ISR +* +* Description: This function is called to switch task context (called from isr) +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + ICU_REG_SWINTR = ICU_SWINTR_BIT_SWINT; /* Trigger the pended interrupt request */ +} + + +/* +********************************************************************************************************* +* Get Kernel Awareness IPL boundary +* +* Description: This function returns the configuration value for the boundary between kernel-aware and +* non-kernel-aware ISRs. +* +* Arguments : None. +* +* Returns : The IPL in the lower bits (typically a number between 1 and 15) +********************************************************************************************************* +*/ + +CPU_INT32U OS_KA_IPL_BoundaryGet (void) +{ + return (CPU_CFG_KA_IPL_BOUNDARY); +} diff --git a/Ports/RX/GNURX/os_dbg.c b/Ports/RX/GNURX/os_dbg.c new file mode 100644 index 0000000..8f2417f --- /dev/null +++ b/Ports/RX/GNURX/os_dbg.c @@ -0,0 +1,325 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define MICRIUM_SOURCE + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#ifdef OS_SAFETY_CRITICAL_IEC61508 + + sizeof(OSSafetyCriticalStartFlag) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TASK_REG_TBL_SIZE > 0u + + sizeof(OSTaskRegNextAvailID) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/RX/IAR/os_cpu.h b/Ports/RX/IAR/os_cpu.h new file mode 100644 index 0000000..b65a58d --- /dev/null +++ b/Ports/RX/IAR/os_cpu.h @@ -0,0 +1,121 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RX Specific Code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RX +* Toolchain : IAR Embedded Workbench for Renesas RX +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; /* 8-bit boolean or logical */ +typedef unsigned char INT8U; /* 8-bit unsigned integer */ +typedef signed char INT8S; /* 8-bit signed integer */ +typedef unsigned short INT16U; /* 16-bit unsigned integer */ +typedef signed short INT16S; /* 16-bit signed integer */ +typedef unsigned long INT32U; /* 32-bit unsigned integer */ +typedef signed long INT32S; /* 32-bit signed integer */ +typedef float FP32; /* 32-bit floating point */ +typedef double FP64; /* 64-bit floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() OSCtxSw() /* Context switch through pended call */ + + +/* +********************************************************************************************************* +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#ifdef CPU_CFG_KA_IPL_BOUNDARY +#define OS_ENTER_CRITICAL() do { cpu_sr = __get_interrupt_level(); \ + __set_interrupt_level(CPU_CFG_KA_IPL_BOUNDARY); } while (0) +#else +#define OS_ENTER_CRITICAL() do { cpu_sr = __get_interrupt_level(); \ + __set_interrupt_level(12); } while (0) +#endif + /* Restore CPU status word. */ +#define OS_EXIT_CRITICAL() do { __set_interrupt_level(cpu_sr); } while (0) +#endif + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +void OSCtxSwISR (void); + +#endif diff --git a/Ports/RX/IAR/os_cpu_a.s b/Ports/RX/IAR/os_cpu_a.s new file mode 100644 index 0000000..5159051 --- /dev/null +++ b/Ports/RX/IAR/os_cpu_a.s @@ -0,0 +1,276 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas RX Specific Code +; +; Filename : os_cpu_a.s +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas RX +; Toolchain : IAR Embedded Workbench for Renesas RX +;******************************************************************************************************** + +#include + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + PUBLIC _OSStartHighRdy ; Public functions + PUBLIC _OSCtxSwISR ; Perform a context switch + + EXTERN _OSRunning ; External function references + EXTERN _OSTCBCur + EXTERN _OSTCBHighRdy + EXTERN _OSPrioCur ; Declared as INT8U , 8-bit long + EXTERN _OSPrioHighRdy ; Declared as INT8U , 8-bit long + EXTERN _OSTaskSwHook + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + section .text:CODE:ROOT + + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame for the RX100 and RX200 families is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> MACHI +; + 4 MACMI +; + 8 R1 (i.e. p_arg) (32-bit contents of 'p_arg') +; + 12 R2 +; + 16 R3 +; + 20 R4 +; + 24 R5 +; + 28 R6 +; + 32 R7 +; + 36 R8 +; + 40 R9 +; + 44 R10 +; + 48 R11 +; + 52 R12 +; + 56 R12 +; + 60 R14 +; + 64 R15 +; + 68 task (32-bit address of 'task') +; + 72 PSW (Initial value of 0x0000) +; HIGH MEMORY +; +; 2) The stack frame for the RX600 family is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> MACHI +; + 4 MACMI +; + 8 FPSW +; + 12 R1 (i.e. p_arg) (32-bit contents of 'p_arg') +; + 16 R2 +; + 20 R3 +; + 24 R4 +; + 28 R5 +; + 32 R6 +; + 36 R7 +; + 40 R8 +; + 44 R9 +; + 48 R10 +; + 52 R11 +; + 56 R12 +; + 60 R12 +; + 64 R14 +; + 68 R15 +; + 72 task (32-bit address of 'task') +; + 76 PSW (Initial value of 0x0000) +; +; HIGH MEMORY +; +; 3) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Switch to the highest priority task. +;********************************************************************************************************* + +_OSStartHighRdy: + MOV.L #_OSTaskSwHook, R5 ; Execute task switch hook + JSR R5 + + MOV.L #_OSRunning, R5 ; Set OSRunning to TRUE + MOV.B #1, [R5] + + SETPSW U + + MOV.L #_OSTCBHighRdy, R5 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L [R5], R2 + MOV.L [R2], SP + + ; RESTORE CONTEXT OF NEW TASK + POPM R1-R2 ; Pop Accumulator registers + SHLL #16, R2 ; Correct for mid read/low write + MVTACLO R2 ; Write Accumulator + MVTACHI R1 + +#if (((__VER__>=250) && (__FPU__==1)) || \ +((__VER__<250) && (__CORE__!=__RX100__) && (__CORE__!=__RX200__))) + POPC FPSW ; Restore FP status word (NOT for RX100 and RX200 families) +#endif + + POPM R1-R15 ; Restore registers + RTE ; Restore PSW and PC + + + +;********************************************************************************************************* +; PENDED CONTEXT SWITCH ISR +; +; Description : This ISR Performs all context switching within the OS. +; +; Arguments : none +; +; Note(s) : 1) Upon entry... +; OSTCBCur Points to the OS_TCB of the task to suspend +; OSTCBHighRdy Contains the pointer from the last scheduling +; +; +; 2) The interrupt stack frame looks as follows. This was caused by the +; execution of SWINT event (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; ISP + 0 ----> 32-bit PC of task +; + 4 32-bit PSW +; + 8 +; HIGH MEMORY +; +; +; 3) The stack frame of the task to resume (for RX100 and RX200 families) looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->StkPtr + 0 ----> MACHI +; + 4 MACLO +; + 8 R1 (p_arg) +; + 12 R2 +; + 16 R3 +; + 20 R4 +; + 24 R5 +; + 28 R6 +; + 32 R7 +; + 36 R8 +; + 40 R9 +; + 44 R10 +; + 48 R11 +; + 52 R12 +; + 56 R12 +; + 60 R14 +; + 64 R15 +; + 68 task (32-bit address of 'task') +; + 72 PSW +; HIGH MEMORY +; +; +; 4) The stack frame of the task to resume (for the RX600 family) looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->StkPtr + 0 ----> MACHI +; + 4 MACLO +; + 8 FPSW +; + 12 R1 (p_arg) +; + 16 R2 +; + 20 R3 +; + 24 R4 +; + 28 R5 +; + 32 R6 +; + 36 R7 +; + 40 R8 +; + 44 R9 +; + 48 R10 +; + 52 R11 +; + 56 R12 +; + 60 R12 +; + 64 R14 +; + 68 R15 +; + 72 task (32-bit address of 'task') +; + 76 PSW +; HIGH MEMORY +;********************************************************************************************************* + +_OSCtxSwISR: + SETPSW I ; Re-enable higher priority interrupts. + + ; Transfer Interrupt Stack Contents to the current user stack + PUSH.L R15 ; Save R15 to interrupt stack as we'll use for temporary register. + MVFC USP, R15 ; Read the user stack pointer + SUB #12, R15 ; Create space on user stack + MVTC R15, USP ; Update USP + + ; SAVE CONTEXT OF TASK BEING SWITCHED OUT + ; Copy the data across from interrupt stack + MOV.L 8[R0], 8[R15] ; PSW + MOV.L 4[R0], 4[R15] ; PC + MOV.L 0[R0], 0[R15] ; R15 + ADD #12, R0 ; correct ISP for data we are done with using (RTE will be from USP) + SETPSW U ; Switch to user stack for pushing rest of registers + PUSHM R1-R14 ; Save remaining registers +#if (((__VER__>=250) && (__FPU__==1)) || \ +((__VER__<250) && (__CORE__!=__RX100__) && (__CORE__!=__RX200__))) + PUSHC FPSW ; Save FPSW (NOT for RX100 and RX200) +#endif + MVFACHI R1 ; Save special registers + MVFACMI R2 + PUSHM R1-R2 + + ; Context is saved, registers can be used, handle OS requirements + MVTIPL #CPU_CFG_KA_IPL_BOUNDARY ; Set the IPL to the KA boundary level + + MOV.L #_OSTCBCur, R5 ; Save current task's SP into its TCB + MOV.L [R5], R2 + MOV.L SP, [R2] + + MOV.L #_OSTaskSwHook, R5 ; Execute task switch hook + JSR R5 + + MOV.L #_OSPrioCur, R3 ; OSPrioCur = OSPrioHighRdy + MOV.L #_OSPrioHighRdy, R2 + MOV.B [R2], [R3] + + MOV.L #_OSTCBCur, R3 ; OSTCBCur = OSTCBHighRdy + MOV.L #_OSTCBHighRdy, R2 + MOV.L [R2], [R3] + MOV.L [R3], R2 + MOV.L [R2], SP ; SP = OSTCBCur->StkPtr + + MVTIPL #1 ; Restore IPL to level 1 + + ; RESTORE CONTEXT OF NEW TASK + POPM R1-R2 ; Load ACC registers from stack + SHLL #16, R2 ; Correct for reading mid/writing low + MVTACHI R1 ; Restore special registers + MVTACLO R2 +#if (((__VER__>=250) && (__FPU__==1)) || \ +((__VER__<250) && (__CORE__!=__RX100__) && (__CORE__!=__RX200__))) + POPC FPSW ; Restore FPSW (NOT for RX100 and RX200) +#endif + POPM R1-R15 + RTE + + END diff --git a/Ports/RX/IAR/os_cpu_c.c b/Ports/RX/IAR/os_cpu_c.c new file mode 100644 index 0000000..c14ccd2 --- /dev/null +++ b/Ports/RX/IAR/os_cpu_c.c @@ -0,0 +1,418 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RX Specific Code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RX +* Toolchain : IAR Embedded Workbench for Renesas RX +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include +#include + + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + +#define PSW_INIT 0x00030000u + + /* ------ SOFTWARE INTERRUPT ACTIVATION REGISTERS ----- */ +#define ICU_BASE_ADDR 0x00087000u +#define ICU_REG_IR027_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x01Bu)) +#define ICU_REG_IER03_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x203u)) +#define ICU_REG_SWINTR (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x2E0u)) +#define ICU_REG_IPR003_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x303u)) + +#define ICU_SWINTR_BIT_SWINT DEF_BIT_00 +#define ICU_IER03_BIT_SWINT DEF_BIT_03 + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif + + ICU_REG_IR027_SWINT = 0u; /* Ensure the software interrupt is clear. */ + ICU_REG_IPR003_SWINT = 1u; /* Pended context switches must be level 1 IPL */ + ICU_REG_IER03_SWINT = ICU_IER03_BIT_SWINT; /* Enable the software interrupt. */ +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + + + (void)opt; /* Prevent compiler warning */ + + p_stk = ptos; /* Load stack pointer */ + *--p_stk = (OS_STK)PSW_INIT; /* PSW */ + *--p_stk = (OS_STK)task; /* PC of task */ + *--p_stk = 0x15151515u; /* R15 */ + *--p_stk = 0x14141414u; /* R14 */ + *--p_stk = 0x13131313u; /* R13 */ + *--p_stk = 0x12121212u; /* R12 */ + *--p_stk = 0x11111111u; /* R11 */ + *--p_stk = 0x10101010u; /* R10 */ + *--p_stk = 0x09090909u; /* R9 */ + *--p_stk = 0x08080808u; /* R8 */ + *--p_stk = 0x07070707u; /* R7 */ + *--p_stk = 0x06060606u; /* R6 */ + *--p_stk = 0x05050505u; /* R5 */ + *--p_stk = 0x04040404u; /* R4 */ + *--p_stk = 0x03030303u; /* R3 */ + *--p_stk = 0x02020202u; /* R2 */ + *--p_stk = (OS_STK)p_arg; /* Pass p_arg in R1 */ + +#if (((__VER__>=250) && (__FPU__==1)) || \ +((__VER__<250) && (__CORE__!=__RX100__) && (__CORE__!=__RX200__))) + *--p_stk = 0x00000100u; /* FPSW is NOT available for RX100 and RX200 families */ +#endif + + *--p_stk = 0x00009ABCu; /* ACC (mid, lower word) */ + *--p_stk = 0x12345678u; /* ACC (high) */ + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif + OS_TRACE_TASK_SWITCHED_IN(OSTCBHighRdy); +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* Context Switch +* +* Description: This function is called to switch task context (called from task) +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OSCtxSw (void) +{ + ICU_REG_SWINTR = ICU_SWINTR_BIT_SWINT; /* Trigger the pended interrupt request */ +} + + +/* +********************************************************************************************************* +* Context Switch from ISR +* +* Description: This function is called to switch task context (called from isr) +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + ICU_REG_SWINTR = ICU_SWINTR_BIT_SWINT; /* Trigger the pended interrupt request */ +} diff --git a/Ports/RX/IAR/os_dbg.c b/Ports/RX/IAR/os_dbg.c new file mode 100644 index 0000000..8f2417f --- /dev/null +++ b/Ports/RX/IAR/os_dbg.c @@ -0,0 +1,325 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define MICRIUM_SOURCE + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#ifdef OS_SAFETY_CRITICAL_IEC61508 + + sizeof(OSSafetyCriticalStartFlag) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TASK_REG_TBL_SIZE > 0u + + sizeof(OSTaskRegNextAvailID) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/RX/RXC/os_cpu.h b/Ports/RX/RXC/os_cpu.h new file mode 100644 index 0000000..7f44fa2 --- /dev/null +++ b/Ports/RX/RXC/os_cpu.h @@ -0,0 +1,124 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RX Specific Code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RXC compiler +* Toolchain : HEW with RXC +* E2STUDIO with RXC +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; /* 8-bit boolean or logical */ +typedef unsigned char INT8U; /* 8-bit unsigned integer */ +typedef signed char INT8S; /* 8-bit signed integer */ +typedef unsigned short INT16U; /* 16-bit unsigned integer */ +typedef signed short INT16S; /* 16-bit signed integer */ +typedef unsigned long INT32U; /* 32-bit unsigned integer */ +typedef signed long INT32S; /* 32-bit signed integer */ +typedef float FP32; /* 32-bit floating point */ +typedef double FP64; /* 64-bit floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* Define size of CPU status register (PSR = 32 bits) */ + + +/* +********************************************************************************************************* +* MACROS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() OSCtxSw() /* Context switch through pended call */ + + +/* +********************************************************************************************************* +* Critical Section Management +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* NOT IMPLEMENTED +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#ifdef CPU_CFG_KA_IPL_BOUNDARY +#define OS_ENTER_CRITICAL() do { cpu_sr = get_ipl(); \ + set_ipl(CPU_CFG_KA_IPL_BOUNDARY); } while (0) +#else +#define OS_ENTER_CRITICAL() do { cpu_sr = get_ipl(); \ + set_ipl(12); } while (0) +#endif + /* Restore CPU status word. */ +#define OS_EXIT_CRITICAL() do { set_ipl(cpu_sr); } while (0) +#endif + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + +void OSCtxSwISR (void); + +CPU_INT32U OS_KA_IPL_BoundaryGet (void); + +#endif diff --git a/Ports/RX/RXC/os_cpu_a.src b/Ports/RX/RXC/os_cpu_a.src new file mode 100644 index 0000000..be975f9 --- /dev/null +++ b/Ports/RX/RXC/os_cpu_a.src @@ -0,0 +1,281 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas RX Specific Code +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas RXC compiler +; Toolchain : HEW with RXC +; E2STUDIO with RXC +;******************************************************************************************************** + + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .GLB _OSRunning ; External function references + .GLB _OSTCBCur + .GLB _OSTCBHighRdy + .GLB _OSPrioCur ; Declared as INT8U , 8-bit long + .GLB _OSPrioHighRdy ; Declared as INT8U , 8-bit long + .GLB _OSTaskSwHook + .GLB _OS_KA_IPL_BoundaryGet + + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + + +;********************************************************************************************************* +; START MULTITASKING +; +; Description : This function is called by OSStart() to start the highest priority task that was created +; by your application before calling OSStart(). +; +; Arguments : none +; +; Note(s) : 1) The stack frame for the RX100 and RX200 families is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> MACHI +; + 4 MACMI +; + 8 R1 (i.e. p_arg) (32-bit contents of 'p_arg') +; + 12 R2 +; + 16 R3 +; + 20 R4 +; + 24 R5 +; + 28 R6 +; + 32 R7 +; + 36 R8 +; + 40 R9 +; + 44 R10 +; + 48 R11 +; + 52 R12 +; + 56 R12 +; + 60 R14 +; + 64 R15 +; + 68 task (32-bit address of 'task') +; + 72 PSW (Initial value of 0x0000) +; HIGH MEMORY +; +; 2) The stack frame for the RX600 family is assumed to look as follows: +; +; LOW MEMORY +; OSTCBHighRdy->OSTCBStkPtr + 0 ----> MACHI +; + 4 MACMI +; + 8 FPSW +; + 12 R1 (i.e. p_arg) (32-bit contents of 'p_arg') +; + 16 R2 +; + 20 R3 +; + 24 R4 +; + 28 R5 +; + 32 R6 +; + 36 R7 +; + 40 R8 +; + 44 R9 +; + 48 R10 +; + 52 R11 +; + 56 R12 +; + 60 R12 +; + 64 R14 +; + 68 R15 +; + 72 task (32-bit address of 'task') +; + 76 PSW (Initial value of 0x0000) +; +; HIGH MEMORY +; +; 3) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Switch to the highest priority task. +;********************************************************************************************************* + + .SECTION P, CODE + .GLB _OSStartHighRdy + +_OSStartHighRdy: + MOV.L #_OSTaskSwHook, R5 ; Execute task switch hook + JSR R5 + + MOV.L #_OSRunning, R5 ; Set OSRunning to TRUE + MOV.B #1, [R5] + + SETPSW U + + MOV.L #_OSTCBHighRdy, R5 ; SP = OSTCBHighRdy->OSTCBStkPtr + MOV.L [R5], R2 + MOV.L [R2], SP + + ; RESTORE CONTEXT OF NEW TASK + POPM R1-R2 ; Pop Accumulator registers + SHLL #16, R2 ; Correct for mid read/low write + MVTACLO R2 ; Write Accumulator + MVTACHI R1 + +.if __RX600 + POPC FPSW ; Restore FP status word (NOT for RX100 and RX200 families) +.endif + + POPM R1-R15 ; Restore registers + RTE ; Restore PSW and PC + + + +;********************************************************************************************************* +; PENDED CONTEXT SWITCH ISR +; +; Description : This ISR Performs all context switching within the OS. +; +; Arguments : none +; +; Note(s) : 1) Upon entry... +; OSTCBCur Points to the OS_TCB of the task to suspend +; OSTCBHighRdy Contains the pointer from the last scheduling +; +; +; 2) The interrupt stack frame looks as follows. This was caused by the +; execution of SWINT event (the registers for the task to suspend need to be +; saved): +; +; LOW MEMORY +; ISP + 0 ----> 32-bit PC of task +; + 4 32-bit PSW +; + 8 +; HIGH MEMORY +; +; +; 3) The stack frame of the task to resume (for RX100 and RX200 families) looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->StkPtr + 0 ----> MACHI +; + 4 MACLO +; + 8 R1 (p_arg) +; + 12 R2 +; + 16 R3 +; + 20 R4 +; + 24 R5 +; + 28 R6 +; + 32 R7 +; + 36 R8 +; + 40 R9 +; + 44 R10 +; + 48 R11 +; + 52 R12 +; + 56 R12 +; + 60 R14 +; + 64 R15 +; + 68 task (32-bit address of 'task') +; + 72 PSW +; HIGH MEMORY +; +; +; 4) The stack frame of the task to resume (for the RX600 family) looks as follows: +; +; LOW MEMORY +; OSTCBHighRdy->StkPtr + 0 ----> MACHI +; + 4 MACLO +; + 8 FPSW +; + 12 R1 (p_arg) +; + 16 R2 +; + 20 R3 +; + 24 R4 +; + 28 R5 +; + 32 R6 +; + 36 R7 +; + 40 R8 +; + 44 R9 +; + 48 R10 +; + 52 R11 +; + 56 R12 +; + 60 R12 +; + 64 R14 +; + 68 R15 +; + 72 task (32-bit address of 'task') +; + 76 PSW +; HIGH MEMORY +;********************************************************************************************************* + + .SECTION P, CODE + .GLB _OSCtxSwISR + +_OSCtxSwISR: + SETPSW I ; Re-enable higher priority interrupts. + + ; Transfer Interrupt Stack Contents to the current user stack + PUSH.L R15 ; Save R15 to interrupt stack as we'll use for temporary register. + MVFC USP, R15 ; Read the user stack pointer + SUB #12, R15 ; Create space on user stack + MVTC R15, USP ; Update USP + + ; SAVE CONTEXT OF TASK BEING SWITCHED OUT + ; Copy the data across from interrupt stack + MOV.L 8[R0], 8[R15] ; PSW + MOV.L 4[R0], 4[R15] ; PC + MOV.L 0[R0], 0[R15] ; R15 + ADD #12, R0 ; correct ISP for data we are done with using (RTE will be from USP) + SETPSW U ; Switch to user stack for pushing rest of registers + PUSHM R1-R14 ; Save remaining registers +.if __RX600 + PUSHC FPSW ; Save FPSW (NOT for RX100 and RX200) +.endif + MVFACHI R1 ; Save special registers + MVFACMI R2 + PUSHM R1-R2 + + ; Context is saved, registers can be used, handle OS requirements + BSR.A _OS_KA_IPL_BoundaryGet ; Set IPL to Kernel Awareness boundary + MVFC PSW, R2 + AND #-0F000001H, R2 + SHLL #24, R1 + OR R1, R2 + MVTC R2, PSW + + MOV.L #_OSTCBCur, R5 ; Save current task's SP into its TCB + MOV.L [R5], R2 + MOV.L SP, [R2] + + MOV.L #_OSTaskSwHook, R5 ; Execute task switch hook + JSR R5 + + MOV.L #_OSPrioCur, R3 ; OSPrioCur = OSPrioHighRdy + MOV.L #_OSPrioHighRdy, R2 + MOV.B [R2], [R3] + + MOV.L #_OSTCBCur, R3 ; OSTCBCur = OSTCBHighRdy + MOV.L #_OSTCBHighRdy, R2 + MOV.L [R2], [R3] + MOV.L [R3], R2 + MOV.L [R2], SP ; SP = OSTCBCur->StkPtr + + MVTIPL #1 ; Restore IPL to level 1 + + ; RESTORE CONTEXT OF NEW TASK + POPM R1-R2 ; Load ACC registers from stack + SHLL #16, R2 ; Correct for reading mid/writing low + MVTACHI R1 ; Restore special registers + MVTACLO R2 +.if __RX600 + POPC FPSW ; Restore FPSW (NOT for RX100 and RX200) +.endif + POPM R1-R15 + RTE + + .END diff --git a/Ports/RX/RXC/os_cpu_c.c b/Ports/RX/RXC/os_cpu_c.c new file mode 100644 index 0000000..34844da --- /dev/null +++ b/Ports/RX/RXC/os_cpu_c.c @@ -0,0 +1,437 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas RX Specific Code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas RXC compiler +* Toolchain : HEW with RXC +* E2STUDIO with RXC +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include +#include + + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + +#define PSW_INIT 0x00030000u + + /* ------ SOFTWARE INTERRUPT ACTIVATION REGISTERS ----- */ +#define ICU_BASE_ADDR 0x00087000u +#define ICU_REG_IR027_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x01Bu)) +#define ICU_REG_IER03_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x203u)) +#define ICU_REG_SWINTR (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x2E0u)) +#define ICU_REG_IPR003_SWINT (*(CPU_REG08 *)(ICU_BASE_ADDR + 0x303u)) + +#define ICU_SWINTR_BIT_SWINT DEF_BIT_00 +#define ICU_IER03_BIT_SWINT DEF_BIT_03 + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif + + ICU_REG_IR027_SWINT = 0u; /* Ensure the software interrupt is clear. */ + ICU_REG_IPR003_SWINT = 1u; /* Pended context switches must be level 1 IPL */ + ICU_REG_IER03_SWINT = ICU_IER03_BIT_SWINT; /* Enable the software interrupt. */ +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt) +{ + OS_STK *p_stk; + + + (void)opt; /* Prevent compiler warning */ + + p_stk = ptos; /* Load stack pointer */ + *--p_stk = (OS_STK)PSW_INIT; /* PSW */ + *--p_stk = (OS_STK)task; /* PC of task */ + *--p_stk = 0x15151515u; /* R15 */ + *--p_stk = 0x14141414u; /* R14 */ + *--p_stk = 0x13131313u; /* R13 */ + *--p_stk = 0x12121212u; /* R12 */ + *--p_stk = 0x11111111u; /* R11 */ + *--p_stk = 0x10101010u; /* R10 */ + *--p_stk = 0x09090909u; /* R9 */ + *--p_stk = 0x08080808u; /* R8 */ + *--p_stk = 0x07070707u; /* R7 */ + *--p_stk = 0x06060606u; /* R6 */ + *--p_stk = 0x05050505u; /* R5 */ + *--p_stk = 0x04040404u; /* R4 */ + *--p_stk = 0x03030303u; /* R3 */ + *--p_stk = 0x02020202u; /* R2 */ + *--p_stk = (OS_STK)p_arg; /* Pass p_arg in R1 */ + +#if __RX600 + *--p_stk = 0x00000100u; /* FPSW is NOT available for RX100 and RX200 families */ +#endif + + *--p_stk = 0x00009ABCu; /* ACC (mid, lower word) */ + *--p_stk = 0x12345678u; /* ACC (high) */ + + return (p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif + OS_TRACE_TASK_SWITCHED_IN(OSTCBHighRdy); +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* Context Switch +* +* Description: This function is called to switch task context (called from task) +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OSCtxSw (void) +{ + ICU_REG_SWINTR = ICU_SWINTR_BIT_SWINT; /* Trigger the pended interrupt request */ +} + + +/* +********************************************************************************************************* +* Context Switch from ISR +* +* Description: This function is called to switch task context (called from isr) +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + ICU_REG_SWINTR = ICU_SWINTR_BIT_SWINT; /* Trigger the pended interrupt request */ +} + + +/* +********************************************************************************************************* +* Get Kernel Awareness IPL boundary +* +* Description: This function returns the configuration value for the boundary between kernel-aware and +* non-kernel-aware ISRs. +* +* Arguments : None. +* +* Returns : The IPL in the lower bits (typically a number between 1 and 15) +********************************************************************************************************* +*/ + +CPU_INT32U OS_KA_IPL_BoundaryGet (void) +{ + return (CPU_CFG_KA_IPL_BOUNDARY); +} diff --git a/Ports/RX/RXC/os_dbg.c b/Ports/RX/RXC/os_dbg.c new file mode 100644 index 0000000..8f2417f --- /dev/null +++ b/Ports/RX/RXC/os_dbg.c @@ -0,0 +1,325 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define MICRIUM_SOURCE + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#ifdef OS_SAFETY_CRITICAL_IEC61508 + + sizeof(OSSafetyCriticalStartFlag) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TASK_REG_TBL_SIZE > 0u + + sizeof(OSTaskRegNextAvailID) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/SH-2/Renesas/os_cpu.h b/Ports/SH-2/Renesas/os_cpu.h new file mode 100644 index 0000000..571273e --- /dev/null +++ b/Ports/SH-2/Renesas/os_cpu.h @@ -0,0 +1,144 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2 Specific code +* Renesas C/C++ Compiler Toolchain v8.0.1.0 +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef unsigned long long INT64U; /* Unsigned 64 bit quantity */ +typedef signed long long INT64S; /* Signed 64 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* The status register (SR) is 32-bits wide */ + +/* +********************************************************************************************************* +* Renesas SH-2 +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() set_imask( 15 ) /* level 14 is used to ensure compatibility with HDI-M */ + /* when using the EVB7045F evaluation board */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_imask( 0 ) +#endif + +#if OS_CRITICAL_METHOD == 2 +/* Not currently supported */ + +/* The accepted way of implementing method 2 is to store the status register (SR - containing the */ +/* current interrupt mask level) on to the stack before changing the mask level to a value */ +/* which masks all interrupts. To do this without a function call (which would use the stack */ +/* when called) requires the use of in line assembler. Unfortunately, there does not appear to */ +/* be away for the Renesas compiler's inline assembler code to tell the compiler which */ +/* registers are being clobbered so that the compiler can take appropriate action. */ + +/* When the Renesas compiler requires a temporary scratch area within a function it can make room */ +/* on the stack by adjusting the stack pointer. Any access to the scratch area then uses an offset */ +/* from the stack pointer. So, if inline assembly code adjusts the stack pointer, as it would when */ +/* storing the current SR value, any reference to the scratch area is broken until the value is popped */ +/* from the stack and the stack pointer contents return to the value expected by the compiler. */ +/* In tests this has been seen to break critical functions including 'OSTCBInit' and */ +/* 'OSTaskCreate'. */ + +/* The only solution I have come up with to this problem is to compile the code to assembler and */ +/* manually alter the affected code which is not really acceptable and so far untested. If anyone */ +/* can come up with a workable solution to this problem I would be greatful to hear it. I have */ +/* adjusted optimisation settings etc to try and fix this problem without success. */ + +/* Therefore it is suggested that method 3, below, is used */ +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = get_cr(); set_imask( 15 ) + /* level 14 is used to ensure compatibility with HDI-M */ + /* when using the EVB7045F evaluation board */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_imask( cpu_sr ) +#endif + +/* +********************************************************************************************************* +* Renesas SH-2 Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on SH2 */ + +#define uCOS 33 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() trapa( uCOS ); /* TRAPA instruction */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ +#endif diff --git a/Ports/SH-2/Renesas/os_cpu_a.src b/Ports/SH-2/Renesas/os_cpu_a.src new file mode 100644 index 0000000..b781722 --- /dev/null +++ b/Ports/SH-2/Renesas/os_cpu_a.src @@ -0,0 +1,279 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas SH-2 Specific code +; Renesas C/C++ Compiler Toolchain v8.0.1.0 +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** + + .EXPORT _OSStartHighRdy + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + .EXPORT _OSTickISR + .IMPORT _OSTaskSwHook + .IMPORT _OSTCBHighRdy + .IMPORT _OSRunning + .IMPORT _OSTCBCur + .IMPORT _OSPrioCur + .IMPORT _OSPrioHighRdy + .IMPORT _OSIntEnter + .IMPORT _OSTimeTick + .IMPORT _OSIntExit + .IMPORT _OSIntNesting + + + .SECTION P,CODE,ALIGN=4 + +_OSStartHighRdy: + mov.l #_OSTaskSwHook, r1 ; address of OSTaskSwHook function in R1 + jsr @r1 ; call OSTaskSwHook() + nop + + mov.l #_OSTCBHighRdy, r1 ; address of OSTCBHighRdy in R1 + mov.l @r1, r2 ; r2 is now the address of the ready task + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OSTCBStkptr + + mov.l #_OSRunning, r1 ; address of OSRunning in R1 + mov #1, r2 ; OSRunning = TRUE (1) + mov.b r2, @r1 + +; restore all processor registers from new task's stack + + mov.l @r15+, r14 + mov.l @r15+, r13 + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + mov.l @r15+, r8 + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + lds.l @r15+, pr + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte ; return from interrupt + nop + + +_OSCtxSw: ; save processor registers on the stack + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + sts.l pr, @-r15 + mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l r2, @-r15 + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + mov.l r8, @-r15 + mov.l r9, @-r15 + mov.l r10, @-r15 + mov.l r11, @-r15 + mov.l r12, @-r15 + mov.l r13, @-r15 + mov.l r14, @-r15 + +; save current task's stack pointer into current task's OS_TCB + + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r0, r3 ; R3 contains address of current TCB + mov.l r15, @r3 ; put stack pointer into it + + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.b @r2, r3 + mov.b r3, @r0 + + mov.l @r1, r2 ; r2 contains address of current TCB + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OSTCBStkPtr + +; restore all processor registers from new task's stack + + mov.l @r15+, r14 + mov.l @r15+, r13 + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + mov.l @r15+, r8 + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + lds.l @r15+, pr + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + +_OSIntCtxSw: + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.b @r2, r3 + mov.b r3, @r0 ; OSPrioCur = OSPrioHighRdy + + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l @r3, r15 ; CPU stack pointer = OSTCBHighRdy->OSTCBStkPtr + +; restore all processor registers from new task's stack + + mov.l @r15+, r14 + mov.l @r15+, r13 + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + mov.l @r15+, r8 + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + lds.l @r15+, pr + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + +_OSTickISR: +; Save processor registers on the stack + + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + sts.l pr, @-r15 + mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l r2, @-r15 + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + mov.l r8, @-r15 + mov.l r9, @-r15 + mov.l r10, @-r15 + mov.l r11, @-r15 + mov.l r12, @-r15 + mov.l r13, @-r15 + mov.l r14, @-r15 + +; clear compare match interupt + + mov.l #_OSIntNesting, r1 ; Increment OSIntNesting + mov.b @r1, r0 + extu.b r0, r0 + add #1, r0 + mov.b r0, @r1 ; If OSIntNesting == 1 save the current stack pointer + tst #1, r0 ; onto the current task's stack + bt _OSTickISR1 + + mov.l #_OSTCBCur, r1 ; Save current task's SP into its TCB + mov.l @r1, r0 + mov r15, @r0 + +_OSTickISR1: + mov.l #CMT0_CMCSR0, r3 ; clear CMT0 compare match flag in CMCSR + mov.l #CMT0_CMF, r2 + mov.l @r3, r3 + mov.l @r2, r2 + mov.w @r3, r1 + and r2, r1 ; clear CMF bit + mov.w r1, @r3 + + mov.l #_OSTimeTick, r0 + jsr @r0 ; call OSTimeTick() + nop + + mov.l #_OSIntExit, r0 + jsr @r0 ; call OSIntExit() + nop + +; restore all processor registers from stack + + mov.l @r15+, r14 + mov.l @r15+, r13 + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + mov.l @r15+, r8 + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + lds.l @r15+, pr + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + .ALIGN 4 +CMT0_CMCSR0: + .DATA.L h'ffff83d2 +CMT0_CMF: + .DATA.L h'0000ff7f + + .END diff --git a/Ports/SH-2/Renesas/os_cpu_c.c b/Ports/SH-2/Renesas/os_cpu_c.c new file mode 100644 index 0000000..e1e0270 --- /dev/null +++ b/Ports/SH-2/Renesas/os_cpu_c.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2 Specific code +* Renesas C/C++ Compiler Toolchain v8.0.1.0 +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +//#include "..\demo\ucos_ii_demo\ucos_ii_demo\includes.h" +#include + +#define INT_MASK_ON 0x00000000L +#define INT_MASK_OFF 0x000000E0L +/* Mask set to level 14 for when the OS is used with the HDI-M debugger on the EVB7045F */ +/* The OS must not mask the interrupts required by HDI-M */ + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *stk; + + + opt = opt; /* prevent compiler warning */ + stk = (INT32U *)ptos; /* load stack pointer */ + *--stk = (INT32U) INT_MASK_ON; /* SR */ + *--stk = (INT32U) task; /* PC of task */ + *--stk = 0xA0L; /* macl */ + *--stk = 0xA1L; /* mach */ + *--stk = 0xA2L; /* gbr */ + *--stk = 0xA3L; /* pr */ + *--stk = 0L; /* r0 */ + *--stk = 1L; /* r1 */ + *--stk = 2L; /* r2 */ + *--stk = 3L; /* r3 */ + *--stk = (INT32U) pdata; /* pass pdata in r4 */ + *--stk = 5L; /* r5 */ + *--stk = 6L; /* r6 */ + *--stk = 7L; /* r7 */ + *--stk = 8L; /* r8 */ + *--stk = 9L; /* r9 */ + *--stk = 10L; /* r10 */ + *--stk = 11L; /* r11 */ + *--stk = 12L; /* r12 */ + *--stk = 13L; /* r13 */ + *--stk = 14L; /* r14 */ + + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif \ No newline at end of file diff --git a/Ports/SH-2/Renesas/os_dbg.c b/Ports/SH-2/Renesas/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/SH-2/Renesas/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/SH2A-FPU/HEW/os_cpu.h b/Ports/SH2A-FPU/HEW/os_cpu.h new file mode 100644 index 0000000..5b914d8 --- /dev/null +++ b/Ports/SH2A-FPU/HEW/os_cpu.h @@ -0,0 +1,157 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2A-FPU Specific code +* Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef unsigned long long INT64U; /* Unsigned 64 bit quantity */ +typedef signed long long INT64S; /* Signed 64 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* The status register (SR) is 32-bits wide */ + +/* +********************************************************************************************************* +* Renesas SH-2A-FPU +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() set_imask( 15 ) /* When using a ROM Monitor e.g. HMON change this level so not to mask + out the debugger interrupts */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_imask( 0 ) +#endif + +#if OS_CRITICAL_METHOD == 2 +/* Not currently supported */ + +/* The accepted way of implementing method 2 is to store the status register (SR - containing the */ +/* current interrupt mask level) on to the stack before changing the mask level to a value */ +/* which masks all interrupts. To do this without a function call (which would use the stack */ +/* when called) requires the use of in line assembler. Unfortunately, there does not appear to */ +/* be away for the Renesas compiler's inline assembler code to tell the compiler which */ +/* registers are being clobbered so that the compiler can take appropriate action. */ + +/* When the Renesas compiler requires a temporary scratch area within a function it can make room */ +/* on the stack by adjusting the stack pointer. Any access to the scratch area then uses an offset */ +/* from the stack pointer. So, if inline assembly code adjusts the stack pointer, as it would when */ +/* storing the current SR value, any reference to the scratch area is broken until the value is popped */ +/* from the stack and the stack pointer contents return to the value expected by the compiler. */ +/* In tests this has been seen to break critical functions including 'OSTCBInit' and */ +/* 'OSTaskCreate'. */ + +/* The only solution I have come up with to this problem is to compile the code to assembler and */ +/* manually alter the affected code which is not really acceptable and so far untested. */ + +/* Therefore it is suggested that method 3, below, is used */ +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = get_cr(); set_imask( 15 ) + /* When using a ROM Monitor e.g. HMON change this level so not to mask + out the debugger interrupts */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_cr( cpu_sr ) +#endif + +/* +********************************************************************************************************* +* Renesas SH-2A-FPU Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on SH-2A-FPU */ + +#define uCOS 33 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() trapa( uCOS ); /* TRAPA instruction */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ + +void OSStartHighRdy(void); +void OSIntCtxSw (void); +void OSCtxSw (void); + +INT32U OS_Get_GBR (void); + +#endif diff --git a/Ports/SH2A-FPU/HEW/os_cpu_a.inc b/Ports/SH2A-FPU/HEW/os_cpu_a.inc new file mode 100644 index 0000000..4de54d6 --- /dev/null +++ b/Ports/SH2A-FPU/HEW/os_cpu_a.inc @@ -0,0 +1,150 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas SH-2A-FPU Specific code +; Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +; +; Filename : os_cpu_a.inc +; Version : V2.93.00 +;******************************************************************************************************** + + .IMPORT _OSIntNesting + .IMPORT _OSTCBCur + .IMPORT _OSIntExit + + .SECTION P, CODE + +;******************************************************************************************************** +; OS_CTX_SAVE +;* Save CPU Context +;******************************************************************************************************** + .MACRO OS_CTX_SAVE ; save processor registers on the stack + movml.l r15, @-r15 ; push registers PR, R14, R13 ... R0 + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l tbr, r0 + mov.l r0, @-r15 + stc.l gbr, @-r15 + sts.l fpul, @-r15 + sts.l fpscr, @-r15 + fmov.s fr15, @-r15 + fmov.s fr14, @-r15 + fmov.s fr13, @-r15 + fmov.s fr12, @-r15 + fmov.s fr11, @-r15 + fmov.s fr10, @-r15 + fmov.s fr9, @-r15 + fmov.s fr8, @-r15 + fmov.s fr7, @-r15 + fmov.s fr6, @-r15 + fmov.s fr5, @-r15 + fmov.s fr4, @-r15 + fmov.s fr3, @-r15 + fmov.s fr2, @-r15 + fmov.s fr1, @-r15 + fmov.s fr0, @-r15 + .ENDM + +;******************************************************************************************************** +; OS_CTX_RESTORE +;* Restore CPU Context +;******************************************************************************************************** + + .MACRO OS_CTX_RESTORE ; restore all processor registers from new task's stack + fmov.s @r15+, fr0 + fmov.s @r15+, fr1 + fmov.s @r15+, fr2 + fmov.s @r15+, fr3 + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + fmov.s @r15+, fr12 + fmov.s @r15+, fr13 + fmov.s @r15+, fr14 + fmov.s @r15+, fr15 + lds.l @r15+, fpscr + lds.l @r15+, fpul + ldc.l @r15+, gbr + mov.l @r15+, r0 + ldc r0, tbr + lds.l @r15+, mach + lds.l @r15+, macl + movml.l @r15+, r15 ; restores R0, R1 ... R14, PR + .ENDM + + +;******************************************************************************************************** +; OS_ISR_ENTER +; +; Description : Interrupt service routine prologue for kernel-aware handler. +; +; Note(s) : 1) A kernel-aware handler should be written as follows: +; +; MyKernelAwareISR: +; OS_ISR_ENTER +; : ; service ISR +; OS_ISR_EXIT +;******************************************************************************************************** + + .MACRO OS_ISR_ENTER + + OS_CTX_SAVE ; Save context & Notify uC/OS about ISR + + + mov.l #_OSIntNesting, r1 ; Set OSIntNestingCtr == 1 (interrupt nesting not supported) + mov.l #1, r2 + mov.b r2, @r1 + + + mov.l #_OSTCBCur, r1 ; Save current task's SP into its TCB + mov.l @r1, r0 + mov r15, @r0 + + .ENDM + + + +;******************************************************************************************************** +; OS_ISR_EXIT +; +; Description : Interrupt service routine epilog for kernel-aware handler. +; +; Note(s) : 1) A kernel-aware handler should be written as follows: +; +; MyKernelAwareISR: +; OS_ISR_ENTER +; : ; service ISR +; OS_ISR_EXIT +;******************************************************************************************************** + + .MACRO OS_ISR_EXIT + + nop + mov.l #_OSIntExit, r0 + jsr @r0 ; call OSIntExit() + nop + + OS_CTX_RESTORE ; Restore context + + rte ; return from interrupt + nop + + .ENDM diff --git a/Ports/SH2A-FPU/HEW/os_cpu_a.src b/Ports/SH2A-FPU/HEW/os_cpu_a.src new file mode 100644 index 0000000..a92206a --- /dev/null +++ b/Ports/SH2A-FPU/HEW/os_cpu_a.src @@ -0,0 +1,138 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas SH-2A-FPU Specific code +; Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** + + .INCLUDE "os_cpu_a.inc" ; Include OS_CTX_SAVE and OS_CTX_RESTORE macros + + + .EXPORT _OS_Get_GBR + .EXPORT _OSStartHighRdy + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + + .IMPORT _OSTaskSwHook + .IMPORT _OSTCBHighRdy + .IMPORT _OSRunning + .IMPORT _OSPrioCur + .IMPORT _OSPrioHighRdy + .IMPORT _OSIntEnter + + + .SECTION P,CODE,ALIGN=4 + + +;******************************************************************************************************** +; OS_Get_GBR() +;******************************************************************************************************** + +_OS_Get_GBR: + stc.l gbr, r0 + rts + nop + + +;******************************************************************************************************** +; OSStartHighRdy() +;******************************************************************************************************** + +_OSStartHighRdy: + mov.l #_OSTaskSwHook, r1 ; address of OSTaskSwHook function in R1 + jsr @r1 ; call OSTaskSwHook() + nop + + mov.l #_OSTCBHighRdy, r1 ; address of OSTCBHighRdy in R1 + mov.l @r1, r2 ; r2 is now the address of the ready task + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OstcBStkptr + + mov.l #_OSRunning, r1 ; address of OSRunning in R1 + mov #1, r2 ; OSRunning = TRUE (1) + mov.b r2, @r1 + + OS_CTX_RESTORE ; restore all processor registers from new task's stack + + rte ; return from interrupt + nop + + +;******************************************************************************************************** +; OSCtxSw() +;******************************************************************************************************** + +_OSCtxSw: + OS_CTX_SAVE ; save processor registers on the stack + + ; save current task's stack pointer into current task's OS_TCB + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r0, r3 ; R3 contains address of current TCB + mov.l r15, @r3 ; put stack pointer into it + + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.b @r2, r3 + mov.b r3, @r0 + + mov.l @r1, r2 ; r2 contains address of current TCB + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OstcBStkPtr + + OS_CTX_RESTORE ; restore all processor registers from new task's stack + + rte + nop + + +;******************************************************************************************************** +; OSIntCtxSw() +;******************************************************************************************************** + +_OSIntCtxSw: + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.b @r2, r3 + mov.b r3, @r0 ; OSPrioCur = OSPrioHighRdy + + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l @r3, r15 ; CPU stack pointer = OSTCBHighRdy->OstcBStkPtr + + OS_CTX_RESTORE ; restore all processor registers from new task's stack + + rte + nop + + + .END diff --git a/Ports/SH2A-FPU/HEW/os_cpu_c.c b/Ports/SH2A-FPU/HEW/os_cpu_c.c new file mode 100644 index 0000000..9c029f9 --- /dev/null +++ b/Ports/SH2A-FPU/HEW/os_cpu_c.c @@ -0,0 +1,355 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2A-FPU Specific code +* Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + /* The OS must not mask the interrupts required by ROM ... */ + /* ... monitor type debugger, e.g. HMON */ +#define INT_MASK_ON 0x00000000L +#define INT_MASK_OFF 0x000000F0L + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *stk; + + + opt = opt; /* prevent compiler warning */ + stk = (INT32U *)ptos; /* load stack pointer */ + *--stk = (INT32U )INT_MASK_ON; /* SR */ + *--stk = (INT32U )task; /* PC of task */ + *--stk = 0xA3L; /* pr */ + *--stk = 14L; /* r14 */ + *--stk = 13L; /* r13 */ + *--stk = 12L; /* r12 */ + *--stk = 11L; /* r11 */ + *--stk = 10L; /* r10 */ + *--stk = 9L; /* r9 */ + *--stk = 8L; /* r8 */ + *--stk = 7L; /* r7 */ + *--stk = 6L; /* r6 */ + *--stk = 5L; /* r5 */ + *--stk = (INT32U)pdata; /* pass pdata in r4 */ + *--stk = 3L; /* r3 */ + *--stk = 2L; /* r2 */ + *--stk = 1L; /* r1 */ + *--stk = 0L; /* r0 */ + *--stk = 0xA0L; /* macl */ + *--stk = 0xA1L; /* mach */ + *--stk = (INT32U)get_tbr(); /* TBR */ + *--stk = (INT32U)OS_Get_GBR(); /* GBR */ + *--stk = 0xFL; /* FPUL */ + *--stk = (INT32U)get_fpscr(); /* FPSCR */ + *--stk = 0xF15L; /* FR15 */ + *--stk = 0xF14L; /* FR14 */ + *--stk = 0xF13L; /* FR13 */ + *--stk = 0xF12L; /* FR12 */ + *--stk = 0xF11L; /* FR11 */ + *--stk = 0xF10L; /* FR10 */ + *--stk = 0xF9L; /* FR9 */ + *--stk = 0xF8L; /* FR8 */ + *--stk = 0xF7L; /* FR7 */ + *--stk = 0xF6L; /* FR6 */ + *--stk = 0xF5L; /* FR5 */ + *--stk = 0xF4L; /* FR4 */ + *--stk = 0xF3L; /* FR3 */ + *--stk = 0xF2L; /* FR2 */ + *--stk = 0xF1L; /* FR1 */ + *--stk = 0xF0L; /* FR0 */ + + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called when a task returns. +* +* Arguments : ptcb is a pointer to the TCB of the task that returned. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +void OSTaskReturnHook (OS_TCB *ptcb) +{ + (void)ptcb; /* Prevent compiler warning */ +} diff --git a/Ports/SH2A-FPU/HEW/os_dbg.c b/Ports/SH2A-FPU/HEW/os_dbg.c new file mode 100644 index 0000000..0a77a2f --- /dev/null +++ b/Ports/SH2A-FPU/HEW/os_dbg.c @@ -0,0 +1,317 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameEn; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameEn; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameEn; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameEn; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameEn; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/SH2A-FPU/Renesas/os_cpu.h b/Ports/SH2A-FPU/Renesas/os_cpu.h new file mode 100644 index 0000000..134f802 --- /dev/null +++ b/Ports/SH2A-FPU/Renesas/os_cpu.h @@ -0,0 +1,154 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2A-FPU Specific code +* Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef unsigned long long INT64U; /* Unsigned 64 bit quantity */ +typedef signed long long INT64S; /* Signed 64 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* The status register (SR) is 32-bits wide */ + +/* +********************************************************************************************************* +* Renesas SH-2A-FPU +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() set_imask( 15 ) /* When using a ROM Monitor e.g. HMON change this level so not to mask + out the debugger interrupts */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_imask( 0 ) +#endif + +#if OS_CRITICAL_METHOD == 2 +/* Not currently supported */ + +/* The accepted way of implementing method 2 is to store the status register (SR - containing the */ +/* current interrupt mask level) on to the stack before changing the mask level to a value */ +/* which masks all interrupts. To do this without a function call (which would use the stack */ +/* when called) requires the use of in line assembler. Unfortunately, there does not appear to */ +/* be away for the Renesas compiler's inline assembler code to tell the compiler which */ +/* registers are being clobbered so that the compiler can take appropriate action. */ + +/* When the Renesas compiler requires a temporary scratch area within a function it can make room */ +/* on the stack by adjusting the stack pointer. Any access to the scratch area then uses an offset */ +/* from the stack pointer. So, if inline assembly code adjusts the stack pointer, as it would when */ +/* storing the current SR value, any reference to the scratch area is broken until the value is popped */ +/* from the stack and the stack pointer contents return to the value expected by the compiler. */ +/* In tests this has been seen to break critical functions including 'OSTCBInit' and */ +/* 'OSTaskCreate'. */ + +/* The only solution I have come up with to this problem is to compile the code to assembler and */ +/* manually alter the affected code which is not really acceptable and so far untested. */ + +/* Therefore it is suggested that method 3, below, is used */ +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = get_cr(); set_imask( 15 ) + /* When using a ROM Monitor e.g. HMON change this level so not to mask + out the debugger interrupts */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_cr( cpu_sr ) +#endif + +/* +********************************************************************************************************* +* Renesas SH-2A-FPU Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on SH-2A-FPU */ + +#define uCOS 33 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() trapa( uCOS ); /* TRAPA instruction */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/SH2A-FPU/Renesas/os_cpu_a.src b/Ports/SH2A-FPU/Renesas/os_cpu_a.src new file mode 100644 index 0000000..23953c4 --- /dev/null +++ b/Ports/SH2A-FPU/Renesas/os_cpu_a.src @@ -0,0 +1,314 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas SH-2A-FPU Specific code +; Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** + + + .EXPORT _OSStartHighRdy + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + .EXPORT _OSTickISR + .IMPORT _OSTaskSwHook + .IMPORT _OSTCBHighRdy + .IMPORT _OSRunning + .IMPORT _OSTCBCur + .IMPORT _OSPrioCur + .IMPORT _OSPrioHighRdy + .IMPORT _OSIntEnter + .IMPORT _OSTimeTick + .IMPORT _OSIntExit + .IMPORT _OSIntNesting + .IMPORT _TickClr ; implement your own function to clear + ; the OS tick source + + + .SECTION P,CODE,ALIGN=4 + +_OSStartHighRdy: + mov.l #_OSTaskSwHook, r1 ; address of OSTaskSwHook function in R1 + jsr @r1 ; call OSTaskSwHook() + nop + + mov.l #_OSTCBHighRdy, r1 ; address of OSTCBHighRdy in R1 + mov.l @r1, r2 ; r2 is now the address of the ready task + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OstcBStkptr + + mov.l #_OSRunning, r1 ; address of OSRunning in R1 + mov #1, r2 ; OSRunning = TRUE (1) + mov.b r2, @r1 + +; restore all processor registers from new task's stack + + fmov.s @r15+, fr0 + fmov.s @r15+, fr1 + fmov.s @r15+, fr2 + fmov.s @r15+, fr3 + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + fmov.s @r15+, fr12 + fmov.s @r15+, fr13 + fmov.s @r15+, fr14 + fmov.s @r15+, fr15 + lds.l @r15+, fpscr + lds.l @r15+, fpul + movml.l @r15+, r15 ; restores R0, R1 ... R14, PR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte ; return from interrupt + nop + + +_OSCtxSw: + mov.l r0, @-r15 ; disable interrupts + stc sr, r0 + or #240,r0 + ldc r0, sr + mov.l @r15+, r0 + + ; save processor registers on the stack + + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + movml.l r15, @-r15 ; push registers PR, R14, R13 ... R0 + sts.l fpul, @-r15 + sts.l fpscr, @-r15 + fmov.s fr15 ,@-r15 + fmov.s fr14 ,@-r15 + fmov.s fr13 ,@-r15 + fmov.s fr12 ,@-r15 + fmov.s fr11 ,@-r15 + fmov.s fr10 ,@-r15 + fmov.s fr9 ,@-r15 + fmov.s fr8 ,@-r15 + fmov.s fr7 ,@-r15 + fmov.s fr6 ,@-r15 + fmov.s fr5 ,@-r15 + fmov.s fr4 ,@-r15 + fmov.s fr3 ,@-r15 + fmov.s fr2 ,@-r15 + fmov.s fr1 ,@-r15 + fmov.s fr0 ,@-r15 + +; save current task's stack pointer into current task's OS_TCB + + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r0, r3 ; R3 contains address of current TCB + mov.l r15, @r3 ; put stack pointer into it + + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.b @r2, r3 + mov.b r3, @r0 + + mov.l @r1, r2 ; r2 contains address of current TCB + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OstcBStkPtr + +; restore all processor registers from new task's stack + + fmov.s @r15+, fr0 + fmov.s @r15+, fr1 + fmov.s @r15+, fr2 + fmov.s @r15+, fr3 + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + fmov.s @r15+, fr12 + fmov.s @r15+, fr13 + fmov.s @r15+, fr14 + fmov.s @r15+, fr15 + lds.l @r15+, fpscr + lds.l @r15+, fpul + movml.l @r15+, r15 ; restores R0, R1 ... R14, PR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + +_OSIntCtxSw: + + mov.l r0, @-r15 ; disable interrupts + stc sr, r0 + or #240,r0 + ldc r0, sr + mov.l @r15+, r0 + + + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.b @r2, r3 + mov.b r3, @r0 ; OSPrioCur = OSPrioHighRdy + + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l @r3, r15 ; CPU stack pointer = OSTCBHighRdy->OstcBStkPtr + +; restore all processor registers from new task's stack + + fmov.s @r15+, fr0 + fmov.s @r15+, fr1 + fmov.s @r15+, fr2 + fmov.s @r15+, fr3 + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + fmov.s @r15+, fr12 + fmov.s @r15+, fr13 + fmov.s @r15+, fr14 + fmov.s @r15+, fr15 + lds.l @r15+, fpscr + lds.l @r15+, fpul + movml.l @r15+, r15 ; restores R0, R1 ... R14, PR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + +_OSTickISR: + mov.l r0, @-r15 ; disable interrupts + stc sr, r0 + or #240,r0 + ldc r0, sr + mov.l @r15+, r0 + + +; Save processor registers on the stack + + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + movml.l r15, @-r15 ; push registers PR, R14, R13 ... R0 + sts.l fpul, @-r15 + sts.l fpscr, @-r15 + fmov.s fr15 ,@-r15 + fmov.s fr14 ,@-r15 + fmov.s fr13 ,@-r15 + fmov.s fr12 ,@-r15 + fmov.s fr11 ,@-r15 + fmov.s fr10 ,@-r15 + fmov.s fr9 ,@-r15 + fmov.s fr8 ,@-r15 + fmov.s fr7 ,@-r15 + fmov.s fr6 ,@-r15 + fmov.s fr5 ,@-r15 + fmov.s fr4 ,@-r15 + fmov.s fr3 ,@-r15 + fmov.s fr2 ,@-r15 + fmov.s fr1 ,@-r15 + fmov.s fr0 ,@-r15 + +; clear compare match interupt + + mov.l #_OSIntNesting, r1 ; Increment OSIntNesting + mov.b @r1, r0 + extu.b r0, r0 + add #1, r0 + mov.b r0, @r1 ; If OSIntNesting == 1 save the current stack pointer + tst #1, r0 ; onto the current task's stack + bt _OSTickISR1 + + mov.l #_OSTCBCur, r1 ; Save current task's SP into its TCB + mov.l @r1, r0 + mov r15, @r0 + +_OSTickISR1: + + mov.l #_TickClr, r3 ; clear timer interrupt source + jsr @r3 + nop + + mov.l #_OSTimeTick, r0 + jsr @r0 ; call OSTimeTick() + nop + + mov.l #_OSIntExit, r0 + jsr @r0 ; call OSIntExit() + nop + +; restore all processor registers from stack + + fmov.s @r15+, fr0 + fmov.s @r15+, fr1 + fmov.s @r15+, fr2 + fmov.s @r15+, fr3 + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + fmov.s @r15+, fr12 + fmov.s @r15+, fr13 + fmov.s @r15+, fr14 + fmov.s @r15+, fr15 + lds.l @r15+, fpscr + lds.l @r15+, fpul + movml.l @r15+, r15 ; restores PR, R0, R1 ... R14 + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + .END diff --git a/Ports/SH2A-FPU/Renesas/os_cpu_c.c b/Ports/SH2A-FPU/Renesas/os_cpu_c.c new file mode 100644 index 0000000..a82f6a8 --- /dev/null +++ b/Ports/SH2A-FPU/Renesas/os_cpu_c.c @@ -0,0 +1,337 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2A-FPU Specific code +* Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + /* The OS must not mask the interrupts required by ROM ... */ + /* ... monitor type debugger, e.g. HMON */ +#define INT_MASK_ON 0x00000000L +#define INT_MASK_OFF 0x000000F0L + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *stk; + + opt = opt; /* prevent compiler warning */ + stk = (INT32U *)ptos; /* load stack pointer */ + *--stk = (INT32U) INT_MASK_ON; /* SR */ + *--stk = (INT32U) task; /* PC of task */ + *--stk = 0xA0L; /* macl */ + *--stk = 0xA1L; /* mach */ + *--stk = 0xA2L; /* gbr */ + *--stk = 0xA3L; /* pr */ + *--stk = 14L; /* r14 */ + *--stk = 13L; /* r13 */ + *--stk = 12L; /* r12 */ + *--stk = 11L; /* r11 */ + *--stk = 10L; /* r10 */ + *--stk = 9L; /* r9 */ + *--stk = 8L; /* r8 */ + *--stk = 7L; /* r7 */ + *--stk = 6L; /* r6 */ + *--stk = 5L; /* r5 */ + *--stk = (INT32U) pdata; /* pass pdata in r4 */ + *--stk = 3L; /* r3 */ + *--stk = 2L; /* r2 */ + *--stk = 1L; /* r1 */ + *--stk = 0L; /* r0 */ + *--stk = 0xFL; /* FPUL */ + *--stk = 0xFL; /* FPSCR */ + *--stk = 0xF15L; /* FR15 */ + *--stk = 0xF14L; /* FR14 */ + *--stk = 0xF13L; /* FR13 */ + *--stk = 0xF12L; /* FR12 */ + *--stk = 0xF11L; /* FR11 */ + *--stk = 0xF10L; /* FR10 */ + *--stk = 0xF9L; /* FR9 */ + *--stk = 0xF8L; /* FR8 */ + *--stk = 0xF7L; /* FR7 */ + *--stk = 0xF6L; /* FR6 */ + *--stk = 0xF5L; /* FR5 */ + *--stk = 0xF4L; /* FR4 */ + *--stk = 0xF3L; /* FR3 */ + *--stk = 0xF2L; /* FR2 */ + *--stk = 0xF1L; /* FR1 */ + *--stk = 0xF0L; /* FR0 */ + + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/SH2A-FPU/Renesas/os_dbg.c b/Ports/SH2A-FPU/Renesas/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/SH2A-FPU/Renesas/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/SH2A/Renesas/os_cpu.h b/Ports/SH2A/Renesas/os_cpu.h new file mode 100644 index 0000000..134f802 --- /dev/null +++ b/Ports/SH2A/Renesas/os_cpu.h @@ -0,0 +1,154 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2A-FPU Specific code +* Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +#include + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef unsigned long long INT64U; /* Unsigned 64 bit quantity */ +typedef signed long long INT64S; /* Signed 64 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned long OS_STK; /* Each stack entry is 32-bit wide */ +typedef unsigned long OS_CPU_SR; /* The status register (SR) is 32-bits wide */ + +/* +********************************************************************************************************* +* Renesas SH-2A-FPU +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +* +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 3 + +#if OS_CRITICAL_METHOD == 1 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() set_imask( 15 ) /* When using a ROM Monitor e.g. HMON change this level so not to mask + out the debugger interrupts */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_imask( 0 ) +#endif + +#if OS_CRITICAL_METHOD == 2 +/* Not currently supported */ + +/* The accepted way of implementing method 2 is to store the status register (SR - containing the */ +/* current interrupt mask level) on to the stack before changing the mask level to a value */ +/* which masks all interrupts. To do this without a function call (which would use the stack */ +/* when called) requires the use of in line assembler. Unfortunately, there does not appear to */ +/* be away for the Renesas compiler's inline assembler code to tell the compiler which */ +/* registers are being clobbered so that the compiler can take appropriate action. */ + +/* When the Renesas compiler requires a temporary scratch area within a function it can make room */ +/* on the stack by adjusting the stack pointer. Any access to the scratch area then uses an offset */ +/* from the stack pointer. So, if inline assembly code adjusts the stack pointer, as it would when */ +/* storing the current SR value, any reference to the scratch area is broken until the value is popped */ +/* from the stack and the stack pointer contents return to the value expected by the compiler. */ +/* In tests this has been seen to break critical functions including 'OSTCBInit' and */ +/* 'OSTaskCreate'. */ + +/* The only solution I have come up with to this problem is to compile the code to assembler and */ +/* manually alter the affected code which is not really acceptable and so far untested. */ + +/* Therefore it is suggested that method 3, below, is used */ +#endif + +#if OS_CRITICAL_METHOD == 3 + /* Disable interrupts */ +#define OS_ENTER_CRITICAL() cpu_sr = get_cr(); set_imask( 15 ) + /* When using a ROM Monitor e.g. HMON change this level so not to mask + out the debugger interrupts */ + + /* Enable interrupts */ +#define OS_EXIT_CRITICAL() set_cr( cpu_sr ) +#endif + +/* +********************************************************************************************************* +* Renesas SH-2A-FPU Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on SH-2A-FPU */ + +#define uCOS 33 /* Interrupt vector # used for context switch */ + +#define OS_TASK_SW() trapa( uCOS ); /* TRAPA instruction */ + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* PROTOTYPES +********************************************************************************************************* +*/ +void OSStartHighRdy( void ); +void OSIntCtxSw( void ); +void OSCtxSw( void ); + +#endif diff --git a/Ports/SH2A/Renesas/os_cpu_a.src b/Ports/SH2A/Renesas/os_cpu_a.src new file mode 100644 index 0000000..f7a6cd1 --- /dev/null +++ b/Ports/SH2A/Renesas/os_cpu_a.src @@ -0,0 +1,212 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas SH-2A-FPU Specific code +; Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +; +; Filename : os_cpu_a.src +; Version : V2.93.00 +;******************************************************************************************************** + + + + .EXPORT _OSStartHighRdy + .EXPORT _OSCtxSw + .EXPORT _OSIntCtxSw + .EXPORT _OSTickISR + .IMPORT _OSTaskSwHook + .IMPORT _OSTCBHighRdy + .IMPORT _OSRunning + .IMPORT _OSTCBCur + .IMPORT _OSPrioCur + .IMPORT _OSPrioHighRdy + .IMPORT _OSIntEnter + .IMPORT _OSTimeTick + .IMPORT _OSIntExit + .IMPORT _OSIntNesting + .IMPORT _TickClr ; implement your own function to clear + ; the OS tick source + + + .SECTION P,CODE,ALIGN=4 + +_OSStartHighRdy: + mov.l #_OSTaskSwHook, r1 ; address of OSTaskSwHook function in R1 + jsr @r1 ; call OSTaskSwHook() + nop + + mov.l #_OSTCBHighRdy, r1 ; address of OSTCBHighRdy in R1 + mov.l @r1, r2 ; r2 is now the address of the ready task + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OstcBStkptr + + mov.l #_OSRunning, r1 ; address of OSRunning in R1 + mov #1, r2 ; OSRunning = TRUE (1) + mov.b r2, @r1 + +; restore all processor registers from new task's stack + + + movml.l @r15+, r15 ; restores R0, R1 ... R14, PR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte ; return from interrupt + nop + + +_OSCtxSw: + mov.l r0, @-r15 ; disable interrupts + stc sr, r0 + or #240,r0 + ldc r0, sr + mov.l @r15+, r0 + + ; save processor registers on the stack + + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + movml.l r15, @-r15 ; push registers PR, R14, R13 ... R0 + + +; save current task's stack pointer into current task's OS_TCB + + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r0, r3 ; R3 contains address of current TCB + mov.l r15, @r3 ; put stack pointer into it + + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.b @r2, r3 + mov.b r3, @r0 + + mov.l @r1, r2 ; r2 contains address of current TCB + mov.l @r2, r15 ; stack pointer = OSTCBHighRdy->OstcBStkPtr + +; restore all processor registers from new task's stack + + + movml.l @r15+, r15 ; restores R0, R1 ... R14, PR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + +_OSIntCtxSw: + + mov.l r0, @-r15 ; disable interrupts + stc sr, r0 + or #240,r0 + ldc r0, sr + mov.l @r15+, r0 + + + mov.l #_OSTaskSwHook, r2 + jsr @r2 ; call OSTaskSWHook + nop + + mov.l #_OSPrioHighRdy, r2 ; get address of OSPrioHighRdy + mov.l #_OSPrioCur, r0 ; get address of OSPrioCur + mov.b @r2, r3 + mov.b r3, @r0 ; OSPrioCur = OSPrioHighRdy + + mov.l #_OSTCBHighRdy, r1 ; get address of OSTCBHighRdy + mov.l #_OSTCBCur, r0 ; get address of OSTCBCur + mov.l @r1, r3 + mov.l r3, @r0 ; OSTCBCur = OSTCBHighRdy + + mov.l @r3, r15 ; CPU stack pointer = OSTCBHighRdy->OstcBStkPtr + +; restore all processor registers from new task's stack + + + movml.l @r15+, r15 ; restores R0, R1 ... R14, PR + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + +_OSTickISR: + mov.l r0, @-r15 ; disable interrupts + stc sr, r0 + or #240,r0 + ldc r0, sr + mov.l @r15+, r0 + + +; Save processor registers on the stack + + sts.l macl, @-r15 + sts.l mach, @-r15 + stc.l gbr, @-r15 + movml.l r15, @-r15 ; push registers PR, R14, R13 ... R0 + + +; clear compare match interupt + + mov.l #_OSIntNesting, r1 ; Increment OSIntNesting + mov.b @r1, r0 + extu.b r0, r0 + add #1, r0 + mov.b r0, @r1 ; If OSIntNesting == 1 save the current stack pointer + tst #1, r0 ; onto the current task's stack + bt _OSTickISR1 + + mov.l #_OSTCBCur, r1 ; Save current task's SP into its TCB + mov.l @r1, r0 + mov r15, @r0 + +_OSTickISR1: + + mov.l #_TickClr, r3 ; clear timer interrupt source + jsr @r3 + nop + + mov.l #_OSTimeTick, r0 + jsr @r0 ; call OSTimeTick() + nop + + mov.l #_OSIntExit, r0 + jsr @r0 ; call OSIntExit() + nop + +; restore all processor registers from stack + + movml.l @r15+, r15 ; restores PR, R0, R1 ... R14 + ldc.l @r15+, gbr + lds.l @r15+, mach + lds.l @r15+, macl + + rte + nop + + .END diff --git a/Ports/SH2A/Renesas/os_cpu_c.c b/Ports/SH2A/Renesas/os_cpu_c.c new file mode 100644 index 0000000..6ad1ec8 --- /dev/null +++ b/Ports/SH2A/Renesas/os_cpu_c.c @@ -0,0 +1,320 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas SH-2A-FPU Specific code +* Renesas SH SERIES C/C++ Compiler (V.9.00.03.006) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* GLOBAL DATA +********************************************************************************************************* +*/ + /* The OS must not mask the interrupts required by ROM ... */ + /* ... monitor type debugger, e.g. HMON */ +#define INT_MASK_ON 0x00000000L +#define INT_MASK_OFF 0x000000F0L + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookBegin (void) +{ +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251 +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0 +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT32U *stk; + + + opt = opt; /* prevent compiler warning */ + stk = (INT32U *)ptos; /* load stack pointer */ + *--stk = (INT32U) INT_MASK_ON; /* SR */ + *--stk = (INT32U) task; /* PC of task */ + *--stk = 0xA0L; /* macl */ + *--stk = 0xA1L; /* mach */ + *--stk = 0xA2L; /* gbr */ + *--stk = 0xA3L; /* pr */ + *--stk = 14L; /* r14 */ + *--stk = 13L; /* r13 */ + *--stk = 12L; /* r12 */ + *--stk = 11L; /* r11 */ + *--stk = 10L; /* r10 */ + *--stk = 9L; /* r9 */ + *--stk = 8L; /* r8 */ + *--stk = 7L; /* r7 */ + *--stk = 6L; /* r6 */ + *--stk = 5L; /* r5 */ + *--stk = (INT32U) pdata; /* pass pdata in r4 */ + *--stk = 3L; /* r3 */ + *--stk = 2L; /* r2 */ + *--stk = 1L; /* r1 */ + *--stk = 0L; /* r0 */ + + return ((OS_STK *)stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TASK_SW_HOOK_EN > 0) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0) && (OS_TIME_TICK_HOOK_EN > 0) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281) && (OS_TMR_EN > 0) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0; + OSTmrSignal(); + } +#endif + +} +#endif diff --git a/Ports/SH2A/Renesas/os_dbg.c b/Ports/SH2A/Renesas/os_dbg.c new file mode 100644 index 0000000..8dee1bf --- /dev/null +++ b/Ports/SH2A/Renesas/os_dbg.c @@ -0,0 +1,316 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameSize = OS_TMR_CFG_NAME_SIZE; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0; +INT16U const OSTmrTblSize = 0; +INT16U const OSTmrWheelSize = 0; +INT16U const OSTmrWheelTblSize = 0; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0) && (OS_TMR_CFG_MAX > 0) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + ptemp = (void *)&OSEventMultiEn; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0 + ptemp = (void *)&OSTmrTbl[0]; + ptemp = (void *)&OSTmrWheelTbl[0]; + + ptemp = (void *)&OSTmrEn; + ptemp = (void *)&OSTmrCfgMax; + ptemp = (void *)&OSTmrCfgNameSize; + ptemp = (void *)&OSTmrCfgWheelSize; + ptemp = (void *)&OSTmrCfgTicksPerSec; + ptemp = (void *)&OSTmrSize; + ptemp = (void *)&OSTmrTblSize; + + ptemp = (void *)&OSTmrWheelSize; + ptemp = (void *)&OSTmrWheelTblSize; +#endif + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Ports/V850E2M/CubeSuite+/os_cpu.h b/Ports/V850E2M/CubeSuite+/os_cpu.h new file mode 100644 index 0000000..4b4eca6 --- /dev/null +++ b/Ports/V850E2M/CubeSuite+/os_cpu.h @@ -0,0 +1,124 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850E2M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850E2M +* Toolchain : CubeSuite+ V1.00.01 +* CX compiler V1.20 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsiged 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 1u +#define OS_ENTER_CRITICAL() __DI() /* Disable Interrupts */ +#define OS_EXIT_CRITICAL() __EI() /* Enable Interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + +/* +********************************************************************************************************* +* Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() __asm("trap 0x00") + +/* +********************************************************************************************************* +* PROTOTYPES +* +* Note(s) : (1) OS_CPU_TickInit() must be implemented by the user to initialize the timer, which will +* be used as the tick interrupt. Moreover, OS_CPU_TickHandler() must be registered in the +* proper vector address of timer that will be used as the tick. +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + /* See Note # 1. */ +void OS_CPU_TickHandler (void); +void OS_CPU_TickInit (INT32U tick_per_sec); +#endif diff --git a/Ports/V850E2M/CubeSuite+/os_cpu_a.asm b/Ports/V850E2M/CubeSuite+/os_cpu_a.asm new file mode 100644 index 0000000..5e0e304 --- /dev/null +++ b/Ports/V850E2M/CubeSuite+/os_cpu_a.asm @@ -0,0 +1,237 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850E2M Port +; +; Filename : os_cpu_a.asm +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850E2M +; Toolchain : CubeSuite+ V1.00.01 +; CX compiler V1.20 +;******************************************************************************************************** + + + $include (os_cpu_a.inc) + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + ; External References + .extern _OSRunning + .extern _OSPrioCur + .extern _OSPrioHighRdy + .extern _OSTCBCur + .extern _OSTCBHighRdy + .extern _OSTaskSwHook + .extern _OSTimeTick + ; Functions declared in this file + .public _OS_CPU_SR_Save + .public _OS_CPU_SR_Restore + .public _OS_CPU_TickHandler + .public _OSStartHighRdy + .public _OSIntCtxSw + .public _OSCtxSw + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .cseg text + .align 4 + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +_OS_CPU_SR_Save: + stsr PSW, r10 ; Save PSW + di ; Disable interrupts + jmp [lp] + +_OS_CPU_SR_Restore: + ldsr r6, PSW ; Restore PSW + jmp [lp] + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +; +;******************************************************************************************************** + +_OSStartHighRdy: + jarl _OSTaskSwHook, lp ; Call OSTaskSwHook(); + + mov 0x01, r2 ; OSRunning = TRUE; + st.b r2 , #_OSRunning[r0] + + mov #_OSTCBHighRdy, r11 ; SWITCH TO HIGHEST PRIORITY TASK: + ld.w 0[r11] , r11 + ld.w 0[r11] , sp + + OS_CTX_RESTORE sp ; Restore Task Context + + eiret + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = sp; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +_OSCtxSw: + OS_CTX_SAVE sp ; Save current Task context + + mov #_OSTCBCur, r11 ; OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] + + jarl _OSTaskSwHook, lp ; OSTaskSwHook(); + + mov #_OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov #_OSPrioCur , r11 + st.b r12 , 0[r11] + + mov #_OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov #_OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp ; Restore new Task's context + + eiret ; return from trap + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) The pseudo-code for OSIntCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +_OSIntCtxSw: + jarl _OSTaskSwHook, lp ; OSTaskSwHook(); + + mov #_OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov #_OSPrioCur , r11 + st.b r12 , 0[r11] + + mov #_OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov #_OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp + + eiret ; Return from interrupt starts new task + + +;******************************************************************************************************** +; OS_CPU_TickHandler +; +; Note(s) : 1) The pseudo-code for _OS_CPU_TickHandler() is: +; a) Save processor registers; +; b) Increment OSIntNestingCtr; +; c) if (OSIntNestingCtr == 1) { +; OSTCBCurPtr->OSTCBStkPtr = SP; +; } +; d) Call OSTimeTick(); +; e) Call OSIntExit(); +; f) Restore processosr Registers; +; +; 2) OS_CPU_TickHandler() must be registered in the proper vector address of timer that will be +; used as the tick. +; +; 3) All the other ISRs must have the following implementation to secure proper register saving & +; restoring when servicing an interrupt +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +_OS_CPU_TickHandler: + OS_ISR_ENTER + + jarl _OSTimeTick, lp ; Call OSTimeTick(); + + OS_ISR_EXIT + + +;******************************************************************************************************** +; ASSEMBLY LANGUAGE PORT FILE END +;******************************************************************************************************** diff --git a/Ports/V850E2M/CubeSuite+/os_cpu_a.inc b/Ports/V850E2M/CubeSuite+/os_cpu_a.inc new file mode 100644 index 0000000..6ab8393 --- /dev/null +++ b/Ports/V850E2M/CubeSuite+/os_cpu_a.inc @@ -0,0 +1,284 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850E2M Port +; +; Filename : os_cpu_a.inc +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850E2M +; Toolchain : CubeSuite+ V1.00.01 +; CX compiler V1.20 +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + .extern _OSTCBCur + .extern _OSIntNesting + .extern _OSIntExit + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + + ; SYSTEM REGISTER + EIPC .set 0 + EIPSW .set 1 + PSW .set 5 + EIIC .set 13 + CTPC .set 16 + CTPSW .set 17 + + ; PROGRAM REGISTER STACK OFFSET + STK_OFFSET_R1 .set 0 + STK_OFFSET_R2 .set STK_OFFSET_R1 + 4 + STK_OFFSET_R6 .set STK_OFFSET_R2 + 4 + STK_OFFSET_R7 .set STK_OFFSET_R6 + 4 + STK_OFFSET_R8 .set STK_OFFSET_R7 + 4 + STK_OFFSET_R9 .set STK_OFFSET_R8 + 4 + STK_OFFSET_R10 .set STK_OFFSET_R9 + 4 + STK_OFFSET_R11 .set STK_OFFSET_R10 + 4 + STK_OFFSET_R12 .set STK_OFFSET_R11 + 4 + STK_OFFSET_R13 .set STK_OFFSET_R12 + 4 + STK_OFFSET_R14 .set STK_OFFSET_R13 + 4 + STK_OFFSET_R15 .set STK_OFFSET_R14 + 4 + STK_OFFSET_R16 .set STK_OFFSET_R15 + 4 + STK_OFFSET_R17 .set STK_OFFSET_R16 + 4 + STK_OFFSET_R18 .set STK_OFFSET_R17 + 4 + STK_OFFSET_R19 .set STK_OFFSET_R18 + 4 + STK_OFFSET_R20 .set STK_OFFSET_R19 + 4 + STK_OFFSET_R21 .set STK_OFFSET_R20 + 4 + STK_OFFSET_R22 .set STK_OFFSET_R21 + 4 + STK_OFFSET_R23 .set STK_OFFSET_R22 + 4 + STK_OFFSET_R24 .set STK_OFFSET_R23 + 4 + STK_OFFSET_R25 .set STK_OFFSET_R24 + 4 + STK_OFFSET_R26 .set STK_OFFSET_R25 + 4 + STK_OFFSET_R27 .set STK_OFFSET_R26 + 4 + STK_OFFSET_R28 .set STK_OFFSET_R27 + 4 + STK_OFFSET_R29 .set STK_OFFSET_R28 + 4 + STK_OFFSET_R30 .set STK_OFFSET_R29 + 4 + STK_OFFSET_R31 .set STK_OFFSET_R30 + 4 + STK_OFFSET_EIPC .set STK_OFFSET_R31 + 4 + ; SYSTEM REGISTER STACK OFFSET + STK_OFFSET_EIPSW .set STK_OFFSET_EIPC + 4 + STK_OFFSET_CTPC .set STK_OFFSET_EIPSW + 4 + STK_OFFSET_CTPSW .set STK_OFFSET_CTPC + 4 + STK_CTX_SIZE .set STK_OFFSET_CTPSW + 4 + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + .cseg text + .align 4 + + +;******************************************************************************************************** +; OS_CTX_SAVE +; +; Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +; the same order as they were saved in OSTaskStkInit(). +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; SAVE PROCESSOR REGISTER +OS_CTX_SAVE .macro REG_SP + addi -STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer + + $NOWARNING ; Note #1 + st.w r1, STK_OFFSET_R1[REG_SP] + $WARNING + st.w r2, STK_OFFSET_R2[REG_SP] + st.w r6, STK_OFFSET_R6[REG_SP] + st.w r7, STK_OFFSET_R7[REG_SP] + st.w r8, STK_OFFSET_R8[REG_SP] + st.w r9, STK_OFFSET_R9[REG_SP] + st.w r10, STK_OFFSET_R10[REG_SP] + st.w r11, STK_OFFSET_R11[REG_SP] + st.w r12, STK_OFFSET_R12[REG_SP] + st.w r13, STK_OFFSET_R13[REG_SP] + st.w r14, STK_OFFSET_R14[REG_SP] + st.w r15, STK_OFFSET_R15[REG_SP] + st.w r16, STK_OFFSET_R16[REG_SP] + st.w r17, STK_OFFSET_R17[REG_SP] + st.w r18, STK_OFFSET_R18[REG_SP] + st.w r19, STK_OFFSET_R19[REG_SP] + st.w r20, STK_OFFSET_R20[REG_SP] + st.w r21, STK_OFFSET_R21[REG_SP] + st.w r22, STK_OFFSET_R22[REG_SP] + st.w r23, STK_OFFSET_R23[REG_SP] + st.w r24, STK_OFFSET_R24[REG_SP] + st.w r25, STK_OFFSET_R25[REG_SP] + st.w r26, STK_OFFSET_R26[REG_SP] + st.w r27, STK_OFFSET_R27[REG_SP] + st.w r28, STK_OFFSET_R28[REG_SP] + st.w r29, STK_OFFSET_R29[REG_SP] + st.w r30, STK_OFFSET_R30[REG_SP] + st.w r31, STK_OFFSET_R31[REG_SP] + + stsr EIPC, r2 + st.w r2, STK_OFFSET_EIPC[REG_SP] ; Restore task's EIPC + + stsr EIPSW, r2 + st.w r2, STK_OFFSET_EIPSW[REG_SP] ; Restore task's EIPSW + + stsr CTPC, r2 + st.w r2, STK_OFFSET_CTPC[REG_SP] ; Restore task's CTPC + + stsr CTPSW, r2 + st.w r2, STK_OFFSET_CTPSW[REG_SP] ; Restore task's CTPSW +.endm + + +;******************************************************************************************************** +; OS_CTX_RESTORE +; +; Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +; reverse order of OS_CTX_SAVE (see above) +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; RESTORE PROCESSOR REGISTER +OS_CTX_RESTORE .macro REG_SP + $NOWARNING ; Note #1 + ld.w STK_OFFSET_R1[REG_SP] , r1 + $WARNING + ld.w STK_OFFSET_R6[REG_SP] , r6 + ld.w STK_OFFSET_R7[REG_SP] , r7 + ld.w STK_OFFSET_R8[REG_SP] , r8 + ld.w STK_OFFSET_R9[REG_SP] , r9 + ld.w STK_OFFSET_R10[REG_SP], r10 + ld.w STK_OFFSET_R11[REG_SP], r11 + ld.w STK_OFFSET_R12[REG_SP], r12 + ld.w STK_OFFSET_R13[REG_SP], r13 + ld.w STK_OFFSET_R14[REG_SP], r14 + ld.w STK_OFFSET_R15[REG_SP], r15 + ld.w STK_OFFSET_R16[REG_SP], r16 + ld.w STK_OFFSET_R17[REG_SP], r17 + ld.w STK_OFFSET_R18[REG_SP], r18 + ld.w STK_OFFSET_R19[REG_SP], r19 + ld.w STK_OFFSET_R20[REG_SP], r20 + ld.w STK_OFFSET_R21[REG_SP], r21 + ld.w STK_OFFSET_R22[REG_SP], r22 + ld.w STK_OFFSET_R23[REG_SP], r23 + ld.w STK_OFFSET_R24[REG_SP], r24 + ld.w STK_OFFSET_R25[REG_SP], r25 + ld.w STK_OFFSET_R26[REG_SP], r26 + ld.w STK_OFFSET_R27[REG_SP], r27 + ld.w STK_OFFSET_R28[REG_SP], r28 + ld.w STK_OFFSET_R29[REG_SP], r29 + ld.w STK_OFFSET_R30[REG_SP], r30 + ld.w STK_OFFSET_R31[REG_SP], r31 + + ld.w STK_OFFSET_EIPSW[REG_SP], r2 ; Restore task's EIPSW + ldsr r2, EIPSW + + ld.w STK_OFFSET_EIPC[REG_SP], r2 ; Restore task's EIPC + ldsr r2, EIPC + + ld.w STK_OFFSET_CTPC[REG_SP], r2 ; Restore task's CTPC + ldsr r2, CTPC + + ld.w STK_OFFSET_CTPSW[REG_SP], r2 ; Restore task's CTPSW + ldsr r2, CTPSW + + ld.w STK_OFFSET_R2[REG_SP] , r2 + + addi STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer +.endm + + +;******************************************************************************************************** +; OS_ISR_ENTER +; +; Description : Interrupt service routine prologue for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_ENTER +; OS_CTX_SAVE ; Call the macro: OS_CTX_SAVE +; OSIntNestingCtr++; +; if (OSIntNestingCtr == 1) { +; OSTCBCurPtr->StkPtr = SP; +; } +; +; This MACRO is to be used by your assembly language based ISRs as follows: +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_ISR_ENTER .macro + OS_CTX_SAVE sp ; Save processor registers on the stack + + ld.b #_OSIntNesting[r0], r2 ; OSIntNestingCtr++; + add 0x1, r2 + st.b r2, #_OSIntNesting[r0] + + cmp 0x1, r2 + bne _b ; if (OSIntNestingCtr == 1) { + + mov #_OSTCBCur, r11 ; OSTCBCurPtr->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] ; } + +_b: +.endm + + +;******************************************************************************************************** +; OS_ISR_EXIT +; +; Description : Interrupt service routine epilog for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_EXIT: +; OSIntExit(); ; Call the C function: OSIntExit(); +; OS_CTX_RESTORE ; Call the macro: OS_CTX_RESTORE +; Return from interrupt ; CPU instruction to return from interrupt/exception +;******************************************************************************************************** + +OS_ISR_EXIT .macro + jarl _OSIntExit, lp ; Call 'OSIntExit()' + + OS_CTX_RESTORE sp ; Restore processor registers from stack + eiret ; CPU instruction to return from Interrupt/exception + +.endm + + +;******************************************************************************************************** +; ASSEMBLY LANGUAGE MACROS FILE END +;******************************************************************************************************** + diff --git a/Ports/V850E2M/CubeSuite+/os_cpu_c.c b/Ports/V850E2M/CubeSuite+/os_cpu_c.c new file mode 100644 index 0000000..75541c0 --- /dev/null +++ b/Ports/V850E2M/CubeSuite+/os_cpu_c.c @@ -0,0 +1,351 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850E2M Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850E2M +* Toolchain : CubeSuite+ V1.00.01 +* CX compiler V1.20 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define V850ES_EIPSW_EN 0x00000000u +#define V850ES_CTPC 0x00000000u +#define V850ES_CTPSW 0x00000000u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in Thread mode, using process stack. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning. */ + stk = ptos; /* Load stack pointer. */ + *(stk) =(INT32U)V850ES_CTPSW; /* CTPSW. */ + *(--stk) =(INT32U)V850ES_CTPC; /* CTPC. */ + *(--stk) =(INT32U)V850ES_EIPSW_EN; /* EIPSW interrupt enable */ + *(--stk) =(INT32U)task; /* EIPC */ + *(--stk) =(INT32U)OS_TaskReturn; /* r31 Link Pointer (LP). to pass return address of function */ + *(--stk) =(INT32U)0x30303030; /* r30 Element Pointer (EP). */ + *(--stk) =(INT32U)0x29292929; /* r29 Used as area for register variable */ + *(--stk) =(INT32U)0x28282828; /* r28 */ + *(--stk) =(INT32U)0x27272727; /* r27 */ + *(--stk) =(INT32U)0x26262626; /* r26 */ + *(--stk) =(INT32U)0x25252525; /* r25 */ + *(--stk) =(INT32U)0x24242424; /* r24 */ + *(--stk) =(INT32U)0x23232323; /* r23 */ + *(--stk) =(INT32U)0x22222222; /* r22 */ + *(--stk) =(INT32U)0x21212121; /* r21 */ + *(--stk) =(INT32U)0x20202020; /* r20 Used as area for register variable */ + *(--stk) =(INT32U)0x19191919; /* r19 Working register */ + *(--stk) =(INT32U)0x18181818; /* r18 Working register */ + *(--stk) =(INT32U)0x17171717; /* r17 Working register */ + *(--stk) =(INT32U)0x16161616; /* r16 Working register */ + *(--stk) =(INT32U)0x15151515; /* r15 Working register */ + *(--stk) =(INT32U)0x14141414; /* r14 Working register */ + *(--stk) =(INT32U)0x13131313; /* r13 Working register */ + *(--stk) =(INT32U)0x12121212; /* r12 Working register */ + *(--stk) =(INT32U)0x11111111; /* r11 Working register */ + *(--stk) =(INT32U)0x10101010; /* r10 Function return value */ + *(--stk) =(INT32U)0x09090909; /* r9 Argument register */ + *(--stk) =(INT32U)0x08080808; /* r8 Argument register */ + *(--stk) =(INT32U)0x07070707; /* r7 Argument register */ + *(--stk) =(INT32U)p_arg ; /* r6 Argument register */ + *(--stk) =(INT32U)0x02020202; /* r2 */ + *(--stk) =(INT32U)0x01010101; /* r1 Assembler-reserved.Used for address generation */ + + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/V850E2M/CubeSuite+/os_dbg.c b/Ports/V850E2M/CubeSuite+/os_dbg.c new file mode 100644 index 0000000..4e40744 --- /dev/null +++ b/Ports/V850E2M/CubeSuite+/os_dbg.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif + diff --git a/Ports/V850E2M/IAR/os_cpu.h b/Ports/V850E2M/IAR/os_cpu.h new file mode 100644 index 0000000..eba8c7f --- /dev/null +++ b/Ports/V850E2M/IAR/os_cpu.h @@ -0,0 +1,119 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850E2M Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850E2M +* Toolchain : IAR EWV850 v3.7x and up +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsiged 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + +/* +********************************************************************************************************* +* Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() asm("trap 0x00") + + +/* +********************************************************************************************************* +* PROTOTYPES +* +* Note(s) : (1) OS_CPU_TickInit() must be implemented by the user to initialize the timer, which will +* be used as the tick interrupt. Moreover, OS_CPU_TickHandler() must be registered in the +* proper vector address of timer that will be used as the tick. +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S85 */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + /* See Note # 1. */ +void OS_CPU_TickHandler (void); +void OS_CPU_TickInit (INT32U tick_per_sec); +#endif diff --git a/Ports/V850E2M/IAR/os_cpu_a.inc b/Ports/V850E2M/IAR/os_cpu_a.inc new file mode 100644 index 0000000..35474ff --- /dev/null +++ b/Ports/V850E2M/IAR/os_cpu_a.inc @@ -0,0 +1,255 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850E2M Port +; +; Filename : os_cpu_a.inc +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850E2M +; Toolchain : IAR EWV850 v3.7x and up +;******************************************************************************************************** + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXTERN OSTCBCur + EXTERN OSIntNesting + EXTERN OSIntExit + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + + ; PROGRAM REGISTER STACK OFFSET +STK_OFFSET_R1 EQU 0 +STK_OFFSET_R2 EQU STK_OFFSET_R1 + 4 +STK_OFFSET_R5 EQU STK_OFFSET_R2 + 4 +STK_OFFSET_R6 EQU STK_OFFSET_R5 + 4 +STK_OFFSET_R7 EQU STK_OFFSET_R6 + 4 +STK_OFFSET_R8 EQU STK_OFFSET_R7 + 4 +STK_OFFSET_R9 EQU STK_OFFSET_R8 + 4 +STK_OFFSET_R10 EQU STK_OFFSET_R9 + 4 +STK_OFFSET_R11 EQU STK_OFFSET_R10 + 4 +STK_OFFSET_R12 EQU STK_OFFSET_R11 + 4 +STK_OFFSET_R13 EQU STK_OFFSET_R12 + 4 +STK_OFFSET_R14 EQU STK_OFFSET_R13 + 4 +STK_OFFSET_R15 EQU STK_OFFSET_R14 + 4 +STK_OFFSET_R16 EQU STK_OFFSET_R15 + 4 +STK_OFFSET_R17 EQU STK_OFFSET_R16 + 4 +STK_OFFSET_R18 EQU STK_OFFSET_R17 + 4 +STK_OFFSET_R19 EQU STK_OFFSET_R18 + 4 +STK_OFFSET_R20 EQU STK_OFFSET_R19 + 4 +STK_OFFSET_R21 EQU STK_OFFSET_R20 + 4 +STK_OFFSET_R22 EQU STK_OFFSET_R21 + 4 +STK_OFFSET_R23 EQU STK_OFFSET_R22 + 4 +STK_OFFSET_R24 EQU STK_OFFSET_R23 + 4 +STK_OFFSET_R26 EQU STK_OFFSET_R24 + 4 +STK_OFFSET_R27 EQU STK_OFFSET_R26 + 4 +STK_OFFSET_R28 EQU STK_OFFSET_R27 + 4 +STK_OFFSET_R29 EQU STK_OFFSET_R28 + 4 +STK_OFFSET_R31 EQU STK_OFFSET_R29 + 4 + ; SYSTEM REGISTER STACK OFFSET +STK_OFFSET_EIPC EQU STK_OFFSET_R31 + 4 +STK_OFFSET_EIPSW EQU STK_OFFSET_EIPC + 4 + +STK_CTX_SIZE EQU STK_OFFSET_EIPSW + 4 + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + + +;******************************************************************************************************** +; OS_CTX_SAVE +; +; Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +; the same order as they were saved in OSTaskStkInit(). +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; SAVE PROCESSOR REGISTER +OS_CTX_SAVE MACRO REG_SP + addi -STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer + + st.w r1, STK_OFFSET_R1[REG_SP] + st.w r2, STK_OFFSET_R2[REG_SP] + st.w r5, STK_OFFSET_R5[REG_SP] + st.w r6, STK_OFFSET_R6[REG_SP] + st.w r7, STK_OFFSET_R7[REG_SP] + st.w r8, STK_OFFSET_R8[REG_SP] + st.w r9, STK_OFFSET_R9[REG_SP] + st.w r10, STK_OFFSET_R10[REG_SP] + st.w r11, STK_OFFSET_R11[REG_SP] + st.w r12, STK_OFFSET_R12[REG_SP] + st.w r13, STK_OFFSET_R13[REG_SP] + st.w r14, STK_OFFSET_R14[REG_SP] + st.w r15, STK_OFFSET_R15[REG_SP] + st.w r16, STK_OFFSET_R16[REG_SP] + st.w r17, STK_OFFSET_R17[REG_SP] + st.w r18, STK_OFFSET_R18[REG_SP] + st.w r19, STK_OFFSET_R19[REG_SP] + st.w r20, STK_OFFSET_R20[REG_SP] + st.w r21, STK_OFFSET_R21[REG_SP] + st.w r22, STK_OFFSET_R22[REG_SP] + st.w r23, STK_OFFSET_R23[REG_SP] + st.w r24, STK_OFFSET_R24[REG_SP] + st.w r26, STK_OFFSET_R26[REG_SP] + st.w r27, STK_OFFSET_R27[REG_SP] + st.w r28, STK_OFFSET_R28[REG_SP] + st.w r29, STK_OFFSET_R29[REG_SP] + st.w r31, STK_OFFSET_R31[REG_SP] + + stsr EIPC, r2 + st.w r2, STK_OFFSET_EIPC[REG_SP] ; Restore task's EIPC + + stsr EIPSW, r2 + st.w r2, STK_OFFSET_EIPSW[REG_SP] ; Restore task's EIPSW + ENDM + + +;******************************************************************************************************** +; OS_CTX_RESTORE +; +; Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +; reverse order of OS_CTX_SAVE (see above) +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; RESTORE PROCESSOR REGISTER +OS_CTX_RESTORE MACRO REG_SP + ld.w STK_OFFSET_R1[REG_SP] , r1 + ld.w STK_OFFSET_R5[REG_SP] , r5 + ld.w STK_OFFSET_R6[REG_SP] , r6 + ld.w STK_OFFSET_R7[REG_SP] , r7 + ld.w STK_OFFSET_R8[REG_SP] , r8 + ld.w STK_OFFSET_R9[REG_SP] , r9 + ld.w STK_OFFSET_R10[REG_SP], r10 + ld.w STK_OFFSET_R11[REG_SP], r11 + ld.w STK_OFFSET_R12[REG_SP], r12 + ld.w STK_OFFSET_R13[REG_SP], r13 + ld.w STK_OFFSET_R14[REG_SP], r14 + ld.w STK_OFFSET_R15[REG_SP], r15 + ld.w STK_OFFSET_R16[REG_SP], r16 + ld.w STK_OFFSET_R17[REG_SP], r17 + ld.w STK_OFFSET_R18[REG_SP], r18 + ld.w STK_OFFSET_R19[REG_SP], r19 + ld.w STK_OFFSET_R20[REG_SP], r20 + ld.w STK_OFFSET_R21[REG_SP], r21 + ld.w STK_OFFSET_R22[REG_SP], r22 + ld.w STK_OFFSET_R23[REG_SP], r23 + ld.w STK_OFFSET_R24[REG_SP], r24 + ld.w STK_OFFSET_R26[REG_SP], r26 + ld.w STK_OFFSET_R27[REG_SP], r27 + ld.w STK_OFFSET_R28[REG_SP], r28 + ld.w STK_OFFSET_R29[REG_SP], r29 + ld.w STK_OFFSET_R31[REG_SP], r31 + + ld.w STK_OFFSET_EIPSW[REG_SP], r2 ; Restore task's EIPSW + ldsr r2, EIPSW + + ld.w STK_OFFSET_EIPC[REG_SP], r2 ; Restore task's EIPC + ldsr r2, EIPC + + ld.w STK_OFFSET_R2[REG_SP] , r2 + + addi STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer + ENDM + + +;******************************************************************************************************** +; OS_ISR_ENTER +; +; Description : Interrupt service routine prologue for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_ENTER +; OS_CTX_SAVE ; Call the macro: OS_CTX_SAVE +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; +; This MACRO is to be used by your assembly language based ISRs as follows: +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_ISR_ENTER MACRO + OS_CTX_SAVE sp ; Save processor registers on the stack + + mov OSIntNesting, r11 ; OSIntNesting++; + ld.b 0[r11], r2 + add 0x1, r2 + st.b r2, 0[r11] + + cmp 0x1, r2 + bne b ; if (OSIntNesting == 1) { + + mov OSTCBCur, r11 ; OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] ; } + +b: + ENDM + + +;******************************************************************************************************** +; OS_ISR_EXIT +; +; Description : Interrupt service routine epilog for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_EXIT: +; OSIntExit(); ; Call the C function: OSIntExit(); +; OS_CTX_RESTORE ; Call the macro: OS_CTX_RESTORE +; Return from interrupt ; CPU instruction to return from interrupt/exception +;******************************************************************************************************** + +OS_ISR_EXIT MACRO + jarl OSIntExit, lp ; Call 'OSIntExit()' + + OS_CTX_RESTORE sp ; Restore processor registers from stack + eiret ; CPU instruction to return from Interrupt/exception + + ENDM + + +;******************************************************************************************************** +; ASSEMBLY LANGUAGE MACROS FILE END +;******************************************************************************************************** + diff --git a/Ports/V850E2M/IAR/os_cpu_a.s85 b/Ports/V850E2M/IAR/os_cpu_a.s85 new file mode 100644 index 0000000..6438d4e --- /dev/null +++ b/Ports/V850E2M/IAR/os_cpu_a.s85 @@ -0,0 +1,240 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850E2M Port +; +; Filename : os_cpu_a.s85 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850E2M +; Toolchain : IAR EWV850 v3.7x and up +;******************************************************************************************************** + +#include "os_cpu_a.inc" + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + ; External References + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSTaskSwHook + EXTERN OSTimeTick + + ; Functions declared in this file + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OS_CPU_TickHandler + PUBLIC OSStartHighRdy + PUBLIC OSIntCtxSw + PUBLIC OSCtxSw + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save: + stsr PSW, r1 ; Save PSW + di ; Disable interrupts + jmp [lp] + +OS_CPU_SR_Restore: + ldsr r1, PSW ; Restore PSW + jmp [lp] + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +; +;******************************************************************************************************** + +OSStartHighRdy: + jarl OSTaskSwHook, lp ; Call OSTaskSwHook(); + + mov 0x01 , r2 ; OSRunning = TRUE; + mov OSRunning, r11 + st.b r2 , 0[r11] + + mov OSTCBHighRdy, r11 ; SWITCH TO HIGHEST PRIORITY TASK: + ld.w 0[r11] , r11 + ld.w 0[r11] , sp + + OS_CTX_RESTORE sp ; Restore Task Context + + eiret + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = sp; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw: + OS_CTX_SAVE sp ; Save current Task context + + mov OSTCBCur, r11 ; OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] + + jarl OSTaskSwHook, lp ; OSTaskSwHook(); + + mov OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov OSPrioCur , r11 + st.b r12 , 0[r11] + + mov OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp ; Restore new Task's context + + eiret ; return from trap + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) The pseudo-code for OSIntCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw: + jarl OSTaskSwHook, lp ; OSTaskSwHook(); + + mov OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov OSPrioCur , r11 + st.b r12 , 0[r11] + + mov OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp + + eiret ; Return from interrupt starts new task + + +;******************************************************************************************************** +; OS_CPU_TickHandler +; +; Note(s) : 1) The pseudo-code for _OS_CPU_TickHandler() is: +; a) Save processor registers; +; b) Increment OSIntNesting; +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; d) Call OSTimeTick(); +; e) Call OSIntExit(); +; f) Restore processosr Registers; +; +; 2) OS_CPU_TickHandler() must be registered in the proper vector address of timer that will be +; used as the tick. +; +; 3) All the other ISRs must have the following implementation to secure proper register saving & +; restoring when servicing an interrupt +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_CPU_TickHandler: + OS_ISR_ENTER + + jarl OSTimeTick, lp ; Call OSTimeTick(); + + OS_ISR_EXIT + + +;******************************************************************************************************** +; CPU ASSEMBLY PORT FILE END +;******************************************************************************************************** + + END diff --git a/Ports/V850E2M/IAR/os_cpu_c.c b/Ports/V850E2M/IAR/os_cpu_c.c new file mode 100644 index 0000000..8c9ce85 --- /dev/null +++ b/Ports/V850E2M/IAR/os_cpu_c.c @@ -0,0 +1,344 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850E2M Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850E2M +* Toolchain : IAR EWV850 v3.71 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define V850ES_EIPSW_EN 0x00000000u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in Thread mode, using process stack. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning. */ + stk = ptos; /* Load stack pointer. */ + *(stk) =(INT32U)V850ES_EIPSW_EN; /* EIPSW interrupt enable */ + *(--stk) =(INT32U)task; /* EIPC */ + *(--stk) =(INT32U)OS_TaskReturn; /* r31 Link Pointer (LP). to pass return address of function */ + *(--stk) =(INT32U)0x29292929; /* r29 */ + *(--stk) =(INT32U)0x28282828; /* r28 */ + *(--stk) =(INT32U)0x27272727; /* r27 */ + *(--stk) =(INT32U)0x26262626; /* r26 */ + *(--stk) =(INT32U)0x24242424; /* r24 */ + *(--stk) =(INT32U)0x23232323; /* r23 */ + *(--stk) =(INT32U)0x22222222; /* r22 */ + *(--stk) =(INT32U)0x21212121; /* r21 */ + *(--stk) =(INT32U)0x20202020; /* r20 */ + *(--stk) =(INT32U)0x19191919; /* r19 */ + *(--stk) =(INT32U)0x18181818; /* r18 */ + *(--stk) =(INT32U)0x17171717; /* r17 */ + *(--stk) =(INT32U)0x16161616; /* r16 */ + *(--stk) =(INT32U)0x15151515; /* r15 */ + *(--stk) =(INT32U)0x14141414; /* r14 */ + *(--stk) =(INT32U)0x13131313; /* r13 */ + *(--stk) =(INT32U)0x12121212; /* r12 */ + *(--stk) =(INT32U)0x11111111; /* r11 */ + *(--stk) =(INT32U)0x10101010; /* r10 */ + *(--stk) =(INT32U)0x09090909; /* r9 */ + *(--stk) =(INT32U)0x08080808; /* r8 */ + *(--stk) =(INT32U)0x07070707; /* r7 */ + *(--stk) =(INT32U)0x06060606; /* r6 */ + *(--stk) =(INT32U)0x05050505; /* r5 */ + *(--stk) =(INT32U)0x02020202; /* r2 */ + *(--stk) =(INT32U)p_arg; /* r1 Argument register/ return value */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/V850E2M/IAR/os_dbg.c b/Ports/V850E2M/IAR/os_dbg.c new file mode 100644 index 0000000..4e40744 --- /dev/null +++ b/Ports/V850E2M/IAR/os_dbg.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif + diff --git a/Ports/V850E2S/IAR/os_cpu.h b/Ports/V850E2S/IAR/os_cpu.h new file mode 100644 index 0000000..9ab7f19 --- /dev/null +++ b/Ports/V850E2S/IAR/os_cpu.h @@ -0,0 +1,119 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850E2S Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850E2S +* Toolchain : IAR EWV850 v3.7x and up +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsiged 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + +/* +********************************************************************************************************* +* Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() asm("trap 0x00") + + +/* +********************************************************************************************************* +* PROTOTYPES +* +* Note(s) : (1) OS_CPU_TickInit() must be implemented by the user to initialize the timer, which will +* be used as the tick interrupt. Moreover, OS_CPU_TickHandler() must be registered in the +* proper vector address of timer that will be used as the tick. +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S85 */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + /* See Note # 1. */ +void OS_CPU_TickHandler (void); +void OS_CPU_TickInit (INT32U tick_per_sec); +#endif diff --git a/Ports/V850E2S/IAR/os_cpu_a.inc b/Ports/V850E2S/IAR/os_cpu_a.inc new file mode 100644 index 0000000..b6af1ff --- /dev/null +++ b/Ports/V850E2S/IAR/os_cpu_a.inc @@ -0,0 +1,256 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850E2S Port +; +; Filename : os_cpu_a.inc +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850E2S +; Toolchain : IAR EWV850 v3.7x and up +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXTERN OSTCBCur + EXTERN OSIntNesting + EXTERN OSIntExit + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + + ; PROGRAM REGISTER STACK OFFSET +STK_OFFSET_R1 EQU 0 +STK_OFFSET_R2 EQU STK_OFFSET_R1 + 4 +STK_OFFSET_R5 EQU STK_OFFSET_R2 + 4 +STK_OFFSET_R6 EQU STK_OFFSET_R5 + 4 +STK_OFFSET_R7 EQU STK_OFFSET_R6 + 4 +STK_OFFSET_R8 EQU STK_OFFSET_R7 + 4 +STK_OFFSET_R9 EQU STK_OFFSET_R8 + 4 +STK_OFFSET_R10 EQU STK_OFFSET_R9 + 4 +STK_OFFSET_R11 EQU STK_OFFSET_R10 + 4 +STK_OFFSET_R12 EQU STK_OFFSET_R11 + 4 +STK_OFFSET_R13 EQU STK_OFFSET_R12 + 4 +STK_OFFSET_R14 EQU STK_OFFSET_R13 + 4 +STK_OFFSET_R15 EQU STK_OFFSET_R14 + 4 +STK_OFFSET_R16 EQU STK_OFFSET_R15 + 4 +STK_OFFSET_R17 EQU STK_OFFSET_R16 + 4 +STK_OFFSET_R18 EQU STK_OFFSET_R17 + 4 +STK_OFFSET_R19 EQU STK_OFFSET_R18 + 4 +STK_OFFSET_R20 EQU STK_OFFSET_R19 + 4 +STK_OFFSET_R21 EQU STK_OFFSET_R20 + 4 +STK_OFFSET_R22 EQU STK_OFFSET_R21 + 4 +STK_OFFSET_R23 EQU STK_OFFSET_R22 + 4 +STK_OFFSET_R24 EQU STK_OFFSET_R23 + 4 +STK_OFFSET_R26 EQU STK_OFFSET_R24 + 4 +STK_OFFSET_R27 EQU STK_OFFSET_R26 + 4 +STK_OFFSET_R28 EQU STK_OFFSET_R27 + 4 +STK_OFFSET_R29 EQU STK_OFFSET_R28 + 4 +STK_OFFSET_R31 EQU STK_OFFSET_R29 + 4 + ; SYSTEM REGISTER STACK OFFSET +STK_OFFSET_EIPC EQU STK_OFFSET_R31 + 4 +STK_OFFSET_EIPSW EQU STK_OFFSET_EIPC + 4 + +STK_CTX_SIZE EQU STK_OFFSET_EIPSW + 4 + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + + +;******************************************************************************************************** +; OS_CTX_SAVE +; +; Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +; the same order as they were saved in OSTaskStkInit(). +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; SAVE PROCESSOR REGISTER +OS_CTX_SAVE MACRO REG_SP + addi -STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer + + st.w r1, STK_OFFSET_R1[REG_SP] + st.w r2, STK_OFFSET_R2[REG_SP] + st.w r5, STK_OFFSET_R5[REG_SP] + st.w r6, STK_OFFSET_R6[REG_SP] + st.w r7, STK_OFFSET_R7[REG_SP] + st.w r8, STK_OFFSET_R8[REG_SP] + st.w r9, STK_OFFSET_R9[REG_SP] + st.w r10, STK_OFFSET_R10[REG_SP] + st.w r11, STK_OFFSET_R11[REG_SP] + st.w r12, STK_OFFSET_R12[REG_SP] + st.w r13, STK_OFFSET_R13[REG_SP] + st.w r14, STK_OFFSET_R14[REG_SP] + st.w r15, STK_OFFSET_R15[REG_SP] + st.w r16, STK_OFFSET_R16[REG_SP] + st.w r17, STK_OFFSET_R17[REG_SP] + st.w r18, STK_OFFSET_R18[REG_SP] + st.w r19, STK_OFFSET_R19[REG_SP] + st.w r20, STK_OFFSET_R20[REG_SP] + st.w r21, STK_OFFSET_R21[REG_SP] + st.w r22, STK_OFFSET_R22[REG_SP] + st.w r23, STK_OFFSET_R23[REG_SP] + st.w r24, STK_OFFSET_R24[REG_SP] + st.w r26, STK_OFFSET_R26[REG_SP] + st.w r27, STK_OFFSET_R27[REG_SP] + st.w r28, STK_OFFSET_R28[REG_SP] + st.w r29, STK_OFFSET_R29[REG_SP] + st.w r31, STK_OFFSET_R31[REG_SP] + + stsr EIPC, r2 + st.w r2, STK_OFFSET_EIPC[REG_SP] ; Restore task's EIPC + + stsr EIPSW, r2 + st.w r2, STK_OFFSET_EIPSW[REG_SP] ; Restore task's EIPSW + ENDM + + +;******************************************************************************************************** +; OS_CTX_RESTORE +; +; Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +; reverse order of OS_CTX_SAVE (see above) +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; RESTORE PROCESSOR REGISTER +OS_CTX_RESTORE MACRO REG_SP + ld.w STK_OFFSET_R1[REG_SP] , r1 + ld.w STK_OFFSET_R5[REG_SP] , r5 + ld.w STK_OFFSET_R6[REG_SP] , r6 + ld.w STK_OFFSET_R7[REG_SP] , r7 + ld.w STK_OFFSET_R8[REG_SP] , r8 + ld.w STK_OFFSET_R9[REG_SP] , r9 + ld.w STK_OFFSET_R10[REG_SP], r10 + ld.w STK_OFFSET_R11[REG_SP], r11 + ld.w STK_OFFSET_R12[REG_SP], r12 + ld.w STK_OFFSET_R13[REG_SP], r13 + ld.w STK_OFFSET_R14[REG_SP], r14 + ld.w STK_OFFSET_R15[REG_SP], r15 + ld.w STK_OFFSET_R16[REG_SP], r16 + ld.w STK_OFFSET_R17[REG_SP], r17 + ld.w STK_OFFSET_R18[REG_SP], r18 + ld.w STK_OFFSET_R19[REG_SP], r19 + ld.w STK_OFFSET_R20[REG_SP], r20 + ld.w STK_OFFSET_R21[REG_SP], r21 + ld.w STK_OFFSET_R22[REG_SP], r22 + ld.w STK_OFFSET_R23[REG_SP], r23 + ld.w STK_OFFSET_R24[REG_SP], r24 + ld.w STK_OFFSET_R26[REG_SP], r26 + ld.w STK_OFFSET_R27[REG_SP], r27 + ld.w STK_OFFSET_R28[REG_SP], r28 + ld.w STK_OFFSET_R29[REG_SP], r29 + ld.w STK_OFFSET_R31[REG_SP], r31 + + ld.w STK_OFFSET_EIPSW[REG_SP], r2 ; Restore task's EIPSW + ldsr r2, EIPSW + + ld.w STK_OFFSET_EIPC[REG_SP], r2 ; Restore task's EIPC + ldsr r2, EIPC + + ld.w STK_OFFSET_R2[REG_SP] , r2 + + addi STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer + ENDM + + +;******************************************************************************************************** +; OS_ISR_ENTER +; +; Description : Interrupt service routine prologue for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_ENTER +; OS_CTX_SAVE ; Call the macro: OS_CTX_SAVE +; OSIntNesting++; +; if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; +; This MACRO is to be used by your assembly language based ISRs as follows: +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_ISR_ENTER MACRO + OS_CTX_SAVE sp ; Save processor registers on the stack + + mov OSIntNesting, r11 ; OSIntNesting++; + ld.b 0[r11], r2 + add 0x1, r2 + st.b r2, 0[r11] + + cmp 0x1, r2 + bne b ; if (OSIntNesting == 1) { + + mov OSTCBCur, r11 ; OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] ; } + +b: + ENDM + + +;******************************************************************************************************** +; OS_ISR_EXIT +; +; Description : Interrupt service routine epilog for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_EXIT: +; OSIntExit(); ; Call the C function: OSIntExit(); +; OS_CTX_RESTORE ; Call the macro: OS_CTX_RESTORE +; Return from interrupt ; CPU instruction to return from interrupt/exception +;******************************************************************************************************** + +OS_ISR_EXIT MACRO + jarl OSIntExit, lp ; Call 'OSIntExit()' + + OS_CTX_RESTORE sp ; Restore processor registers from stack + eiret ; CPU instruction to return from Interrupt/exception + + ENDM + + +;******************************************************************************************************** +; ASSEMBLY LANGUAGE MACROS FILE END +;******************************************************************************************************** + diff --git a/Ports/V850E2S/IAR/os_cpu_a.s85 b/Ports/V850E2S/IAR/os_cpu_a.s85 new file mode 100644 index 0000000..fb7136a --- /dev/null +++ b/Ports/V850E2S/IAR/os_cpu_a.s85 @@ -0,0 +1,241 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850E2S Port +; +; Filename : os_cpu_a.s85 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850E2S +; Toolchain : IAR EWV850 v3.7x and up +;******************************************************************************************************** + + +#include "os_cpu_a.inc" + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + ; External References + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSTaskSwHook + EXTERN OSTimeTick + + ; Functions declared in this file + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OS_CPU_TickHandler + PUBLIC OSStartHighRdy + PUBLIC OSIntCtxSw + PUBLIC OSCtxSw + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save: + stsr PSW, r1 ; Save PSW + di ; Disable interrupts + jmp [lp] + +OS_CPU_SR_Restore: + ldsr r1, PSW ; Restore PSW + jmp [lp] + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +; +;******************************************************************************************************** + +OSStartHighRdy: + jarl OSTaskSwHook, lp ; Call OSTaskSwHook(); + + mov 0x01 , r2 ; OSRunning = TRUE; + mov OSRunning, r11 + st.b r2 , 0[r11] + + mov OSTCBHighRdy, r11 ; SWITCH TO HIGHEST PRIORITY TASK: + ld.w 0[r11] , r11 + ld.w 0[r11] , sp + + OS_CTX_RESTORE sp ; Restore Task Context + + eiret + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = sp; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw: + OS_CTX_SAVE sp ; Save current Task context + + mov OSTCBCur, r11 ; OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] + + jarl OSTaskSwHook, lp ; OSTaskSwHook(); + + mov OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov OSPrioCur , r11 + st.b r12 , 0[r11] + + mov OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp ; Restore new Task's context + + eiret ; return from trap + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) The pseudo-code for OSIntCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw: + jarl OSTaskSwHook, lp ; OSTaskSwHook(); + + mov OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov OSPrioCur , r11 + st.b r12 , 0[r11] + + mov OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp + + eiret ; Return from interrupt starts new task + + +;******************************************************************************************************** +; OS_CPU_TickHandler +; +; Note(s) : 1) The pseudo-code for _OS_CPU_TickHandler() is: +; a) Save processor registers; +; b) Increment OSIntNesting; +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; d) Call OSTimeTick(); +; e) Call OSIntExit(); +; f) Restore processosr Registers; +; +; 2) OS_CPU_TickHandler() must be registered in the proper vector address of timer that will be +; used as the tick. +; +; 3) All the other ISRs must have the following implementation to secure proper register saving & +; restoring when servicing an interrupt +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_CPU_TickHandler: + OS_ISR_ENTER + + jarl OSTimeTick, lp ; Call OSTimeTick(); + + OS_ISR_EXIT + + +;******************************************************************************************************** +; CPU ASSEMBLY PORT FILE END +;******************************************************************************************************** + + END diff --git a/Ports/V850E2S/IAR/os_cpu_c.c b/Ports/V850E2S/IAR/os_cpu_c.c new file mode 100644 index 0000000..d8c7c36 --- /dev/null +++ b/Ports/V850E2S/IAR/os_cpu_c.c @@ -0,0 +1,344 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850E2S Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850E2S +* Toolchain : IAR EWV850 v3.7x and up +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define V850ES_EIPSW_EN 0x00000000u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in Thread mode, using process stack. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning. */ + stk = ptos; /* Load stack pointer. */ + *(stk) =(INT32U)V850ES_EIPSW_EN; /* EIPSW interrupt enable */ + *(--stk) =(INT32U)task; /* EIPC */ + *(--stk) =(INT32U)OS_TaskReturn; /* r31 Link Pointer (LP). to pass return address of function */ + *(--stk) =(INT32U)0x29292929; /* r29 */ + *(--stk) =(INT32U)0x28282828; /* r28 */ + *(--stk) =(INT32U)0x27272727; /* r27 */ + *(--stk) =(INT32U)0x26262626; /* r26 */ + *(--stk) =(INT32U)0x24242424; /* r24 */ + *(--stk) =(INT32U)0x23232323; /* r23 */ + *(--stk) =(INT32U)0x22222222; /* r22 */ + *(--stk) =(INT32U)0x21212121; /* r21 */ + *(--stk) =(INT32U)0x20202020; /* r20 */ + *(--stk) =(INT32U)0x19191919; /* r19 */ + *(--stk) =(INT32U)0x18181818; /* r18 */ + *(--stk) =(INT32U)0x17171717; /* r17 */ + *(--stk) =(INT32U)0x16161616; /* r16 */ + *(--stk) =(INT32U)0x15151515; /* r15 */ + *(--stk) =(INT32U)0x14141414; /* r14 */ + *(--stk) =(INT32U)0x13131313; /* r13 */ + *(--stk) =(INT32U)0x12121212; /* r12 */ + *(--stk) =(INT32U)0x11111111; /* r11 */ + *(--stk) =(INT32U)0x10101010; /* r10 */ + *(--stk) =(INT32U)0x09090909; /* r9 */ + *(--stk) =(INT32U)0x08080808; /* r8 */ + *(--stk) =(INT32U)0x07070707; /* r7 */ + *(--stk) =(INT32U)0x06060606; /* r6 */ + *(--stk) =(INT32U)0x05050505; /* r5 */ + *(--stk) =(INT32U)0x02020202; /* r2 */ + *(--stk) =(INT32U)p_arg; /* r1 Argument register/ return value */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/V850E2S/IAR/os_dbg.c b/Ports/V850E2S/IAR/os_dbg.c new file mode 100644 index 0000000..4e40744 --- /dev/null +++ b/Ports/V850E2S/IAR/os_dbg.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif + diff --git a/Ports/V850ES/CubeSuite/os_cpu.h b/Ports/V850ES/CubeSuite/os_cpu.h new file mode 100644 index 0000000..3bc702d --- /dev/null +++ b/Ports/V850ES/CubeSuite/os_cpu.h @@ -0,0 +1,123 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850ES Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850ES +* Toolchain : CubeSuite V1.20 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsiged 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 1u +#define OS_ENTER_CRITICAL() __DI() /* Disable Interrupts */ +#define OS_EXIT_CRITICAL() __EI() /* Enable Interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + +/* +********************************************************************************************************* +* Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() __asm("trap 0x00") + +/* +********************************************************************************************************* +* PROTOTYPES +* +* Note(s) : (1) OS_CPU_TickInit() must be implemented by the user to initialize the timer, which will +* be used as the tick interrupt. Moreover, OS_CPU_TickHandler() must be registered in the +* proper vector address of timer that will be used as the tick. +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + /* See Note # 1. */ +void OS_CPU_TickHandler (void); +void OS_CPU_TickInit (INT32U tick_per_sec); +#endif diff --git a/Ports/V850ES/CubeSuite/os_cpu_a.inc b/Ports/V850ES/CubeSuite/os_cpu_a.inc new file mode 100644 index 0000000..1d151da --- /dev/null +++ b/Ports/V850ES/CubeSuite/os_cpu_a.inc @@ -0,0 +1,280 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Renesas V850ES Port +# +# Filename : os_cpu_a.inc +# Version : V2.93.00 +#******************************************************************************************************** +# For : Renesas V850ES +# Toolchain : CubeSuite V1.20 +# CA850 compiler +#******************************************************************************************************** + +#******************************************************************************************************** +# PUBLIC FUNCTIONS +#******************************************************************************************************** + + .extern _OSTCBCur + .extern _OSIntNesting + .extern _OSIntExit + + +#******************************************************************************************************** +# EQUATES +#******************************************************************************************************** + + -- SYSTEM REGISTER + .set EIPC , 0 + .set EIPSW, 1 + .set ECR , 4 + .set PSW , 5 + .set CTPC , 16 + .set CTPSW, 17 + + -- PROGRAM REGISTER STACK OFFSET + .set STK_OFFSET_R1 , 0 + .set STK_OFFSET_R2 , STK_OFFSET_R1 + 4 + .set STK_OFFSET_R6 , STK_OFFSET_R2 + 4 + .set STK_OFFSET_R7 , STK_OFFSET_R6 + 4 + .set STK_OFFSET_R8 , STK_OFFSET_R7 + 4 + .set STK_OFFSET_R9 , STK_OFFSET_R8 + 4 + .set STK_OFFSET_R10 , STK_OFFSET_R9 + 4 + .set STK_OFFSET_R11 , STK_OFFSET_R10 + 4 + .set STK_OFFSET_R12 , STK_OFFSET_R11 + 4 + .set STK_OFFSET_R13 , STK_OFFSET_R12 + 4 + .set STK_OFFSET_R14 , STK_OFFSET_R13 + 4 + .set STK_OFFSET_R15 , STK_OFFSET_R14 + 4 + .set STK_OFFSET_R16 , STK_OFFSET_R15 + 4 + .set STK_OFFSET_R17 , STK_OFFSET_R16 + 4 + .set STK_OFFSET_R18 , STK_OFFSET_R17 + 4 + .set STK_OFFSET_R19 , STK_OFFSET_R18 + 4 + .set STK_OFFSET_R20 , STK_OFFSET_R19 + 4 + .set STK_OFFSET_R21 , STK_OFFSET_R20 + 4 + .set STK_OFFSET_R22 , STK_OFFSET_R21 + 4 + .set STK_OFFSET_R23 , STK_OFFSET_R22 + 4 + .set STK_OFFSET_R24 , STK_OFFSET_R23 + 4 + .set STK_OFFSET_R25 , STK_OFFSET_R24 + 4 + .set STK_OFFSET_R26 , STK_OFFSET_R25 + 4 + .set STK_OFFSET_R27 , STK_OFFSET_R26 + 4 + .set STK_OFFSET_R28 , STK_OFFSET_R27 + 4 + .set STK_OFFSET_R29 , STK_OFFSET_R28 + 4 + .set STK_OFFSET_R30 , STK_OFFSET_R29 + 4 + .set STK_OFFSET_R31 , STK_OFFSET_R30 + 4 + .set STK_OFFSET_EIPC , STK_OFFSET_R31 + 4 + -- SYSTEM REGISTER STACK OFFSET + .set STK_OFFSET_EIPSW, STK_OFFSET_EIPC + 4 + .set STK_OFFSET_CTPC , STK_OFFSET_EIPSW + 4 + .set STK_OFFSET_CTPSW, STK_OFFSET_CTPC + 4 + .set STK_CTX_SIZE , STK_OFFSET_CTPSW + 4 + +#******************************************************************************************************** +# CODE GENERATION DIRECTIVES +#******************************************************************************************************** + + .text + .align 4 + + +#******************************************************************************************************** +# OS_CTX_SAVE +# +# Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +# the same order as they were saved in OSTaskStkInit(). +# +# Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +# expansion is performed using the assembler. If r1 is specified as a source or +# destination register, the assembler outputs a warning message; which can be suppressed +# with the following syntax: +# $NOWARNING +# r1 used as source/destination register +# $WARNING +#******************************************************************************************************** + + -- SAVE PROCESSOR REGISTER +.macro OS_CTX_SAVE REG_SP + addi -STK_CTX_SIZE, REG_SP, REG_SP -- Adjust the Stack Pointer + + st.w r1, STK_OFFSET_R1[REG_SP] + st.w r2, STK_OFFSET_R2[REG_SP] + st.w r6, STK_OFFSET_R6[REG_SP] + st.w r7, STK_OFFSET_R7[REG_SP] + st.w r8, STK_OFFSET_R8[REG_SP] + st.w r9, STK_OFFSET_R9[REG_SP] + st.w r10, STK_OFFSET_R10[REG_SP] + st.w r11, STK_OFFSET_R11[REG_SP] + st.w r12, STK_OFFSET_R12[REG_SP] + st.w r13, STK_OFFSET_R13[REG_SP] + st.w r14, STK_OFFSET_R14[REG_SP] + st.w r15, STK_OFFSET_R15[REG_SP] + st.w r16, STK_OFFSET_R16[REG_SP] + st.w r17, STK_OFFSET_R17[REG_SP] + st.w r18, STK_OFFSET_R18[REG_SP] + st.w r19, STK_OFFSET_R19[REG_SP] + st.w r20, STK_OFFSET_R20[REG_SP] + st.w r21, STK_OFFSET_R21[REG_SP] + st.w r22, STK_OFFSET_R22[REG_SP] + st.w r23, STK_OFFSET_R23[REG_SP] + st.w r24, STK_OFFSET_R24[REG_SP] + st.w r25, STK_OFFSET_R25[REG_SP] + st.w r26, STK_OFFSET_R26[REG_SP] + st.w r27, STK_OFFSET_R27[REG_SP] + st.w r28, STK_OFFSET_R28[REG_SP] + st.w r29, STK_OFFSET_R29[REG_SP] + st.w r30, STK_OFFSET_R30[REG_SP] + st.w r31, STK_OFFSET_R31[REG_SP] + + stsr EIPC, r2 + st.w r2, STK_OFFSET_EIPC[REG_SP] -- Restore task's EIPC + + stsr EIPSW, r2 + st.w r2, STK_OFFSET_EIPSW[REG_SP] -- Restore task's EIPSW + + stsr CTPC, r2 + st.w r2, STK_OFFSET_CTPC[REG_SP] -- Restore task's CTPC + + stsr CTPSW, r2 + st.w r2, STK_OFFSET_CTPSW[REG_SP] -- Restore task's CTPSW +.endm + + +#******************************************************************************************************** +# OS_CTX_RESTORE +# +# Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +# reverse order of OS_CTX_SAVE (see above) +# +# Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +# expansion is performed using the assembler. If r1 is specified as a source or +# destination register, the assembler outputs a warning message; which can be suppressed +# with the following syntax: +# $NOWARNING +# r1 used as source/destination register +# $WARNING +#******************************************************************************************************** + + -- RESTORE PROCESSOR REGISTER +.macro OS_CTX_RESTORE REG_SP + ld.w STK_OFFSET_R1[REG_SP] , r1 + ld.w STK_OFFSET_R6[REG_SP] , r6 + ld.w STK_OFFSET_R7[REG_SP] , r7 + ld.w STK_OFFSET_R8[REG_SP] , r8 + ld.w STK_OFFSET_R9[REG_SP] , r9 + ld.w STK_OFFSET_R10[REG_SP], r10 + ld.w STK_OFFSET_R11[REG_SP], r11 + ld.w STK_OFFSET_R12[REG_SP], r12 + ld.w STK_OFFSET_R13[REG_SP], r13 + ld.w STK_OFFSET_R14[REG_SP], r14 + ld.w STK_OFFSET_R15[REG_SP], r15 + ld.w STK_OFFSET_R16[REG_SP], r16 + ld.w STK_OFFSET_R17[REG_SP], r17 + ld.w STK_OFFSET_R18[REG_SP], r18 + ld.w STK_OFFSET_R19[REG_SP], r19 + ld.w STK_OFFSET_R20[REG_SP], r20 + ld.w STK_OFFSET_R21[REG_SP], r21 + ld.w STK_OFFSET_R22[REG_SP], r22 + ld.w STK_OFFSET_R23[REG_SP], r23 + ld.w STK_OFFSET_R24[REG_SP], r24 + ld.w STK_OFFSET_R25[REG_SP], r25 + ld.w STK_OFFSET_R26[REG_SP], r26 + ld.w STK_OFFSET_R27[REG_SP], r27 + ld.w STK_OFFSET_R28[REG_SP], r28 + ld.w STK_OFFSET_R29[REG_SP], r29 + ld.w STK_OFFSET_R30[REG_SP], r30 + ld.w STK_OFFSET_R31[REG_SP], r31 + + ld.w STK_OFFSET_EIPSW[REG_SP], r2 -- Restore task's EIPSW + ldsr r2, EIPSW + + ld.w STK_OFFSET_EIPC[REG_SP], r2 -- Restore task's EIPC + ldsr r2, EIPC + + ld.w STK_OFFSET_CTPC[REG_SP], r2 -- Restore task's CTPC + ldsr r2, CTPC + + ld.w STK_OFFSET_CTPSW[REG_SP], r2 -- Restore task's CTPSW + ldsr r2, CTPSW + + ld.w STK_OFFSET_R2[REG_SP] , r2 + + addi STK_CTX_SIZE, REG_SP, REG_SP -- Adjust the Stack Pointer +.endm + + +#******************************************************************************************************** +# OS_ISR_ENTER +# +# Description : Interrupt service routine prologue for kernel-aware handler. +# This macro implements the following code in assembly language: +# +# OS_ISR_ENTER +# OS_CTX_SAVE ; Call the macro: OS_CTX_SAVE +# OSIntNestingCtr++; +# if (OSIntNestingCtr == 1) { +# OSTCBCurPtr->StkPtr = SP; +# } +# +# This MACRO is to be used by your assembly language based ISRs as follows: +# +# MyISR +# OS_ISR_ENTER +# ISR Body here +# OS_ISR_EXIT +#******************************************************************************************************** + +.macro OS_ISR_ENTER + OS_CTX_SAVE sp -- Save processor registers on the stack + + ld.b #_OSIntNesting[r0], r2 -- OSIntNestingCtr++; + add 0x1, r2 + st.b r2, #_OSIntNesting[r0] + + cmp 0x1, r2 + bne _b -- if (OSIntNestingCtr == 1) { + + mov #_OSTCBCur, r11 -- OSTCBCurPtr->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] -- } + +_b: +.endm + + +#******************************************************************************************************** +# OS_ISR_EXIT +# +# Description : Interrupt service routine epilog for kernel-aware handler. +# This macro implements the following code in assembly language: +# +# OS_ISR_EXIT: +# OSIntExit(); ; Call the C function: OSIntExit(); +# OS_CTX_RESTORE ; Call the macro: OS_CTX_RESTORE +# Return from interrupt ; CPU instruction to return from interrupt/exception +#******************************************************************************************************** + +.macro OS_ISR_EXIT + jarl _OSIntExit, lp -- Call 'OSIntExit()' + + OS_CTX_RESTORE sp -- Restore processor registers from stack + reti -- CPU instruction to return from Interrupt/exception + +.endm + + +#******************************************************************************************************** +# ASSEMBLY LANGUAGE MACROS FILE END +#******************************************************************************************************** + diff --git a/Ports/V850ES/CubeSuite/os_cpu_a.s b/Ports/V850ES/CubeSuite/os_cpu_a.s new file mode 100644 index 0000000..bae9d09 --- /dev/null +++ b/Ports/V850ES/CubeSuite/os_cpu_a.s @@ -0,0 +1,245 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Renesas V850ES Port +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** +# For : Renesas V850ES +# Toolchain : CubeSuite V1.20 +# CA850 compiler +#******************************************************************************************************** + +.include "os_cpu_a.inc" + +#******************************************************************************************************** +# PUBLIC FUNCTIONS +#******************************************************************************************************** + -- External References + .extern _OSRunning + .extern _OSPrioCur + .extern _OSPrioHighRdy + .extern _OSTCBCur + .extern _OSTCBHighRdy + .extern _OSTaskSwHook + .extern _OSTimeTick + -- Functions declared in this file + .globl _OS_CPU_SR_Save + .globl _OS_CPU_SR_Restore + .globl _OS_CPU_TickHandler + .globl _OSStartHighRdy + .globl _OSIntCtxSw + .globl _OSCtxSw + +#******************************************************************************************************** +# INTERRUPT VECTOR ENTRY FOR TRAP 00 +#******************************************************************************************************** + + .section "TRAP00", text -- TRAP instruction for Context Switching + .globl __trap00 +__trap00: + jr _OSCtxSw + +#******************************************************************************************************** +# CODE GENERATION DIRECTIVES +#******************************************************************************************************** + + .text + .align 4 + +#******************************************************************************************************** +# CRITICAL SECTION METHOD 3 FUNCTIONS +# +# Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +# would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +# disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +# disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +# into the CPU's status register. +# +# Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +# void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +# +# +# Note(s) : (1) These functions are used in general like this: +# +# void Task (void *p_arg) +# { +# /* Allocate storage for CPU status register. */ +# #if (OS_CRITICAL_METHOD == 3) +# OS_CPU_SR os_cpu_sr; +# #endif +# +# : +# : +# OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +# : +# : +# OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +# : +# : +# } +#******************************************************************************************************** + +_OS_CPU_SR_Save: + stsr PSW, r10 -- Save PSW + di -- Disable interrupts + jmp [lp] + +_OS_CPU_SR_Restore: + ldsr r6, PSW -- Restore PSW + jmp [lp] + +#******************************************************************************************************** +# START MULTITASKING +# void OSStartHighRdy(void) +# +# Note(s) : 1) OSStartHighRdy() MUST: +# a) Call OSTaskSwHook() then, +# b) Set OSRunning to TRUE, +# c) Switch to the highest priority task. +# +#******************************************************************************************************** + +_OSStartHighRdy: + jarl _OSTaskSwHook, lp -- Call OSTaskSwHook(); + + mov 0x01, r2 -- OSRunning = TRUE; + st.b r2 , #_OSRunning[r0] + + mov #_OSTCBHighRdy, r11 -- SWITCH TO HIGHEST PRIORITY TASK: + ld.w 0[r11] , r11 + ld.w 0[r11] , sp + + OS_CTX_RESTORE sp -- Restore Task Context + + reti + +#******************************************************************************************************** +# PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +# +# Note(s) : 1) The pseudo-code for OSCtxSw() is: +# a) Save the current task's context onto the current task's stack, +# b) OSTCBCur->OSTCBStkPtr = sp; +# c) OSTaskSwHook(); +# d) OSPrioCur = OSPrioHighRdy; +# e) OSTCBCur = OSTCBHighRdy; +# f) SP = OSTCBHighRdy->OSTCBStkPtr; +# g) Restore the new task's context from the new task's stack, +# h) Return to new task's code. +# +# 2) Upon entry: +# OSTCBCur points to the OS_TCB of the task to suspend, +# OSTCBHighRdy points to the OS_TCB of the task to resume. +#******************************************************************************************************** + +_OSCtxSw: + OS_CTX_SAVE sp -- Save current Task context + + mov #_OSTCBCur, r11 -- OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] + + jarl _OSTaskSwHook, lp -- OSTaskSwHook(); + + mov #_OSPrioHighRdy, r11 -- OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov #_OSPrioCur , r11 + st.b r12 , 0[r11] + + mov #_OSTCBHighRdy, r11 -- OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov #_OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp -- SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp -- Restore new Task's context + + reti -- return from trap + +#******************************************************************************************************** +# PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +# +# Note(s) : 1) The pseudo-code for OSIntCtxSw() is: +# a) OSTaskSwHook(); +# b) OSPrioCur = OSPrioHighRdy; +# c) OSTCBCur = OSTCBHighRdy; +# d) SP = OSTCBHighRdy->OSTCBStkPtr; +# e) Restore the new task's context from the new task's stack, +# f) Return to new task's code. +# +# 2) Upon entry: +# OSTCBCur points to the OS_TCB of the task to suspend, +# OSTCBHighRdy points to the OS_TCB of the task to resume. +#******************************************************************************************************** + +_OSIntCtxSw: + jarl _OSTaskSwHook, lp -- OSTaskSwHook(); + + mov #_OSPrioHighRdy, r11 -- OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov #_OSPrioCur , r11 + st.b r12 , 0[r11] + + mov #_OSTCBHighRdy, r11 -- OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov #_OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp -- SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp + + reti -- Return from interrupt starts new task + + +#******************************************************************************************************** +# OS_CPU_TickHandler +# +# Note(s) : 1) The pseudo-code for _OS_CPU_TickHandler() is: +# a) Save processor registers; +# b) Increment OSIntNestingCtr; +# c) if (OSIntNestingCtr == 1) { +# OSTCBCurPtr->OSTCBStkPtr = SP; +# } +# d) Call OSTimeTick(); +# e) Call OSIntExit(); +# f) Restore processosr Registers; +# +# 2) OS_CPU_TickHandler() must be registered in the proper vector address of timer that will be +# used as the tick. +# +# 3) All the other ISRs must have the following implementation to secure proper register saving & +# restoring when servicing an interrupt +# +# MyISR +# OS_ISR_ENTER +# ISR Body here +# OS_ISR_EXIT +#******************************************************************************************************** + +_OS_CPU_TickHandler: + OS_ISR_ENTER + + jarl _OSTimeTick, lp -- Call OSTimeTick(); + + OS_ISR_EXIT + + +#******************************************************************************************************** +# ASSEMBLY LANGUAGE PORT FILE END +#******************************************************************************************************** diff --git a/Ports/V850ES/CubeSuite/os_cpu_c.c b/Ports/V850ES/CubeSuite/os_cpu_c.c new file mode 100644 index 0000000..a0a7a71 --- /dev/null +++ b/Ports/V850ES/CubeSuite/os_cpu_c.c @@ -0,0 +1,351 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850ES Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850ES +* Toolchain : CubeSuite V1.20 +* CA850 compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define V850ES_EIPSW_EN 0x00000000u +#define V850ES_CTPC 0x00000000u +#define V850ES_CTPSW 0x00000000u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in Thread mode, using process stack. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning. */ + stk = ptos; /* Load stack pointer. */ + *(stk) =(INT32U)V850ES_CTPSW; /* CTPSW. */ + *(--stk) =(INT32U)V850ES_CTPC; /* CTPC. */ + *(--stk) =(INT32U)V850ES_EIPSW_EN; /* EIPSW interrupt enable */ + *(--stk) =(INT32U)task; /* EIPC */ + *(--stk) =(INT32U)OS_TaskReturn; /* r31 Link Pointer (LP). to pass return address of function */ + *(--stk) =(INT32U)0x30303030; /* r30 Element Pointer (EP). */ + *(--stk) =(INT32U)0x29292929; /* r29 Used as area for register variable */ + *(--stk) =(INT32U)0x28282828; /* r28 */ + *(--stk) =(INT32U)0x27272727; /* r27 */ + *(--stk) =(INT32U)0x26262626; /* r26 */ + *(--stk) =(INT32U)0x25252525; /* r25 */ + *(--stk) =(INT32U)0x24242424; /* r24 */ + *(--stk) =(INT32U)0x23232323; /* r23 */ + *(--stk) =(INT32U)0x22222222; /* r22 */ + *(--stk) =(INT32U)0x21212121; /* r21 */ + *(--stk) =(INT32U)0x20202020; /* r20 Used as area for register variable */ + *(--stk) =(INT32U)0x19191919; /* r19 Working register */ + *(--stk) =(INT32U)0x18181818; /* r18 Working register */ + *(--stk) =(INT32U)0x17171717; /* r17 Working register */ + *(--stk) =(INT32U)0x16161616; /* r16 Working register */ + *(--stk) =(INT32U)0x15151515; /* r15 Working register */ + *(--stk) =(INT32U)0x14141414; /* r14 Working register */ + *(--stk) =(INT32U)0x13131313; /* r13 Working register */ + *(--stk) =(INT32U)0x12121212; /* r12 Working register */ + *(--stk) =(INT32U)0x11111111; /* r11 Working register */ + *(--stk) =(INT32U)0x10101010; /* r10 Function return value */ + *(--stk) =(INT32U)0x09090909; /* r9 Argument register */ + *(--stk) =(INT32U)0x08080808; /* r8 Argument register */ + *(--stk) =(INT32U)0x07070707; /* r7 Argument register */ + *(--stk) =(INT32U)p_arg ; /* r6 Argument register */ + *(--stk) =(INT32U)0x02020202; /* r2 */ + *(--stk) =(INT32U)0x01010101; /* r1 Assembler-reserved.Used for address generation */ + + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/V850ES/CubeSuite/os_dbg.c b/Ports/V850ES/CubeSuite/os_dbg.c new file mode 100644 index 0000000..4e40744 --- /dev/null +++ b/Ports/V850ES/CubeSuite/os_dbg.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif + diff --git a/Ports/V850ES/IAR/os_cpu.h b/Ports/V850ES/IAR/os_cpu.h new file mode 100644 index 0000000..4f9ffe2 --- /dev/null +++ b/Ports/V850ES/IAR/os_cpu.h @@ -0,0 +1,120 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850ES Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850ES +* Toolchain : IAR EWV850 v3.7x and up +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsiged 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + +/* +********************************************************************************************************* +* Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() asm("trap 0x00") + + +/* +********************************************************************************************************* +* PROTOTYPES +* +* Note(s) : (1) OS_CPU_TickInit() must be implemented by the user to initialize the timer, which will +* be used as the tick interrupt. Moreover, OS_CPU_TickHandler() must be registered in the +* proper vector address of timer that will be used as the tick. +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.S85 */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); + /* See Note # 1. */ +void OS_CPU_TickHandler (void); +void OS_CPU_TickInit (INT32U tick_per_sec); +#endif diff --git a/Ports/V850ES/IAR/os_cpu_a.inc b/Ports/V850ES/IAR/os_cpu_a.inc new file mode 100644 index 0000000..7511267 --- /dev/null +++ b/Ports/V850ES/IAR/os_cpu_a.inc @@ -0,0 +1,256 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850ES Port +; +; Filename : os_cpu_a.inc +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850ES +; Toolchain : IAR EWV850 v3.7x and up +;******************************************************************************************************** + + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + EXTERN OSTCBCur + EXTERN OSIntNesting + EXTERN OSIntExit + + +;******************************************************************************************************** +; EQUATES +;******************************************************************************************************** + + ; PROGRAM REGISTER STACK OFFSET +STK_OFFSET_R1 EQU 0 +STK_OFFSET_R2 EQU STK_OFFSET_R1 + 4 +STK_OFFSET_R5 EQU STK_OFFSET_R2 + 4 +STK_OFFSET_R6 EQU STK_OFFSET_R5 + 4 +STK_OFFSET_R7 EQU STK_OFFSET_R6 + 4 +STK_OFFSET_R8 EQU STK_OFFSET_R7 + 4 +STK_OFFSET_R9 EQU STK_OFFSET_R8 + 4 +STK_OFFSET_R10 EQU STK_OFFSET_R9 + 4 +STK_OFFSET_R11 EQU STK_OFFSET_R10 + 4 +STK_OFFSET_R12 EQU STK_OFFSET_R11 + 4 +STK_OFFSET_R13 EQU STK_OFFSET_R12 + 4 +STK_OFFSET_R14 EQU STK_OFFSET_R13 + 4 +STK_OFFSET_R15 EQU STK_OFFSET_R14 + 4 +STK_OFFSET_R16 EQU STK_OFFSET_R15 + 4 +STK_OFFSET_R17 EQU STK_OFFSET_R16 + 4 +STK_OFFSET_R18 EQU STK_OFFSET_R17 + 4 +STK_OFFSET_R19 EQU STK_OFFSET_R18 + 4 +STK_OFFSET_R20 EQU STK_OFFSET_R19 + 4 +STK_OFFSET_R21 EQU STK_OFFSET_R20 + 4 +STK_OFFSET_R22 EQU STK_OFFSET_R21 + 4 +STK_OFFSET_R23 EQU STK_OFFSET_R22 + 4 +STK_OFFSET_R24 EQU STK_OFFSET_R23 + 4 +STK_OFFSET_R26 EQU STK_OFFSET_R24 + 4 +STK_OFFSET_R27 EQU STK_OFFSET_R26 + 4 +STK_OFFSET_R28 EQU STK_OFFSET_R27 + 4 +STK_OFFSET_R29 EQU STK_OFFSET_R28 + 4 +STK_OFFSET_R31 EQU STK_OFFSET_R29 + 4 + ; SYSTEM REGISTER STACK OFFSET +STK_OFFSET_EIPC EQU STK_OFFSET_R31 + 4 +STK_OFFSET_EIPSW EQU STK_OFFSET_EIPC + 4 + +STK_CTX_SIZE EQU STK_OFFSET_EIPSW + 4 + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + + +;******************************************************************************************************** +; OS_CTX_SAVE +; +; Description : This MACRO saves the CPU registers (i.e. CPU context) onto the current task's stack using +; the same order as they were saved in OSTaskStkInit(). +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; SAVE PROCESSOR REGISTER +OS_CTX_SAVE MACRO REG_SP + addi -STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer + + st.w r1, STK_OFFSET_R1[REG_SP] + st.w r2, STK_OFFSET_R2[REG_SP] + st.w r5, STK_OFFSET_R5[REG_SP] + st.w r6, STK_OFFSET_R6[REG_SP] + st.w r7, STK_OFFSET_R7[REG_SP] + st.w r8, STK_OFFSET_R8[REG_SP] + st.w r9, STK_OFFSET_R9[REG_SP] + st.w r10, STK_OFFSET_R10[REG_SP] + st.w r11, STK_OFFSET_R11[REG_SP] + st.w r12, STK_OFFSET_R12[REG_SP] + st.w r13, STK_OFFSET_R13[REG_SP] + st.w r14, STK_OFFSET_R14[REG_SP] + st.w r15, STK_OFFSET_R15[REG_SP] + st.w r16, STK_OFFSET_R16[REG_SP] + st.w r17, STK_OFFSET_R17[REG_SP] + st.w r18, STK_OFFSET_R18[REG_SP] + st.w r19, STK_OFFSET_R19[REG_SP] + st.w r20, STK_OFFSET_R20[REG_SP] + st.w r21, STK_OFFSET_R21[REG_SP] + st.w r22, STK_OFFSET_R22[REG_SP] + st.w r23, STK_OFFSET_R23[REG_SP] + st.w r24, STK_OFFSET_R24[REG_SP] + st.w r26, STK_OFFSET_R26[REG_SP] + st.w r27, STK_OFFSET_R27[REG_SP] + st.w r28, STK_OFFSET_R28[REG_SP] + st.w r29, STK_OFFSET_R29[REG_SP] + st.w r31, STK_OFFSET_R31[REG_SP] + + stsr EIPC, r2 + st.w r2, STK_OFFSET_EIPC[REG_SP] ; Restore task's EIPC + + stsr EIPSW, r2 + st.w r2, STK_OFFSET_EIPSW[REG_SP] ; Restore task's EIPSW + ENDM + + +;******************************************************************************************************** +; OS_CTX_RESTORE +; +; Description : This MACRO restores the CPU registers (i.e. context) from the new task's stack in the +; reverse order of OS_CTX_SAVE (see above) +; +; Note(s) : 1) The assembler-reserved register (r1) is used as a temporary register when instruction +; expansion is performed using the assembler. If r1 is specified as a source or +; destination register, the assembler outputs a warning message; which can be suppressed +; with the following syntax: +; $NOWARNING +; r1 used as source/destination register +; $WARNING +;******************************************************************************************************** + + ; RESTORE PROCESSOR REGISTER +OS_CTX_RESTORE MACRO REG_SP + ld.w STK_OFFSET_R1[REG_SP] , r1 + ld.w STK_OFFSET_R5[REG_SP] , r5 + ld.w STK_OFFSET_R6[REG_SP] , r6 + ld.w STK_OFFSET_R7[REG_SP] , r7 + ld.w STK_OFFSET_R8[REG_SP] , r8 + ld.w STK_OFFSET_R9[REG_SP] , r9 + ld.w STK_OFFSET_R10[REG_SP], r10 + ld.w STK_OFFSET_R11[REG_SP], r11 + ld.w STK_OFFSET_R12[REG_SP], r12 + ld.w STK_OFFSET_R13[REG_SP], r13 + ld.w STK_OFFSET_R14[REG_SP], r14 + ld.w STK_OFFSET_R15[REG_SP], r15 + ld.w STK_OFFSET_R16[REG_SP], r16 + ld.w STK_OFFSET_R17[REG_SP], r17 + ld.w STK_OFFSET_R18[REG_SP], r18 + ld.w STK_OFFSET_R19[REG_SP], r19 + ld.w STK_OFFSET_R20[REG_SP], r20 + ld.w STK_OFFSET_R21[REG_SP], r21 + ld.w STK_OFFSET_R22[REG_SP], r22 + ld.w STK_OFFSET_R23[REG_SP], r23 + ld.w STK_OFFSET_R24[REG_SP], r24 + ld.w STK_OFFSET_R26[REG_SP], r26 + ld.w STK_OFFSET_R27[REG_SP], r27 + ld.w STK_OFFSET_R28[REG_SP], r28 + ld.w STK_OFFSET_R29[REG_SP], r29 + ld.w STK_OFFSET_R31[REG_SP], r31 + + ld.w STK_OFFSET_EIPSW[REG_SP], r2 ; Restore task's EIPSW + ldsr r2, EIPSW + + ld.w STK_OFFSET_EIPC[REG_SP], r2 ; Restore task's EIPC + ldsr r2, EIPC + + ld.w STK_OFFSET_R2[REG_SP] , r2 + + addi STK_CTX_SIZE, REG_SP, REG_SP ; Adjust the Stack Pointer + ENDM + + +;******************************************************************************************************** +; OS_ISR_ENTER +; +; Description : Interrupt service routine prologue for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_ENTER +; OS_CTX_SAVE ; Call the macro: OS_CTX_SAVE +; OSIntNesting++; +; if (OSIntNestingCtr == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; +; This MACRO is to be used by your assembly language based ISRs as follows: +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_ISR_ENTER MACRO + OS_CTX_SAVE sp ; Save processor registers on the stack + + mov OSIntNesting, r11 ; OSIntNesting++; + ld.b 0[r11], r2 + add 0x1, r2 + st.b r2, 0[r11] + + cmp 0x1, r2 + bne b ; if (OSIntNesting == 1) { + + mov OSTCBCur, r11 ; OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] ; } + +b: + ENDM + + +;******************************************************************************************************** +; OS_ISR_EXIT +; +; Description : Interrupt service routine epilog for kernel-aware handler. +; This macro implements the following code in assembly language: +; +; OS_ISR_EXIT: +; OSIntExit(); ; Call the C function: OSIntExit(); +; OS_CTX_RESTORE ; Call the macro: OS_CTX_RESTORE +; Return from interrupt ; CPU instruction to return from interrupt/exception +;******************************************************************************************************** + +OS_ISR_EXIT MACRO + jarl OSIntExit, lp ; Call 'OSIntExit()' + + OS_CTX_RESTORE sp ; Restore processor registers from stack + reti ; CPU instruction to return from Interrupt/exception + + ENDM + + +;******************************************************************************************************** +; ASSEMBLY LANGUAGE MACROS FILE END +;******************************************************************************************************** + diff --git a/Ports/V850ES/IAR/os_cpu_a.s85 b/Ports/V850ES/IAR/os_cpu_a.s85 new file mode 100644 index 0000000..c0dbaf2 --- /dev/null +++ b/Ports/V850ES/IAR/os_cpu_a.s85 @@ -0,0 +1,250 @@ +;******************************************************************************************************** +; uC/OS-II +; The Real-Time Kernel +; +; Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +; +; SPDX-License-Identifier: APACHE-2.0 +; +; This software is subject to an open source license and is distributed by +; Silicon Laboratories Inc. pursuant to the terms of the Apache License, +; Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +; +;******************************************************************************************************** + +;******************************************************************************************************** +; +; Renesas V850ES Port +; +; Filename : os_cpu_a.s85 +; Version : V2.93.00 +;******************************************************************************************************** +; For : Renesas V850ES +; Toolchain : IAR EWV850 v3.7x and up +;******************************************************************************************************** + + +#include "os_cpu_a.inc" + +;******************************************************************************************************** +; PUBLIC FUNCTIONS +;******************************************************************************************************** + + ; External References + EXTERN OSRunning + EXTERN OSPrioCur + EXTERN OSPrioHighRdy + EXTERN OSTCBCur + EXTERN OSTCBHighRdy + EXTERN OSTaskSwHook + EXTERN OSTimeTick + + ; Functions declared in this file + PUBLIC OS_CPU_SR_Save + PUBLIC OS_CPU_SR_Restore + PUBLIC OS_CPU_TickHandler + PUBLIC OSStartHighRdy + PUBLIC OSIntCtxSw + PUBLIC OSCtxSw + +;******************************************************************************************************** +; INTERRUPT VECTOR ENTRY FOR TRAP 00 +;******************************************************************************************************** + + COMMON INTVEC:CODE:ROOT(2) + ORG 0x040 ; TRAP interrupt vector 00 +TRAP_INT40: + jr OSCtxSw + +;******************************************************************************************************** +; CODE GENERATION DIRECTIVES +;******************************************************************************************************** + + RSEG CODE:CODE:NOROOT(2) + + +;******************************************************************************************************** +; CRITICAL SECTION METHOD 3 FUNCTIONS +; +; Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +; would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +; disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +; disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +; into the CPU's status register. +; +; Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +; void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +; +; +; Note(s) : (1) These functions are used in general like this: +; +; void Task (void *p_arg) +; { +; /* Allocate storage for CPU status register. */ +; #if (OS_CRITICAL_METHOD == 3) +; OS_CPU_SR os_cpu_sr; +; #endif +; +; : +; : +; OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +; : +; : +; OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +; : +; : +; } +;******************************************************************************************************** + +OS_CPU_SR_Save: + stsr PSW, r1 ; Save PSW + di ; Disable interrupts + jmp [lp] + +OS_CPU_SR_Restore: + ldsr r1, PSW ; Restore PSW + jmp [lp] + +;******************************************************************************************************** +; START MULTITASKING +; void OSStartHighRdy(void) +; +; Note(s) : 1) OSStartHighRdy() MUST: +; a) Call OSTaskSwHook() then, +; b) Set OSRunning to TRUE, +; c) Switch to the highest priority task. +; +;******************************************************************************************************** + +OSStartHighRdy: + jarl OSTaskSwHook, lp ; Call OSTaskSwHook(); + + mov 0x01 , r2 ; OSRunning = TRUE; + mov OSRunning, r11 + st.b r2 , 0[r11] + + mov OSTCBHighRdy, r11 ; SWITCH TO HIGHEST PRIORITY TASK: + ld.w 0[r11] , r11 + ld.w 0[r11] , sp + + OS_CTX_RESTORE sp ; Restore Task Context + + reti + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +; +; Note(s) : 1) The pseudo-code for OSCtxSw() is: +; a) Save the current task's context onto the current task's stack, +; b) OSTCBCur->OSTCBStkPtr = sp; +; c) OSTaskSwHook(); +; d) OSPrioCur = OSPrioHighRdy; +; e) OSTCBCur = OSTCBHighRdy; +; f) SP = OSTCBHighRdy->OSTCBStkPtr; +; g) Restore the new task's context from the new task's stack, +; h) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSCtxSw: + OS_CTX_SAVE sp ; Save current Task context + + mov OSTCBCur, r11 ; OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] + + jarl OSTaskSwHook, lp ; OSTaskSwHook(); + + mov OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov OSPrioCur , r11 + st.b r12 , 0[r11] + + mov OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp ; Restore new Task's context + + reti ; return from trap + +;******************************************************************************************************** +; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +; +; Note(s) : 1) The pseudo-code for OSIntCtxSw() is: +; a) OSTaskSwHook(); +; b) OSPrioCur = OSPrioHighRdy; +; c) OSTCBCur = OSTCBHighRdy; +; d) SP = OSTCBHighRdy->OSTCBStkPtr; +; e) Restore the new task's context from the new task's stack, +; f) Return to new task's code. +; +; 2) Upon entry: +; OSTCBCur points to the OS_TCB of the task to suspend, +; OSTCBHighRdy points to the OS_TCB of the task to resume. +;******************************************************************************************************** + +OSIntCtxSw: + jarl OSTaskSwHook, lp ; OSTaskSwHook(); + + mov OSPrioHighRdy, r11 ; OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov OSPrioCur , r11 + st.b r12 , 0[r11] + + mov OSTCBHighRdy, r11 ; OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp ; SP = OSTCBHighRdy->OSTCBStkPtr; + + OS_CTX_RESTORE sp + + reti ; Return from interrupt starts new task + + +;******************************************************************************************************** +; OS_CPU_TickHandler +; +; Note(s) : 1) The pseudo-code for _OS_CPU_TickHandler() is: +; a) Save processor registers; +; b) Increment OSIntNesting; +; c) if (OSIntNesting == 1) { +; OSTCBCur->OSTCBStkPtr = SP; +; } +; d) Call OSTimeTick(); +; e) Call OSIntExit(); +; f) Restore processosr Registers; +; +; 2) OS_CPU_TickHandler() must be registered in the proper vector address of timer that will be +; used as the tick. +; +; 3) All the other ISRs must have the following implementation to secure proper register saving & +; restoring when servicing an interrupt +; +; MyISR +; OS_ISR_ENTER +; ISR Body here +; OS_ISR_EXIT +;******************************************************************************************************** + +OS_CPU_TickHandler: + OS_ISR_ENTER + + jarl OSTimeTick, lp ; Call OSTimeTick(); + + OS_ISR_EXIT + + +;******************************************************************************************************** +; OS CPU ASSEMBLY PORT FILE END +;******************************************************************************************************** + + END diff --git a/Ports/V850ES/IAR/os_cpu_c.c b/Ports/V850ES/IAR/os_cpu_c.c new file mode 100644 index 0000000..e3121f4 --- /dev/null +++ b/Ports/V850ES/IAR/os_cpu_c.c @@ -0,0 +1,344 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850ES Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850ES +* Toolchain : IAR EWV850 v3.7x and up +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define V850ES_EIPSW_EN 0x00000000u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in Thread mode, using process stack. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + opt = opt; /* 'opt' is not used, prevent warning. */ + stk = ptos; /* Load stack pointer. */ + *(stk) =(INT32U)V850ES_EIPSW_EN; /* EIPSW interrupt enable */ + *(--stk) =(INT32U)task; /* EIPC */ + *(--stk) =(INT32U)OS_TaskReturn; /* r31 Link Pointer (LP). to pass return address of function */ + *(--stk) =(INT32U)0x29292929; /* r29 */ + *(--stk) =(INT32U)0x28282828; /* r28 */ + *(--stk) =(INT32U)0x27272727; /* r27 */ + *(--stk) =(INT32U)0x26262626; /* r26 */ + *(--stk) =(INT32U)0x24242424; /* r24 */ + *(--stk) =(INT32U)0x23232323; /* r23 */ + *(--stk) =(INT32U)0x22222222; /* r22 */ + *(--stk) =(INT32U)0x21212121; /* r21 */ + *(--stk) =(INT32U)0x20202020; /* r20 */ + *(--stk) =(INT32U)0x19191919; /* r19 */ + *(--stk) =(INT32U)0x18181818; /* r18 */ + *(--stk) =(INT32U)0x17171717; /* r17 */ + *(--stk) =(INT32U)0x16161616; /* r16 */ + *(--stk) =(INT32U)0x15151515; /* r15 */ + *(--stk) =(INT32U)0x14141414; /* r14 */ + *(--stk) =(INT32U)0x13131313; /* r13 */ + *(--stk) =(INT32U)0x12121212; /* r12 */ + *(--stk) =(INT32U)0x11111111; /* r11 */ + *(--stk) =(INT32U)0x10101010; /* r10 */ + *(--stk) =(INT32U)0x09090909; /* r9 */ + *(--stk) =(INT32U)0x08080808; /* r8 */ + *(--stk) =(INT32U)0x07070707; /* r7 */ + *(--stk) =(INT32U)0x06060606; /* r6 */ + *(--stk) =(INT32U)0x05050505; /* r5 */ + *(--stk) =(INT32U)0x02020202; /* r2 */ + *(--stk) =(INT32U)p_arg; /* r1 Argument register/ return value */ + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/V850ES/IAR/os_dbg.c b/Ports/V850ES/IAR/os_dbg.c new file mode 100644 index 0000000..4e40744 --- /dev/null +++ b/Ports/V850ES/IAR/os_dbg.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif + diff --git a/Ports/V850ES/PM+/os_cpu.h b/Ports/V850ES/PM+/os_cpu.h new file mode 100644 index 0000000..2f752db --- /dev/null +++ b/Ports/V850ES/PM+/os_cpu.h @@ -0,0 +1,122 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850ES Port +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850ES +* Toolchain : PM+ v6.32 +* CA850 v3.44 compiler +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned short INT16U; /* Unsigned 16 bit quantity */ +typedef signed short INT16S; /* Signed 16 bit quantity */ +typedef unsigned int INT32U; /* Unsiged 32 bit quantity */ +typedef signed int INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ +typedef unsigned short OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* NOT IMPLEMENTED +* +* Method #3: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +* would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +* disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +* disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +* into the CPU's status register. +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#if OS_CRITICAL_METHOD == 1u +#define OS_ENTER_CRITICAL() __DI() /* Disable Interrupts */ +#define OS_EXIT_CRITICAL() __EI() /* Enable Interrupts */ +#endif + +#if OS_CRITICAL_METHOD == 3u +#define OS_ENTER_CRITICAL() {cpu_sr = OS_CPU_SR_Save();} +#define OS_EXIT_CRITICAL() {OS_CPU_SR_Restore(cpu_sr);} +#endif + +/* +********************************************************************************************************* +* Miscellaneous +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1u /* Stack growth (0 == Up. 1 == Down) */ +#define OS_TASK_SW() __asm("trap 0x00") + +/* +********************************************************************************************************* +* PROTOTYPES +* +* Note(s) : (1) OS_CPU_IntHandlerSrc() must be implemented to handle maskable interrupts according to +* the exception code provided by the System Register ECR. +********************************************************************************************************* +*/ + +#if OS_CRITICAL_METHOD == 3u /* See OS_CPU_A.ASM */ +OS_CPU_SR OS_CPU_SR_Save (void); +void OS_CPU_SR_Restore (OS_CPU_SR cpu_sr); +#endif + +void OSCtxSw (void); +void OSIntCtxSw (void); +void OSStartHighRdy (void); +void OS_CPU_IntHandler (void); +void OS_CPU_IntHandlerSrc (INT32U src_id); /* See Note # 1. */ +#endif diff --git a/Ports/V850ES/PM+/os_cpu_a.s b/Ports/V850ES/PM+/os_cpu_a.s new file mode 100644 index 0000000..f4636e2 --- /dev/null +++ b/Ports/V850ES/PM+/os_cpu_a.s @@ -0,0 +1,394 @@ +#******************************************************************************************************** +# uC/OS-II +# The Real-Time Kernel +# +# Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +# +# SPDX-License-Identifier: APACHE-2.0 +# +# This software is subject to an open source license and is distributed by +# Silicon Laboratories Inc. pursuant to the terms of the Apache License, +# Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +# +#******************************************************************************************************** + +#******************************************************************************************************** +# +# Renesas V850ES Port +# +# Filename : os_cpu_a.s +# Version : V2.93.00 +#******************************************************************************************************** +# For : Renesas V850ES +# Toolchain : PM+ v6.32 +# CA850 v3.44 compiler +#******************************************************************************************************** + +#******************************************************************************************************** +# PUBLIC FUNCTIONS +#******************************************************************************************************** + -- External References + .extern _OSRunning + .extern _OSPrioCur + .extern _OSPrioHighRdy + .extern _OSTCBCur + .extern _OSTCBHighRdy + .extern _OSTaskSwHook + .extern _OSIntNesting + .extern _OSIntExit + .extern _OS_CPU_IntHandlerSrc + -- Functions declared in this file + .globl _OS_CPU_SR_Save + .globl _OS_CPU_SR_Restore + .globl _OS_CPU_IntHandler + .globl _OSStartHighRdy + .globl _OSIntCtxSw + .globl _OSCtxSw + +#******************************************************************************************************** +# EQUATES +#******************************************************************************************************** + + -- SYSTEM REGISTER + .set EIPC , 0 + .set EIPSW, 1 + .set ECR , 4 + .set PSW , 5 + .set CTPC , 16 + .set CTPSW, 17 + + -- PROGRAM REGISTER STACK OFFSET + .set STK_OFFSET_R1 , 0 + .set STK_OFFSET_R2 , STK_OFFSET_R1 + 4 + .set STK_OFFSET_R6 , STK_OFFSET_R2 + 4 + .set STK_OFFSET_R7 , STK_OFFSET_R6 + 4 + .set STK_OFFSET_R8 , STK_OFFSET_R7 + 4 + .set STK_OFFSET_R9 , STK_OFFSET_R8 + 4 + .set STK_OFFSET_R10 , STK_OFFSET_R9 + 4 + .set STK_OFFSET_R11 , STK_OFFSET_R10 + 4 + .set STK_OFFSET_R12 , STK_OFFSET_R11 + 4 + .set STK_OFFSET_R13 , STK_OFFSET_R12 + 4 + .set STK_OFFSET_R14 , STK_OFFSET_R13 + 4 + .set STK_OFFSET_R15 , STK_OFFSET_R14 + 4 + .set STK_OFFSET_R16 , STK_OFFSET_R15 + 4 + .set STK_OFFSET_R17 , STK_OFFSET_R16 + 4 + .set STK_OFFSET_R18 , STK_OFFSET_R17 + 4 + .set STK_OFFSET_R19 , STK_OFFSET_R18 + 4 + .set STK_OFFSET_R20 , STK_OFFSET_R19 + 4 + .set STK_OFFSET_R21 , STK_OFFSET_R20 + 4 + .set STK_OFFSET_R22 , STK_OFFSET_R21 + 4 + .set STK_OFFSET_R23 , STK_OFFSET_R22 + 4 + .set STK_OFFSET_R24 , STK_OFFSET_R23 + 4 + .set STK_OFFSET_R25 , STK_OFFSET_R24 + 4 + .set STK_OFFSET_R26 , STK_OFFSET_R25 + 4 + .set STK_OFFSET_R27 , STK_OFFSET_R26 + 4 + .set STK_OFFSET_R28 , STK_OFFSET_R27 + 4 + .set STK_OFFSET_R29 , STK_OFFSET_R28 + 4 + .set STK_OFFSET_R30 , STK_OFFSET_R29 + 4 + .set STK_OFFSET_R31 , STK_OFFSET_R30 + 4 + .set STK_OFFSET_EIPC , STK_OFFSET_R31 + 4 + -- SYSTEM REGISTER STACK OFFSET + .set STK_OFFSET_EIPSW, STK_OFFSET_EIPC + 4 + .set STK_OFFSET_CTPC , STK_OFFSET_EIPSW + 4 + .set STK_OFFSET_CTPSW, STK_OFFSET_CTPC + 4 + .set STK_CTX_SIZE , STK_OFFSET_CTPSW + 4 + +#******************************************************************************************************** +# INTERRUPT VECTOR ENTRY FOR TRAP 00 +#******************************************************************************************************** + + .section "TRAP00", text -- TRAP instruction for Context Switching + .globl __trap00 +__trap00: + jr _OSCtxSw + +#******************************************************************************************************** +# CODE GENERATION DIRECTIVES +#******************************************************************************************************** + + .text + .align 4 + +#******************************************************************************************************** +# MACRO DEFINITIONS +#******************************************************************************************************** + + -- RESTORE PROCESSOR REGISTER +.macro POPALL SP + ld.w STK_OFFSET_R1[SP] , r1 + ld.w STK_OFFSET_R6[SP] , r6 + ld.w STK_OFFSET_R7[SP] , r7 + ld.w STK_OFFSET_R8[SP] , r8 + ld.w STK_OFFSET_R9[SP] , r9 + ld.w STK_OFFSET_R10[SP], r10 + ld.w STK_OFFSET_R11[SP], r11 + ld.w STK_OFFSET_R12[SP], r12 + ld.w STK_OFFSET_R13[SP], r13 + ld.w STK_OFFSET_R14[SP], r14 + ld.w STK_OFFSET_R15[SP], r15 + ld.w STK_OFFSET_R16[SP], r16 + ld.w STK_OFFSET_R17[SP], r17 + ld.w STK_OFFSET_R18[SP], r18 + ld.w STK_OFFSET_R19[SP], r19 + ld.w STK_OFFSET_R20[SP], r20 + ld.w STK_OFFSET_R21[SP], r21 + ld.w STK_OFFSET_R22[SP], r22 + ld.w STK_OFFSET_R23[SP], r23 + ld.w STK_OFFSET_R24[SP], r24 + ld.w STK_OFFSET_R25[SP], r25 + ld.w STK_OFFSET_R26[SP], r26 + ld.w STK_OFFSET_R27[SP], r27 + ld.w STK_OFFSET_R28[SP], r28 + ld.w STK_OFFSET_R29[SP], r29 + ld.w STK_OFFSET_R30[SP], r30 + ld.w STK_OFFSET_R31[SP], r31 + + ld.w STK_OFFSET_EIPSW[SP], r2 -- Restore task's EIPSW + ldsr r2, EIPSW + + ld.w STK_OFFSET_EIPC[SP], r2 -- Restore task's EIPC + ldsr r2, EIPC + + ld.w STK_OFFSET_CTPC[SP], r2 -- Restore task's CTPC + ldsr r2, CTPC + + ld.w STK_OFFSET_CTPSW[SP], r2 -- Restore task's CTPSW + ldsr r2, CTPSW + + ld.w STK_OFFSET_R2[SP] , r2 + + addi STK_CTX_SIZE, SP, SP -- Adjust the Stack Pointer +.endm + + -- SAVE PROCESSOR REGISTER +.macro PUSHALL SP + addi -STK_CTX_SIZE, SP, SP -- Adjust the Stack Pointer + + st.w r1, STK_OFFSET_R1[SP] + st.w r2, STK_OFFSET_R2[SP] + st.w r6, STK_OFFSET_R6[SP] + st.w r7, STK_OFFSET_R7[SP] + st.w r8, STK_OFFSET_R8[SP] + st.w r9, STK_OFFSET_R9[SP] + st.w r10, STK_OFFSET_R10[SP] + st.w r11, STK_OFFSET_R11[SP] + st.w r12, STK_OFFSET_R12[SP] + st.w r13, STK_OFFSET_R13[SP] + st.w r14, STK_OFFSET_R14[SP] + st.w r15, STK_OFFSET_R15[SP] + st.w r16, STK_OFFSET_R16[SP] + st.w r17, STK_OFFSET_R17[SP] + st.w r18, STK_OFFSET_R18[SP] + st.w r19, STK_OFFSET_R19[SP] + st.w r20, STK_OFFSET_R20[SP] + st.w r21, STK_OFFSET_R21[SP] + st.w r22, STK_OFFSET_R22[SP] + st.w r23, STK_OFFSET_R23[SP] + st.w r24, STK_OFFSET_R24[SP] + st.w r25, STK_OFFSET_R25[SP] + st.w r26, STK_OFFSET_R26[SP] + st.w r27, STK_OFFSET_R27[SP] + st.w r28, STK_OFFSET_R28[SP] + st.w r29, STK_OFFSET_R29[SP] + st.w r30, STK_OFFSET_R30[SP] + st.w r31, STK_OFFSET_R31[SP] + + stsr EIPC, r2 + st.w r2, STK_OFFSET_EIPC[SP] -- Restore task's EIPC + + stsr EIPSW, r2 + st.w r2, STK_OFFSET_EIPSW[SP] -- Restore task's EIPSW + + stsr CTPC, r2 + st.w r2, STK_OFFSET_CTPC[SP] -- Restore task's CTPC + + stsr CTPSW, r2 + st.w r2, STK_OFFSET_CTPSW[SP] -- Restore task's CTPSW +.endm + +#******************************************************************************************************** +# CRITICAL SECTION METHOD 3 FUNCTIONS +# +# Description: Disable/Enable interrupts by preserving the state of interrupts. Generally speaking you +# would store the state of the interrupt disable flag in the local variable 'cpu_sr' and then +# disable interrupts. 'cpu_sr' is allocated in all of uC/OS-II's functions that need to +# disable interrupts. You would restore the interrupt disable state by copying back 'cpu_sr' +# into the CPU's status register. +# +# Prototypes : OS_CPU_SR OS_CPU_SR_Save (void); +# void OS_CPU_SR_Restore (OS_CPU_SR os_cpu_sr); +# +# +# Note(s) : (1) These functions are used in general like this: +# +# void Task (void *p_arg) +# { +# /* Allocate storage for CPU status register. */ +# #if (OS_CRITICAL_METHOD == 3) +# OS_CPU_SR os_cpu_sr; +# #endif +# +# : +# : +# OS_ENTER_CRITICAL(); /* os_cpu_sr = OS_CPU_SR_Save(); */ +# : +# : +# OS_EXIT_CRITICAL(); /* OS_CPU_SR_Restore(cpu_sr); */ +# : +# : +# } +#******************************************************************************************************** + +_OS_CPU_SR_Save: + stsr PSW, r10 -- Save PSW + di -- Disable interrupts + jmp [lp] + +_OS_CPU_SR_Restore: + ldsr r6, PSW -- Restore PSW + jmp [lp] + +#******************************************************************************************************** +# START MULTITASKING +# void OSStartHighRdy(void) +# +# Note(s) : 1) OSStartHighRdy() MUST: +# a) Call OSTaskSwHook() then, +# b) Set OSRunning to TRUE, +# c) Switch to the highest priority task. +# +#******************************************************************************************************** + +_OSStartHighRdy: + jarl _OSTaskSwHook, lp -- Call OSTaskSwHook(); + + mov 0x01, r2 -- OSRunning = TRUE; + st.b r2 , #_OSRunning[r0] + + mov #_OSTCBHighRdy, r11 -- SWITCH TO HIGHEST PRIORITY TASK: + ld.w 0[r11] , r11 + ld.w 0[r11] , sp + + POPALL sp -- Restore Task Context + + reti + +#******************************************************************************************************** +# PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw() +# +# Note(s) : 1) The pseudo-code for OSCtxSw() is: +# a) Save the current task's context onto the current task's stack, +# b) OSTCBCur->OSTCBStkPtr = sp; +# c) OSTaskSwHook(); +# d) OSPrioCur = OSPrioHighRdy; +# e) OSTCBCur = OSTCBHighRdy; +# f) SP = OSTCBHighRdy->OSTCBStkPtr; +# g) Restore the new task's context from the new task's stack, +# h) Return to new task's code. +# +# 2) Upon entry: +# OSTCBCur points to the OS_TCB of the task to suspend, +# OSTCBHighRdy points to the OS_TCB of the task to resume. +#******************************************************************************************************** + +_OSCtxSw: + PUSHALL sp -- Save current Task context + + mov #_OSTCBCur, r11 -- OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] + + jarl _OSTaskSwHook, lp -- OSTaskSwHook(); + + mov #_OSPrioHighRdy, r11 -- OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov #_OSPrioCur , r11 + st.b r12 , 0[r11] + + mov #_OSTCBHighRdy, r11 -- OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov #_OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp -- SP = OSTCBHighRdy->OSTCBStkPtr; + + POPALL sp -- Restore new Task's context + + reti -- return from trap + +#******************************************************************************************************** +# PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw() +# +# Note(s) : 1) The pseudo-code for OSIntCtxSw() is: +# a) OSTaskSwHook(); +# b) OSPrioCur = OSPrioHighRdy; +# c) OSTCBCur = OSTCBHighRdy; +# d) SP = OSTCBHighRdy->OSTCBStkPtr; +# e) Restore the new task's context from the new task's stack, +# f) Return to new task's code. +# +# 2) Upon entry: +# OSTCBCur points to the OS_TCB of the task to suspend, +# OSTCBHighRdy points to the OS_TCB of the task to resume. +#******************************************************************************************************** + +_OSIntCtxSw: + jarl _OSTaskSwHook, lp -- OSTaskSwHook(); + + mov #_OSPrioHighRdy, r11 -- OSPrioCur = OSPrioHighRdy; + ld.b 0[r11] , r12 + mov #_OSPrioCur , r11 + st.b r12 , 0[r11] + + mov #_OSTCBHighRdy, r11 -- OSTCBCur = OSTCBHighRdy; + ld.w 0[r11] , r12 + mov #_OSTCBCur , r11 + st.w r12 , 0[r11] + + ld.w 0[r12], sp -- SP = OSTCBHighRdy->OSTCBStkPtr; + + POPALL sp + + reti -- Return from interrupt starts new task + +#******************************************************************************************************** +# INTERRUPT/EXCEPTION HANDLER +# +# Note(s) : 1) The pseudo-code for OS_CPU_IntHandler() is: +# a) Save processor registers; +# b) Increment OSIntNesting; +# c) if (OSIntNesting == 1) { +# OSTCBCur->OSTCBStkPtr = SP; +# } +# d) Call OSIntExit(); +# e) Call OS_CPU_IntHandlerSrc(); +# f) Restore processosr Registers; +# +# 2) OS_CPU_IntHandlerSrc() must be implemented to handle maskable interrupts according to +# to exception code provided by the system register ECR. +# +#******************************************************************************************************** + +_OS_CPU_IntHandler: + PUSHALL sp -- Saves Processor registers + + ld.b #_OSIntNesting[r0], r2 -- increment OSIntNesting + add 0x1, r2 + st.b r2, #_OSIntNesting[r0] + + cmp 0x1, r2 + bne _OS_CPU_IntHandler01 -- if (OSIntNesting == 1) { + + mov #_OSTCBCur, r11 -- OSTCBCur->OSTCBStkPtr = SP; + ld.w 0[r11] , r11 + st.w sp , 0[r11] -- } + +_OS_CPU_IntHandler01: + stsr ECR, r6 -- get interrupt/exception source code that occured. + jarl _OS_CPU_IntHandlerSrc, lp + + jarl _OSIntExit, lp + + POPALL sp -- Restore processor register + + reti diff --git a/Ports/V850ES/PM+/os_cpu_c.c b/Ports/V850ES/PM+/os_cpu_c.c new file mode 100644 index 0000000..aa72bf7 --- /dev/null +++ b/Ports/V850ES/PM+/os_cpu_c.c @@ -0,0 +1,352 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Renesas V850ES Port +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +* For : Renesas V850ES +* Toolchain : PM+ v6.32 +* CA850 v3.44 compiler +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define V850ES_EIPSW_EN 0x00000000u +#define V850ES_CTPC 0x00000000u +#define V850ES_CTPSW 0x00000000u + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0 +static INT16U OSTmrCtr; +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookBegin (void) +{ +#if(OS_TMR_EN > 0) + OSTmrCtr = 0; +#endif +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSInitHookEnd (void) +{ +} +#endif + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskCreateHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskCreateHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskDelHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskDelHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTaskIdleHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskIdleHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : ptcb is a pointer to the task control block of the task that is returning. +* +* Note(s) : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskReturnHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskReturnHook(ptcb); +#else + (void)ptcb; +#endif +} +#endif + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ + +#if OS_CPU_HOOKS_EN > 0u +void OSTaskStatHook (void) +{ +#if OS_APP_HOOKS_EN > 0 + App_TaskStatHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* p_arg is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_xxx). +* +* Returns : Always returns the location of the new top-of-stack once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* 2) All tasks run in Thread mode, using process stack. +* +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_STK *stk; + + + + opt = opt; /* 'opt' is not used, prevent warning. */ + stk = ptos; /* Load stack pointer. */ + *(stk) =(INT32U)V850ES_CTPSW; /* CTPSW. */ + *(--stk) =(INT32U)V850ES_CTPC; /* CTPC. */ + *(--stk) =(INT32U)V850ES_EIPSW_EN; /* EIPSW interrupt enable */ + *(--stk) =(INT32U)task; /* EIPC */ + *(--stk) =(INT32U)OS_TaskReturn; /* r31 Link Pointer (LP). to pass return address of function */ + *(--stk) =(INT32U)0x30303030; /* r30 Element Pointer (EP). */ + *(--stk) =(INT32U)0x29292929; /* r29 Used as area for register variable */ + *(--stk) =(INT32U)0x28282828; /* r28 */ + *(--stk) =(INT32U)0x27272727; /* r27 */ + *(--stk) =(INT32U)0x26262626; /* r26 */ + *(--stk) =(INT32U)0x25252525; /* r25 */ + *(--stk) =(INT32U)0x24242424; /* r24 */ + *(--stk) =(INT32U)0x23232323; /* r23 */ + *(--stk) =(INT32U)0x22222222; /* r22 */ + *(--stk) =(INT32U)0x21212121; /* r21 */ + *(--stk) =(INT32U)0x20202020; /* r20 Used as area for register variable */ + *(--stk) =(INT32U)0x19191919; /* r19 Working register */ + *(--stk) =(INT32U)0x18181818; /* r18 Working register */ + *(--stk) =(INT32U)0x17171717; /* r17 Working register */ + *(--stk) =(INT32U)0x16161616; /* r16 Working register */ + *(--stk) =(INT32U)0x15151515; /* r15 Working register */ + *(--stk) =(INT32U)0x14141414; /* r14 Working register */ + *(--stk) =(INT32U)0x13131313; /* r13 Working register */ + *(--stk) =(INT32U)0x12121212; /* r12 Working register */ + *(--stk) =(INT32U)0x11111111; /* r11 Working register */ + *(--stk) =(INT32U)0x10101010; /* r10 Function return value */ + *(--stk) =(INT32U)0x09090909; /* r9 Argument register */ + *(--stk) =(INT32U)0x08080808; /* r8 Argument register */ + *(--stk) =(INT32U)0x07070707; /* r7 Argument register */ + *(--stk) =(INT32U)p_arg ; /* r6 Argument register */ + *(--stk) =(INT32U)0x02020202; /* r2 */ + *(--stk) =(INT32U)0x01010101; /* r1 Assembler-reserved.Used for address generation */ + + + return (stk); +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TaskSwHook(); +#endif +} +#endif + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_CPU_HOOKS_EN > 0u +void OSTCBInitHook (OS_TCB *ptcb) +{ +#if OS_APP_HOOKS_EN > 0u + App_TCBInitHook(ptcb); +#else + (void)ptcb; /* Prevent compiler warning */ +#endif +} +#endif + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if OS_APP_HOOKS_EN > 0u + App_TimeTickHook(); +#endif + +#if OS_TMR_EN > 0u + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif diff --git a/Ports/V850ES/PM+/os_dbg.c b/Ports/V850ES/PM+/os_dbg.c new file mode 100644 index 0000000..4e40744 --- /dev/null +++ b/Ports/V850ES/PM+/os_dbg.c @@ -0,0 +1,318 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif + diff --git a/Ports/Win32/Visual Studio/os_cpu.h b/Ports/Win32/Visual Studio/os_cpu.h new file mode 100644 index 0000000..4cac15d --- /dev/null +++ b/Ports/Win32/Visual Studio/os_cpu.h @@ -0,0 +1,105 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Microsoft Win32 Specific code +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CPU_H +#define OS_CPU_H + +#include + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + + +/* +********************************************************************************************************** +* DATA TYPES +********************************************************************************************************** +*/ + +typedef CPU_BOOLEAN BOOLEAN; +typedef CPU_INT08U INT8U; /* Unsigned 8 bit quantity */ +typedef CPU_INT08S INT8S; /* Signed 8 bit quantity */ +typedef CPU_INT16U INT16U; /* Unsigned 16 bit quantity */ +typedef CPU_INT16S INT16S; /* Signed 16 bit quantity */ +typedef CPU_INT32U INT32U; /* Unsigned 32 bit quantity */ +typedef CPU_INT32S INT32S; /* Signed 32 bit quantity */ +typedef CPU_FP32 FP32; /* Single precision floating point */ +typedef CPU_FP64 FP64; /* Double precision floating point */ + +typedef CPU_STK OS_STK; /* Define size of CPU stack entry */ +typedef CPU_SR OS_CPU_SR; /* Define size of CPU status register */ + + +/* +********************************************************************************************************* +* Critical Method MACROS +********************************************************************************************************* +*/ + +#define OS_CRITICAL_METHOD 3u + +#define OS_ENTER_CRITICAL() { CPU_CRITICAL_ENTER(); } +#define OS_EXIT_CRITICAL() { CPU_CRITICAL_EXIT(); } + +/* +********************************************************************************************************** +* Miscellaneous +********************************************************************************************************** +*/ + +#define OS_STK_GROWTH 1u /* Stack grows from HIGH to LOW memory on WIN32 */ + +#define OS_TASK_SW() { OSCtxSw(); } /* Perform task switch */ + +/* +********************************************************************************************************** +* Function Prototypes +********************************************************************************************************** +*/ + +void OSCtxSw (void); +void OSIntCtxSw(void); + +void OSStartHighRdy(void); + +CPU_BOOLEAN OSIntCurTaskSuspend(void); +CPU_BOOLEAN OSIntCurTaskResume (void); + +void OSDebuggerBreak(void); + +/* +********************************************************************************************************* +* MODULE END +* +* Note(s) : (1) See 'lib_def.h MODULE'. +********************************************************************************************************* +*/ + +#endif /* End of os cpu module include. */ diff --git a/Ports/Win32/Visual Studio/os_cpu_c.c b/Ports/Win32/Visual Studio/os_cpu_c.c new file mode 100644 index 0000000..7922e9e --- /dev/null +++ b/Ports/Win32/Visual Studio/os_cpu_c.c @@ -0,0 +1,1394 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Microsoft Win32 Specific code +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS + + +/* +********************************************************************************************************* +* INCLUDE FILES +********************************************************************************************************* +*/ + +#include +#include + +#define _WIN32_WINNT 0x0600 +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include + + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + +#define WIN32_SLEEP 1u +#define WIN32_MM_TMR 2u /* Use the high resolution Multimedia timer. */ + +#define TIMER_METHOD WIN32_MM_TMR + +#define WIN_MM_MIN_RES 1u /* Minimum timer resolution. */ + +#define OS_MSG_TRACE 1u /* Allow print trace messages. */ + +#ifdef _MSC_VER +#define MS_VC_EXCEPTION 0x406D1388 +#endif + + +/* +********************************************************************************************************* +* LOCAL DATA TYPES +********************************************************************************************************* +*/ + +typedef enum os_task_state { + STATE_NONE = 0, + STATE_CREATED, + STATE_RUNNING, + STATE_SUSPENDED, + STATE_INTERRUPTED, + STATE_TERMINATING, + STATE_TERMINATED +} OS_TASK_STATE; + + +typedef struct os_task_stk { + void *TaskArgPtr; + INT16U TaskOpt; + void (*Task)(void*); + HANDLE ThreadHandle; + DWORD ThreadID; + volatile OS_TASK_STATE TaskState; + HANDLE SignalPtr; /* Task synchronization signal. */ + HANDLE InitSignalPtr; /* Task created signal. */ + CPU_BOOLEAN Terminate; /* Task terminate flag. */ + OS_TCB *OSTCBPtr; +} OS_TASK_STK; + + +#ifdef _MSC_VER +#pragma pack(push,8) +typedef struct threadname_info { + DWORD dwType; /* Must be 0x1000. */ + LPCSTR szName; /* Pointer to name (in user addr space). */ + DWORD dwThreadID; /* Thread ID (-1 = caller thread). */ + DWORD dwFlags; /* Reserved for future use, must be zero. */ +} THREADNAME_INFO; +#pragma pack(pop) +#endif + + +#if (TIMER_METHOD == WIN32_MM_TMR) +#ifdef _MSC_VER +#pragma comment (lib, "winmm.lib") +#endif +#endif + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +#if (OS_VERSION >= 281u) && (OS_TMR_EN > 0u) +static INT16U OSTmrCtr; +#endif /* #if (OS_VERSION >= 281) && (OS_TMR_EN > 0) */ + +static HANDLE OSTerminate_SignalPtr; + +static HANDLE OSTick_Thread; +static DWORD OSTick_ThreadId; +#if (TIMER_METHOD == WIN32_MM_TMR) +static HANDLE OSTick_SignalPtr; +static TIMECAPS OSTick_TimerCap; +static MMRESULT OSTick_TimerId; +#endif + + +/* +********************************************************************************************************* +* LOCAL FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +static DWORD WINAPI OSTickW32 (LPVOID p_arg); +static DWORD WINAPI OSTaskW32 (LPVOID p_arg); + +static void OSTaskTerminate (OS_TASK_STK *p_stk); + +static BOOL WINAPI OSCtrlBreakHandler(DWORD ctrl); + +static void OSSetThreadName (DWORD thread_id, + INT8U *p_name); + +#if (OS_MSG_TRACE > 0u) +static int OS_Printf (char *p_str, ...); +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : None. +* +* Note(s) : 1) Interrupts should be disabled during this call. +* +* 2) Kernel objects must have unique names. Otherwise, a duplicate handle will be given for +* consecutive created objects. A GetLastError() ERROR_ALREADY_EXISTS can be checked when +* this case happens. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 203u) +void OSInitHookBegin (void) +{ + HANDLE hProc; + + +#if (OS_VERSION >= 281u) && (OS_TMR_EN > 0u) + OSTmrCtr = 0u; +#endif + +#if (TIMER_METHOD == WIN32_SLEEP) && \ + (OS_TICKS_PER_SEC > 100u) && \ + (OS_MSG_TRACE > 0u) + OS_Printf("Warning: Sleep TIMER_METHOD cannot maintain time accuracy with the current setting of OS_TICKS_PER_SEC. Consider using Multimedia TIMER_METHOD.\n\n"); +#endif + + + OSTerminate_SignalPtr = NULL; + OSTick_Thread = NULL; +#if (TIMER_METHOD == WIN32_MM_TMR) + OSTick_SignalPtr = NULL; +#endif + + + CPU_IntInit(); /* Initialize Critical Section objects. */ + + + hProc = GetCurrentProcess(); + SetPriorityClass(hProc, HIGH_PRIORITY_CLASS); + SetProcessAffinityMask(hProc, 1); + + OSSetThreadName(GetCurrentThreadId(), (INT8U *)"main()"); + + + OSTerminate_SignalPtr = CreateEvent(NULL, TRUE, FALSE, NULL); /* Manual reset enabled to broadcast terminate signal. */ + if (OSTerminate_SignalPtr == NULL) { +#if (OS_MSG_TRACE > 0u) + OS_Printf("Error: CreateEvent [OSTerminate] failed.\n"); +#endif + return; + } + SetConsoleCtrlHandler((PHANDLER_ROUTINE)OSCtrlBreakHandler, TRUE); + + OSTick_Thread = CreateThread(NULL, 0, OSTickW32, 0, CREATE_SUSPENDED, &OSTick_ThreadId); + if (OSTick_Thread == NULL) { +#if (OS_MSG_TRACE > 0u) + OS_Printf("Error: CreateThread [OSTickW32] failed.\n"); +#endif + CloseHandle(OSTerminate_SignalPtr); + OSTerminate_SignalPtr = NULL; + return; + } + +#if (OS_MSG_TRACE > 0u) + OS_Printf("OSTick created, Thread ID %5.0d\n", OSTick_ThreadId); +#endif + + SetThreadPriority(OSTick_Thread, THREAD_PRIORITY_HIGHEST); + +#if (TIMER_METHOD == WIN32_MM_TMR) + if (timeGetDevCaps(&OSTick_TimerCap, sizeof(OSTick_TimerCap)) != TIMERR_NOERROR) { +#if (OS_MSG_TRACE > 0u) + OS_Printf("Error: Cannot retrieve Timer capabilities.\n"); +#endif + CloseHandle(OSTick_Thread); + CloseHandle(OSTerminate_SignalPtr); + + OSTick_Thread = NULL; + OSTerminate_SignalPtr = NULL; + return; + } + + if (OSTick_TimerCap.wPeriodMin < WIN_MM_MIN_RES) { + OSTick_TimerCap.wPeriodMin = WIN_MM_MIN_RES; + } + + if (timeBeginPeriod(OSTick_TimerCap.wPeriodMin) != TIMERR_NOERROR) { +#if (OS_MSG_TRACE > 0u) + OS_Printf("Error: Cannot set Timer minimum resolution.\n"); +#endif + CloseHandle(OSTick_Thread); + CloseHandle(OSTerminate_SignalPtr); + + OSTick_Thread = NULL; + OSTerminate_SignalPtr = NULL; + return; + } + + OSTick_SignalPtr = CreateEvent(NULL, TRUE, FALSE, NULL); + if (OSTick_SignalPtr == NULL) { +#if (OS_MSG_TRACE > 0u) + OS_Printf("Error: CreateEvent [OSTick] failed.\n"); +#endif + timeEndPeriod(OSTick_TimerCap.wPeriodMin); + CloseHandle(OSTick_Thread); + CloseHandle(OSTerminate_SignalPtr); + + OSTick_Thread = NULL; + OSTerminate_SignalPtr = NULL; + return; + } + +#ifdef _MSC_VER +#pragma warning (disable : 4055) +#endif + OSTick_TimerId = timeSetEvent((UINT )(1000u / OS_TICKS_PER_SEC), + (UINT ) OSTick_TimerCap.wPeriodMin, + (LPTIMECALLBACK) OSTick_SignalPtr, + (DWORD_PTR ) NULL, + (UINT )(TIME_PERIODIC | TIME_CALLBACK_EVENT_SET)); +#ifdef _MSC_VER +#pragma warning (default : 4055) +#endif + + if (OSTick_TimerId == 0u) { +#if (OS_MSG_TRACE > 0u) + OS_Printf("Error: Cannot start Timer.\n"); +#endif + CloseHandle(OSTick_SignalPtr); + timeEndPeriod(OSTick_TimerCap.wPeriodMin); + CloseHandle(OSTick_Thread); + CloseHandle(OSTerminate_SignalPtr); + + OSTick_SignalPtr = NULL; + OSTick_Thread = NULL; + OSTerminate_SignalPtr = NULL; + return; + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : None. +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 203u) +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : p_tcb Pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) +void OSTaskCreateHook (OS_TCB *p_tcb) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskCreateHook(p_tcb); +#else + (void)p_tcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : p_tcb Pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) +void OSTaskDelHook (OS_TCB *p_tcb) +{ + OS_TASK_STK *p_stk; + + +#if (OS_APP_HOOKS_EN > 0u) + App_TaskDelHook(p_tcb); +#endif + + p_stk = (OS_TASK_STK *)p_tcb->OSTCBStkPtr; + + switch (p_stk->TaskState) { + case STATE_RUNNING: + if (GetCurrentThreadId() == p_stk->ThreadID) { + p_stk->Terminate = DEF_TRUE; + p_stk->TaskState = STATE_TERMINATING; + + } else { + + TerminateThread(p_stk->ThreadHandle, 0xFFFFFFFF); + CloseHandle(p_stk->ThreadHandle); + + OSTaskTerminate(p_stk); + } + break; + + + case STATE_CREATED: + case STATE_SUSPENDED: + case STATE_INTERRUPTED: + TerminateThread(p_stk->ThreadHandle, 0xFFFFFFFF); + CloseHandle(p_stk->ThreadHandle); + + OSTaskTerminate(p_stk); + break; + + + default: + break; + } +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK HOOK +* +* Description: This function is called by the idle task. This hook has been added to allow you to do +* such things as STOP the CPU to conserve power. +* +* Arguments : None. +* +* Note(s) : 1) Interrupts are enabled during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION >= 251u) +void OSTaskIdleHook (void) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskIdleHook(); +#endif + + Sleep(1u); /* Reduce CPU utilization. */ +} +#endif + + +/* +********************************************************************************************************* +* TASK RETURN HOOK +* +* Description: This function is called if a task accidentally returns. In other words, a task should +* either be an infinite loop or delete itself when done. +* +* Arguments : p_tcb Pointer to the task control block of the task that is returning. +* +* Note(s) : None. +********************************************************************************************************* +*/ + +#if (OS_CPU_HOOKS_EN > 0u) +void OSTaskReturnHook (OS_TCB *p_tcb) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskReturnHook(p_tcb); +#else + (void)p_tcb; /* Prevent compiler warning */ +#endif +} +#endif + + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : None. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) +void OSTaskStatHook (void) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskStatHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task Pointer to the task code. +* +* p_arg Pointer to a user supplied data area that will be passed to the task +* when the task first executes. +* +* ptos Pointer to the top of stack. It is assumed that 'ptos' points to the +* highest valid address on the stack. +* +* opt Options used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT16U opt) +{ + OS_TASK_STK *p_stk; + + /* Load stack pointer */ + p_stk = (OS_TASK_STK *)((char *)ptos - sizeof(OS_TASK_STK)); + p_stk->TaskArgPtr = p_arg; + p_stk->TaskOpt = opt; + p_stk->Task = task; + p_stk->ThreadHandle = NULL; + p_stk->ThreadID = 0u; + p_stk->TaskState = STATE_NONE; + p_stk->SignalPtr = NULL; + p_stk->InitSignalPtr = NULL; + p_stk->Terminate = DEF_FALSE; + p_stk->OSTCBPtr = NULL; + + return ((OS_STK *)p_stk); +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : None. +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u) +void OSTaskSwHook (void) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TaskSwHook(); +#endif +} +#endif + + +/* +********************************************************************************************************* +* OS_TCBInit() HOOK +* +* Description: This function is called by OS_TCBInit() after setting up most of the task control block. +* +* Arguments : p_tcb Pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +* +* 2) Kernel objects must have unique names. Otherwise, a duplicate handle will be given for +* consecutive created objects. A GetLastError() ERROR_ALREADY_EXISTS can be checked when +* this case happens. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_VERSION > 203u) +void OSTCBInitHook (OS_TCB *p_tcb) +{ + OS_TASK_STK *p_stk; + + +#if (OS_APP_HOOKS_EN > 0u) + App_TCBInitHook(p_tcb); +#else + (void)p_tcb; /* Prevent compiler warning */ +#endif + + p_stk = (OS_TASK_STK *)p_tcb->OSTCBStkPtr; + + p_stk->SignalPtr = CreateEvent(NULL, FALSE, FALSE, NULL); /* See Note #2. */ + if (p_stk->SignalPtr == NULL) { +#if (OS_MSG_TRACE > 0u) + OS_Printf("Task[%3.1d] cannot allocate signal event.\n", p_tcb->OSTCBPrio); +#endif + return; + } + + p_stk->InitSignalPtr = CreateEvent(NULL, TRUE, FALSE, NULL); /* See Note #2. */ + if (p_stk->InitSignalPtr == NULL) { + CloseHandle(p_stk->SignalPtr); + p_stk->SignalPtr = NULL; + +#if (OS_MSG_TRACE > 0u) + OS_Printf("Task[%3.1d] cannot allocate initialization complete signal event.\n", p_tcb->OSTCBPrio); +#endif + return; + } + + p_stk->ThreadHandle = CreateThread(NULL, 0, OSTaskW32, p_tcb, CREATE_SUSPENDED, &p_stk->ThreadID); + if (p_stk->ThreadHandle == NULL) { + CloseHandle(p_stk->InitSignalPtr); + CloseHandle(p_stk->SignalPtr); + + p_stk->InitSignalPtr = NULL; + p_stk->SignalPtr = NULL; +#if (OS_MSG_TRACE > 0u) + OS_Printf("Task[%3.1d] failed to be created.\n", p_tcb->OSTCBPrio); +#endif + return; + } + +#if (OS_MSG_TRACE > 0u) + OS_Printf("Task[%3.1d] created, Thread ID %5.0d\n", p_tcb->OSTCBPrio, p_stk->ThreadID); +#endif + + p_stk->TaskState = STATE_CREATED; + p_stk->OSTCBPtr = p_tcb; +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : None. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if (OS_CPU_HOOKS_EN > 0u) && (OS_TIME_TICK_HOOK_EN > 0u) +void OSTimeTickHook (void) +{ +#if (OS_APP_HOOKS_EN > 0u) + App_TimeTickHook(); +#endif + +#if (OS_VERSION >= 281u) && (OS_TMR_EN > 0u) + OSTmrCtr++; + if (OSTmrCtr >= (OS_TICKS_PER_SEC / OS_TMR_CFG_TICKS_PER_SEC)) { + OSTmrCtr = 0u; + OSTmrSignal(); + } +#endif +} +#endif + + +/* +********************************************************************************************************* +* START HIGHEST PRIORITY TASK READY-TO-RUN +* +* Description: This function is called by OSStart() to start the highest priority task that was created +* by your application before calling OSStart(). +* +* Arguments : None. +* +* Note(s) : 1) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to TRUE, +* c) Switch to the highest priority task. +********************************************************************************************************* +*/ + +void OSStartHighRdy (void) +{ + OS_TASK_STK *p_stk; + OS_TCB *p_tcb; + INT8U prio; + CPU_SR_ALLOC(); + + + OSTaskSwHook(); + OSRunning = 1; + + p_stk = (OS_TASK_STK *)OSTCBHighRdy->OSTCBStkPtr; /* OSTCBCur = OSTCBHighRdy; */ + /* OSPrioCur = OSPrioHighRdy; */ + ResumeThread(p_stk->ThreadHandle); + /* Wait while task is created and until it is ready to run. */ + SignalObjectAndWait(p_stk->SignalPtr, p_stk->InitSignalPtr, INFINITE, FALSE); + ResumeThread(OSTick_Thread); /* Start OSTick Thread. */ + WaitForSingleObject(OSTick_Thread, INFINITE); /* Wait until OSTick Thread has terminated. */ + + +#if (TIMER_METHOD == WIN32_MM_TMR) + timeKillEvent(OSTick_TimerId); + timeEndPeriod(OSTick_TimerCap.wPeriodMin); + CloseHandle(OSTick_SignalPtr); +#endif + + CloseHandle(OSTick_Thread); + CloseHandle(OSTerminate_SignalPtr); + + +#if (OS_MSG_TRACE > 0u) + OS_Printf("\nDeleting uC/OS-II tasks...\n"); +#endif + /* Delete all created tasks/threads. */ + CPU_CRITICAL_ENTER(); + p_tcb = OSTCBList; + while (p_tcb != (OS_TCB *)0) { + if (p_tcb != OS_TCB_RESERVED) { + prio = p_tcb->OSTCBPrio; + if (prio == OS_TASK_IDLE_PRIO) { + OSTaskDelHook(p_tcb); + p_tcb = p_tcb->OSTCBNext; + } else { + p_tcb = p_tcb->OSTCBNext; + (void)OSTaskDel(prio); + } + } else { + p_tcb = p_tcb->OSTCBNext; + } + } + CPU_CRITICAL_EXIT(); + + CPU_IntEnd(); /* Delete Critical Section objects. */ +} + + +/* +********************************************************************************************************* +* TASK LEVEL CONTEXT SWITCH +* +* Description: This function is called when a task makes a higher priority task ready-to-run. +* +* Arguments : None. +* +* Note(s) : 1) Upon entry, +* OSTCBCur points to the OS_TCB of the task to suspend +* OSTCBHighRdy points to the OS_TCB of the task to resume +* +* 2) OSCtxSw() MUST: +* a) Save processor registers then, +* b) Save current task's stack pointer into the current task's OS_TCB, +* c) Call OSTaskSwHook(), +* d) Set OSTCBCur = OSTCBHighRdy, +* e) Set OSPrioCur = OSPrioHighRdy, +* f) Switch to the highest priority task. +* +* pseudo-code: +* void OSCtxSw (void) +* { +* Save processor registers; +* +* OSTCBCur->OSTCBStkPtr = SP; +* +* OSTaskSwHook(); +* +* OSTCBCur = OSTCBHighRdy; +* OSPrioCur = OSPrioHighRdy; +* +* Restore processor registers from (OSTCBHighRdy->OSTCBStkPtr); +* } +********************************************************************************************************* +*/ + +void OSCtxSw (void) +{ + OS_TASK_STK *p_stk; + OS_TASK_STK *p_stk_new; +#if (OS_MSG_TRACE > 0u) + OS_TCB *p_tcb_cur; + OS_TCB *p_tcb_new; +#endif + CPU_SR_ALLOC(); + + +#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) + cpu_sr = 0u; +#endif + +#if (OS_MSG_TRACE > 0u) + p_tcb_cur = OSTCBCur; + p_tcb_new = OSTCBHighRdy; +#endif + + + p_stk = (OS_TASK_STK *)OSTCBCur->OSTCBStkPtr; + + OSTaskSwHook(); + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; + + if (p_stk->TaskState == STATE_RUNNING) { + p_stk->TaskState = STATE_SUSPENDED; + } + p_stk_new = (OS_TASK_STK *)OSTCBHighRdy->OSTCBStkPtr; + switch (p_stk_new->TaskState) { + case STATE_CREATED: /* TaskState updated to STATE_RUNNING once thread runs. */ + ResumeThread(p_stk_new->ThreadHandle); + /* Wait while task is created and until it is ready to run. */ + SignalObjectAndWait(p_stk_new->SignalPtr, p_stk_new->InitSignalPtr, INFINITE, FALSE); + break; + + + case STATE_SUSPENDED: + p_stk_new->TaskState = STATE_RUNNING; + SetEvent(p_stk_new->SignalPtr); + break; + + + case STATE_INTERRUPTED: + p_stk_new->TaskState = STATE_RUNNING; + ResumeThread(p_stk_new->ThreadHandle); + break; + + +#if (OS_MSG_TRACE > 0u) + case STATE_NONE: + OS_Printf("[OSCtxSw] Error: Invalid state STATE_NONE\nCur Task[%3.1d] Thread ID %5.0d: '%s'\nNew Task[%3.1d] Thread ID %5.0d: '%s'\n\n", + p_tcb_cur->OSTCBPrio, + p_stk->ThreadID, + p_tcb_cur->OSTCBTaskName, + p_tcb_new->OSTCBPrio, + p_stk_new->ThreadID, + p_tcb_new->OSTCBTaskName); + return; + + + case STATE_RUNNING: + OS_Printf("[OSCtxSw] Error: Invalid state STATE_RUNNING\nCur Task[%3.1d] Thread ID %5.0d: '%s'\nNew Task[%3.1d] Thread ID %5.0d: '%s'\n\n", + p_tcb_cur->OSTCBPrio, + p_stk->ThreadID, + p_tcb_cur->OSTCBTaskName, + p_tcb_new->OSTCBPrio, + p_stk_new->ThreadID, + p_tcb_new->OSTCBTaskName); + return; + + + case STATE_TERMINATING: + OS_Printf("[OSCtxSw] Error: Invalid state STATE_TERMINATING\nCur Task[%3.1d] Thread ID %5.0d: '%s'\nNew Task[%3.1d] Thread ID %5.0d: '%s'\n\n", + p_tcb_cur->OSTCBPrio, + p_stk->ThreadID, + p_tcb_cur->OSTCBTaskName, + p_tcb_new->OSTCBPrio, + p_stk_new->ThreadID, + p_tcb_new->OSTCBTaskName); + return; + + + case STATE_TERMINATED: + OS_Printf("[OSCtxSw] Error: Invalid state STATE_TERMINATED\nCur Task[%3.1d] Thread ID %5.0d: '%s'\nNew Task[%3.1d] Thread ID %5.0d: '%s'\n\n", + p_tcb_cur->OSTCBPrio, + p_stk->ThreadID, + p_tcb_cur->OSTCBTaskName, + p_tcb_new->OSTCBPrio, + p_stk_new->ThreadID, + p_tcb_new->OSTCBTaskName); + return; + + +#endif + default: + return; + } + + + if (p_stk->Terminate == DEF_TRUE) { + OSTaskTerminate(p_stk); + + CPU_CRITICAL_EXIT(); + + ExitThread(0u); /* ExitThread() never returns. */ + return; + } + CPU_CRITICAL_EXIT(); + WaitForSingleObject(p_stk->SignalPtr, INFINITE); + CPU_CRITICAL_ENTER(); +} + + +/* +********************************************************************************************************* +* INTERRUPT LEVEL CONTEXT SWITCH +* +* Description: This function is called by OSIntExit() to perform a context switch from an ISR. +* +* Arguments : None. +* +* Note(s) : 1) OSIntCtxSw() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSTCBCur = OSTCBHighRdy, +* c) Set OSPrioCur = OSPrioHighRdy, +* d) Switch to the highest priority task. +* +* 2) OSIntCurTaskSuspend() MUST be called prior to OSIntEnter(). +* +* 3) OSIntCurTaskResume() MUST be called after OSIntExit() to switch to the highest +* priority task. +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSTaskSwHook(); + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; +} + + +/* +********************************************************************************************************* +* OSIntCurTaskSuspend() +* +* Description: This function suspends current task for context switch. +* +* Arguments : None. +* +* Returns : DEF_TRUE, current task suspended successfully. +* DEF_FALSE, current task NOT suspended. +* +* Notes : 1) Current task MUST be suspended before OSIntEnter(). +* +* 2) Suspending current task before OSIntEnter() and resuming it after OSIntExit() prevents +* task-level code to run concurrently with ISR-level code +********************************************************************************************************* +*/ + +CPU_BOOLEAN OSIntCurTaskSuspend (void) +{ + OS_TCB *p_tcb; + OS_TASK_STK *p_stk; + CPU_BOOLEAN ret; + + + p_tcb = OSTCBCur; + p_stk = (OS_TASK_STK *)p_tcb->OSTCBStkPtr; + switch (p_stk->TaskState) { + case STATE_RUNNING: + SuspendThread(p_stk->ThreadHandle); + SwitchToThread(); + + p_stk->TaskState = STATE_INTERRUPTED; + + ret = DEF_TRUE; + break; + + + case STATE_TERMINATING: /* Task has terminated (run-to-completion/deleted itself). */ + TerminateThread(p_stk->ThreadHandle, 0xFFFFFFFF); + CloseHandle(p_stk->ThreadHandle); + + OSTaskTerminate(p_stk); + + ret = DEF_TRUE; + break; + + +#if (OS_MSG_TRACE > 0u) + case STATE_NONE: + OS_Printf("[OSIntCtxSw Suspend] Error: Invalid state STATE_NONE\nCur Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk->ThreadID); + + ret = DEF_FALSE; + break; + + + case STATE_CREATED: + OS_Printf("[OSIntCtxSw Suspend] Error: Invalid state STATE_CREATED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk->ThreadID); + + ret = DEF_FALSE; + break; + + + case STATE_INTERRUPTED: + OS_Printf("[OSIntCtxSw Suspend] Error: Invalid state STATE_INTERRUPTED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk->ThreadID); + + ret = DEF_FALSE; + break; + + + case STATE_SUSPENDED: + OS_Printf("[OSIntCtxSw Suspend] Error: Invalid state STATE_SUSPENDED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk->ThreadID); + + ret = DEF_FALSE; + break; + + + case STATE_TERMINATED: + OS_Printf("[OSIntCtxSw Suspend] Error: Invalid state STATE_TERMINATED\nCur Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk->ThreadID); + + ret = DEF_FALSE; + break; + + +#endif + default: + ret = DEF_FALSE; + break; + } + + return (ret); +} + + +/* +********************************************************************************************************* +* OSIntCurTaskResume() +* +* Description: This function resumes current task for context switch. +* +* Arguments : None. +* +* Returns : DEF_TRUE, current task resumed successfully. +* DEF_FALSE, current task NOT resumed. +* +* Notes : 1) Current task MUST be resumed after OSIntExit(). +* +* 2) Suspending current task before OSIntEnter() and resuming it after OSIntExit() prevents +* task-level code to run concurrently with ISR-level code +********************************************************************************************************* +*/ + +CPU_BOOLEAN OSIntCurTaskResume (void) +{ + OS_TCB *p_tcb; + OS_TASK_STK *p_stk_new; + CPU_BOOLEAN ret; + + + p_tcb = OSTCBHighRdy; + p_stk_new = (OS_TASK_STK *)p_tcb->OSTCBStkPtr; + switch (p_stk_new->TaskState) { + case STATE_CREATED: + ResumeThread(p_stk_new->ThreadHandle); + /* Wait while task is created and until it is ready to run. */ + SignalObjectAndWait(p_stk_new->SignalPtr, p_stk_new->InitSignalPtr, INFINITE, FALSE); + ret = DEF_TRUE; + break; + + + case STATE_INTERRUPTED: + p_stk_new->TaskState = STATE_RUNNING; + ResumeThread(p_stk_new->ThreadHandle); + ret = DEF_TRUE; + break; + + + case STATE_SUSPENDED: + p_stk_new->TaskState = STATE_RUNNING; + SetEvent(p_stk_new->SignalPtr); + ret = DEF_TRUE; + break; + + +#if (OS_MSG_TRACE > 0u) + case STATE_NONE: + OS_Printf("[OSIntCtxSw Resume] Error: Invalid state STATE_NONE\nNew Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk_new->ThreadID); + ret = DEF_FALSE; + break; + + + case STATE_RUNNING: + OS_Printf("[OSIntCtxSw Resume] Error: Invalid state STATE_RUNNING\nNew Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk_new->ThreadID); + ret = DEF_FALSE; + break; + + + case STATE_TERMINATING: + OS_Printf("[OSIntCtxSw Resume] Error: Invalid state STATE_TERMINATING\nNew Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk_new->ThreadID); + ret = DEF_FALSE; + break; + + + case STATE_TERMINATED: + OS_Printf("[OSIntCtxSw Resume] Error: Invalid state STATE_TERMINATED\nNew Task[%3.1d] '%s' Thread ID %5.0d\n", + p_tcb->OSTCBPrio, + p_tcb->OSTCBTaskName, + p_stk_new->ThreadID); + ret = DEF_FALSE; + break; + + +#endif + default: + ret = DEF_FALSE; + break; + } + + return (ret); +} + + +/* +********************************************************************************************************* +* WIN32 TASK - OSTickW32() +* +* Description: This functions is the Win32 task that generates the tick interrupts for uC/OS-II. +* +* Arguments : p_arg Pointer to argument of the task. +* +* Note(s) : 1) Priorities of these tasks are very important. +********************************************************************************************************* +*/ + +static DWORD WINAPI OSTickW32 (LPVOID p_arg) +{ + CPU_BOOLEAN terminate; + CPU_BOOLEAN suspended; +#if (TIMER_METHOD == WIN32_MM_TMR) + HANDLE wait_signal[2]; +#endif + CPU_SR_ALLOC(); + + +#if (TIMER_METHOD == WIN32_MM_TMR) + wait_signal[0] = OSTerminate_SignalPtr; + wait_signal[1] = OSTick_SignalPtr; +#endif + + + (void)p_arg; /* Prevent compiler warning */ + + terminate = DEF_FALSE; + while (!terminate) { +#if (TIMER_METHOD == WIN32_MM_TMR) + switch (WaitForMultipleObjects(2, wait_signal, FALSE, INFINITE)) { + case WAIT_OBJECT_0 + 1u: + ResetEvent(OSTick_SignalPtr); +#elif (TIMER_METHOD == WIN32_SLEEP) + switch (WaitForSingleObject(OSTerminate_SignalPtr, 1000u / OS_TICKS_PER_SEC)) { + case WAIT_TIMEOUT: +#endif + CPU_CRITICAL_ENTER(); + + suspended = OSIntCurTaskSuspend(); + if (suspended == DEF_TRUE) { + OSIntEnter(); + OSTimeTick(); + OSIntExit(); + OSIntCurTaskResume(); + } + + CPU_CRITICAL_EXIT(); + break; + + + case WAIT_OBJECT_0 + 0u: + terminate = DEF_TRUE; + break; + + + default: +#if (OS_MSG_TRACE > 0u) + OS_Printf("[OSTickW32] Error: Invalid signal.\n"); +#endif + terminate = DEF_TRUE; + break; + } + } + +#if (OS_MSG_TRACE > 0u) + OS_Printf("[OSTickW32] Terminated.\n"); +#endif + + return (0u); +} + + +/* +********************************************************************************************************* +* WIN32 TASK - OSTaskW32() +* +* Description: This function is a generic Win32 task wrapper for uC/OS-II tasks. +* +* Arguments : p_arg Pointer to argument of the task. +* +* Note(s) : 1) Priorities of these tasks are very important. +********************************************************************************************************* +*/ + +static DWORD WINAPI OSTaskW32 (LPVOID p_arg) +{ + OS_TASK_STK *p_stk; + OS_TCB *p_tcb; + + + p_tcb = (OS_TCB *)p_arg; + p_stk = (OS_TASK_STK *)p_tcb->OSTCBStkPtr; + + p_stk->TaskState = STATE_SUSPENDED; + WaitForSingleObject(p_stk->SignalPtr, INFINITE); + + OSSetThreadName(p_stk->ThreadID, p_tcb->OSTCBTaskName); + +#if (OS_MSG_TRACE > 0u) + OS_Printf("Task[%3.1d] '%s' Running\n", p_tcb->OSTCBPrio, p_tcb->OSTCBTaskName); +#endif + + p_stk->TaskState = STATE_RUNNING; + SetEvent(p_stk->InitSignalPtr); /* Indicate task has initialized successfully. */ + + p_stk->Task(p_stk->TaskArgPtr); + + OSTaskDel(p_tcb->OSTCBPrio); /* Thread may exit at OSCtxSw(). */ + + return (0u); +} + + +/* +********************************************************************************************************* +* OSTaskTerminate() +* +* Description: This function handles task termination control signals. +* +* Arguments : p_stk Pointer to the stack of the task to clear its control signals. +********************************************************************************************************* +*/ + +static void OSTaskTerminate (OS_TASK_STK *p_stk) +{ +#if (OS_MSG_TRACE > 0u) + OS_TCB *p_tcb; +#endif + + +#if (OS_MSG_TRACE > 0u) + p_tcb = p_stk->OSTCBPtr; + OS_Printf("Task[%3.1d] '%s' Deleted\n", p_tcb->OSTCBPrio, p_tcb->OSTCBTaskName); +#endif + CloseHandle(p_stk->InitSignalPtr); + CloseHandle(p_stk->SignalPtr); + + p_stk->ThreadID = 0u; + p_stk->ThreadHandle = NULL; + p_stk->InitSignalPtr = NULL; + p_stk->SignalPtr = NULL; + p_stk->TaskState = STATE_TERMINATED; + p_stk->OSTCBPtr = NULL; +} + + +/* +********************************************************************************************************* +* OSCtrlBreakHandler() +* +* Description: This function handles control signals sent to the console window. +* +* Arguments : ctrl Control signal type. +* +* Returns : TRUE, control signal was handled. +* FALSE, control signal was NOT handled. +********************************************************************************************************* +*/ + +static BOOL WINAPI OSCtrlBreakHandler (DWORD ctrl) +{ + BOOL ret; + + + ret = FALSE; + + switch (ctrl) { + case CTRL_C_EVENT: /* CTRL-C pressed. */ + case CTRL_BREAK_EVENT: /* CTRL-BREAK pressed. */ + case CTRL_CLOSE_EVENT: /* Console window is closing. */ + case CTRL_LOGOFF_EVENT: /* Logoff has started. */ + case CTRL_SHUTDOWN_EVENT: /* System shutdown in process. */ +#if (OS_MSG_TRACE > 0u) + OS_Printf("\nTerminating Scheduler...\n"); +#endif + SetEvent(OSTerminate_SignalPtr); + + if (ctrl == CTRL_CLOSE_EVENT) { + Sleep(500); /* Give a chance to OSTickW32 to terminate. */ + } else { + ret = TRUE; + } + break; + + + default: + break; + } + + return (ret); +} + + +/* +********************************************************************************************************* +* OS_Printf() +* +* Description: This function is analog of printf. +* +* Arguments : p_str Pointer to format string output. +* +* Returns : Number of characters written. +********************************************************************************************************* +*/ +#if (OS_MSG_TRACE > 0u) +static int OS_Printf (char *p_str, ...) +{ + va_list param; + int ret; + + + va_start(param, p_str); +#ifdef _MSC_VER + ret = vprintf_s(p_str, param); +#else + ret = vprintf(p_str, param); +#endif + va_end(param); + + return (ret); +} +#endif + + +/* +********************************************************************************************************* +* OSDebuggerBreak() +* +* Description: This function throws a breakpoint exception when a debugger is present. +* +* Arguments : None. +********************************************************************************************************* +*/ + +void OSDebuggerBreak (void) +{ +#ifdef _MSC_VER + __try { + DebugBreak(); + } + __except(GetExceptionCode() == EXCEPTION_BREAKPOINT ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { + return; + } +#else +#ifdef _DEBUG + DebugBreak(); +#endif +#endif +} + + +/* +********************************************************************************************************* +* OSSetThreadName() +* +* Description: This function sets thread names. +* +* Arguments : thread_id Thread ID. +* +* p_name Pointer to name of the thread string. +* +* Note(s) : Visual Studio allows threads to be named into debug session. +********************************************************************************************************* +*/ + +static void OSSetThreadName (DWORD thread_id, INT8U *p_name) +{ +#ifdef _MSC_VER + THREADNAME_INFO info; + + + info.dwType = (DWORD )0x1000u; + info.szName = (LPCSTR)p_name; + info.dwThreadID = (DWORD )thread_id; + info.dwFlags = (DWORD )0u; + + __try { + RaiseException(MS_VC_EXCEPTION, 0u, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except(EXCEPTION_EXECUTE_HANDLER) { + } +#endif +} + diff --git a/Ports/XA/Tasking/os_cpu.h b/Ports/XA/Tasking/os_cpu.h new file mode 100644 index 0000000..266a13c --- /dev/null +++ b/Ports/XA/Tasking/os_cpu.h @@ -0,0 +1,233 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Philips XA Specific code +* LARGE MEMORY MODEL +* +* Filename : os_cpu.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifdef OS_CPU_GLOBALS +#define OS_CPU_EXT +#else +#define OS_CPU_EXT extern +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + +typedef unsigned char BOOLEAN; +typedef unsigned char INT8U; /* Unsigned 8 bit quantity */ +typedef signed char INT8S; /* Signed 8 bit quantity */ +typedef unsigned int INT16U; /* Unsigned 16 bit quantity */ +typedef signed int INT16S; /* Signed 16 bit quantity */ +typedef unsigned long INT32U; /* Unsigned 32 bit quantity */ +typedef signed long INT32S; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ + +typedef unsigned int OS_STK; /* Each stack entry is 16-bit wide */ + +#define BYTE INT8S /* Define data types for backward compatibility ... */ +#define UBYTE INT8U /* ... to uC/OS V1.xx. Not actually needed for ... */ +#define WORD INT16S /* ... uC/OS-II. */ +#define UWORD INT16U +#define LONG INT32S +#define ULONG INT32U + +/* +********************************************************************************************************* +* CRITICAL SECTION CONTROL +* +* Method #1: Disable/Enable interrupts using simple instructions. After critical section, interrupts +* will be enabled even if they were disabled before entering the critical section. +* +* Method #2: Disable/Enable interrupts by preserving the state of interrupts. In other words, if +* interrupts were disabled before entering the critical section, they will be disabled when +* leaving the critical section. +* The XA port doesn't currently support this method. +********************************************************************************************************* +*/ +#define OS_CRITICAL_METHOD 1 + + +#if OS_CRITICAL_METHOD == 1 +#define OS_ENTER_CRITICAL() EA = 0 /* Disable interrupts */ +#define OS_EXIT_CRITICAL() EA = 1 /* Enable interrupts */ +#endif + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory on XA */ + +#define OS_TASK_SW() _intxa(31) /* Trap #15, (Interrupt 31) invokes OSCtxSw() */ + +/* +********************************************************************************************************* +* SAVE PROCESSOR CONTEXT ONTO USER STACK +* +* Note(s) : 1) The final OR.B instruction, forces all register indirect addressing to be via the ES +* segment register. In the large memory model this is assumed by the compiler to be the +* default value and is required for correct operation of code generated by the C & C++ +* compilers. If an assembly routine (e.g. a Tasking library function) fiddles with the +* SSEL value and we just interrupted one of those, then we may have "inherited" a non-0xFFH +* value. If we had specified the SSEL register in the _frame() directive for this ISR, the +* compiler would have generated the instruction automatically. Since an empty _frame() +* is used we will have to set SSEL ourselve. The value will be restored on RETI. +* Thanks to Scott and Peter for this finding: +* Scott Finneran sfinneran@lucent.com +* Peter Miller millerp@canb.auug.org.au +********************************************************************************************************* +*/ + +_inline void CPU_PushAllToUserStk (void) +{ +#pragma asm + ; SAVE PROCESSOR CONTEXT ONTO USER STACK + PUSHU R0,R1,R2,R3,R4,R5,R6 ;24~, Save interrupted task's context + PUSHU.B ES ; 5~, Save ES + PUSHU.B SSEL ; 5~, Save SSEL + POP R2 ; 5~, Move PSW from SS to US + PUSHU R2 ; 5~ + POP R2 ; 5~, Move PCH from SS to US + PUSHU R2 ; 5~ + POP R2 ; 5~, Move PCL from SS to US + PUSHU R2 ; 5~ + + OR.B SSEL,#0FFH ; All addressing via ES +#pragma endasm +} + +/* +********************************************************************************************************* +* RESTORE PROCESSOR CONTEXT FROM USER STACK +********************************************************************************************************* +*/ + +_inline void CPU_PopAllFromUserStk (void) +{ +#pragma asm + ; RESTORE PROCESSOR CONTEXT FROM USER STACK + POPU R2 ; 5~, Move PCL from US to SS + PUSH R2 ; 5~ + POPU R2 ; 5~, Move PCH from US to SS + PUSH R2 ; 5~ + POPU R2 ; 5~, Move PSW from US to SS + PUSH R2 ; 5~ + POPU.B SSEL ; 5~, Get SSEL + POPU.B ES ; 5~, Get ES + POPU R0,R1,R2,R3,R4,R5,R6 ;18~, Load interrupted task's context +#pragma endasm +} + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* TASKING ATTRIBUTES +* (Target Specific Functions) +********************************************************************************************************* +*/ + +_trap(15) _using(0x8F00) void OSCtxSw(void); +_interrupt(33) _using(0x8F00) _frame() void OSTickISR(void); + + +/* +********************************************************************************************************* +* EXCEPTIONS +********************************************************************************************************* +*/ + +_interrupt(1) _using(0x8F00) void OS_XAResetISR(void); +_interrupt(2) _using(0x8F00) void OS_XABreakptISR(void); +_interrupt(3) _using(0x8F00) void OS_XATraceISR(void); +_interrupt(4) _using(0x8F00) void OS_XAStkOvfISR(void); +_interrupt(5) _using(0x8F00) void OS_XADivide0ISR(void); +_interrupt(6) _using(0x8F00) void OS_XAUserRETIISR(void); + +/* +********************************************************************************************************* +* TRAPS +********************************************************************************************************* +*/ + +_trap(0) _using(0x8F00) void OS_XATrap00ISR(void); +_trap(1) _using(0x8F00) void OS_XATrap01ISR(void); +_trap(2) _using(0x8F00) void OS_XATrap02ISR(void); +_trap(3) _using(0x8F00) void OS_XATrap03ISR(void); +_trap(4) _using(0x8F00) void OS_XATrap04ISR(void); +_trap(5) _using(0x8F00) void OS_XATrap05ISR(void); +_trap(6) _using(0x8F00) void OS_XATrap06ISR(void); +_trap(7) _using(0x8F00) void OS_XATrap07ISR(void); +_trap(8) _using(0x8F00) void OS_XATrap08ISR(void); +_trap(9) _using(0x8F00) void OS_XATrap09ISR(void); +_trap(10) _using(0x8F00) void OS_XATrap10ISR(void); +_trap(11) _using(0x8F00) void OS_XATrap11ISR(void); +_trap(12) _using(0x8F00) void OS_XATrap12ISR(void); +_trap(13) _using(0x8F00) void OS_XATrap13ISR(void); +_trap(14) _using(0x8F00) void OS_XATrap14ISR(void); + +#if 0 +_trap(15) _using(0x8F00) void OS_XATrap15ISR(void); /* Used by OSCtxSw() */ +#endif + +/* +********************************************************************************************************* +* EVENT INTERRUPTS +********************************************************************************************************* +*/ + +_interrupt(32) _using(0x8F00) _frame() void OS_XAExt0ISR(void); + +#if 0 +_interrupt(33) _using(0x8F00) _frame() void OS_XATmr0ISR(void); /* Used by OSTickISR() */ +#endif + +_interrupt(34) _using(0x8F00) _frame() void OS_XAExt1ISR(void); +_interrupt(35) _using(0x8F00) _frame() void OS_XATmr1ISR(void); +_interrupt(36) _using(0x8F00) _frame() void OS_XATmr2ISR(void); +_interrupt(37) _using(0x8F00) _frame() void OS_XAComm0RxISR(void); +_interrupt(38) _using(0x8F00) _frame() void OS_XAComm0TxISR(void); +_interrupt(39) _using(0x8F00) _frame() void OS_XAComm1RxISR(void); +_interrupt(40) _using(0x8F00) _frame() void OS_XAComm1TxISR(void); + +/* +********************************************************************************************************* +* SOFTWARE INTERRUPTS +********************************************************************************************************* +*/ + +_interrupt(64) _using(0x8F00) _frame() void OS_XASwi1ISR(void); +_interrupt(65) _using(0x8F00) _frame() void OS_XASwi2ISR(void); +_interrupt(66) _using(0x8F00) _frame() void OS_XASwi3ISR(void); +_interrupt(67) _using(0x8F00) _frame() void OS_XASwi4ISR(void); +_interrupt(68) _using(0x8F00) _frame() void OS_XASwi5ISR(void); +_interrupt(69) _using(0x8F00) _frame() void OS_XASwi6ISR(void); +_interrupt(70) _using(0x8F00) _frame() void OS_XASwi7ISR(void); diff --git a/Ports/XA/Tasking/os_cpu_c.c b/Ports/XA/Tasking/os_cpu_c.c new file mode 100644 index 0000000..65a0125 --- /dev/null +++ b/Ports/XA/Tasking/os_cpu_c.c @@ -0,0 +1,697 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* Philips XA Specific code +* LARGE MEMORY MODEL +* (TASKING Compiler) +* +* Filename : os_cpu_c.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_CPU_GLOBALS +#include + +/* +********************************************************************************************************* +* SAVE 'DS:USP' IN TCB OF TASK BEING SWITCHED OUT +********************************************************************************************************* +*/ + +_inline void CPU_USPSave (void) +{ +#pragma asm + ; OSTCBCur->OSTCBStkPtr = DS:USP + SETB 0218H ; 4~, SSEL.0 = 1 (R0 uses ES register) + MOV.B ES, #SEG(_OSTCBCur) ; 3~, ES:R0 = &OSTCBCur + MOV.W R0, #SOF(_OSTCBCur) ; 3~ + MOV.W R2, [R0+] ; 4~, R3:R2 = OSTCBCur + MOV.W R3, [R0] ; 5~ + MOV.W R0, R2 ; 3~, ES:R0 = R3:R2 + MOV.B ES, R3L ; 3~ + MOV.B R3H, #0 ; 3~, R3:R2 = DS:USP + MOV.B R3L, DS ; 3~ + MOV R2, USP ; 3~ + MOV.W [R0+], R2 ; 3~, OSTCBCur->OSTCBStkPtr = DS:USP + MOV.W [R0], R3 ; 5~ +#pragma endasm +} + +/* +********************************************************************************************************* +* RESTORE 'DS:USP' FROM TCB OF TASK BEING SWITCHED IN +********************************************************************************************************* +*/ + +_inline void CPU_USPLoad (void) +{ +#pragma asm + ; DS:USP = OSTCBHighRdy->OSTCBStkPtr + SETB 0218H ; 4~, SSEL.0 = 1 (R0 uses ES register) + MOV.B ES, #SEG(_OSTCBHighRdy) ; 3~, ES:R0 = &OSTCBHighRdy + MOV.W R0, #SOF(_OSTCBHighRdy) ; 3~ + MOV.W R2, [R0+] ; 3~, R3:R2 = OSTCBHighRdy + MOV.W R3, [R0] ; 5~ + MOV.B ES, R3L ; 3~, ES:R0 = R3:R2 + MOV.W R0, R2 ; 3~ + MOV.W R2, [R0+] ; 5~, R3:R2 = OSTCBHighRdy->OSTCBStkPtr + MOV.W R3, [R0] ; 4~ + MOV USP, R2 ; 3~, DS:USP = R3:R2 + MOV.B DS, R3L ; 4~ +#pragma endasm +} + +/* +********************************************************************************************************* +* RETURN FROM ISR +********************************************************************************************************* +*/ + +_inline void CPU_RetFromISR (void) +{ + EA = 1; /* Re-enable interrupts because RETI does not */ +#pragma asm + RETI +#pragma endasm +} + + +/* +********************************************************************************************************* +* INITIALIZE A TASK'S STACK +* +* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the +* stack frame of the task being created. This function is highly processor specific. +* +* Arguments : task is a pointer to the task code +* +* pdata is a pointer to a user supplied data area that will be passed to the task +* when the task first executes. For the TASKING compiler, 'pdata' is passed +* in R1:R0. +* +* ptos is a pointer to the top of stack. It is assumed that 'ptos' points to +* a 'free' entry on the task stack. If OS_STK_GROWTH is set to 1 then +* 'ptos' will contain the HIGHEST valid address of the stack. Similarly, if +* OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address +* of the stack. +* +* opt specifies options that can be used to alter the behavior of OSTaskStkInit(). +* (see uCOS_II.H for OS_TASK_OPT_???). +* +* Returns : Always returns the location of the new top-of-stack' once the processor registers have +* been placed on the stack in the proper order. +* +* Note(s) : 1) Interrupts are enabled when your task starts executing. +* +* 2) Two bytes are placed on the stack for the ES register because the 'POPU.B ES' +* instruction actually pops 2 bytes off the stack. The upper byte of the popped value +* is discarded by the XA. +* +* 3) Two bytes are placed on the stack for the SSEL register because the 'POPU.B SSEL' +* instruction actually pops 2 bytes off the stack. The upper byte of the popped value +* is discarded by the XA. +* +* 4) The last stacking operation (before the return) places the task address and the PSW +* in the reverse order of an interrupt. This is done because the task address and PSW +* are actually placed on the USER stack and moved to the SYSTEM stack when a task is +* 'switched-in'. +* +* 5) 'pdata' is assumed to be in R1:R0 for the TASKING compiler. +********************************************************************************************************* +*/ + +OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) +{ + INT16U *stk; + INT32U data; + INT32U temp; + + + opt = opt; /* 'opt' is not used, prevent warning */ + stk = (INT16U *)ptos; /* Load stack pointer */ + + /* Simulate FCALL with argument ... */ + temp = (INT32U)task; /* ... Convert 'task' pointer to 32-bit value */ + *--stk = (INT16U)( temp & 0xFFFFL); /* ... Place lower 16 bits of 'task' on stack */ + *--stk = (INT16U)((temp >> 16) & 0x00FFL); /* ... Place upper 8 bits of 'task' on stack */ + + /* Simulate INTERRUPT stacking ... */ + *--stk = (INT16U)0x6666; /* R6 = 0x6666 */ + *--stk = (INT16U)0x5555; /* R5 = 0x5555 */ + *--stk = (INT16U)0x4444; /* R4 = 0x4444 */ + *--stk = (INT16U)0x3333; /* R3 = 0x3333 */ + *--stk = (INT16U)0x2222; /* R2 = 0x2222 */ + data = (INT32U)pdata; /* ... Convert 'pdata' pointer to 32-bit value */ + *--stk = (INT16U)((data >> 16) & 0x00FFL); /* R1:R0 = pdata (passed in registers R1:R0) */ + *--stk = (INT16U)( data & 0xFFFFL); /* */ + *--stk = (INT16U)0x0000; /* ES = 0x00 ES used by CEIBO emulator! */ + *--stk = (INT16U)0xFFFF; /* SSEL = 0xFF Allow writes to ES register */ + /* NOTE: Push in reverse order because these will */ + /* be placed on the System Stack during a */ + /* context switch to this task. */ + *--stk = (INT16U)0x0000; /* PSW = User Mode, Register bank #0, Ints. En. */ + *--stk = (INT16U)((temp >> 16) & 0x00FFL); /* PC(H), i.e. in reverse order. */ + *--stk = (INT16U)( temp & 0xFFFFL); /* PC(L) */ + return ((OS_STK *)stk); /* Return pointer to task's top-of-stack */ +} + + +#if OS_CPU_HOOKS_EN +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (BEGINNING) +* +* Description: This function is called by OSInit() at the beginning of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_VERSION > 203 +void OSInitHookBegin (void) +{ +} +#endif + +/* +********************************************************************************************************* +* OS INITIALIZATION HOOK +* (END) +* +* Description: This function is called by OSInit() at the end of OSInit(). +* +* Arguments : none +* +* Note(s) : 1) Interrupts should be disabled during this call. +********************************************************************************************************* +*/ +#if OS_VERSION > 203 +void OSInitHookEnd (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* TASK CREATION HOOK +* +* Description: This function is called when a task is created. +* +* Arguments : ptcb is a pointer to the task control block of the task being created. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +void OSTaskCreateHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} + + +/* +********************************************************************************************************* +* TASK DELETION HOOK +* +* Description: This function is called when a task is deleted. +* +* Arguments : ptcb is a pointer to the task control block of the task being deleted. +* +* Note(s) : 1) Interrupts are disabled during this call. +********************************************************************************************************* +*/ +void OSTaskDelHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent compiler warning */ +} + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description: This function is called when a task switch is performed. This allows you to perform other +* operations during a context switch. +* +* Arguments : none +* +* Note(s) : 1) Interrupts are disabled during this call. +* 2) It is assumed that the global pointer 'OSTCBHighRdy' points to the TCB of the task that +* will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCur' points to the +* task being switched out (i.e. the preempted task). +********************************************************************************************************* +*/ +void OSTaskSwHook (void) +{ +} + +/* +********************************************************************************************************* +* STATISTIC TASK HOOK +* +* Description: This function is called every second by uC/OS-II's statistics task. This allows your +* application to add functionality to the statistics task. +* +* Arguments : none +********************************************************************************************************* +*/ +void OSTaskStatHook (void) +{ +} + +/* +********************************************************************************************************* +* OSTCBInit() HOOK +* +* Description: This function is called by OSTCBInit() after setting up most of the TCB. +* +* Arguments : ptcb is a pointer to the TCB of the task being created. +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +#if OS_VERSION > 203 +void OSTCBInitHook (OS_TCB *ptcb) +{ + ptcb = ptcb; /* Prevent Compiler warning */ +} +#endif + + +/* +********************************************************************************************************* +* TICK HOOK +* +* Description: This function is called every tick. +* +* Arguments : none +* +* Note(s) : 1) Interrupts may or may not be ENABLED during this call. +********************************************************************************************************* +*/ +void OSTimeTickHook (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* START HIGHEST PRIORITY TASK +* +* Description : This function is called by OSStart() to start the highest priority task that was created +* by your application before calling OSStart(). +* +* Arguments : none +* +* Note(s) : 1) The stack frame (16-bit wide stack) is assumed to look as follows: +* +* LOW MEMORY +* OSTCBHighRdy->OSTCBStkPtr + 0 ----> Pointer to task (Lower 16 bits) +* + 2 Pointer to task (Upper 8 bits) +* + 4 PSW (initialized to 0x0000) +* + 6 SSEL (initialized to 0x8080) +* + 8 ES (initialized to 0xEEEE) +* + 10 R0 +* + 12 R1 +* + 14 R2 +* + 16 R3 +* + 18 R4 +* + 20 R5 +* + 22 R6 +* + 24 Pointer to task (Upper 8 bits) +* + 26 Pointer to task (Lower 16 bits) +* + 28 pdata (Lower 16 bits) +* + 30 pdata (Upper 8 bits) +* HIGH MEMORY +* +* 2) OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() +* b) Set OSRunning to TRUE +* c) Switch to the highest priority task. +* +* 3) It is assumed that this function is called with the XA in SYSTEM mode. +********************************************************************************************************* +*/ + +void OSStartHighRdy (void) +{ + OSTaskSwHook(); + + OSRunning = TRUE; + + CPU_USPLoad(); /* Get DS:USP from High Priority Task's OS_TCB */ + + CPU_PopAllFromUserStk(); /* Restore processor registers from USER stack */ + + CPU_RetFromISR(); +} + + +/* +********************************************************************************************************* +* TASK LEVEL CONTEXT SWITCH +* +* Description : This function is called when a task makes a higher priority task ready-to-run. +* +* Arguments : none +* +* Note(s) : 1) Upon entry, +* OSTCBCur points to the OS_TCB of the task to suspend +* OSTCBHighRdy points to the OS_TCB of the task to resume +* +* 2) The stack frame of the task to suspend looks as follows. +* +* LOW MEMORY +* SSP + 0 ----> PSW +* + 2 Return PC (Upper 8 bits) +* + 4 Return PC (Lower 16 bits) +* HIGH MEMORY +* +* 3) The stack frame of the task to resume looks as follows: +* +* LOW MEMORY +* OSTCBHighRdy->OSTCBStkPtr + 0 ----> Pointer to task (Lower 16 bits) +* + 2 Pointer to task (Upper 8 bits) +* + 4 PSW +* + 6 SSEL +* + 8 ES +* + 10 R0 +* + 12 R1 +* + 14 R2 +* + 16 R3 +* + 18 R4 +* + 20 R5 +* + 22 R6 +* HIGH MEMORY +********************************************************************************************************* +*/ + +_trap(15) +_using(0x8F00) +void OSCtxSw (void) +{ + CPU_PushAllToUserStk(); /* Save the processor context on the USER stack */ + + CPU_USPSave(); /* Save DS:USP to Current Task's OS_TCB */ + + OSTaskSwHook(); /* 20~, Invoke user defined context switch hook */ + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; + + CPU_USPLoad(); /* Get DS:USP from High Priority Task's OS_TCB */ + + CPU_PopAllFromUserStk(); /* Restore processor registers from USER stack */ + + CPU_RetFromISR(); +} + + +/* +********************************************************************************************************* +* PERFORM A CONTEXT SWITCH (From an ISR) +* +* Description : This function is called when an ISR makes a higher priority task ready-to-run. +* +* Arguments : none +* +* Note(s) : 1) Upon entry, +* OSTCBCur points to the OS_TCB of the task to suspend +* OSTCBHighRdy points to the OS_TCB of the task to resume +* +* 2) The stack frame of the task to suspend looks as follows. +* +* LOW MEMORY +* ------- SSP + 0 Return PC to OSIntExit(), lower 16 bits +* | + 2 Return PC to OSIntExit(), upper 8 bits +* + 8 | + 4 Return PC to ISR, lower 16 bits +* | + 6 Return PC to ISR, upper 8 bits +* ------> + 8 PSW +* + 10 PC, upper 8 bits +* + 12 PC, lower 16 bits +* HIGH MEMORY +* +* 3) The stack frame of the task to resume looks as follows: +* +* LOW MEMORY +* OSTCBHighRdy->OSTCBStkPtr + 0 ----> Pointer to task (Lower 16 bits) +* + 2 Pointer to task (Upper 8 bits) +* + 4 PSW +* + 6 SSEL +* + 8 ES +* + 10 R0 +* + 12 R1 +* + 14 R2 +* + 16 R3 +* + 18 R4 +* + 20 R5 +* + 22 R6 +* HIGH MEMORY +********************************************************************************************************* +*/ + +void OSIntCtxSw (void) +{ + OSTaskSwHook(); /* 20~, Invoke user defined context switch hook */ + + OSTCBCur = OSTCBHighRdy; + OSPrioCur = OSPrioHighRdy; + + CPU_USPLoad(); /* Get DS:USP from High Priority Task's OS_TCB */ + + CPU_PopAllFromUserStk(); /* Restore processor registers from USER stack */ + + CPU_RetFromISR(); +} + + +/* +********************************************************************************************************* +* TICK ISR +* +* Notes: 1) Your ISR MUST be coded as shown below: +* a) Declare your function with the '_interrupt()' attribute passing it the vector number. +* b) Add the '_using()' attribute and pass it '0x8F00' to set the PSW +* c) Add the _'frame()' attribute and specify NO argument. +* d) declare the function as a function returning 'void' with 'void' argument +* e) Save the processor context as shown in the code below. +* f) Increment 'OSIntNesting' +* g) Invoke YOUR C ISR handler +* h) Call OSIntExit() at the end of your ISR +* i) Restore the processor registers as shown in the code below. DO NOT restore R0..R6. +* 2) You DON'T need to add an RETI instruction because it is also inserted by the Tasking +* compiler. +********************************************************************************************************* +*/ + +_interrupt(33) _using(0x8F00) _frame() void OSTickISR (void) +{ + CPU_PushAllToUserStk(); /* Save the processor context on the USER stack */ + + OSIntNesting++; /* Notify uC/OS-II of ISR entry */ + if (OSintNesting == 1) { + CPU_USPSave(); /* Save DS:USP to Current Task's OS_TCB */ + } + + OSTimeTick(); /* Process tick */ + OSIntExit(); /* Notify uC/OS-II of ISR exit */ + + CPU_PopAllFromUserStk(); /* Restore processor registers from USER stack */ +} + + +/* +********************************************************************************************************* +* INTERRUPT STUBS +********************************************************************************************************* +*/ + +_interrupt(1) _using(0x8F00) void OS_XAResetISR (void) +{ +} + +_interrupt(2) _using(0x8F00) void OS_XABreakptISR (void) +{ +} + +_interrupt(3) _using(0x8F00) void OS_XATraceISR (void) +{ +} + +_interrupt(4) _using(0x8F00) void OS_XAStkOvfISR (void) +{ +} + +_interrupt(5) _using(0x8F00) void OS_XADivide0ISR (void) +{ +} + +_interrupt(6) _using(0x8F00) void OS_XAUserRETIISR (void) +{ +} + +_trap(0) _using(0x8F00) void OS_XATrap00ISR (void) +{ +} + +_trap(1) _using(0x8F00) void OS_XATrap01ISR (void) +{ +} + +_trap(2) _using(0x8F00) void OS_XATrap02ISR (void) +{ +} + +_trap(3) _using(0x8F00) void OS_XATrap03ISR (void) +{ +} + +_trap(4) _using(0x8F00) void OS_XATrap04ISR (void) +{ +} + +_trap(5) _using(0x8F00) void OS_XATrap05ISR (void) +{ +} + +_trap(6) _using(0x8F00) void OS_XATrap06ISR (void) +{ +} + +_trap(7) _using(0x8F00) void OS_XATrap07ISR (void) +{ +} + +_trap(8) _using(0x8F00) void OS_XATrap08ISR (void) +{ +} + +_trap(9) _using(0x8F00) void OS_XATrap09ISR (void) +{ +} + +_trap(10) _using(0x8F00) void OS_XATrap10ISR (void) +{ +} + +_trap(11) _using(0x8F00) void OS_XATrap11ISR (void) +{ +} + +_trap(12) _using(0x8F00) void OS_XATrap12ISR (void) +{ +} + +_trap(13) _using(0x8F00) void OS_XATrap13ISR (void) +{ +} + +_trap(14) _using(0x8F00) void OS_XATrap14ISR (void) +{ +} + +#if 0 +_trap(15) _using(0x8F00) void OS_XATrap15ISR (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* EVENT INTERRUPTS +********************************************************************************************************* +*/ + +_interrupt(32) _using(0x8F00) _frame() void OS_XAExt0ISR (void) +{ +} + +#if 0 +_interrupt(33) _using(0x8F00) _frame() void OS_XATmr0ISR (void) +{ +} +#endif + +_interrupt(34) _using(0x8F00) _frame() void OS_XAExt1ISR (void) +{ +} + +_interrupt(35) _using(0x8F00) _frame() void OS_XATmr1ISR (void) +{ +} + +_interrupt(36) _using(0x8F00) _frame() void OS_XATmr2ISR (void) +{ +} + +_interrupt(37) _using(0x8F00) _frame() void OS_XAComm0RxISR (void) +{ +} + +_interrupt(38) _using(0x8F00) _frame() void OS_XAComm0TxISR (void) +{ +} + +_interrupt(39) _using(0x8F00) _frame() void OS_XAComm1RxISR (void) +{ +} + +_interrupt(40) _using(0x8F00) _frame() void OS_XAComm1TxISR (void) +{ +} + + +/* +********************************************************************************************************* +* SOFTWARE INTERRUPTS +********************************************************************************************************* +*/ + +_interrupt(64) _using(0x8F00) _frame() void OS_XASwi1ISR (void) +{ +} + +_interrupt(65) _using(0x8F00) _frame() void OS_XASwi2ISR (void) +{ +} + +_interrupt(66) _using(0x8F00) _frame() void OS_XASwi3ISR (void) +{ +} + +_interrupt(67) _using(0x8F00) _frame() void OS_XASwi4ISR (void) +{ +} + +_interrupt(68) _using(0x8F00) _frame() void OS_XASwi5ISR (void) +{ +} + +_interrupt(69) _using(0x8F00) _frame() void OS_XASwi6ISR (void) +{ +} + +_interrupt(70) _using(0x8F00) _frame() void OS_XASwi7ISR (void) +{ +} diff --git a/Ports/XA/Tasking/os_dbg.c b/Ports/XA/Tasking/os_dbg.c new file mode 100644 index 0000000..e9180c7 --- /dev/null +++ b/Ports/XA/Tasking/os_dbg.c @@ -0,0 +1,267 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0 + +INT32U const OSEndiannessTest = 0x12345678L; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameSize = OS_EVENT_NAME_SIZE; /* Size (in bytes) of event names */ +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0; +INT16U const OSEventTblSize = 0; +#endif + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0; +INT16U const OSFlagNodeSize = 0; +INT16U const OSFlagWidth = 0; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */ + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameSize = OS_MEM_NAME_SIZE; /* Size (in bytes) of partition names */ +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0; +INT16U const OSMemTblSize = 0; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameSize = OS_TASK_NAME_SIZE; /* Size (in bytes) of task names */ +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0 + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN > 0) && (OS_MAX_EVENTS > 0) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif +#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif +#if OS_TASK_STAT_EN > 0 + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif +#if OS_TICK_STEP_EN > 0 + + sizeof(OSTickStepState) +#endif +#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif +#if (OS_Q_EN > 0) && (OS_MAX_QS > 0) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif +#if OS_TIME_GET_SET_EN > 0 + + sizeof(OSTime) +#endif + + sizeof(OSIntNesting) + + sizeof(OSIntExitY) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALISATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +********************************************************************************************************* +*/ + +#if OS_VERSION >= 270 && OS_DEBUG_EN > 0 +void OSDebugInit (void) +{ + void *ptemp; + + + ptemp = (void *)&OSDebugEn; + + ptemp = (void *)&OSEndiannessTest; + + ptemp = (void *)&OSEventMax; + ptemp = (void *)&OSEventNameSize; + ptemp = (void *)&OSEventEn; + ptemp = (void *)&OSEventSize; + ptemp = (void *)&OSEventTblSize; + + ptemp = (void *)&OSFlagEn; + ptemp = (void *)&OSFlagGrpSize; + ptemp = (void *)&OSFlagNodeSize; + ptemp = (void *)&OSFlagWidth; + ptemp = (void *)&OSFlagMax; + ptemp = (void *)&OSFlagNameSize; + + ptemp = (void *)&OSLowestPrio; + + ptemp = (void *)&OSMboxEn; + + ptemp = (void *)&OSMemEn; + ptemp = (void *)&OSMemMax; + ptemp = (void *)&OSMemNameSize; + ptemp = (void *)&OSMemSize; + ptemp = (void *)&OSMemTblSize; + + ptemp = (void *)&OSMutexEn; + + ptemp = (void *)&OSPtrSize; + + ptemp = (void *)&OSQEn; + ptemp = (void *)&OSQMax; + ptemp = (void *)&OSQSize; + + ptemp = (void *)&OSRdyTblSize; + + ptemp = (void *)&OSSemEn; + + ptemp = (void *)&OSStkWidth; + + ptemp = (void *)&OSTaskCreateEn; + ptemp = (void *)&OSTaskCreateExtEn; + ptemp = (void *)&OSTaskDelEn; + ptemp = (void *)&OSTaskIdleStkSize; + ptemp = (void *)&OSTaskProfileEn; + ptemp = (void *)&OSTaskMax; + ptemp = (void *)&OSTaskNameSize; + ptemp = (void *)&OSTaskStatEn; + ptemp = (void *)&OSTaskStatStkSize; + ptemp = (void *)&OSTaskStatStkChkEn; + ptemp = (void *)&OSTaskSwHookEn; + + ptemp = (void *)&OSTCBPrioTblMax; + ptemp = (void *)&OSTCBSize; + + ptemp = (void *)&OSTicksPerSec; + ptemp = (void *)&OSTimeTickHookEn; + + ptemp = (void *)&OSVersionNbr; + + ptemp = (void *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Source/os.h b/Source/os.h new file mode 100644 index 0000000..d6b300b --- /dev/null +++ b/Source/os.h @@ -0,0 +1,36 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : os.h +* Version : V2.93.00 +********************************************************************************************************* +* Note : This file is included in the uC/OS-II for compatibility with uC/OS-III and should not be used +* in normal circumstances. +********************************************************************************************************* +*/ + +#ifndef OS_H +#define OS_H + +#include "ucos_ii.h" + + +typedef INT8U OS_ERR; + +#endif diff --git a/Source/os_core.c b/Source/os_core.c new file mode 100644 index 0000000..606a45f --- /dev/null +++ b/Source/os_core.c @@ -0,0 +1,2153 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* CORE FUNCTIONS +* +* Filename : os_core.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_CORE_C +#define OS_CORE_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#define OS_GLOBALS +#include +#endif + +/* +********************************************************************************************************* +* PRIORITY RESOLUTION TABLE +* +* Note: Index into table is bit pattern to resolve highest priority +* Indexed value corresponds to highest priority bit position (i.e. 0..7) +********************************************************************************************************* +*/ + +INT8U const OSUnMapTbl[256] = { + 0u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x00 to 0x0F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x10 to 0x1F */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x20 to 0x2F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x30 to 0x3F */ + 6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x40 to 0x4F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x50 to 0x5F */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x60 to 0x6F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x70 to 0x7F */ + 7u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x80 to 0x8F */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0x90 to 0x9F */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xA0 to 0xAF */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xB0 to 0xBF */ + 6u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xC0 to 0xCF */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xD0 to 0xDF */ + 5u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, /* 0xE0 to 0xEF */ + 4u, 0u, 1u, 0u, 2u, 0u, 1u, 0u, 3u, 0u, 1u, 0u, 2u, 0u, 1u, 0u /* 0xF0 to 0xFF */ +}; + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +********************************************************************************************************* +*/ + +static void OS_InitEventList(void); + +static void OS_InitMisc(void); + +static void OS_InitRdyList(void); + +static void OS_InitTaskIdle(void); + +#if OS_TASK_STAT_EN > 0u +static void OS_InitTaskStat(void); +#endif + +static void OS_InitTCBList(void); + +static void OS_SchedNew(void); + + +/* +********************************************************************************************************* +* GET THE NAME OF A SEMAPHORE, MUTEX, MAILBOX or QUEUE +* +* Description: This function is used to obtain the name assigned to a semaphore, mutex, mailbox or queue. +* +* Arguments : pevent is a pointer to the event group. 'pevent' can point either to a semaphore, +* a mutex, a mailbox or a queue. Where this function is concerned, the actual +* type is irrelevant. +* +* pname is a pointer to a pointer to an ASCII string that will receive the name of the semaphore, +* mutex, mailbox or queue. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the name was copied to 'pname' +* OS_ERR_EVENT_TYPE if 'pevent' is not pointing to the proper event +* control block type. +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_PEVENT_NULL if you passed a NULL pointer for 'pevent' +* OS_ERR_NAME_GET_ISR if you are trying to call this function from an ISR +* +* Returns : The length of the string or 0 if the 'pevent' is a NULL pointer. +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN) && (OS_EVENT_NAME_EN > 0u) +INT8U OSEventNameGet (OS_EVENT *pevent, + INT8U **pname, + INT8U *perr) +{ + INT8U len; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Is 'pevent' a NULL pointer? */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } + if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; + return (0u); + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_GET_ISR; + return (0u); + } + switch (pevent->OSEventType) { + case OS_EVENT_TYPE_SEM: + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_MBOX: + case OS_EVENT_TYPE_Q: + break; + + default: + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + OS_ENTER_CRITICAL(); + *pname = pevent->OSEventName; + len = OS_StrLen(*pname); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (len); +} +#endif + + +/* +********************************************************************************************************* +* ASSIGN A NAME TO A SEMAPHORE, MUTEX, MAILBOX or QUEUE +* +* Description: This function assigns a name to a semaphore, mutex, mailbox or queue. +* +* Arguments : pevent is a pointer to the event group. 'pevent' can point either to a semaphore, +* a mutex, a mailbox or a queue. Where this function is concerned, it doesn't +* matter the actual type. +* +* pname is a pointer to an ASCII string that will be used as the name of the semaphore, +* mutex, mailbox or queue. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_EVENT_TYPE if 'pevent' is not pointing to the proper event +* control block type. +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_PEVENT_NULL if you passed a NULL pointer for 'pevent' +* OS_ERR_NAME_SET_ISR if you called this function from an ISR +* +* Returns : None +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN) && (OS_EVENT_NAME_EN > 0u) +void OSEventNameSet (OS_EVENT *pevent, + INT8U *pname, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Is 'pevent' a NULL pointer? */ + *perr = OS_ERR_PEVENT_NULL; + return; + } + if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; + return; + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_SET_ISR; + return; + } + switch (pevent->OSEventType) { + case OS_EVENT_TYPE_SEM: + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_MBOX: + case OS_EVENT_TYPE_Q: + break; + + default: + *perr = OS_ERR_EVENT_TYPE; + return; + } + OS_ENTER_CRITICAL(); + pevent->OSEventName = pname; + OS_EXIT_CRITICAL(); + OS_TRACE_EVENT_NAME_SET(pevent, pname); + *perr = OS_ERR_NONE; +} +#endif + + +/* +********************************************************************************************************* +* PEND ON MULTIPLE EVENTS +* +* Description: This function waits for multiple events. If multiple events are ready at the start of the +* pend call, then all available events are returned as ready. If the task must pend on the +* multiple events, then only the first posted or aborted event is returned as ready. +* +* Arguments : pevents_pend is a pointer to a NULL-terminated array of event control blocks to wait for. +* +* pevents_rdy is a pointer to an array to return which event control blocks are available +* or ready. The size of the array MUST be greater than or equal to the size +* of the 'pevents_pend' array, including terminating NULL. +* +* pmsgs_rdy is a pointer to an array to return messages from any available message-type +* events. The size of the array MUST be greater than or equal to the size of +* the 'pevents_pend' array, excluding the terminating NULL. Since NULL +* messages are valid messages, this array cannot be NULL-terminated. Instead, +* every available message-type event returns its messages in the 'pmsgs_rdy' +* array at the same index as the event is returned in the 'pevents_rdy' array. +* All other 'pmsgs_rdy' array indices are filled with NULL messages. +* +* timeout is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for the resources up to the amount of time specified by this argument. +* If you specify 0, however, your task will wait forever for the specified +* events or, until the resources becomes available (or the events occur). +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE The call was successful and your task owns the resources +* or, the events you are waiting for occurred; check the +* 'pevents_rdy' array for which events are available. +* OS_ERR_PEND_ABORT The wait on the events was aborted; check the +* 'pevents_rdy' array for which events were aborted. +* OS_ERR_TIMEOUT The events were not received within the specified +* 'timeout'. +* OS_ERR_PEVENT_NULL If 'pevents_pend', 'pevents_rdy', or 'pmsgs_rdy' is a +* NULL pointer. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to an array of semaphores, +* mailboxes, and/or queues. +* OS_ERR_PEND_ISR If you called this function from an ISR and the result +* would lead to a suspension. +* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked. +* +* Returns : > 0 the number of events returned as ready or aborted. +* == 0 if no events are returned as ready because of timeout or upon error. +* +* Notes : 1) a. Validate 'pevents_pend' array as valid OS_EVENTs : +* +* semaphores, mailboxes, queues +* +* b. Return ALL available events and messages, if any +* +* c. Add current task priority as pending to each events's wait list +* Performed in OS_EventTaskWaitMulti() +* +* d. Wait on any of multiple events +* +* e. Remove current task priority as pending from each events's wait list +* Performed in OS_EventTaskRdy(), if events posted or aborted +* +* f. Return any event posted or aborted, if any +* else +* Return timeout +* +* 2) 'pevents_rdy' initialized to NULL PRIOR to all other validation or function handling in +* case of any error(s). +********************************************************************************************************* +*/ + +#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) +INT16U OSEventPendMulti (OS_EVENT **pevents_pend, + OS_EVENT **pevents_rdy, + void **pmsgs_rdy, + INT32U timeout, + INT8U *perr) +{ + OS_EVENT **pevents; + OS_EVENT *pevent; +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + OS_Q *pq; +#endif + BOOLEAN events_rdy; + INT16U events_rdy_nbr; + INT8U events_stat; +#if (OS_CRITICAL_METHOD == 3u) /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if (OS_ARG_CHK_EN > 0u) + if (pevents_pend == (OS_EVENT **)0) { /* Validate 'pevents_pend' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } + if (*pevents_pend == (OS_EVENT *)0) { /* Validate 'pevents_pend' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } + if (pevents_rdy == (OS_EVENT **)0) { /* Validate 'pevents_rdy' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } + if (pmsgs_rdy == (void **)0) { /* Validate 'pmsgs_rdy' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } +#endif + + *pevents_rdy = (OS_EVENT *)0; /* Init array to NULL in case of errors */ + + pevents = pevents_pend; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { + switch (pevent->OSEventType) { /* Validate event block types */ +#if (OS_SEM_EN > 0u) + case OS_EVENT_TYPE_SEM: + break; +#endif +#if (OS_MBOX_EN > 0u) + case OS_EVENT_TYPE_MBOX: + break; +#endif +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + case OS_EVENT_TYPE_Q: + break; +#endif + + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_FLAG: + default: + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + pevents++; + pevent = *pevents; + } + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + return (0u); + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + return (0u); + } + + events_rdy = OS_FALSE; + events_rdy_nbr = 0u; + events_stat = OS_STAT_RDY; + pevents = pevents_pend; + pevent = *pevents; + OS_ENTER_CRITICAL(); + while (pevent != (OS_EVENT *)0) { /* See if any events already available */ + switch (pevent->OSEventType) { +#if (OS_SEM_EN > 0u) + case OS_EVENT_TYPE_SEM: + if (pevent->OSEventCnt > 0u) { /* If semaphore count > 0, resource available; */ + pevent->OSEventCnt--; /* ... decrement semaphore, ... */ + *pevents_rdy++ = pevent; /* ... and return available semaphore event */ + events_rdy = OS_TRUE; + *pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores */ + events_rdy_nbr++; + + } else { + events_stat |= OS_STAT_SEM; /* Configure multi-pend for semaphore events */ + } + break; +#endif + +#if (OS_MBOX_EN > 0u) + case OS_EVENT_TYPE_MBOX: + if (pevent->OSEventPtr != (void *)0) { /* If mailbox NOT empty; ... */ + /* ... return available message, ... */ + *pmsgs_rdy++ = (void *)pevent->OSEventPtr; + pevent->OSEventPtr = (void *)0; + *pevents_rdy++ = pevent; /* ... and return available mailbox event */ + events_rdy = OS_TRUE; + events_rdy_nbr++; + + } else { + events_stat |= OS_STAT_MBOX; /* Configure multi-pend for mailbox events */ + } + break; +#endif + +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + case OS_EVENT_TYPE_Q: + pq = (OS_Q *)pevent->OSEventPtr; + if (pq->OSQEntries > 0u) { /* If queue NOT empty; ... */ + /* ... return available message, ... */ + *pmsgs_rdy++ = (void *)*pq->OSQOut++; + if (pq->OSQOut == pq->OSQEnd) { /* If OUT ptr at queue end, ... */ + pq->OSQOut = pq->OSQStart; /* ... wrap to queue start */ + } + pq->OSQEntries--; /* Update number of queue entries */ + *pevents_rdy++ = pevent; /* ... and return available queue event */ + events_rdy = OS_TRUE; + events_rdy_nbr++; + + } else { + events_stat |= OS_STAT_Q; /* Configure multi-pend for queue events */ + } + break; +#endif + + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_FLAG: + default: + OS_EXIT_CRITICAL(); + *pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */ + *perr = OS_ERR_EVENT_TYPE; + return (events_rdy_nbr); + } + pevents++; + pevent = *pevents; + } + + if ( events_rdy == OS_TRUE) { /* Return any events already available */ + *pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (events_rdy_nbr); + } + + /* Otherwise, must wait until any event occurs */ + OSTCBCur->OSTCBStat |= events_stat | /* Resource not available, ... */ + OS_STAT_MULTI; /* ... pend on multiple events */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ + OS_EventTaskWaitMulti(pevents_pend); /* Suspend task until events or timeout occurs */ + + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next highest priority task ready */ + OS_ENTER_CRITICAL(); + + switch (OSTCBCur->OSTCBStatPend) { /* Handle event posted, aborted, or timed-out */ + case OS_STAT_PEND_OK: + case OS_STAT_PEND_ABORT: + pevent = OSTCBCur->OSTCBEventMultiRdy; + if (pevent != (OS_EVENT *)0) { /* If task event ptr != NULL, ... */ + *pevents_rdy++ = pevent; /* ... return available event ... */ + *pevents_rdy = (OS_EVENT *)0; /* ... & NULL terminate return event array */ + events_rdy_nbr = 1; + + } else { /* Else NO event available, handle as timeout */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_TO; + OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend); + } + break; + + case OS_STAT_PEND_TO: /* If events timed out, ... */ + default: /* ... remove task from events' wait lists */ + OS_EventTaskRemoveMulti(OSTCBCur, pevents_pend); + break; + } + + switch (OSTCBCur->OSTCBStatPend) { + case OS_STAT_PEND_OK: + switch (pevent->OSEventType) { /* Return event's message */ +#if (OS_SEM_EN > 0u) + case OS_EVENT_TYPE_SEM: + *pmsgs_rdy++ = (void *)0; /* NO message returned for semaphores */ + break; +#endif + +#if ((OS_MBOX_EN > 0u) || \ + ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))) + case OS_EVENT_TYPE_MBOX: + case OS_EVENT_TYPE_Q: + *pmsgs_rdy++ = (void *)OSTCBCur->OSTCBMsg; /* Return received message */ + break; +#endif + + case OS_EVENT_TYPE_MUTEX: + case OS_EVENT_TYPE_FLAG: + default: + OS_EXIT_CRITICAL(); + *pevents_rdy = (OS_EVENT *)0; /* NULL terminate return event array */ + *perr = OS_ERR_EVENT_TYPE; + return (events_rdy_nbr); + } + *perr = OS_ERR_NONE; + break; + + case OS_STAT_PEND_ABORT: + *pmsgs_rdy++ = (void *)0; /* NO message returned for abort */ + *perr = OS_ERR_PEND_ABORT; /* Indicate that event aborted */ + break; + + case OS_STAT_PEND_TO: + default: + *pmsgs_rdy++ = (void *)0; /* NO message returned for timeout */ + *perr = OS_ERR_TIMEOUT; /* Indicate that events timed out */ + break; + } + + OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; /* Clear event pointers */ + OSTCBCur->OSTCBEventMultiRdy = (OS_EVENT *)0; +#if ((OS_MBOX_EN > 0u) || \ + ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u))) + OSTCBCur->OSTCBMsg = (void *)0; /* Clear task message */ +#endif + OS_EXIT_CRITICAL(); + + return (events_rdy_nbr); +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZATION +* +* Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to +* creating any uC/OS-II object and, prior to calling OSStart(). +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +void OSInit (void) +{ +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + INT8U err; +#endif +#endif + + OSInitHookBegin(); /* Call port specific initialization code */ + + OS_InitMisc(); /* Initialize miscellaneous variables */ + + OS_InitRdyList(); /* Initialize the Ready List */ + + OS_InitTCBList(); /* Initialize the free list of OS_TCBs */ + + OS_InitEventList(); /* Initialize the free list of OS_EVENTs */ + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + OS_FlagInit(); /* Initialize the event flag structures */ +#endif + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + OS_MemInit(); /* Initialize the memory manager */ +#endif + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + OS_QInit(); /* Initialize the message queue structures */ +#endif + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + OS_TLS_Init(&err); /* Initialize TLS, before creating tasks */ + if (err != OS_ERR_NONE) { + return; + } +#endif +#endif + + OS_InitTaskIdle(); /* Create the Idle Task */ +#if OS_TASK_STAT_EN > 0u + OS_InitTaskStat(); /* Create the Statistic Task */ +#endif + +#if OS_TMR_EN > 0u + OSTmr_Init(); /* Initialize the Timer Manager */ +#endif + + OSInitHookEnd(); /* Call port specific init. code */ + +#if OS_DEBUG_EN > 0u + OSDebugInit(); +#endif +} + + +/* +********************************************************************************************************* +* ENTER ISR +* +* Description: This function is used to notify uC/OS-II that you are about to service an interrupt +* service routine (ISR). This allows uC/OS-II to keep track of interrupt nesting and thus +* only perform rescheduling at the last nested ISR. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function should be called with interrupts already disabled +* 2) Your ISR can directly increment OSIntNesting without calling this function because +* OSIntNesting has been declared 'global'. +* 3) You MUST still call OSIntExit() even though you increment OSIntNesting directly. +* 4) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call +* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the +* end of the ISR. +* 5) You are allowed to nest interrupts up to 255 levels deep. +* 6) I removed the OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL() around the increment because +* OSIntEnter() is always called with interrupts disabled. +********************************************************************************************************* +*/ + +void OSIntEnter (void) +{ + if (OSRunning == OS_TRUE) { + if (OSIntNesting < 255u) { + OSIntNesting++; /* Increment ISR nesting level */ + } + OS_TRACE_ISR_ENTER(); + } +} + + +/* +********************************************************************************************************* +* EXIT ISR +* +* Description: This function is used to notify uC/OS-II that you have completed servicing an ISR. When +* the last nested ISR has completed, uC/OS-II will call the scheduler to determine whether +* a new, high-priority task, is ready to run. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) You MUST invoke OSIntEnter() and OSIntExit() in pair. In other words, for every call +* to OSIntEnter() at the beginning of the ISR you MUST have a call to OSIntExit() at the +* end of the ISR. +* 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock()) +********************************************************************************************************* +*/ + +void OSIntExit (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSRunning == OS_TRUE) { + OS_ENTER_CRITICAL(); + if (OSIntNesting > 0u) { /* Prevent OSIntNesting from wrapping */ + OSIntNesting--; + } + if (OSIntNesting == 0u) { /* Reschedule only if all ISRs complete ... */ + if (OSLockNesting == 0u) { /* ... and not locked. */ + OS_SchedNew(); + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; + if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ +#if OS_TASK_PROFILE_EN > 0u + OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ +#endif + OSCtxSwCtr++; /* Keep track of the number of ctx switches */ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + OS_TLS_TaskSw(); +#endif +#endif + OS_TRACE_ISR_EXIT_TO_SCHEDULER(); + + OSIntCtxSw(); /* Perform interrupt level ctx switch */ + } else { + OS_TRACE_ISR_EXIT(); + } + } else { + OS_TRACE_ISR_EXIT(); + } + } else { + OS_TRACE_ISR_EXIT(); + } + + OS_EXIT_CRITICAL(); + } +} + + +/* +********************************************************************************************************* +* INDICATE THAT IT'S NO LONGER SAFE TO CREATE OBJECTS +* +* Description: This function is called by the application code to indicate that all initialization has +* been completed and that kernel objects are no longer allowed to be created. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) You should call this function when you no longer want to allow application code to +* create kernel objects. +* 2) You need to define the macro 'OS_SAFETY_CRITICAL_IEC61508' +********************************************************************************************************* +*/ + +#ifdef OS_SAFETY_CRITICAL_IEC61508 +void OSSafetyCriticalStart (void) +{ + OSSafetyCriticalStartFlag = OS_TRUE; +} + +#endif + + +/* +********************************************************************************************************* +* PREVENT SCHEDULING +* +* Description: This function is used to prevent rescheduling to take place. This allows your application +* to prevent context switches until you are ready to permit context switching. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair. In other words, for every +* call to OSSchedLock() you MUST have a call to OSSchedUnlock(). +********************************************************************************************************* +*/ + +#if OS_SCHED_LOCK_EN > 0u +void OSSchedLock (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */ + OS_ENTER_CRITICAL(); + if (OSIntNesting == 0u) { /* Can't call from an ISR */ + if (OSLockNesting < 255u) { /* Prevent OSLockNesting from wrapping back to 0 */ + OSLockNesting++; /* Increment lock nesting level */ + } + } + OS_EXIT_CRITICAL(); + } +} +#endif + + +/* +********************************************************************************************************* +* ENABLE SCHEDULING +* +* Description: This function is used to re-allow rescheduling. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) You MUST invoke OSSchedLock() and OSSchedUnlock() in pair. In other words, for every +* call to OSSchedLock() you MUST have a call to OSSchedUnlock(). +********************************************************************************************************* +*/ + +#if OS_SCHED_LOCK_EN > 0u +void OSSchedUnlock (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSRunning == OS_TRUE) { /* Make sure multitasking is running */ + OS_ENTER_CRITICAL(); + if (OSIntNesting == 0u) { /* Can't call from an ISR */ + if (OSLockNesting > 0u) { /* Do not decrement if already 0 */ + OSLockNesting--; /* Decrement lock nesting level */ + if (OSLockNesting == 0u) { /* See if scheduler is enabled */ + OS_EXIT_CRITICAL(); + OS_Sched(); /* See if a HPT is ready */ + } else { + OS_EXIT_CRITICAL(); + } + } else { + OS_EXIT_CRITICAL(); + } + } else { + OS_EXIT_CRITICAL(); + } + } +} +#endif + + +/* +********************************************************************************************************* +* START MULTITASKING +* +* Description: This function is used to start the multitasking process which lets uC/OS-II manages the +* task that you have created. Before you can call OSStart(), you MUST have called OSInit() +* and you MUST have created at least one task. +* +* Arguments : none +* +* Returns : none +* +* Note : OSStartHighRdy() MUST: +* a) Call OSTaskSwHook() then, +* b) Set OSRunning to OS_TRUE. +* c) Load the context of the task pointed to by OSTCBHighRdy. +* d_ Execute the task. +********************************************************************************************************* +*/ + +void OSStart (void) +{ + if (OSRunning == OS_FALSE) { + OS_SchedNew(); /* Find highest priority's task priority number */ + OSPrioCur = OSPrioHighRdy; + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */ + OSTCBCur = OSTCBHighRdy; + OSStartHighRdy(); /* Execute target specific code to start task */ + } +} + + +/* +********************************************************************************************************* +* STATISTICS INITIALIZATION +* +* Description: This function is called by your application to establish CPU usage by first determining +* how high a 32-bit counter would count to in 1 second if no other tasks were to execute +* during that time. CPU usage is then determined by a low priority task which keeps track +* of this 32-bit counter every second but this time, with other tasks running. CPU usage is +* determined by: +* +* OSIdleCtr +* CPU Usage (%) = 100 * (1 - ------------) +* OSIdleCtrMax +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0u +void OSStatInit (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OSTimeDly(2u); /* Synchronize with clock tick */ + OS_ENTER_CRITICAL(); + OSIdleCtr = 0uL; /* Clear idle counter */ + OS_EXIT_CRITICAL(); + OSTimeDly(OS_TICKS_PER_SEC / 10u); /* Determine MAX. idle counter value for 1/10 second */ + OS_ENTER_CRITICAL(); + OSIdleCtrMax = OSIdleCtr; /* Store maximum idle counter count in 1/10 second */ + OSStatRdy = OS_TRUE; + OS_EXIT_CRITICAL(); +} +#endif + + +/* +********************************************************************************************************* +* PROCESS SYSTEM TICK +* +* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known +* as a 'clock tick'). This function should be called by the ticker ISR but, can also be +* called by a high priority task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +void OSTimeTick (void) +{ + OS_TCB *ptcb; +#if OS_TICK_STEP_EN > 0u + BOOLEAN step; +#endif +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_TIME_TICK_HOOK_EN > 0u + OSTimeTickHook(); /* Call user definable hook */ +#endif +#if OS_TIME_GET_SET_EN > 0u + OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter */ + OSTime++; + OS_TRACE_TICK_INCREMENT(OSTime); + OS_EXIT_CRITICAL(); +#endif + if (OSRunning == OS_TRUE) { +#if OS_TICK_STEP_EN > 0u + switch (OSTickStepState) { /* Determine whether we need to process a tick */ + case OS_TICK_STEP_DIS: /* Yes, stepping is disabled */ + step = OS_TRUE; + break; + + case OS_TICK_STEP_WAIT: /* No, waiting for uC/OS-View to set ... */ + step = OS_FALSE; /* .. OSTickStepState to OS_TICK_STEP_ONCE */ + break; + + case OS_TICK_STEP_ONCE: /* Yes, process tick once and wait for next ... */ + step = OS_TRUE; /* ... step command from uC/OS-View */ + OSTickStepState = OS_TICK_STEP_WAIT; + break; + + default: /* Invalid case, correct situation */ + step = OS_TRUE; + OSTickStepState = OS_TICK_STEP_DIS; + break; + } + if (step == OS_FALSE) { /* Return if waiting for step command */ + return; + } +#endif + ptcb = OSTCBList; /* Point at first TCB in TCB list */ + while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) { /* Go through all TCBs in TCB list */ + OS_ENTER_CRITICAL(); + if (ptcb->OSTCBDly != 0u) { /* No, Delayed or waiting for event with TO */ + ptcb->OSTCBDly--; /* Decrement nbr of ticks to end of delay */ + if (ptcb->OSTCBDly == 0u) { /* Check for timeout */ + + if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { + ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_PEND_ANY; /* Yes, Clear status flag */ + ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */ + } else { + ptcb->OSTCBStatPend = OS_STAT_PEND_OK; + } + + if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */ + OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OS_TRACE_TASK_READY(ptcb); + } + } + } + ptcb = ptcb->OSTCBNext; /* Point at next TCB in TCB list */ + OS_EXIT_CRITICAL(); + } + } +} + + +/* +********************************************************************************************************* +* GET VERSION +* +* Description: This function is used to return the version number of uC/OS-II. The returned value +* corresponds to uC/OS-II's version number multiplied by 10000. In other words, version +* 2.01.00 would be returned as 20100. +* +* Arguments : none +* +* Returns : The version number of uC/OS-II multiplied by 10000. +********************************************************************************************************* +*/ + +INT16U OSVersion (void) +{ + return (OS_VERSION); +} + + +/* +********************************************************************************************************* +* DUMMY FUNCTION +* +* Description: This function doesn't do anything. It is called by OSTaskDel(). +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0u +void OS_Dummy (void) +{ +} +#endif + + +/* +********************************************************************************************************* +* MAKE TASK READY TO RUN BASED ON EVENT OCCURING +* +* Description: This function is called by other uC/OS-II services and is used to ready a task that was +* waiting for an event to occur. +* +* Arguments : pevent is a pointer to the event control block corresponding to the event. +* +* pmsg is a pointer to a message. This pointer is used by message oriented services +* such as MAILBOXEs and QUEUEs. The pointer is not used when called by other +* service functions. +* +* msk is a mask that is used to clear the status byte of the TCB. For example, +* OSSemPost() will pass OS_STAT_SEM, OSMboxPost() will pass OS_STAT_MBOX etc. +* +* pend_stat is used to indicate the readied task's pending status: +* +* OS_STAT_PEND_OK Task ready due to a post (or delete), not a timeout or +* an abort. +* OS_STAT_PEND_ABORT Task ready due to an abort. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +INT8U OS_EventTaskRdy (OS_EVENT *pevent, + void *pmsg, + INT8U msk, + INT8U pend_stat) +{ + OS_TCB *ptcb; + INT8U y; + INT8U x; + INT8U prio; +#if OS_LOWEST_PRIO > 63u + OS_PRIO *ptbl; +#endif + + +#if OS_LOWEST_PRIO <= 63u + y = OSUnMapTbl[pevent->OSEventGrp]; /* Find HPT waiting for message */ + x = OSUnMapTbl[pevent->OSEventTbl[y]]; + prio = (INT8U)((y << 3u) + x); /* Find priority of task getting the msg */ +#else + if ((pevent->OSEventGrp & 0xFFu) != 0u) { /* Find HPT waiting for message */ + y = OSUnMapTbl[ pevent->OSEventGrp & 0xFFu]; + } else { + y = OSUnMapTbl[(OS_PRIO)(pevent->OSEventGrp >> 8u) & 0xFFu] + 8u; + } + ptbl = &pevent->OSEventTbl[y]; + if ((*ptbl & 0xFFu) != 0u) { + x = OSUnMapTbl[*ptbl & 0xFFu]; + } else { + x = OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u; + } + prio = (INT8U)((y << 4u) + x); /* Find priority of task getting the msg */ +#endif + + ptcb = OSTCBPrioTbl[prio]; /* Point to this task's OS_TCB */ + ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from readying task */ +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) + ptcb->OSTCBMsg = pmsg; /* Send message directly to waiting task */ +#else + pmsg = pmsg; /* Prevent compiler warning if not used */ +#endif + ptcb->OSTCBStat &= (INT8U)~msk; /* Clear bit associated with event type */ + ptcb->OSTCBStatPend = pend_stat; /* Set pend status of post or abort */ + /* See if task is ready (could be susp'd) */ + if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { + OSRdyGrp |= ptcb->OSTCBBitY; /* Put task in the ready to run list */ + OSRdyTbl[y] |= ptcb->OSTCBBitX; + OS_TRACE_TASK_READY(ptcb); + } + + OS_EventTaskRemove(ptcb, pevent); /* Remove this task from event wait list */ +#if (OS_EVENT_MULTI_EN > 0u) + if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { /* Remove this task from events' wait lists */ + OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr); + ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; /* No longer pending on multi list */ + ptcb->OSTCBEventMultiRdy = (OS_EVENT *)pevent;/* Return event as first multi-pend event ready*/ + } +#endif + + return (prio); +} +#endif + + +/* +********************************************************************************************************* +* MAKE TASK WAIT FOR EVENT TO OCCUR +* +* Description: This function is called by other uC/OS-II services to suspend a task because an event has +* not occurred. +* +* Arguments : pevent is a pointer to the event control block for which the task will be waiting for. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +void OS_EventTaskWait (OS_EVENT *pevent) +{ + INT8U y; + + + OSTCBCur->OSTCBEventPtr = pevent; /* Store ptr to ECB in TCB */ + + pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; /* Put task in waiting list */ + pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; + + y = OSTCBCur->OSTCBY; /* Task no longer ready */ + OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; + OS_TRACE_TASK_SUSPENDED(OSTCBCur); + if (OSRdyTbl[y] == 0u) { /* Clear event grp bit if this was only task pending */ + OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; + } +} +#endif + + +/* +********************************************************************************************************* +* MAKE TASK WAIT FOR ANY OF MULTIPLE EVENTS TO OCCUR +* +* Description: This function is called by other uC/OS-II services to suspend a task because any one of +* multiple events has not occurred. +* +* Arguments : pevents_wait is a pointer to an array of event control blocks, NULL-terminated, for +* which the task will be waiting for. +* +* Returns : none. +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) +void OS_EventTaskWaitMulti (OS_EVENT **pevents_wait) +{ + OS_EVENT **pevents; + OS_EVENT *pevent; + INT8U y; + + + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)pevents_wait; /* Store ptr to ECBs in TCB */ + OSTCBCur->OSTCBEventMultiRdy = (OS_EVENT *)0; + + pevents = pevents_wait; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { /* Put task in waiting lists */ + pevent->OSEventTbl[OSTCBCur->OSTCBY] |= OSTCBCur->OSTCBBitX; + pevent->OSEventGrp |= OSTCBCur->OSTCBBitY; + pevents++; + pevent = *pevents; + } + + y = OSTCBCur->OSTCBY; /* Task no longer ready */ + OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; + OS_TRACE_TASK_SUSPENDED(OSTCBCur); + if (OSRdyTbl[y] == 0u) { /* Clear event grp bit if this was only task pending */ + OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; + } +} +#endif + + +/* +********************************************************************************************************* +* REMOVE TASK FROM EVENT WAIT LIST +* +* Description: Remove a task from an event's wait list. +* +* Arguments : ptcb is a pointer to the task to remove. +* +* pevent is a pointer to the event control block. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +void OS_EventTaskRemove (OS_TCB *ptcb, + OS_EVENT *pevent) +{ + INT8U y; + + + y = ptcb->OSTCBY; + pevent->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Remove task from wait list */ + if (pevent->OSEventTbl[y] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Unlink OS_EVENT from OS_TCB */ +} +#endif + + +/* +********************************************************************************************************* +* REMOVE TASK FROM MULTIPLE EVENTS WAIT LISTS +* +* Description: Remove a task from multiple events' wait lists. +* +* Arguments : ptcb is a pointer to the task to remove. +* +* pevents_multi is a pointer to the array of event control blocks, NULL-terminated. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if ((OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u)) +void OS_EventTaskRemoveMulti (OS_TCB *ptcb, + OS_EVENT **pevents_multi) +{ + OS_EVENT **pevents; + OS_EVENT *pevent; + INT8U y; + OS_PRIO bity; + OS_PRIO bitx; + + + y = ptcb->OSTCBY; + bity = ptcb->OSTCBBitY; + bitx = ptcb->OSTCBBitX; + pevents = pevents_multi; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { /* Remove task from all events' wait lists */ + pevent->OSEventTbl[y] &= (OS_PRIO)~bitx; + if (pevent->OSEventTbl[y] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~bity; + } + pevents++; + pevent = *pevents; + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE EVENT CONTROL BLOCK'S WAIT LIST +* +* Description: This function is called by other uC/OS-II services to initialize the event wait list. +* +* Arguments : pevent is a pointer to the event control block allocated to the event. +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ +#if (OS_EVENT_EN) +void OS_EventWaitListInit (OS_EVENT *pevent) +{ + INT8U i; + + + pevent->OSEventGrp = 0u; /* No task waiting on event */ + for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { + pevent->OSEventTbl[i] = 0u; + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE FREE LIST OF EVENT CONTROL BLOCKS +* +* Description: This function is called by OSInit() to initialize the free list of event control blocks. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitEventList (void) +{ +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +#if (OS_MAX_EVENTS > 1u) + INT16U ix; + INT16U ix_next; + OS_EVENT *pevent1; + OS_EVENT *pevent2; + + + OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); /* Clear the event table */ + for (ix = 0u; ix < (OS_MAX_EVENTS - 1u); ix++) { /* Init. list of free EVENT control blocks */ + ix_next = ix + 1u; + pevent1 = &OSEventTbl[ix]; + pevent2 = &OSEventTbl[ix_next]; + pevent1->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent1->OSEventPtr = pevent2; +#if OS_EVENT_NAME_EN > 0u + pevent1->OSEventName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + } + pevent1 = &OSEventTbl[ix]; + pevent1->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent1->OSEventPtr = (OS_EVENT *)0; +#if OS_EVENT_NAME_EN > 0u + pevent1->OSEventName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + OSEventFreeList = &OSEventTbl[0]; +#else + OSEventFreeList = &OSEventTbl[0]; /* Only have ONE event control block */ + OSEventFreeList->OSEventType = OS_EVENT_TYPE_UNUSED; + OSEventFreeList->OSEventPtr = (OS_EVENT *)0; +#if OS_EVENT_NAME_EN > 0u + OSEventFreeList->OSEventName = (INT8U *)"?"; /* Unknown name */ +#endif +#endif +#endif +} + + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE MISCELLANEOUS VARIABLES +* +* Description: This function is called by OSInit() to initialize miscellaneous variables. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitMisc (void) +{ +#if OS_TIME_GET_SET_EN > 0u + OSTime = 0uL; /* Clear the 32-bit system clock */ +#endif + + OSIntNesting = 0u; /* Clear the interrupt nesting counter */ + OSLockNesting = 0u; /* Clear the scheduling lock counter */ + + OSTaskCtr = 0u; /* Clear the number of tasks */ + + OSRunning = OS_FALSE; /* Indicate that multitasking not started */ + + OSCtxSwCtr = 0u; /* Clear the context switch counter */ + OSIdleCtr = 0uL; /* Clear the 32-bit idle counter */ + +#if OS_TASK_STAT_EN > 0u + OSIdleCtrRun = 0uL; + OSIdleCtrMax = 0uL; + OSStatRdy = OS_FALSE; /* Statistic task is not ready */ +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + OSSafetyCriticalStartFlag = OS_FALSE; /* Still allow creation of objects */ +#endif + +#if OS_TASK_REG_TBL_SIZE > 0u + OSTaskRegNextAvailID = 0u; /* Initialize the task register ID */ +#endif +} + + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE READY LIST +* +* Description: This function is called by OSInit() to initialize the Ready List. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitRdyList (void) +{ + INT8U i; + + + OSRdyGrp = 0u; /* Clear the ready list */ + for (i = 0u; i < OS_RDY_TBL_SIZE; i++) { + OSRdyTbl[i] = 0u; + } + + OSPrioCur = 0u; + OSPrioHighRdy = 0u; + + OSTCBHighRdy = (OS_TCB *)0; + OSTCBCur = (OS_TCB *)0; +} + + +/* +********************************************************************************************************* +* INITIALIZATION +* CREATING THE IDLE TASK +* +* Description: This function creates the Idle Task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitTaskIdle (void) +{ +#if OS_TASK_NAME_EN > 0u + INT8U err; +#endif + + +#if OS_TASK_CREATE_EXT_EN > 0u + #if OS_STK_GROWTH == 1u + (void)OSTaskCreateExt(OS_TaskIdle, + (void *)0, /* No arguments passed to OS_TaskIdle() */ + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Top-Of-Stack */ + OS_TASK_IDLE_PRIO, /* Lowest priority level */ + OS_TASK_IDLE_ID, + &OSTaskIdleStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_IDLE_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ + #else + (void)OSTaskCreateExt(OS_TaskIdle, + (void *)0, /* No arguments passed to OS_TaskIdle() */ + &OSTaskIdleStk[0], /* Set Top-Of-Stack */ + OS_TASK_IDLE_PRIO, /* Lowest priority level */ + OS_TASK_IDLE_ID, + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u],/* Set Bottom-Of-Stack */ + OS_TASK_IDLE_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack checking + clear stack */ + #endif +#else + #if OS_STK_GROWTH == 1u + (void)OSTaskCreate(OS_TaskIdle, + (void *)0, + &OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1u], + OS_TASK_IDLE_PRIO); + #else + (void)OSTaskCreate(OS_TaskIdle, + (void *)0, + &OSTaskIdleStk[0], + OS_TASK_IDLE_PRIO); + #endif +#endif + +#if OS_TASK_NAME_EN > 0u + OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)(void *)"uC/OS-II Idle", &err); +#endif +} + + +/* +********************************************************************************************************* +* INITIALIZATION +* CREATING THE STATISTIC TASK +* +* Description: This function creates the Statistic Task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0u +static void OS_InitTaskStat (void) +{ +#if OS_TASK_NAME_EN > 0u + INT8U err; +#endif + + +#if OS_TASK_CREATE_EXT_EN > 0u + #if OS_STK_GROWTH == 1u + (void)OSTaskCreateExt(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO, /* One higher than the idle task */ + OS_TASK_STAT_ID, + &OSTaskStatStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_STAT_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ + #else + (void)OSTaskCreateExt(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[0], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO, /* One higher than the idle task */ + OS_TASK_STAT_ID, + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Bottom-Of-Stack */ + OS_TASK_STAT_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear */ + #endif +#else + #if OS_STK_GROWTH == 1u + (void)OSTaskCreate(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1u], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO); /* One higher than the idle task */ + #else + (void)OSTaskCreate(OS_TaskStat, + (void *)0, /* No args passed to OS_TaskStat()*/ + &OSTaskStatStk[0], /* Set Top-Of-Stack */ + OS_TASK_STAT_PRIO); /* One higher than the idle task */ + #endif +#endif + +#if OS_TASK_NAME_EN > 0u + OSTaskNameSet(OS_TASK_STAT_PRIO, (INT8U *)(void *)"uC/OS-II Stat", &err); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE FREE LIST OF TASK CONTROL BLOCKS +* +* Description: This function is called by OSInit() to initialize the free list of OS_TCBs. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +static void OS_InitTCBList (void) +{ + INT8U ix; + INT8U ix_next; + OS_TCB *ptcb1; + OS_TCB *ptcb2; + + + OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl)); /* Clear all the TCBs */ + OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl)); /* Clear the priority table */ + for (ix = 0u; ix < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u); ix++) { /* Init. list of free TCBs */ + ix_next = ix + 1u; + ptcb1 = &OSTCBTbl[ix]; + ptcb2 = &OSTCBTbl[ix_next]; + ptcb1->OSTCBNext = ptcb2; +#if OS_TASK_NAME_EN > 0u + ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + } + ptcb1 = &OSTCBTbl[ix]; + ptcb1->OSTCBNext = (OS_TCB *)0; /* Last OS_TCB */ +#if OS_TASK_NAME_EN > 0u + ptcb1->OSTCBTaskName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + OSTCBList = (OS_TCB *)0; /* TCB lists initializations */ + OSTCBFreeList = &OSTCBTbl[0]; +} + + +/* +********************************************************************************************************* +* CLEAR A SECTION OF MEMORY +* +* Description: This function is called by other uC/OS-II services to clear a contiguous block of RAM. +* +* Arguments : pdest is the start of the RAM to clear (i.e. write 0x00 to) +* +* size is the number of bytes to clear. +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Note that we can only clear up to 64K bytes of RAM. This is not an issue because none +* of the uses of this function gets close to this limit. +* 3) The clear is done one byte at a time since this will work on any processor irrespective +* of the alignment of the destination. +********************************************************************************************************* +*/ + +void OS_MemClr (INT8U *pdest, + INT16U size) +{ + while (size > 0u) { + *pdest++ = (INT8U)0; + size--; + } +} + + +/* +********************************************************************************************************* +* COPY A BLOCK OF MEMORY +* +* Description: This function is called by other uC/OS-II services to copy a block of memory from one +* location to another. +* +* Arguments : pdest is a pointer to the 'destination' memory block +* +* psrc is a pointer to the 'source' memory block +* +* size is the number of bytes to copy. +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. There is +* no provision to handle overlapping memory copy. However, that's not a problem since this +* is not a situation that will happen. +* 2) Note that we can only copy up to 64K bytes of RAM +* 3) The copy is done one byte at a time since this will work on any processor irrespective +* of the alignment of the source and destination. +********************************************************************************************************* +*/ + +void OS_MemCopy (INT8U *pdest, + INT8U *psrc, + INT16U size) +{ + while (size > 0u) { + *pdest++ = *psrc++; + size--; + } +} + + +/* +********************************************************************************************************* +* SCHEDULER +* +* Description: This function is called by other uC/OS-II services to determine whether a new, high +* priority task has been made ready to run. This function is invoked by TASK level code +* and is not used to reschedule tasks from ISRs (see OSIntExit() for ISR rescheduling). +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Rescheduling is prevented when the scheduler is locked (see OS_SchedLock()) +********************************************************************************************************* +*/ + +void OS_Sched (void) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OS_ENTER_CRITICAL(); + if (OSIntNesting == 0u) { /* Schedule only if all ISRs done and ... */ + if (OSLockNesting == 0u) { /* ... scheduler is not locked */ + OS_SchedNew(); + OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; + if (OSPrioHighRdy != OSPrioCur) { /* No Ctx Sw if current task is highest rdy */ +#if OS_TASK_PROFILE_EN > 0u + OSTCBHighRdy->OSTCBCtxSwCtr++; /* Inc. # of context switches to this task */ +#endif + OSCtxSwCtr++; /* Increment context switch counter */ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + OS_TLS_TaskSw(); +#endif +#endif + + OS_TASK_SW(); /* Perform a context switch */ + } + } + } + OS_EXIT_CRITICAL(); +} + + +/* +********************************************************************************************************* +* FIND HIGHEST PRIORITY TASK READY TO RUN +* +* Description: This function is called by other uC/OS-II services to determine the highest priority task +* that is ready to run. The global variable 'OSPrioHighRdy' is changed accordingly. +* +* Arguments : none +* +* Returns : none +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) Interrupts are assumed to be disabled when this function is called. +********************************************************************************************************* +*/ + +static void OS_SchedNew (void) +{ +#if OS_LOWEST_PRIO <= 63u /* See if we support up to 64 tasks */ + INT8U y; + + + y = OSUnMapTbl[OSRdyGrp]; + OSPrioHighRdy = (INT8U)((y << 3u) + OSUnMapTbl[OSRdyTbl[y]]); +#else /* We support up to 256 tasks */ + INT8U y; + OS_PRIO *ptbl; + + + if ((OSRdyGrp & 0xFFu) != 0u) { + y = OSUnMapTbl[OSRdyGrp & 0xFFu]; + } else { + y = OSUnMapTbl[(OS_PRIO)(OSRdyGrp >> 8u) & 0xFFu] + 8u; + } + ptbl = &OSRdyTbl[y]; + if ((*ptbl & 0xFFu) != 0u) { + OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(*ptbl & 0xFFu)]); + } else { + OSPrioHighRdy = (INT8U)((y << 4u) + OSUnMapTbl[(OS_PRIO)(*ptbl >> 8u) & 0xFFu] + 8u); + } +#endif +} + + +/* +********************************************************************************************************* +* DETERMINE THE LENGTH OF AN ASCII STRING +* +* Description: This function is called by other uC/OS-II services to determine the size of an ASCII string +* (excluding the NUL character). +* +* Arguments : psrc is a pointer to the string for which we need to know the size. +* +* Returns : The size of the string (excluding the NUL terminating character) +* +* Notes : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* 2) The string to check must be less than 255 characters long. +********************************************************************************************************* +*/ + +#if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u) || (OS_TMR_CFG_NAME_EN > 0u) +INT8U OS_StrLen (INT8U *psrc) +{ + INT8U len; + + +#if OS_ARG_CHK_EN > 0u + if (psrc == (INT8U *)0) { + return (0u); + } +#endif + + len = 0u; + while (*psrc != OS_ASCII_NUL) { + psrc++; + len++; + } + return (len); +} +#endif + + +/* +********************************************************************************************************* +* IDLE TASK +* +* Description: This task is internal to uC/OS-II and executes whenever no other higher priority tasks +* executes because they are ALL waiting for event(s) to occur. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) OSTaskIdleHook() is called after the critical section to ensure that interrupts will be +* enabled for at least a few instructions. On some processors (ex. Philips XA), enabling +* and then disabling interrupts didn't allow the processor enough time to have interrupts +* enabled before they were disabled again. uC/OS-II would thus never recognize +* interrupts. +* 2) This hook has been added to allow you to do such things as STOP the CPU to conserve +* power. +********************************************************************************************************* +*/ + +void OS_TaskIdle (void *p_arg) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + (void)p_arg; /* Prevent compiler warning for not using 'p_arg' */ + for (;;) { + OS_ENTER_CRITICAL(); + OSIdleCtr++; + OS_EXIT_CRITICAL(); + OSTaskIdleHook(); /* Call user definable HOOK */ + } +} + + +/* +********************************************************************************************************* +* STATISTICS TASK +* +* Description: This task is internal to uC/OS-II and is used to compute some statistics about the +* multitasking environment. Specifically, OS_TaskStat() computes the CPU usage. +* CPU usage is determined by: +* +* OSIdleCtr +* OSCPUUsage = 100 * (1 - ------------) (units are in %) +* OSIdleCtrMax +* +* Arguments : parg this pointer is not used at this time. +* +* Returns : none +* +* Notes : 1) This task runs at a priority level higher than the idle task. In fact, it runs at the +* next higher priority, OS_TASK_IDLE_PRIO-1. +* 2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0. +* 3) You MUST have at least a delay of 2/10 seconds to allow for the system to establish the +* maximum value for the idle counter. +********************************************************************************************************* +*/ + +#if OS_TASK_STAT_EN > 0u +void OS_TaskStat (void *p_arg) +{ + INT8S usage; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */ + while (OSStatRdy == OS_FALSE) { + OSTimeDly(2u * OS_TICKS_PER_SEC / 10u); /* Wait until statistic task is ready */ + } + OSIdleCtrMax /= 100uL; + if (OSIdleCtrMax == 0uL) { + OSCPUUsage = 0u; +#if OS_TASK_SUSPEND_EN > 0u + (void)OSTaskSuspend(OS_PRIO_SELF); +#else + for (;;) { + OSTimeDly(OS_TICKS_PER_SEC); + } +#endif + } + OS_ENTER_CRITICAL(); + OSIdleCtr = OSIdleCtrMax * 100uL; /* Set initial CPU usage as 0% */ + OS_EXIT_CRITICAL(); + for (;;) { + OSTimeDly(1); /* Synchronize with clock tick */ + + OS_ENTER_CRITICAL(); + OSIdleCtr = 0uL; /* Reset the idle counter for the next second */ + OS_EXIT_CRITICAL(); + + OSTimeDly(OS_TICKS_PER_SEC / 10u); /* Accumulate OSIdleCtr for the next 1/10 second */ + + OS_ENTER_CRITICAL(); + OSIdleCtrRun = OSIdleCtr; /* Store number of cycles which elapsed while idle */ + OS_EXIT_CRITICAL(); + + usage = 100 - (INT8S)(OSIdleCtrRun / OSIdleCtrMax); + if (usage >= 0) { /* Make sure we don't have a negative percentage */ + OSCPUUsage = (INT8U)usage; + } else { + OSCPUUsage = 0u; + OSIdleCtrMax = OSIdleCtrRun / 100uL; /* Update max counter value to current one */ + } + + OSTaskStatHook(); /* Invoke user definable hook */ +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) + OS_TaskStatStkChk(); /* Check the stacks for each task */ +#endif + } +} +#endif + + +/* +********************************************************************************************************* +* CHECK ALL TASK STACKS +* +* Description: This function is called by OS_TaskStat() to check the stacks of each active task. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStatStkChk (void) +{ + OS_TCB *ptcb; + OS_STK_DATA stk_data; + INT8U err; + INT8U prio; + + + for (prio = 0u; prio <= OS_TASK_IDLE_PRIO; prio++) { + err = OSTaskStkChk(prio, &stk_data); + if (err == OS_ERR_NONE) { + ptcb = OSTCBPrioTbl[prio]; + if (ptcb != (OS_TCB *)0) { /* Make sure task 'ptcb' is ... */ + if (ptcb != OS_TCB_RESERVED) { /* ... still valid. */ +#if OS_TASK_PROFILE_EN > 0u + #if OS_STK_GROWTH == 1u + ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom + ptcb->OSTCBStkSize; + #else + ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom - ptcb->OSTCBStkSize; + #endif + ptcb->OSTCBStkUsed = stk_data.OSUsed; /* Store number of entries used */ +#endif + } + } + } + } +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE TCB +* +* Description: This function is internal to uC/OS-II and is used to initialize a Task Control Block when +* a task is created (see OSTaskCreate() and OSTaskCreateExt()). +* +* Arguments : prio is the priority of the task being created +* +* ptos is a pointer to the task's top-of-stack assuming that the CPU registers +* have been placed on the stack. Note that the top-of-stack corresponds to a +* 'high' memory location is OS_STK_GROWTH is set to 1 and a 'low' memory +* location if OS_STK_GROWTH is set to 0. Note that stack growth is CPU +* specific. +* +* pbos is a pointer to the bottom of stack. A NULL pointer is passed if called by +* 'OSTaskCreate()'. +* +* id is the task's ID (0..65535) +* +* stk_size is the size of the stack (in 'stack units'). If the stack units are INT8Us +* then, 'stk_size' contains the number of bytes for the stack. If the stack +* units are INT32Us then, the stack contains '4 * stk_size' bytes. The stack +* units are established by the #define constant OS_STK which is CPU +* specific. 'stk_size' is 0 if called by 'OSTaskCreate()'. +* +* pext is a pointer to a user supplied memory area that is used to extend the task +* control block. This allows you to store the contents of floating-point +* registers, MMU registers or anything else you could find useful during a +* context switch. You can even assign a name to each task and store this name +* in this TCB extension. A NULL pointer is passed if called by OSTaskCreate(). +* +* opt options as passed to 'OSTaskCreateExt()' or, +* 0 if called from 'OSTaskCreate()'. +* +* Returns : OS_ERR_NONE if the call was successful +* OS_ERR_TASK_NO_MORE_TCB if there are no more free TCBs to be allocated and thus, the task +* cannot be created. +* +* Note : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +INT8U OS_TCBInit (INT8U prio, + OS_STK *ptos, + OS_STK *pbos, + INT16U id, + INT32U stk_size, + void *pext, + INT16U opt) +{ + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif +#if OS_TASK_REG_TBL_SIZE > 0u + INT8U i; +#endif +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + INT8U j; +#endif +#endif + + + OS_ENTER_CRITICAL(); + ptcb = OSTCBFreeList; /* Get a free TCB from the free TCB list */ + if (ptcb != (OS_TCB *)0) { + OSTCBFreeList = ptcb->OSTCBNext; /* Update pointer to free TCB list */ + OS_EXIT_CRITICAL(); + ptcb->OSTCBStkPtr = ptos; /* Load Stack pointer in TCB */ + ptcb->OSTCBPrio = prio; /* Load task priority into TCB */ + ptcb->OSTCBStat = OS_STAT_RDY; /* Task is ready to run */ + ptcb->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ + ptcb->OSTCBDly = 0u; /* Task is not delayed */ + +#if OS_TASK_CREATE_EXT_EN > 0u + ptcb->OSTCBExtPtr = pext; /* Store pointer to TCB extension */ + ptcb->OSTCBStkSize = stk_size; /* Store stack size */ + ptcb->OSTCBStkBottom = pbos; /* Store pointer to bottom of stack */ + ptcb->OSTCBOpt = opt; /* Store task options */ + ptcb->OSTCBId = id; /* Store task ID */ +#else + pext = pext; /* Prevent compiler warning if not used */ + stk_size = stk_size; + pbos = pbos; + opt = opt; + id = id; +#endif + +#if OS_TASK_DEL_EN > 0u + ptcb->OSTCBDelReq = OS_ERR_NONE; +#endif + +#if OS_LOWEST_PRIO <= 63u /* Pre-compute X, Y */ + ptcb->OSTCBY = (INT8U)(prio >> 3u); + ptcb->OSTCBX = (INT8U)(prio & 0x07u); +#else /* Pre-compute X, Y */ + ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0xFFu); + ptcb->OSTCBX = (INT8U) (prio & 0x0Fu); +#endif + /* Pre-compute BitX and BitY */ + ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY); + ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX); + +#if (OS_EVENT_EN) + ptcb->OSTCBEventPtr = (OS_EVENT *)0; /* Task is not pending on an event */ +#if (OS_EVENT_MULTI_EN > 0u) + ptcb->OSTCBEventMultiPtr = (OS_EVENT **)0; /* Task is not pending on any events */ + ptcb->OSTCBEventMultiRdy = (OS_EVENT *)0; /* No events readied for Multipend */ +#endif +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) && (OS_TASK_DEL_EN > 0u) + ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; /* Task is not pending on an event flag */ +#endif + +#if (OS_MBOX_EN > 0u) || ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) + ptcb->OSTCBMsg = (void *)0; /* No message received */ +#endif + +#if OS_TASK_PROFILE_EN > 0u + ptcb->OSTCBCtxSwCtr = 0uL; /* Initialize profiling variables */ + ptcb->OSTCBCyclesStart = 0uL; + ptcb->OSTCBCyclesTot = 0uL; + ptcb->OSTCBStkBase = (OS_STK *)0; + ptcb->OSTCBStkUsed = 0uL; +#endif + +#if OS_TASK_NAME_EN > 0u + ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; +#endif + +#if OS_TASK_REG_TBL_SIZE > 0u /* Initialize the task variables */ + for (i = 0u; i < OS_TASK_REG_TBL_SIZE; i++) { + ptcb->OSTCBRegTbl[i] = 0u; + } +#endif + + OSTCBInitHook(ptcb); + + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = ptcb; + OS_EXIT_CRITICAL(); + + OSTaskCreateHook(ptcb); /* Call user defined hook */ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + for (j = 0u; j < OS_TLS_TBL_SIZE; j++) { + ptcb->OSTCBTLSTbl[j] = (OS_TLS)0; + } + OS_TLS_TaskCreate(ptcb); /* Call TLS hook */ +#endif +#endif + + OS_ENTER_CRITICAL(); + ptcb->OSTCBNext = OSTCBList; /* Link into TCB chain */ + ptcb->OSTCBPrev = (OS_TCB *)0; + if (OSTCBList != (OS_TCB *)0) { + OSTCBList->OSTCBPrev = ptcb; + } + OSTCBList = ptcb; + OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OSTaskCtr++; /* Increment the #tasks counter */ + OS_TRACE_TASK_READY(ptcb); + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NO_MORE_TCB); +} + +#endif diff --git a/Source/os_dbg_r.c b/Source/os_dbg_r.c new file mode 100644 index 0000000..fc5dff2 --- /dev/null +++ b/Source/os_dbg_r.c @@ -0,0 +1,342 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* DEBUGGER CONSTANTS +* +* Filename : os_dbg_r.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define MICRIUM_SOURCE + +#include + +/* +********************************************************************************************************* +* DEBUG DATA +********************************************************************************************************* +*/ + +INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */ + +#if OS_DEBUG_EN > 0u + +INT32U const OSEndiannessTest = 0x12345678uL; /* Variable to test CPU endianness */ + +INT16U const OSEventEn = OS_EVENT_EN; +INT16U const OSEventMax = OS_MAX_EVENTS; /* Number of event control blocks */ +INT16U const OSEventNameEn = OS_EVENT_NAME_EN; +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +INT16U const OSEventSize = sizeof(OS_EVENT); /* Size in Bytes of OS_EVENT */ +INT16U const OSEventTblSize = sizeof(OSEventTbl); /* Size of OSEventTbl[] in bytes */ +#else +INT16U const OSEventSize = 0u; +INT16U const OSEventTblSize = 0u; +#endif +INT16U const OSEventMultiEn = OS_EVENT_MULTI_EN; + + +INT16U const OSFlagEn = OS_FLAG_EN; +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +INT16U const OSFlagGrpSize = sizeof(OS_FLAG_GRP); /* Size in Bytes of OS_FLAG_GRP */ +INT16U const OSFlagNodeSize = sizeof(OS_FLAG_NODE); /* Size in Bytes of OS_FLAG_NODE */ +INT16U const OSFlagWidth = sizeof(OS_FLAGS); /* Width (in bytes) of OS_FLAGS */ +#else +INT16U const OSFlagGrpSize = 0u; +INT16U const OSFlagNodeSize = 0u; +INT16U const OSFlagWidth = 0u; +#endif +INT16U const OSFlagMax = OS_MAX_FLAGS; +INT16U const OSFlagNameEn = OS_FLAG_NAME_EN; + +INT16U const OSLowestPrio = OS_LOWEST_PRIO; + +INT16U const OSMboxEn = OS_MBOX_EN; + +INT16U const OSMemEn = OS_MEM_EN; +INT16U const OSMemMax = OS_MAX_MEM_PART; /* Number of memory partitions */ +INT16U const OSMemNameEn = OS_MEM_NAME_EN; +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +INT16U const OSMemSize = sizeof(OS_MEM); /* Mem. Partition header sine (bytes) */ +INT16U const OSMemTblSize = sizeof(OSMemTbl); +#else +INT16U const OSMemSize = 0u; +INT16U const OSMemTblSize = 0u; +#endif +INT16U const OSMutexEn = OS_MUTEX_EN; + +INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */ + +INT16U const OSQEn = OS_Q_EN; +INT16U const OSQMax = OS_MAX_QS; /* Number of queues */ +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +INT16U const OSQSize = sizeof(OS_Q); /* Size in bytes of OS_Q structure */ +#else +INT16U const OSQSize = 0u; +#endif + +INT16U const OSRdyTblSize = OS_RDY_TBL_SIZE; /* Number of bytes in the ready table */ + +INT16U const OSSemEn = OS_SEM_EN; + +INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */ + +INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN; +INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN; +INT16U const OSTaskDelEn = OS_TASK_DEL_EN; +INT16U const OSTaskIdleStkSize = OS_TASK_IDLE_STK_SIZE; +INT16U const OSTaskProfileEn = OS_TASK_PROFILE_EN; +INT16U const OSTaskMax = OS_MAX_TASKS + OS_N_SYS_TASKS; /* Total max. number of tasks */ +INT16U const OSTaskNameEn = OS_TASK_NAME_EN; +INT16U const OSTaskStatEn = OS_TASK_STAT_EN; +INT16U const OSTaskStatStkSize = OS_TASK_STAT_STK_SIZE; +INT16U const OSTaskStatStkChkEn = OS_TASK_STAT_STK_CHK_EN; +INT16U const OSTaskSwHookEn = OS_TASK_SW_HOOK_EN; +INT16U const OSTaskRegTblSize = OS_TASK_REG_TBL_SIZE; + +INT16U const OSTCBPrioTblMax = OS_LOWEST_PRIO + 1u; /* Number of entries in OSTCBPrioTbl[] */ +INT16U const OSTCBSize = sizeof(OS_TCB); /* Size in Bytes of OS_TCB */ +INT16U const OSTicksPerSec = OS_TICKS_PER_SEC; +INT16U const OSTimeTickHookEn = OS_TIME_TICK_HOOK_EN; +INT16U const OSVersionNbr = OS_VERSION; + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) +INT16U const OS_TLS_TblSize = OS_TLS_TBL_SIZE * sizeof(OS_TLS); +#else +INT16U const OS_TLS_TblSize = 0u; +#endif +#endif + +INT16U const OSTmrEn = OS_TMR_EN; +INT16U const OSTmrCfgMax = OS_TMR_CFG_MAX; +INT16U const OSTmrCfgNameEn = OS_TMR_CFG_NAME_EN; +INT16U const OSTmrCfgWheelSize = OS_TMR_CFG_WHEEL_SIZE; +INT16U const OSTmrCfgTicksPerSec = OS_TMR_CFG_TICKS_PER_SEC; + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) +INT16U const OSTmrSize = sizeof(OS_TMR); +INT16U const OSTmrTblSize = sizeof(OSTmrTbl); +INT16U const OSTmrWheelSize = sizeof(OS_TMR_WHEEL); +INT16U const OSTmrWheelTblSize = sizeof(OSTmrWheelTbl); +#else +INT16U const OSTmrSize = 0u; +INT16U const OSTmrTblSize = 0u; +INT16U const OSTmrWheelSize = 0u; +INT16U const OSTmrWheelTblSize = 0u; +#endif + +#endif + + +/* +********************************************************************************************************* +* DEBUG DATA +* TOTAL DATA SPACE (i.e. RAM) USED BY uC/OS-II +********************************************************************************************************* +*/ +#if OS_DEBUG_EN > 0u + +INT16U const OSDataSize = sizeof(OSCtxSwCtr) +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) + + sizeof(OSEventFreeList) + + sizeof(OSEventTbl) +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + + sizeof(OSFlagTbl) + + sizeof(OSFlagFreeList) +#endif + +#if OS_TASK_STAT_EN > 0u + + sizeof(OSCPUUsage) + + sizeof(OSIdleCtrMax) + + sizeof(OSIdleCtrRun) + + sizeof(OSStatRdy) + + sizeof(OSTaskStatStk) +#endif + +#if OS_TICK_STEP_EN > 0u + + sizeof(OSTickStepState) +#endif + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + + sizeof(OSMemFreeList) + + sizeof(OSMemTbl) +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + + sizeof(OSSafetyCriticalStartFlag) +#endif + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + + sizeof(OSQFreeList) + + sizeof(OSQTbl) +#endif + +#if OS_TASK_REG_TBL_SIZE > 0u + + sizeof(OSTaskRegNextAvailID) +#endif + +#if OS_TIME_GET_SET_EN > 0u + + sizeof(OSTime) +#endif + +#if (OS_TMR_EN > 0u) && (OS_TMR_CFG_MAX > 0u) + + sizeof(OSTmrFree) + + sizeof(OSTmrUsed) + + sizeof(OSTmrTime) + + sizeof(OSTmrSem) + + sizeof(OSTmrSemSignal) + + sizeof(OSTmrTbl) + + sizeof(OSTmrFreeList) + + sizeof(OSTmrTaskStk) + + sizeof(OSTmrWheelTbl) +#endif + + sizeof(OSIntNesting) + + sizeof(OSLockNesting) + + sizeof(OSPrioCur) + + sizeof(OSPrioHighRdy) + + sizeof(OSRdyGrp) + + sizeof(OSRdyTbl) + + sizeof(OSRunning) + + sizeof(OSTaskCtr) + + sizeof(OSIdleCtr) + + sizeof(OSTaskIdleStk) + + sizeof(OSTCBCur) + + sizeof(OSTCBFreeList) + + sizeof(OSTCBHighRdy) + + sizeof(OSTCBList) + + sizeof(OSTCBPrioTbl) + + sizeof(OSTCBTbl); + +#endif + + +/* +********************************************************************************************************* +* OS DEBUG INITIALIZATION +* +* Description: This function is used to make sure that debug variables that are unused in the application +* are not optimized away. This function might not be necessary for all compilers. In this +* case, you should simply DELETE the code in this function while still leaving the declaration +* of the function itself. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : (1) This code doesn't do anything, it simply prevents the compiler from optimizing out +* the 'const' variables which are declared in this file. +* (2) You may decide to 'compile out' the code (by using #if 0/#endif) INSIDE the function +* if your compiler DOES NOT optimize out the 'const' variables above. +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void) +{ + void const *ptemp; + + + ptemp = (void const *)&OSDebugEn; + + ptemp = (void const *)&OSEndiannessTest; + + ptemp = (void const *)&OSEventMax; + ptemp = (void const *)&OSEventNameEn; + ptemp = (void const *)&OSEventEn; + ptemp = (void const *)&OSEventSize; + ptemp = (void const *)&OSEventTblSize; + ptemp = (void const *)&OSEventMultiEn; + + ptemp = (void const *)&OSFlagEn; + ptemp = (void const *)&OSFlagGrpSize; + ptemp = (void const *)&OSFlagNodeSize; + ptemp = (void const *)&OSFlagWidth; + ptemp = (void const *)&OSFlagMax; + ptemp = (void const *)&OSFlagNameEn; + + ptemp = (void const *)&OSLowestPrio; + + ptemp = (void const *)&OSMboxEn; + + ptemp = (void const *)&OSMemEn; + ptemp = (void const *)&OSMemMax; + ptemp = (void const *)&OSMemNameEn; + ptemp = (void const *)&OSMemSize; + ptemp = (void const *)&OSMemTblSize; + + ptemp = (void const *)&OSMutexEn; + + ptemp = (void const *)&OSPtrSize; + + ptemp = (void const *)&OSQEn; + ptemp = (void const *)&OSQMax; + ptemp = (void const *)&OSQSize; + + ptemp = (void const *)&OSRdyTblSize; + + ptemp = (void const *)&OSSemEn; + + ptemp = (void const *)&OSStkWidth; + + ptemp = (void const *)&OSTaskCreateEn; + ptemp = (void const *)&OSTaskCreateExtEn; + ptemp = (void const *)&OSTaskDelEn; + ptemp = (void const *)&OSTaskIdleStkSize; + ptemp = (void const *)&OSTaskProfileEn; + ptemp = (void const *)&OSTaskMax; + ptemp = (void const *)&OSTaskNameEn; + ptemp = (void const *)&OSTaskStatEn; + ptemp = (void const *)&OSTaskStatStkSize; + ptemp = (void const *)&OSTaskStatStkChkEn; + ptemp = (void const *)&OSTaskSwHookEn; + + ptemp = (void const *)&OSTCBPrioTblMax; + ptemp = (void const *)&OSTCBSize; + + ptemp = (void const *)&OSTicksPerSec; + ptemp = (void const *)&OSTimeTickHookEn; + +#if OS_TMR_EN > 0u + ptemp = (void const *)&OSTmrTbl[0]; + ptemp = (void const *)&OSTmrWheelTbl[0]; + + ptemp = (void const *)&OSTmrEn; + ptemp = (void const *)&OSTmrCfgMax; + ptemp = (void const *)&OSTmrCfgNameEn; + ptemp = (void const *)&OSTmrCfgWheelSize; + ptemp = (void const *)&OSTmrCfgTicksPerSec; + ptemp = (void const *)&OSTmrSize; + ptemp = (void const *)&OSTmrTblSize; + + ptemp = (void const *)&OSTmrWheelSize; + ptemp = (void const *)&OSTmrWheelTblSize; +#endif + + ptemp = (void const *)&OSVersionNbr; + + ptemp = (void const *)&OSDataSize; + + ptemp = ptemp; /* Prevent compiler warning for 'ptemp' not being used! */ +} +#endif diff --git a/Source/os_flag.c b/Source/os_flag.c new file mode 100644 index 0000000..83b16fd --- /dev/null +++ b/Source/os_flag.c @@ -0,0 +1,1286 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* EVENT FLAG MANAGEMENT +* +* Filename : os_flag.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_FLAG_C +#define OS_FLAG_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +/* +********************************************************************************************************* +* LOCAL PROTOTYPES +********************************************************************************************************* +*/ + +static void OS_FlagBlock(OS_FLAG_GRP *pgrp, OS_FLAG_NODE *pnode, OS_FLAGS flags, INT8U wait_type, INT32U timeout); +static BOOLEAN OS_FlagTaskRdy(OS_FLAG_NODE *pnode, OS_FLAGS flags_rdy, INT8U pend_stat); + + +/* +********************************************************************************************************* +* CHECK THE STATUS OF FLAGS IN AN EVENT FLAG GROUP +* +* Description: This function is called to check the status of a combination of bits to be set or cleared +* in an event flag group. Your application can check for ANY bit to be set/cleared or ALL +* bits to be set/cleared. +* +* This call does not block if the desired flags are not present. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check. +* The bits you want are specified by setting the corresponding bits in +* 'flags'. e.g. if your application wants to wait for bits 0 and 1 then +* 'flags' would contain 0x03. +* +* wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits +* to be set/cleared. +* You can specify the following argument: +* +* OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'flags' to be clear (0) +* OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'flags' to be clear (0) +* OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'flags' to be set (1) +* OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'flags' to be set (1) +* +* NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by +* the call. Example, to wait for any flag in a group AND then clear +* the flags that are present, set 'wait_type' to: +* +* OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME +* +* perr is a pointer to an error code and can be: +* OS_ERR_NONE No error +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument. +* OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer instead of the event flag +* group handle. +* OS_ERR_FLAG_NOT_RDY The desired flags you are waiting for are not +* available. +* +* Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error +* occurred. +* +* Called from: Task or ISR +* +* Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The +* function NOW returns the flags that were ready INSTEAD of the current state of the +* event flags. +********************************************************************************************************* +*/ + +#if OS_FLAG_ACCEPT_EN > 0u +OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT8U *perr) +{ + OS_FLAGS flags_rdy; + INT8U result; + BOOLEAN consume; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_FLAGS)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return ((OS_FLAGS)0); + } + result = (INT8U)(wait_type & OS_FLAG_CONSUME); + if (result != (INT8U)0) { /* See if we need to consume the flags */ + wait_type &= ~OS_FLAG_CONSUME; + consume = OS_TRUE; + } else { + consume = OS_FALSE; + } + + *perr = OS_ERR_NONE; /* Assume NO error until proven otherwise. */ + OS_ENTER_CRITICAL(); + switch (wait_type) { + case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we wanted */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; + + case OS_FLAG_WAIT_SET_ANY: + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we got */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; + + case OS_FLAG_WAIT_CLR_ANY: + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */ + } + } else { + *perr = OS_ERR_FLAG_NOT_RDY; + } + OS_EXIT_CRITICAL(); + break; +#endif + + default: + OS_EXIT_CRITICAL(); + flags_rdy = (OS_FLAGS)0; + *perr = OS_ERR_FLAG_WAIT_TYPE; + break; + } + return (flags_rdy); +} +#endif + + +/* +********************************************************************************************************* +* CREATE AN EVENT FLAG +* +* Description: This function is called to create an event flag group. +* +* Arguments : flags Contains the initial value to store in the event flag group. +* +* perr is a pointer to an error code which will be returned to your application: +* OS_ERR_NONE if the call was successful. +* OS_ERR_CREATE_ISR if you attempted to create an Event Flag from an +* ISR. +* OS_ERR_FLAG_GRP_DEPLETED if there are no more event flag groups +* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create an event flag after +* safety critical operation started. +* +* Returns : A pointer to an event flag group or a NULL pointer if no more groups are available. +* +* Called from: Task ONLY +********************************************************************************************************* +*/ + +OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, + INT8U *perr) +{ + OS_FLAG_GRP *pgrp; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_FLAG_GRP *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_CREATE_RUN_TIME; + return ((OS_FLAG_GRP *)0); + } +#endif + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_CREATE_ISR; /* ... can't CREATE from an ISR */ + return ((OS_FLAG_GRP *)0); + } + OS_ENTER_CRITICAL(); + pgrp = OSFlagFreeList; /* Get next free event flag */ + if (pgrp != (OS_FLAG_GRP *)0) { /* See if we have event flag groups available */ + /* Adjust free list */ + OSFlagFreeList = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList; + pgrp->OSFlagType = OS_EVENT_TYPE_FLAG; /* Set to event flag group type */ + pgrp->OSFlagFlags = flags; /* Set to desired initial value */ + pgrp->OSFlagWaitList = (void *)0; /* Clear list of tasks waiting on flags */ +#if OS_FLAG_NAME_EN > 0u + pgrp->OSFlagName = (INT8U *)(void *)"?"; +#endif + OS_TRACE_FLAG_CREATE(pgrp, pgrp->OSFlagName); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_FLAG_GRP_DEPLETED; + } + return (pgrp); /* Return pointer to event flag group */ +} + + +/* +********************************************************************************************************* +* DELETE AN EVENT FLAG GROUP +* +* Description: This function deletes an event flag group and readies all tasks pending on the event flag +* group. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* opt determines delete options as follows: +* opt == OS_DEL_NO_PEND Deletes the event flag group ONLY if no task pending +* opt == OS_DEL_ALWAYS Deletes the event flag group even if tasks are +* waiting. In this case, all the tasks pending will be +* readied. +* +* perr is a pointer to an error code that can contain one of the following values: +* OS_ERR_NONE The call was successful and the event flag group was +* deleted +* OS_ERR_DEL_ISR If you attempted to delete the event flag group from +* an ISR +* OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to an event flag group +* OS_ERR_ILLEGAL_DEL_RUN_TIME If you tried to delete an event flag after +* safety critical operation started. +* OS_ERR_INVALID_OPT An invalid option was specified +* OS_ERR_TASK_WAITING One or more tasks were waiting on the event flag +* group. +* +* Returns : pgrp upon error +* (OS_EVENT *)0 if the event flag group was successfully deleted. +* +* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of +* the event flag group MUST check the return code of OSFlagAccept() and OSFlagPend(). +* 2) This call can potentially disable interrupts for a long time. The interrupt disable +* time is directly proportional to the number of tasks waiting on the event flag group. +* 3) All tasks that were waiting for the event flag will be readied and returned an +* OS_ERR_PEND_ABORT if OSFlagDel() was called with OS_DEL_ALWAYS +********************************************************************************************************* +*/ + +#if OS_FLAG_DEL_EN > 0u +OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp, + INT8U opt, + INT8U *perr) +{ + BOOLEAN tasks_waiting; + OS_FLAG_NODE *pnode; + OS_FLAG_GRP *pgrp_return; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_FLAG_GRP *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_DEL_RUN_TIME; + return ((OS_FLAG_GRP *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return (pgrp); + } +#endif + + OS_TRACE_FLAG_DEL_ENTER(pgrp, opt); + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ + OS_TRACE_FLAG_DEL_EXIT(*perr); + return (pgrp); + } + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event group type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_FLAG_DEL_EXIT(*perr); + return (pgrp); + } + OS_ENTER_CRITICAL(); + if (pgrp->OSFlagWaitList != (void *)0) { /* See if any tasks waiting on event flags */ + tasks_waiting = OS_TRUE; /* Yes */ + } else { + tasks_waiting = OS_FALSE; /* No */ + } + switch (opt) { + case OS_DEL_NO_PEND: /* Delete group if no task waiting */ + if (tasks_waiting == OS_FALSE) { +#if OS_FLAG_NAME_EN > 0u + pgrp->OSFlagName = (INT8U *)(void *)"?"; +#endif + pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /* Return group to free list */ + pgrp->OSFlagFlags = (OS_FLAGS)0; + OSFlagFreeList = pgrp; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + pgrp_return = (OS_FLAG_GRP *)0; /* Event Flag Group has been deleted */ + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_TASK_WAITING; + pgrp_return = pgrp; + } + break; + + case OS_DEL_ALWAYS: /* Always delete the event flag group */ + pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; + while (pnode != (OS_FLAG_NODE *)0) { /* Ready ALL tasks waiting for flags */ + (void)OS_FlagTaskRdy(pnode, (OS_FLAGS)0, OS_STAT_PEND_ABORT); + pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; + } +#if OS_FLAG_NAME_EN > 0u + pgrp->OSFlagName = (INT8U *)(void *)"?"; +#endif + pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp->OSFlagWaitList = (void *)OSFlagFreeList;/* Return group to free list */ + pgrp->OSFlagFlags = (OS_FLAGS)0; + OSFlagFreeList = pgrp; + OS_EXIT_CRITICAL(); + if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ + OS_Sched(); /* Find highest priority task ready to run */ + } + *perr = OS_ERR_NONE; + pgrp_return = (OS_FLAG_GRP *)0; /* Event Flag Group has been deleted */ + break; + + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_INVALID_OPT; + pgrp_return = pgrp; + break; + } + + OS_TRACE_FLAG_DEL_EXIT(*perr); + + return (pgrp_return); +} +#endif + + +/* +********************************************************************************************************* +* GET THE NAME OF AN EVENT FLAG GROUP +* +* Description: This function is used to obtain the name assigned to an event flag group +* +* Arguments : pgrp is a pointer to the event flag group. +* +* pname is pointer to a pointer to an ASCII string that will receive the name of the event flag +* group. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_EVENT_TYPE if 'pevent' is not pointing to an event flag group +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_FLAG_INVALID_PGRP if you passed a NULL pointer for 'pgrp' +* OS_ERR_NAME_GET_ISR if you called this function from an ISR +* +* Returns : The length of the string or 0 if the 'pgrp' is a NULL pointer. +********************************************************************************************************* +*/ + +#if OS_FLAG_NAME_EN > 0u +INT8U OSFlagNameGet (OS_FLAG_GRP *pgrp, + INT8U **pname, + INT8U *perr) +{ + INT8U len; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pgrp == (OS_FLAG_GRP *)0) { /* Is 'pgrp' a NULL pointer? */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return (0u); + } + if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; + return (0u); + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_GET_ISR; + return (0u); + } + OS_ENTER_CRITICAL(); + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + *pname = pgrp->OSFlagName; + len = OS_StrLen(*pname); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (len); +} +#endif + + +/* +********************************************************************************************************* +* ASSIGN A NAME TO AN EVENT FLAG GROUP +* +* Description: This function assigns a name to an event flag group. +* +* Arguments : pgrp is a pointer to the event flag group. +* +* pname is a pointer to an ASCII string that will be used as the name of the event flag +* group. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_EVENT_TYPE if 'pevent' is not pointing to an event flag group +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_FLAG_INVALID_PGRP if you passed a NULL pointer for 'pgrp' +* OS_ERR_NAME_SET_ISR if you called this function from an ISR +* +* Returns : None +********************************************************************************************************* +*/ + +#if OS_FLAG_NAME_EN > 0u +void OSFlagNameSet (OS_FLAG_GRP *pgrp, + INT8U *pname, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pgrp == (OS_FLAG_GRP *)0) { /* Is 'pgrp' a NULL pointer? */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return; + } + if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; + return; + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_SET_ISR; + return; + } + OS_ENTER_CRITICAL(); + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_EVENT_TYPE; + return; + } + pgrp->OSFlagName = pname; + OS_EXIT_CRITICAL(); + OS_TRACE_EVENT_NAME_SET(pgrp, pname); + *perr = OS_ERR_NONE; + return; +} +#endif + + +/* +********************************************************************************************************* +* WAIT ON AN EVENT FLAG GROUP +* +* Description: This function is called to wait for a combination of bits to be set in an event flag +* group. Your application can wait for ANY bit to be set or ALL bits to be set. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to wait for. +* The bits you want are specified by setting the corresponding bits in +* 'flags'. e.g. if your application wants to wait for bits 0 and 1 then +* 'flags' would contain 0x03. +* +* wait_type specifies whether you want ALL bits to be set or ANY of the bits to be set. +* You can specify the following argument: +* +* OS_FLAG_WAIT_CLR_ALL You will wait for ALL bits in 'mask' to be clear (0) +* OS_FLAG_WAIT_SET_ALL You will wait for ALL bits in 'mask' to be set (1) +* OS_FLAG_WAIT_CLR_ANY You will wait for ANY bit in 'mask' to be clear (0) +* OS_FLAG_WAIT_SET_ANY You will wait for ANY bit in 'mask' to be set (1) +* +* NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by +* the call. Example, to wait for any flag in a group AND then clear +* the flags that are present, set 'wait_type' to: +* +* OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME +* +* timeout is an optional timeout (in clock ticks) that your task will wait for the +* desired bit combination. If you specify 0, however, your task will wait +* forever at the specified event flag group or, until a message arrives. +* +* perr is a pointer to an error code and can be: +* OS_ERR_NONE The desired bits have been set within the specified +* 'timeout'. +* OS_ERR_PEND_ISR If you tried to PEND from an ISR +* OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer. +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* OS_ERR_TIMEOUT The bit(s) have not been set in the specified +* 'timeout'. +* OS_ERR_PEND_ABORT The wait on the flag was aborted. +* OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument. +* +* Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error +* occurred. +* +* Called from: Task ONLY +* +* Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The +* function NOW returns the flags that were ready INSTEAD of the current state of the +* event flags. +********************************************************************************************************* +*/ + +OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT32U timeout, + INT8U *perr) +{ + OS_FLAG_NODE node; + OS_FLAGS flags_rdy; + INT8U result; + INT8U pend_stat; + BOOLEAN consume; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_FLAGS)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + + OS_TRACE_FLAG_PEND_ENTER(pgrp, flags, timeout, wait_type); + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + OS_TRACE_FLAG_PEND_EXIT(*perr); + return ((OS_FLAGS)0); + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + OS_TRACE_FLAG_PEND_EXIT(*perr); + return ((OS_FLAGS)0); + } + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_FLAG_PEND_EXIT(*perr); + return ((OS_FLAGS)0); + } + result = (INT8U)(wait_type & OS_FLAG_CONSUME); + if (result != (INT8U)0) { /* See if we need to consume the flags */ + wait_type &= (INT8U)~(INT8U)OS_FLAG_CONSUME; + consume = OS_TRUE; + } else { + consume = OS_FALSE; + } + + OS_ENTER_CRITICAL(); + switch (wait_type) { + case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we wanted */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + OS_TRACE_FLAG_PEND_EXIT(*perr); + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; + + case OS_FLAG_WAIT_SET_ANY: + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags that we got */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + OS_TRACE_FLAG_PEND_EXIT(*perr); + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy == flags) { /* Must match ALL the bits that we want */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + OS_TRACE_FLAG_PEND_EXIT(*perr); + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; + + case OS_FLAG_WAIT_CLR_ANY: + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */ + if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */ + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */ + } + OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */ + OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */ + *perr = OS_ERR_NONE; + OS_TRACE_FLAG_PEND_EXIT(*perr); + return (flags_rdy); + } else { /* Block task until events occur or timeout */ + OS_FlagBlock(pgrp, &node, flags, wait_type, timeout); + OS_EXIT_CRITICAL(); + } + break; +#endif + + default: + OS_EXIT_CRITICAL(); + flags_rdy = (OS_FLAGS)0; + *perr = OS_ERR_FLAG_WAIT_TYPE; + OS_TRACE_FLAG_PEND_EXIT(*perr); + return (flags_rdy); + } + + OS_Sched(); /* Find next HPT ready to run */ + OS_ENTER_CRITICAL(); + if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) { /* Have we timed-out or aborted? */ + pend_stat = OSTCBCur->OSTCBStatPend; + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OS_FlagUnlink(&node); + OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Yes, make task ready-to-run */ + OS_EXIT_CRITICAL(); + flags_rdy = (OS_FLAGS)0; + switch (pend_stat) { + case OS_STAT_PEND_ABORT: + *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted waiting */ + break; + + case OS_STAT_PEND_TO: + default: + *perr = OS_ERR_TIMEOUT; /* Indicate that we timed-out waiting */ + break; + } + OS_TRACE_FLAG_PEND_EXIT(*perr); + return (flags_rdy); + } + flags_rdy = OSTCBCur->OSTCBFlagsRdy; + if (consume == OS_TRUE) { /* See if we need to consume the flags */ + switch (wait_type) { + case OS_FLAG_WAIT_SET_ALL: + case OS_FLAG_WAIT_SET_ANY: /* Clear ONLY the flags we got */ + pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: + case OS_FLAG_WAIT_CLR_ANY: /* Set ONLY the flags we got */ + pgrp->OSFlagFlags |= flags_rdy; + break; +#endif + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_FLAG_WAIT_TYPE; + OS_TRACE_FLAG_PEND_EXIT(*perr); + return ((OS_FLAGS)0); + } + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; /* Event(s) must have occurred */ + OS_TRACE_FLAG_PEND_EXIT(*perr); + return (flags_rdy); +} + + +/* +********************************************************************************************************* +* GET FLAGS WHO CAUSED TASK TO BECOME READY +* +* Description: This function is called to obtain the flags that caused the task to become ready to run. +* In other words, this function allows you to tell "Who done it!". +* +* Arguments : None +* +* Returns : The flags that caused the task to be ready. +* +* Called from: Task ONLY +********************************************************************************************************* +*/ + +OS_FLAGS OSFlagPendGetFlagsRdy (void) +{ + OS_FLAGS flags; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OS_ENTER_CRITICAL(); + flags = OSTCBCur->OSTCBFlagsRdy; + OS_EXIT_CRITICAL(); + return (flags); +} + + +/* +********************************************************************************************************* +* POST EVENT FLAG BIT(S) +* +* Description: This function is called to set or clear some bits in an event flag group. The bits to +* set or clear are specified by a 'bit mask'. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* flags If 'opt' (see below) is OS_FLAG_SET, each bit that is set in 'flags' will +* set the corresponding bit in the event flag group. e.g. to set bits 0, 4 +* and 5 you would set 'flags' to: +* +* 0x31 (note, bit 0 is least significant bit) +* +* If 'opt' (see below) is OS_FLAG_CLR, each bit that is set in 'flags' will +* CLEAR the corresponding bit in the event flag group. e.g. to clear bits 0, +* 4 and 5 you would specify 'flags' as: +* +* 0x31 (note, bit 0 is least significant bit) +* +* opt indicates whether the flags will be: +* set (OS_FLAG_SET) or +* cleared (OS_FLAG_CLR) +* +* perr is a pointer to an error code and can be: +* OS_ERR_NONE The call was successfull +* OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* OS_ERR_FLAG_INVALID_OPT You specified an invalid option +* +* Returns : the new value of the event flags bits that are still set. +* +* Called From: Task or ISR +* +* WARNING(s) : 1) The execution time of this function depends on the number of tasks waiting on the event +* flag group. +* 2) The amount of time interrupts are DISABLED depends on the number of tasks waiting on +* the event flag group. +********************************************************************************************************* +*/ +OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U opt, + INT8U *perr) +{ + OS_FLAG_NODE *pnode; + BOOLEAN sched; + OS_FLAGS flags_cur; + OS_FLAGS flags_rdy; + BOOLEAN rdy; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_FLAGS)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + + OS_TRACE_FLAG_POST_ENTER(pgrp, flags, opt); + + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Make sure we are pointing to an event flag grp */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_FLAG_POST_EXIT(*perr); + return ((OS_FLAGS)0); + } + + OS_ENTER_CRITICAL(); + switch (opt) { + case OS_FLAG_CLR: + pgrp->OSFlagFlags &= (OS_FLAGS)~flags; /* Clear the flags specified in the group */ + break; + + case OS_FLAG_SET: + pgrp->OSFlagFlags |= flags; /* Set the flags specified in the group */ + break; + + default: + OS_EXIT_CRITICAL(); /* INVALID option */ + *perr = OS_ERR_FLAG_INVALID_OPT; + OS_TRACE_FLAG_POST_EXIT(*perr); + return ((OS_FLAGS)0); + } + sched = OS_FALSE; /* Indicate that we don't need rescheduling */ + pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; + while (pnode != (OS_FLAG_NODE *)0) { /* Go through all tasks waiting on event flag(s) */ + switch (pnode->OSFlagNodeWaitType) { + case OS_FLAG_WAIT_SET_ALL: /* See if all req. flags are set for current node */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); + if (flags_rdy == pnode->OSFlagNodeFlags) { /* Make task RTR, event(s) Rx'd */ + rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK); + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; + + case OS_FLAG_WAIT_SET_ANY: /* See if any flag set */ + flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags); + if (flags_rdy != (OS_FLAGS)0) { /* Make task RTR, event(s) Rx'd */ + rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK); + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; + +#if OS_FLAG_WAIT_CLR_EN > 0u + case OS_FLAG_WAIT_CLR_ALL: /* See if all req. flags are set for current node */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags; + if (flags_rdy == pnode->OSFlagNodeFlags) { /* Make task RTR, event(s) Rx'd */ + rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK); + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; + + case OS_FLAG_WAIT_CLR_ANY: /* See if any flag set */ + flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags; + if (flags_rdy != (OS_FLAGS)0) { /* Make task RTR, event(s) Rx'd */ + rdy = OS_FlagTaskRdy(pnode, flags_rdy, OS_STAT_PEND_OK); + if (rdy == OS_TRUE) { + sched = OS_TRUE; /* When done we will reschedule */ + } + } + break; +#endif + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_FLAG_WAIT_TYPE; + OS_TRACE_FLAG_POST_EXIT(*perr); + return ((OS_FLAGS)0); + } + pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; /* Point to next task waiting for event flag(s) */ + } + OS_EXIT_CRITICAL(); + if (sched == OS_TRUE) { + OS_Sched(); + } + OS_ENTER_CRITICAL(); + flags_cur = pgrp->OSFlagFlags; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + OS_TRACE_FLAG_POST_EXIT(*perr); + + return (flags_cur); +} + + +/* +********************************************************************************************************* +* QUERY EVENT FLAG +* +* Description: This function is used to check the value of the event flag group. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* perr is a pointer to an error code returned to the called: +* OS_ERR_NONE The call was successfull +* OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer +* OS_ERR_EVENT_TYPE You are not pointing to an event flag group +* +* Returns : The current value of the event flag group. +* +* Called From: Task or ISR +********************************************************************************************************* +*/ + +#if OS_FLAG_QUERY_EN > 0u +OS_FLAGS OSFlagQuery (OS_FLAG_GRP *pgrp, + INT8U *perr) +{ + OS_FLAGS flags; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_FLAGS)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */ + *perr = OS_ERR_FLAG_INVALID_PGRP; + return ((OS_FLAGS)0); + } +#endif + if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return ((OS_FLAGS)0); + } + OS_ENTER_CRITICAL(); + flags = pgrp->OSFlagFlags; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (flags); /* Return the current value of the event flags */ +} +#endif + + +/* +********************************************************************************************************* +* SUSPEND TASK UNTIL EVENT FLAG(s) RECEIVED OR TIMEOUT OCCURS +* +* Description: This function is internal to uC/OS-II and is used to put a task to sleep until the desired +* event flag bit(s) are set. +* +* Arguments : pgrp is a pointer to the desired event flag group. +* +* pnode is a pointer to a structure which contains data about the task waiting for +* event flag bit(s) to be set. +* +* flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check. +* The bits you want are specified by setting the corresponding bits in +* 'flags'. e.g. if your application wants to wait for bits 0 and 1 then +* 'flags' would contain 0x03. +* +* wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits +* to be set/cleared. +* You can specify the following argument: +* +* OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'mask' to be clear (0) +* OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'mask' to be clear (0) +* OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'mask' to be set (1) +* OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'mask' to be set (1) +* +* timeout is the desired amount of time that the task will wait for the event flag +* bit(s) to be set. +* +* Returns : none +* +* Called by : OSFlagPend() OS_FLAG.C +* +* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +static void OS_FlagBlock (OS_FLAG_GRP *pgrp, + OS_FLAG_NODE *pnode, + OS_FLAGS flags, + INT8U wait_type, + INT32U timeout) +{ + OS_FLAG_NODE *pnode_next; + INT8U y; + + + OSTCBCur->OSTCBStat |= OS_STAT_FLAG; + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Store timeout in task's TCB */ +#if OS_TASK_DEL_EN > 0u + OSTCBCur->OSTCBFlagNode = pnode; /* TCB to link to node */ +#endif + pnode->OSFlagNodeFlags = flags; /* Save the flags that we need to wait for */ + pnode->OSFlagNodeWaitType = wait_type; /* Save the type of wait we are doing */ + pnode->OSFlagNodeTCB = (void *)OSTCBCur; /* Link to task's TCB */ + pnode->OSFlagNodeNext = pgrp->OSFlagWaitList; /* Add node at beginning of event flag wait list */ + pnode->OSFlagNodePrev = (void *)0; + pnode->OSFlagNodeFlagGrp = (void *)pgrp; /* Link to Event Flag Group */ + pnode_next = (OS_FLAG_NODE *)pgrp->OSFlagWaitList; + if (pnode_next != (void *)0) { /* Is this the first NODE to insert? */ + pnode_next->OSFlagNodePrev = pnode; /* No, link in doubly linked list */ + } + pgrp->OSFlagWaitList = (void *)pnode; + + y = OSTCBCur->OSTCBY; /* Suspend current task until flag(s) received */ + OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; + OS_TRACE_TASK_SUSPENDED(OSTCBCur); + if (OSRdyTbl[y] == 0x00u) { + OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; + } +} + + +/* +********************************************************************************************************* +* INITIALIZE THE EVENT FLAG MODULE +* +* Description: This function is called by uC/OS-II to initialize the event flag module. Your application +* MUST NOT call this function. In other words, this function is internal to uC/OS-II. +* +* Arguments : none +* +* Returns : none +* +* WARNING : You MUST NOT call this function from your code. This is an INTERNAL function to uC/OS-II. +********************************************************************************************************* +*/ + +void OS_FlagInit (void) +{ +#if OS_MAX_FLAGS == 1u + OSFlagFreeList = (OS_FLAG_GRP *)&OSFlagTbl[0]; /* Only ONE event flag group! */ + OSFlagFreeList->OSFlagType = OS_EVENT_TYPE_UNUSED; + OSFlagFreeList->OSFlagWaitList = (void *)0; + OSFlagFreeList->OSFlagFlags = (OS_FLAGS)0; +#if OS_FLAG_NAME_EN > 0u + OSFlagFreeList->OSFlagName = (INT8U *)"?"; +#endif +#endif + +#if OS_MAX_FLAGS >= 2u + INT16U ix; + INT16U ix_next; + OS_FLAG_GRP *pgrp1; + OS_FLAG_GRP *pgrp2; + + + OS_MemClr((INT8U *)&OSFlagTbl[0], sizeof(OSFlagTbl)); /* Clear the flag group table */ + for (ix = 0u; ix < (OS_MAX_FLAGS - 1u); ix++) { /* Init. list of free EVENT FLAGS */ + ix_next = ix + 1u; + pgrp1 = &OSFlagTbl[ix]; + pgrp2 = &OSFlagTbl[ix_next]; + pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp1->OSFlagWaitList = (void *)pgrp2; +#if OS_FLAG_NAME_EN > 0u + pgrp1->OSFlagName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + } + pgrp1 = &OSFlagTbl[ix]; + pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED; + pgrp1->OSFlagWaitList = (void *)0; +#if OS_FLAG_NAME_EN > 0u + pgrp1->OSFlagName = (INT8U *)(void *)"?"; /* Unknown name */ +#endif + OSFlagFreeList = &OSFlagTbl[0]; +#endif +} + + +/* +********************************************************************************************************* +* MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED +* +* Description: This function is internal to uC/OS-II and is used to make a task ready-to-run because the +* desired event flag bits have been set. +* +* Arguments : pnode is a pointer to a structure which contains data about the task waiting for +* event flag bit(s) to be set. +* +* flags_rdy contains the bit pattern of the event flags that cause the task to become +* ready-to-run. +* +* pend_stat is used to indicate the readied task's pending status: +* +* +* Returns : OS_TRUE If the task has been placed in the ready list and thus needs scheduling +* OS_FALSE The task is still not ready to run and thus scheduling is not necessary +* +* Called by : OSFlagsPost() OS_FLAG.C +* +* Note(s) : 1) This function assumes that interrupts are disabled. +* 2) This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +static BOOLEAN OS_FlagTaskRdy (OS_FLAG_NODE *pnode, + OS_FLAGS flags_rdy, + INT8U pend_stat) +{ + OS_TCB *ptcb; + BOOLEAN sched; + + + ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; /* Point to TCB of waiting task */ + ptcb->OSTCBDly = 0u; + ptcb->OSTCBFlagsRdy = flags_rdy; + ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_FLAG; + ptcb->OSTCBStatPend = pend_stat; + if (ptcb->OSTCBStat == OS_STAT_RDY) { /* Task now ready? */ + OSRdyGrp |= ptcb->OSTCBBitY; /* Put task into ready list */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OS_TRACE_TASK_READY(ptcb); + sched = OS_TRUE; + } else { + sched = OS_FALSE; + } + OS_FlagUnlink(pnode); + return (sched); +} + + +/* +********************************************************************************************************* +* UNLINK EVENT FLAG NODE FROM WAITING LIST +* +* Description: This function is internal to uC/OS-II and is used to unlink an event flag node from a +* list of tasks waiting for the event flag. +* +* Arguments : pnode is a pointer to a structure which contains data about the task waiting for +* event flag bit(s) to be set. +* +* Returns : none +* +* Called by : OS_FlagTaskRdy() OS_FLAG.C +* OSFlagPend() OS_FLAG.C +* OSTaskDel() OS_TASK.C +* +* Note(s) : 1) This function assumes that interrupts are disabled. +* 2) This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_FlagUnlink (OS_FLAG_NODE *pnode) +{ +#if OS_TASK_DEL_EN > 0u + OS_TCB *ptcb; +#endif + OS_FLAG_GRP *pgrp; + OS_FLAG_NODE *pnode_prev; + OS_FLAG_NODE *pnode_next; + + + pnode_prev = (OS_FLAG_NODE *)pnode->OSFlagNodePrev; + pnode_next = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; + if (pnode_prev == (OS_FLAG_NODE *)0) { /* Is it first node in wait list? */ + pgrp = (OS_FLAG_GRP *)pnode->OSFlagNodeFlagGrp; + pgrp->OSFlagWaitList = (void *)pnode_next; /* Update list for new 1st node */ + if (pnode_next != (OS_FLAG_NODE *)0) { + pnode_next->OSFlagNodePrev = (OS_FLAG_NODE *)0; /* Link new 1st node PREV to NULL */ + } + } else { /* No, A node somewhere in the list */ + pnode_prev->OSFlagNodeNext = pnode_next; /* Link around the node to unlink */ + if (pnode_next != (OS_FLAG_NODE *)0) { /* Was this the LAST node? */ + pnode_next->OSFlagNodePrev = pnode_prev; /* No, Link around current node */ + } + } +#if OS_TASK_DEL_EN > 0u + ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; + ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0; +#endif +} +#endif +#endif /* OS_FLAG_C */ diff --git a/Source/os_mbox.c b/Source/os_mbox.c new file mode 100644 index 0000000..5a63aa5 --- /dev/null +++ b/Source/os_mbox.c @@ -0,0 +1,708 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MESSAGE MAILBOX MANAGEMENT +* +* Filename : os_mbox.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_MBOX_C +#define OS_MBOX_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + +#if OS_MBOX_EN > 0u +/* +********************************************************************************************************* +* ACCEPT MESSAGE FROM MAILBOX +* +* Description: This function checks the mailbox to see if a message is available. Unlike OSMboxPend(), +* OSMboxAccept() does not suspend the calling task if a message is not available. +* +* Arguments : pevent is a pointer to the event control block +* +* Returns : != (void *)0 is the message in the mailbox if one is available. The mailbox is cleared +* so the next time OSMboxAccept() is called, the mailbox will be empty. +* == (void *)0 if the mailbox is empty or, +* if 'pevent' is a NULL pointer or, +* if you didn't pass the proper event pointer. +********************************************************************************************************* +*/ + +#if OS_MBOX_ACCEPT_EN > 0u +void *OSMboxAccept (OS_EVENT *pevent) +{ + void *pmsg; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return ((void *)0); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ + return ((void *)0); + } + OS_ENTER_CRITICAL(); + pmsg = pevent->OSEventPtr; + pevent->OSEventPtr = (void *)0; /* Clear the mailbox */ + OS_EXIT_CRITICAL(); + return (pmsg); /* Return the message received (or NULL) */ +} +#endif + + +/* +********************************************************************************************************* +* CREATE A MESSAGE MAILBOX +* +* Description: This function creates a message mailbox if free event control blocks are available. +* +* Arguments : pmsg is a pointer to a message that you wish to deposit in the mailbox. If +* you set this value to the NULL pointer (i.e. (void *)0) then the mailbox +* will be considered empty. +* +* Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the +* created mailbox +* == (OS_EVENT *)0 if no event control blocks were available +********************************************************************************************************* +*/ + +OS_EVENT *OSMboxCreate (void *pmsg) +{ + OS_EVENT *pevent; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */ + } + OS_ENTER_CRITICAL(); + pevent = OSEventFreeList; /* Get next free event control block */ + if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */ + OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; + } + OS_EXIT_CRITICAL(); + if (pevent != (OS_EVENT *)0) { + pevent->OSEventType = OS_EVENT_TYPE_MBOX; + pevent->OSEventCnt = 0u; + pevent->OSEventPtr = pmsg; /* Deposit message in event control block */ +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + OS_EventWaitListInit(pevent); + + OS_TRACE_MBOX_CREATE(pevent, pevent->OSEventName); + } + return (pevent); /* Return pointer to event control block */ +} + + +/* +********************************************************************************************************* +* DELETE A MAIBOX +* +* Description: This function deletes a mailbox and readies all tasks pending on the mailbox. +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* mailbox. +* +* opt determines delete options as follows: +* opt == OS_DEL_NO_PEND Delete the mailbox ONLY if no task pending +* opt == OS_DEL_ALWAYS Deletes the mailbox even if tasks are waiting. +* In this case, all the tasks pending will be readied. +* +* perr is a pointer to an error code that can contain one of the following values: +* OS_ERR_NONE The call was successful and the mailbox was deleted +* OS_ERR_DEL_ISR If you attempted to delete the mailbox from an ISR +* OS_ERR_INVALID_OPT An invalid option was specified +* OS_ERR_ILLEGAL_DEL_RUN_TIME If you tried to delete a mailbox after safety +* critical operation started. +* OS_ERR_TASK_WAITING One or more tasks were waiting on the mailbox +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* +* Returns : pevent upon error +* (OS_EVENT *)0 if the mailbox was successfully deleted. +* +* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of +* the mailbox MUST check the return code of OSMboxPend(). +* 2) OSMboxAccept() callers will not know that the intended mailbox has been deleted! +* 3) This call can potentially disable interrupts for a long time. The interrupt disable +* time is directly proportional to the number of tasks waiting on the mailbox. +* 4) Because ALL tasks pending on the mailbox will be readied, you MUST be careful in +* applications where the mailbox is used for mutual exclusion because the resource(s) +* will no longer be guarded by the mailbox. +* 5) All tasks that were waiting for the mailbox will be readied and returned an +* OS_ERR_PEND_ABORT if OSMboxDel() was called with OS_DEL_ALWAYS +********************************************************************************************************* +*/ + +#if OS_MBOX_DEL_EN > 0u +OS_EVENT *OSMboxDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr) +{ + BOOLEAN tasks_waiting; + OS_EVENT *pevent_return; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_DEL_RUN_TIME; + return ((OS_EVENT *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (pevent); + } +#endif + + OS_TRACE_MBOX_DEL_ENTER(pevent, opt); + + if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_MBOX_DEL_EXIT(*perr); + return (pevent); + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ + OS_TRACE_MBOX_DEL_EXIT(*perr); + return (pevent); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mailbox */ + tasks_waiting = OS_TRUE; /* Yes */ + } else { + tasks_waiting = OS_FALSE; /* No */ + } + switch (opt) { + case OS_DEL_NO_PEND: /* Delete mailbox only if no task waiting */ + if (tasks_waiting == OS_FALSE) { +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; /* Get next free event control block */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */ + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_TASK_WAITING; + pevent_return = pevent; + } + break; + + case OS_DEL_ALWAYS: /* Always delete the mailbox */ + while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mailbox */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT); + } +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; /* Get next free event control block */ + OS_EXIT_CRITICAL(); + if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ + OS_Sched(); /* Find highest priority task ready to run */ + } + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */ + break; + + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_INVALID_OPT; + pevent_return = pevent; + break; + } + + OS_TRACE_MBOX_DEL_EXIT(*perr); + + return (pevent_return); +} +#endif + + +/* +********************************************************************************************************* +* PEND ON MAILBOX FOR A MESSAGE +* +* Description: This function waits for a message to be sent to a mailbox +* +* Arguments : pevent is a pointer to the event control block associated with the desired mailbox +* +* timeout is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for a message to arrive at the mailbox up to the amount of time +* specified by this argument. If you specify 0, however, your task will wait +* forever at the specified mailbox or, until a message arrives. +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE The call was successful and your task received a +* message. +* OS_ERR_TIMEOUT A message was not received within the specified 'timeout'. +* OS_ERR_PEND_ABORT The wait on the mailbox was aborted. +* OS_ERR_EVENT_TYPE Invalid event type +* OS_ERR_PEND_ISR If you called this function from an ISR and the result +* would lead to a suspension. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked +* +* Returns : != (void *)0 is a pointer to the message received +* == (void *)0 if no message was received or, +* if 'pevent' is a NULL pointer or, +* if you didn't pass the proper pointer to the event control block. +********************************************************************************************************* +*/ + +void *OSMboxPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr) +{ + void *pmsg; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((void *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return ((void *)0); + } +#endif + + OS_TRACE_MBOX_PEND_ENTER(pevent, timeout); + + if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_MBOX_PEND_EXIT(*perr); + return ((void *)0); + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + OS_TRACE_MBOX_PEND_EXIT(*perr); + return ((void *)0); + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + OS_TRACE_MBOX_PEND_EXIT(*perr); + return ((void *)0); + } + OS_ENTER_CRITICAL(); + pmsg = pevent->OSEventPtr; + if (pmsg != (void *)0) { /* See if there is already a message */ + pevent->OSEventPtr = (void *)0; /* Clear the mailbox */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + OS_TRACE_MBOX_PEND_EXIT(*perr); + return (pmsg); /* Return the message received (or NULL) */ + } + OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */ + OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next highest priority task ready to run */ + OS_ENTER_CRITICAL(); + switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ + case OS_STAT_PEND_OK: + pmsg = OSTCBCur->OSTCBMsg; + *perr = OS_ERR_NONE; + break; + + case OS_STAT_PEND_ABORT: + pmsg = (void *)0; + *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ + break; + + case OS_STAT_PEND_TO: + default: + OS_EventTaskRemove(OSTCBCur, pevent); + pmsg = (void *)0; + *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ + break; + } + OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ + OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ +#if (OS_EVENT_MULTI_EN > 0u) + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; + OSTCBCur->OSTCBEventMultiRdy = (OS_EVENT *)0; +#endif + OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */ + OS_EXIT_CRITICAL(); + OS_TRACE_MBOX_PEND_EXIT(*perr); + + return (pmsg); /* Return received message */ +} + + +/* +********************************************************************************************************* +* ABORT WAITING ON A MESSAGE MAILBOX +* +* Description: This function aborts & readies any tasks currently waiting on a mailbox. This function +* should be used to fault-abort the wait on the mailbox, rather than to normally signal +* the mailbox via OSMboxPost() or OSMboxPostOpt(). +* +* Arguments : pevent is a pointer to the event control block associated with the desired mailbox. +* +* opt determines the type of ABORT performed: +* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the +* mailbox +* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the +* mailbox +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE No tasks were waiting on the mailbox. +* OS_ERR_PEND_ABORT At least one task waiting on the mailbox was readied +* and informed of the aborted wait; check return value +* for the number of tasks whose wait on the mailbox +* was aborted. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* +* Returns : == 0 if no tasks were waiting on the mailbox, or upon error. +* > 0 if one or more tasks waiting on the mailbox are now readied and informed. +********************************************************************************************************* +*/ + +#if OS_MBOX_PEND_ABORT_EN > 0u +INT8U OSMboxPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr) +{ + INT8U nbr_tasks; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task waiting on mailbox? */ + nbr_tasks = 0u; + switch (opt) { + case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */ + while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on mailbox */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT); + nbr_tasks++; + } + break; + + case OS_PEND_OPT_NONE: + default: /* No, ready HPT waiting on mailbox */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT); + nbr_tasks++; + break; + } + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find HPT ready to run */ + *perr = OS_ERR_PEND_ABORT; + return (nbr_tasks); + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (0u); /* No tasks waiting on mailbox */ +} +#endif + + +/* +********************************************************************************************************* +* POST MESSAGE TO A MAILBOX +* +* Description: This function sends a message to a mailbox +* +* Arguments : pevent is a pointer to the event control block associated with the desired mailbox +* +* pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer. +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one +* message at a time and thus, the message MUST be consumed before you +* are allowed to send another one. +* OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer +* +* Note(s) : 1) HPT means Highest Priority Task +********************************************************************************************************* +*/ + +#if OS_MBOX_POST_EN > 0u +INT8U OSMboxPost (OS_EVENT *pevent, + void *pmsg) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } + if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */ + return (OS_ERR_POST_NULL_PTR); + } +#endif + + OS_TRACE_MBOX_POST_ENTER(pevent); + + if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ + OS_TRACE_MBOX_POST_EXIT(OS_ERR_EVENT_TYPE); + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */ + /* Ready HPT waiting on event */ + (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK); + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find highest priority task ready to run */ + OS_TRACE_MBOX_POST_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */ + OS_EXIT_CRITICAL(); + OS_TRACE_MBOX_POST_EXIT(OS_ERR_MBOX_FULL); + return (OS_ERR_MBOX_FULL); + } + pevent->OSEventPtr = pmsg; /* Place message in mailbox */ + OS_EXIT_CRITICAL(); + OS_TRACE_MBOX_POST_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* POST MESSAGE TO A MAILBOX +* +* Description: This function sends a message to a mailbox +* +* Arguments : pevent is a pointer to the event control block associated with the desired mailbox +* +* pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer. +* +* opt determines the type of POST performed: +* OS_POST_OPT_NONE POST to a single waiting task +* (Identical to OSMboxPost()) +* OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the mailbox +* +* OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one +* message at a time and thus, the message MUST be consumed before you +* are allowed to send another one. +* OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer +* +* Note(s) : 1) HPT means Highest Priority Task +* +* Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the +* interrupt disable time is proportional to the number of tasks waiting on the mailbox. +********************************************************************************************************* +*/ + +#if OS_MBOX_POST_OPT_EN > 0u +INT8U OSMboxPostOpt (OS_EVENT *pevent, + void *pmsg, + INT8U opt) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } + if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */ + return (OS_ERR_POST_NULL_PTR); + } +#endif + + OS_TRACE_MBOX_POST_OPT_ENTER(pevent, opt); + + if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ + OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_EVENT_TYPE); + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */ + if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */ + while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on mailbox */ + (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK); + } + } else { /* No, Post to HPT waiting on mbox */ + (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK); + } + OS_EXIT_CRITICAL(); + if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */ + OS_Sched(); /* Find HPT ready to run */ + } + OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */ + OS_EXIT_CRITICAL(); + OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_MBOX_FULL); + return (OS_ERR_MBOX_FULL); + } + pevent->OSEventPtr = pmsg; /* Place message in mailbox */ + OS_EXIT_CRITICAL(); + OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* QUERY A MESSAGE MAILBOX +* +* Description: This function obtains information about a message mailbox. +* +* Arguments : pevent is a pointer to the event control block associated with the desired mailbox +* +* p_mbox_data is a pointer to a structure that will contain information about the message +* mailbox. +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mailbox. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_PDATA_NULL If 'p_mbox_data' is a NULL pointer +********************************************************************************************************* +*/ + +#if OS_MBOX_QUERY_EN > 0u +INT8U OSMboxQuery (OS_EVENT *pevent, + OS_MBOX_DATA *p_mbox_data) +{ + INT8U i; + OS_PRIO *psrc; + OS_PRIO *pdest; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } + if (p_mbox_data == (OS_MBOX_DATA *)0) { /* Validate 'p_mbox_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */ + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + p_mbox_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */ + psrc = &pevent->OSEventTbl[0]; + pdest = &p_mbox_data->OSEventTbl[0]; + for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { + *pdest++ = *psrc++; + } + p_mbox_data->OSMsg = pevent->OSEventPtr; /* Get message from mailbox */ + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif /* OS_MBOX_QUERY_EN */ +#endif /* OS_MBOX_EN */ +#endif /* OS_MBOX_C */ diff --git a/Source/os_mem.c b/Source/os_mem.c new file mode 100644 index 0000000..b1e13b2 --- /dev/null +++ b/Source/os_mem.c @@ -0,0 +1,489 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MEMORY MANAGEMENT +* +* Filename : os_mem.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_MEM_C +#define OS_MEM_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +/* +********************************************************************************************************* +* CREATE A MEMORY PARTITION +* +* Description : Create a fixed-sized memory partition that will be managed by uC/OS-II. +* +* Arguments : addr is the starting address of the memory partition +* +* nblks is the number of memory blocks to create from the partition. +* +* blksize is the size (in bytes) of each block in the memory partition. +* +* perr is a pointer to a variable containing an error message which will be set by +* this function to either: +* +* OS_ERR_NONE if the memory partition has been created correctly. +* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a memory partition after +* safety critical operation started. +* OS_ERR_MEM_INVALID_ADDR if you are specifying an invalid address for the memory +* storage of the partition or, the block does not align +* on a pointer boundary +* OS_ERR_MEM_INVALID_PART no free partitions available +* OS_ERR_MEM_INVALID_BLKS user specified an invalid number of blocks (must be >= 2) +* OS_ERR_MEM_INVALID_SIZE user specified an invalid block size +* - must be greater than the size of a pointer +* - must be able to hold an integral number of pointers +* Returns : != (OS_MEM *)0 is the partition was created +* == (OS_MEM *)0 if the partition was not created because of invalid arguments or, no +* free partition is available. +********************************************************************************************************* +*/ + +OS_MEM *OSMemCreate (void *addr, + INT32U nblks, + INT32U blksize, + INT8U *perr) +{ + OS_MEM *pmem; + INT8U *pblk; + void **plink; + INT32U loops; + INT32U i; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_MEM *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_CREATE_RUN_TIME; + return ((OS_MEM *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (addr == (void *)0) { /* Must pass a valid address for the memory part.*/ + *perr = OS_ERR_MEM_INVALID_ADDR; + return ((OS_MEM *)0); + } + if (((INT32U)addr & (sizeof(void *) - 1u)) != 0u){ /* Must be pointer size aligned */ + *perr = OS_ERR_MEM_INVALID_ADDR; + return ((OS_MEM *)0); + } + if (nblks < 2u) { /* Must have at least 2 blocks per partition */ + *perr = OS_ERR_MEM_INVALID_BLKS; + return ((OS_MEM *)0); + } + if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer */ + *perr = OS_ERR_MEM_INVALID_SIZE; + return ((OS_MEM *)0); + } +#endif + OS_ENTER_CRITICAL(); + pmem = OSMemFreeList; /* Get next free memory partition */ + if (OSMemFreeList != (OS_MEM *)0) { /* See if pool of free partitions was empty */ + OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList; + } + OS_EXIT_CRITICAL(); + if (pmem == (OS_MEM *)0) { /* See if we have a memory partition */ + *perr = OS_ERR_MEM_INVALID_PART; + return ((OS_MEM *)0); + } + plink = (void **)addr; /* Create linked list of free memory blocks */ + pblk = (INT8U *)addr; + loops = nblks - 1u; + for (i = 0u; i < loops; i++) { + pblk += blksize; /* Point to the FOLLOWING block */ + *plink = (void *)pblk; /* Save pointer to NEXT block in CURRENT block */ + plink = (void **)pblk; /* Position to NEXT block */ + } + *plink = (void *)0; /* Last memory block points to NULL */ + pmem->OSMemAddr = addr; /* Store start address of memory partition */ + pmem->OSMemFreeList = addr; /* Initialize pointer to pool of free blocks */ + pmem->OSMemNFree = nblks; /* Store number of free blocks in MCB */ + pmem->OSMemNBlks = nblks; + pmem->OSMemBlkSize = blksize; /* Store block size of each memory blocks */ + + OS_TRACE_MEM_CREATE(pmem); + + *perr = OS_ERR_NONE; + return (pmem); +} + + +/* +********************************************************************************************************* +* GET A MEMORY BLOCK +* +* Description : Get a memory block from a partition +* +* Arguments : pmem is a pointer to the memory partition control block +* +* perr is a pointer to a variable containing an error message which will be set by this +* function to either: +* +* OS_ERR_NONE if the memory partition has been created correctly. +* OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller +* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' +* +* Returns : A pointer to a memory block if no error is detected +* A pointer to NULL if an error is detected +********************************************************************************************************* +*/ + +void *OSMemGet (OS_MEM *pmem, + INT8U *perr) +{ + void *pblk; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((void *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */ + *perr = OS_ERR_MEM_INVALID_PMEM; + return ((void *)0); + } +#endif + + OS_TRACE_MEM_GET_ENTER(pmem); + + OS_ENTER_CRITICAL(); + if (pmem->OSMemNFree > 0u) { /* See if there are any free memory blocks */ + pblk = pmem->OSMemFreeList; /* Yes, point to next free memory block */ + pmem->OSMemFreeList = *(void **)pblk; /* Adjust pointer to new free list */ + pmem->OSMemNFree--; /* One less memory block in this partition */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; /* No error */ + OS_TRACE_MEM_GET_EXIT(*perr); + return (pblk); /* Return memory block to caller */ + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */ + OS_TRACE_MEM_GET_EXIT(*perr); + return ((void *)0); /* Return NULL pointer to caller */ +} + + +/* +********************************************************************************************************* +* GET THE NAME OF A MEMORY PARTITION +* +* Description: This function is used to obtain the name assigned to a memory partition. +* +* Arguments : pmem is a pointer to the memory partition +* +* pname is a pointer to a pointer to an ASCII string that will receive the name of the memory partition. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the name was copied to 'pname' +* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_NAME_GET_ISR You called this function from an ISR +* +* Returns : The length of the string or 0 if 'pmem' is a NULL pointer. +********************************************************************************************************* +*/ + +#if OS_MEM_NAME_EN > 0u +INT8U OSMemNameGet (OS_MEM *pmem, + INT8U **pname, + INT8U *perr) +{ + INT8U len; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pmem == (OS_MEM *)0) { /* Is 'pmem' a NULL pointer? */ + *perr = OS_ERR_MEM_INVALID_PMEM; + return (0u); + } + if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; + return (0u); + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_GET_ISR; + return (0u); + } + OS_ENTER_CRITICAL(); + *pname = pmem->OSMemName; + len = OS_StrLen(*pname); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (len); +} +#endif + + +/* +********************************************************************************************************* +* ASSIGN A NAME TO A MEMORY PARTITION +* +* Description: This function assigns a name to a memory partition. +* +* Arguments : pmem is a pointer to the memory partition +* +* pname is a pointer to an ASCII string that contains the name of the memory partition. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the name was copied to 'pname' +* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_MEM_NAME_TOO_LONG if the name doesn't fit in the storage area +* OS_ERR_NAME_SET_ISR if you called this function from an ISR +* +* Returns : None +********************************************************************************************************* +*/ + +#if OS_MEM_NAME_EN > 0u +void OSMemNameSet (OS_MEM *pmem, + INT8U *pname, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pmem == (OS_MEM *)0) { /* Is 'pmem' a NULL pointer? */ + *perr = OS_ERR_MEM_INVALID_PMEM; + return; + } + if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; + return; + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_SET_ISR; + return; + } + OS_ENTER_CRITICAL(); + pmem->OSMemName = pname; + OS_EXIT_CRITICAL(); + OS_TRACE_EVENT_NAME_SET(pmem, pname); + *perr = OS_ERR_NONE; +} +#endif + + +/* +********************************************************************************************************* +* RELEASE A MEMORY BLOCK +* +* Description : Returns a memory block to a partition +* +* Arguments : pmem is a pointer to the memory partition control block +* +* pblk is a pointer to the memory block being released. +* +* Returns : OS_ERR_NONE if the memory block was inserted into the partition +* OS_ERR_MEM_FULL if you are returning a memory block to an already FULL memory +* partition (You freed more blocks than you allocated!) +* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' +* OS_ERR_MEM_INVALID_PBLK if you passed a NULL pointer for the block to release. +********************************************************************************************************* +*/ + +INT8U OSMemPut (OS_MEM *pmem, + void *pblk) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#if OS_ARG_CHK_EN > 0u + if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */ + return (OS_ERR_MEM_INVALID_PMEM); + } + if (pblk == (void *)0) { /* Must release a valid block */ + return (OS_ERR_MEM_INVALID_PBLK); + } +#endif + + OS_TRACE_MEM_PUT_ENTER(pmem, pblk); + + OS_ENTER_CRITICAL(); + if (pmem->OSMemNFree >= pmem->OSMemNBlks) { /* Make sure all blocks not already returned */ + OS_EXIT_CRITICAL(); + OS_TRACE_MEM_PUT_EXIT(OS_ERR_MEM_FULL); + return (OS_ERR_MEM_FULL); + } + *(void **)pblk = pmem->OSMemFreeList; /* Insert released block into free block list */ + pmem->OSMemFreeList = pblk; + pmem->OSMemNFree++; /* One more memory block in this partition */ + OS_EXIT_CRITICAL(); + OS_TRACE_MEM_PUT_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); /* Notify caller that memory block was released */ +} + + +/* +********************************************************************************************************* +* QUERY MEMORY PARTITION +* +* Description : This function is used to determine the number of free memory blocks and the number of +* used memory blocks from a memory partition. +* +* Arguments : pmem is a pointer to the memory partition control block +* +* p_mem_data is a pointer to a structure that will contain information about the memory +* partition. +* +* Returns : OS_ERR_NONE if no errors were found. +* OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' +* OS_ERR_MEM_INVALID_PDATA if you passed a NULL pointer to the data recipient. +********************************************************************************************************* +*/ + +#if OS_MEM_QUERY_EN > 0u +INT8U OSMemQuery (OS_MEM *pmem, + OS_MEM_DATA *p_mem_data) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition */ + return (OS_ERR_MEM_INVALID_PMEM); + } + if (p_mem_data == (OS_MEM_DATA *)0) { /* Must release a valid storage area for the data */ + return (OS_ERR_MEM_INVALID_PDATA); + } +#endif + OS_ENTER_CRITICAL(); + p_mem_data->OSAddr = pmem->OSMemAddr; + p_mem_data->OSFreeList = pmem->OSMemFreeList; + p_mem_data->OSBlkSize = pmem->OSMemBlkSize; + p_mem_data->OSNBlks = pmem->OSMemNBlks; + p_mem_data->OSNFree = pmem->OSMemNFree; + OS_EXIT_CRITICAL(); + p_mem_data->OSNUsed = p_mem_data->OSNBlks - p_mem_data->OSNFree; + return (OS_ERR_NONE); +} +#endif /* OS_MEM_QUERY_EN */ + + +/* +********************************************************************************************************* +* INITIALIZE MEMORY PARTITION MANAGER +* +* Description : This function is called by uC/OS-II to initialize the memory partition manager. Your +* application MUST NOT call this function. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_MemInit (void) +{ +#if OS_MAX_MEM_PART == 1u + OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /* Clear the memory partition table */ + OSMemFreeList = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list */ +#if OS_MEM_NAME_EN > 0u + OSMemFreeList->OSMemName = (INT8U *)"?"; /* Unknown name */ +#endif +#endif + +#if OS_MAX_MEM_PART >= 2u + OS_MEM *pmem; + INT16U i; + + + OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /* Clear the memory partition table */ + for (i = 0u; i < (OS_MAX_MEM_PART - 1u); i++) { /* Init. list of free memory partitions */ + pmem = &OSMemTbl[i]; /* Point to memory control block (MCB) */ + pmem->OSMemFreeList = (void *)&OSMemTbl[i + 1u]; /* Chain list of free partitions */ +#if OS_MEM_NAME_EN > 0u + pmem->OSMemName = (INT8U *)(void *)"?"; +#endif + } + pmem = &OSMemTbl[i]; + pmem->OSMemFreeList = (void *)0; /* Initialize last node */ +#if OS_MEM_NAME_EN > 0u + pmem->OSMemName = (INT8U *)(void *)"?"; +#endif + + OSMemFreeList = &OSMemTbl[0]; /* Point to beginning of free list */ +#endif +} +#endif /* OS_MEM_EN */ +#endif /* OS_MEM_C */ diff --git a/Source/os_mutex.c b/Source/os_mutex.c new file mode 100644 index 0000000..8a7f619 --- /dev/null +++ b/Source/os_mutex.c @@ -0,0 +1,818 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MUTUAL EXCLUSION SEMAPHORE MANAGEMENT +* +* Filename : os_mutex.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_MUTEX_C +#define OS_MUTEX_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + + +#if OS_MUTEX_EN > 0u +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +#define OS_MUTEX_KEEP_LOWER_8 ((INT16U)0x00FFu) +#define OS_MUTEX_KEEP_UPPER_8 ((INT16U)0xFF00u) + +#define OS_MUTEX_AVAILABLE ((INT16U)0x00FFu) + +/* +********************************************************************************************************* +* LOCAL CONSTANTS +********************************************************************************************************* +*/ + +static void OSMutex_RdyAtPrio(OS_TCB *ptcb, INT8U prio); + + +/* +********************************************************************************************************* +* ACCEPT MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function checks the mutual exclusion semaphore to see if a resource is available. +* Unlike OSMutexPend(), OSMutexAccept() does not suspend the calling task if the resource is +* not available or the event did not occur. +* +* Arguments : pevent is a pointer to the event control block +* +* perr is a pointer to an error code which will be returned to your application: +* OS_ERR_NONE if the call was successful. +* OS_ERR_EVENT_TYPE if 'pevent' is not a pointer to a mutex +* OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer +* OS_ERR_PEND_ISR if you called this function from an ISR +* OS_ERR_PCP_LOWER If the priority of the task that owns the Mutex is +* HIGHER (i.e. a lower number) than the PCP. This error +* indicates that you did not set the PCP higher (lower +* number) than ALL the tasks that compete for the Mutex. +* Unfortunately, this is something that could not be +* detected when the Mutex is created because we don't know +* what tasks will be using the Mutex. +* +* Returns : == OS_TRUE if the resource is available, the mutual exclusion semaphore is acquired +* == OS_FALSE a) if the resource is not available +* b) you didn't pass a pointer to a mutual exclusion semaphore +* c) you called this function from an ISR +* +* Warning(s) : This function CANNOT be called from an ISR because mutual exclusion semaphores are +* intended to be used by tasks only. +********************************************************************************************************* +*/ + +#if OS_MUTEX_ACCEPT_EN > 0u +BOOLEAN OSMutexAccept (OS_EVENT *pevent, + INT8U *perr) +{ + INT8U pcp; /* Priority Ceiling Priority (PCP) */ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_FALSE); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (OS_FALSE); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return (OS_FALSE); + } + if (OSIntNesting > 0u) { /* Make sure it's not called from an ISR */ + *perr = OS_ERR_PEND_ISR; + return (OS_FALSE); + } + OS_ENTER_CRITICAL(); /* Get value (0 or 1) of Mutex */ + pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PCP from mutex */ + if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) { + pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Mask off LSByte (Acquire Mutex) */ + pevent->OSEventCnt |= (INT16U)OSTCBCur->OSTCBPrio; /* Save current task priority in LSByte */ + pevent->OSEventPtr = (void *)OSTCBCur; /* Link TCB of task owning Mutex */ + if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) && + (OSTCBCur->OSTCBPrio <= pcp)) { /* PCP 'must' have a SMALLER prio ... */ + OS_EXIT_CRITICAL(); /* ... than current task! */ + *perr = OS_ERR_PCP_LOWER; + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + } + return (OS_TRUE); + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (OS_FALSE); +} +#endif + + +/* +********************************************************************************************************* +* CREATE A MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function creates a mutual exclusion semaphore. +* +* Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In +* other words, when the semaphore is acquired and a higher priority task +* attempts to obtain the semaphore then the priority of the task owning the +* semaphore is raised to this priority. It is assumed that you will specify +* a priority that is LOWER in value than ANY of the tasks competing for the +* mutex. If the priority is specified as OS_PRIO_MUTEX_CEIL_DIS, then the +* priority ceiling promotion is disabled. This way, the tasks accessing the +* semaphore do not have their priority promoted. +* +* perr is a pointer to an error code which will be returned to your application: +* OS_ERR_NONE if the call was successful. +* OS_ERR_CREATE_ISR if you attempted to create a MUTEX from an +* ISR +* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a mutex after +* safety critical operation started. +* OS_ERR_PRIO_EXIST if a task at the priority ceiling priority +* already exist. +* OS_ERR_PEVENT_NULL No more event control blocks available. +* OS_ERR_PRIO_INVALID if the priority you specify is higher that +* the maximum allowed (i.e. > OS_LOWEST_PRIO) +* +* Returns : != (void *)0 is a pointer to the event control clock (OS_EVENT) associated with the +* created mutex. +* == (void *)0 if an error is detected. +* +* Note(s) : 1) The LEAST significant 8 bits of '.OSEventCnt' hold the priority number of the task +* owning the mutex or 0xFF if no task owns the mutex. +* +* 2) The MOST significant 8 bits of '.OSEventCnt' hold the priority number used to +* reduce priority inversion or 0xFF (OS_PRIO_MUTEX_CEIL_DIS) if priority ceiling +* promotion is disabled. +********************************************************************************************************* +*/ + +OS_EVENT *OSMutexCreate (INT8U prio, + INT8U *perr) +{ + OS_EVENT *pevent; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_CREATE_RUN_TIME; + return ((OS_EVENT *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (prio != OS_PRIO_MUTEX_CEIL_DIS) { + if (prio >= OS_LOWEST_PRIO) { /* Validate PCP */ + *perr = OS_ERR_PRIO_INVALID; + return ((OS_EVENT *)0); + } + } +#endif + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_CREATE_ISR; /* ... can't CREATE mutex from an ISR */ + return ((OS_EVENT *)0); + } + OS_ENTER_CRITICAL(); + if (prio != OS_PRIO_MUTEX_CEIL_DIS) { + if (OSTCBPrioTbl[prio] != (OS_TCB *)0) { /* Mutex priority must not already exist */ + OS_EXIT_CRITICAL(); /* Task already exist at priority ... */ + *perr = OS_ERR_PRIO_EXIST; /* ... ceiling priority */ + return ((OS_EVENT *)0); + } + OSTCBPrioTbl[prio] = OS_TCB_RESERVED; /* Reserve the table entry */ + } + + pevent = OSEventFreeList; /* Get next free event control block */ + if (pevent == (OS_EVENT *)0) { /* See if an ECB was available */ + if (prio != OS_PRIO_MUTEX_CEIL_DIS) { + OSTCBPrioTbl[prio] = (OS_TCB *)0; /* No, Release the table entry */ + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_PEVENT_NULL; /* No more event control blocks */ + return (pevent); + } + OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; /* Adjust the free list */ + OS_EXIT_CRITICAL(); + pevent->OSEventType = OS_EVENT_TYPE_MUTEX; + pevent->OSEventCnt = (INT16U)((INT16U)prio << 8u) | OS_MUTEX_AVAILABLE; /* Resource is avail. */ + pevent->OSEventPtr = (void *)0; /* No task owning the mutex */ +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + OS_EventWaitListInit(pevent); + OS_TRACE_MUTEX_CREATE(pevent, pevent->OSEventName); + *perr = OS_ERR_NONE; + return (pevent); +} + + +/* +********************************************************************************************************* +* DELETE A MUTEX +* +* Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it. +* +* Arguments : pevent is a pointer to the event control block associated with the desired mutex. +* +* opt determines delete options as follows: +* opt == OS_DEL_NO_PEND Delete mutex ONLY if no task pending +* opt == OS_DEL_ALWAYS Deletes the mutex even if tasks are waiting. +* In this case, all the tasks pending will be readied. +* +* perr is a pointer to an error code that can contain one of the following values: +* OS_ERR_NONE The call was successful and the mutex was deleted +* OS_ERR_DEL_ISR If you attempted to delete the MUTEX from an ISR +* OS_ERR_INVALID_OPT An invalid option was specified +* OS_ERR_ILLEGAL_DEL_RUN_TIME If you tried to delete a mutex after safety +* critical operation started. +* OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* +* Returns : pevent upon error +* (OS_EVENT *)0 if the mutex was successfully deleted. +* +* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of +* the mutex MUST check the return code of OSMutexPend(). +* +* 2) This call can potentially disable interrupts for a long time. The interrupt disable +* time is directly proportional to the number of tasks waiting on the mutex. +* +* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the +* resource(s) will no longer be guarded by the mutex. +* +* 4) IMPORTANT: In the 'OS_DEL_ALWAYS' case, we assume that the owner of the Mutex (if there +* is one) is ready-to-run and is thus NOT pending on another kernel object or +* has delayed itself. In other words, if a task owns the mutex being deleted, +* that task will be made ready-to-run at its original priority. +********************************************************************************************************* +*/ + +#if OS_MUTEX_DEL_EN > 0u +OS_EVENT *OSMutexDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr) +{ + BOOLEAN tasks_waiting; + OS_EVENT *pevent_return; + INT8U pcp; /* Priority ceiling priority */ + INT8U prio; + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_DEL_RUN_TIME; + return ((OS_EVENT *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (pevent); + } +#endif + + OS_TRACE_MUTEX_DEL_ENTER(pevent, opt); + + if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_MUTEX_DEL_EXIT(*perr); + return (pevent); + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ + OS_TRACE_MUTEX_DEL_EXIT(*perr); + return (pevent); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mutex */ + tasks_waiting = OS_TRUE; /* Yes */ + } else { + tasks_waiting = OS_FALSE; /* No */ + } + switch (opt) { + case OS_DEL_NO_PEND: /* DELETE MUTEX ONLY IF NO TASK WAITING --- */ + if (tasks_waiting == OS_FALSE) { +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pcp = (INT8U)(pevent->OSEventCnt >> 8u); + if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { + OSTCBPrioTbl[pcp] = (OS_TCB *)0; /* Free up the PCP */ + } + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */ + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_TASK_WAITING; + pevent_return = pevent; + } + break; + + case OS_DEL_ALWAYS: /* ALWAYS DELETE THE MUTEX ---------------- */ + pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PCP of mutex */ + if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { + prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's orig prio */ + ptcb = (OS_TCB *)pevent->OSEventPtr; + if (ptcb != (OS_TCB *)0) { /* See if any task owns the mutex */ + if (ptcb->OSTCBPrio == pcp) { /* See if original prio was changed */ + OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(OSTCBCur, prio); + OSMutex_RdyAtPrio(ptcb, prio); /* Yes, Restore the task's original prio */ + } + } + } + while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mutex */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_ABORT); + } +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pcp = (INT8U)(pevent->OSEventCnt >> 8u); + if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { + OSTCBPrioTbl[pcp] = (OS_TCB *)0; /* Free up the PCP */ + } + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; /* Get next free event control block */ + OS_EXIT_CRITICAL(); + if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ + OS_Sched(); /* Find highest priority task ready to run */ + } + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Mutex has been deleted */ + break; + + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_INVALID_OPT; + pevent_return = pevent; + break; + } + + OS_TRACE_MUTEX_DEL_EXIT(*perr); + + return (pevent_return); +} +#endif + + +/* +********************************************************************************************************* +* PEND ON MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function waits for a mutual exclusion semaphore. +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* mutex. +* +* timeout is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for the resource up to the amount of time specified by this argument. +* If you specify 0, however, your task will wait forever at the specified +* mutex or, until the resource becomes available. +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* OS_ERR_NONE The call was successful and your task owns the mutex +* OS_ERR_TIMEOUT The mutex was not available within the specified 'timeout'. +* OS_ERR_PEND_ABORT The wait on the mutex was aborted. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex +* OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer +* OS_ERR_PEND_ISR If you called this function from an ISR and the result +* would lead to a suspension. +* OS_ERR_PCP_LOWER If the priority of the task that owns the Mutex is +* HIGHER (i.e. a lower number) than the PCP. This error +* indicates that you did not set the PCP higher (lower +* number) than ALL the tasks that compete for the Mutex. +* Unfortunately, this is something that could not be +* detected when the Mutex is created because we don't know +* what tasks will be using the Mutex. +* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked +* +* Returns : none +* +* Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex. +* +* 2) You MUST NOT change the priority of the task that owns the mutex +********************************************************************************************************* +*/ + +void OSMutexPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr) +{ + INT8U pcp; /* Priority Ceiling Priority (PCP) */ + INT8U mprio; /* Mutex owner priority */ + BOOLEAN rdy; /* Flag indicating task was ready */ + OS_TCB *ptcb; + OS_EVENT *pevent2; + INT8U y; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return; + } +#endif + + OS_TRACE_MUTEX_PEND_ENTER(pevent, timeout); + + if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_MUTEX_PEND_EXIT(*perr); + return; + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + OS_TRACE_MUTEX_PEND_EXIT(*perr); + return; + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + OS_TRACE_MUTEX_PEND_EXIT(*perr); + return; + } + + OS_ENTER_CRITICAL(); + pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get PCP from mutex */ + /* Is Mutex available? */ + if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) { + pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Yes, Acquire the resource */ + pevent->OSEventCnt |= (INT16U)OSTCBCur->OSTCBPrio; /* Save priority of owning task */ + pevent->OSEventPtr = (void *)OSTCBCur; /* Point to owning task's OS_TCB */ + if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) && + (OSTCBCur->OSTCBPrio <= pcp)) { /* PCP 'must' have a SMALLER prio ... */ + OS_EXIT_CRITICAL(); /* ... than current task! */ + *perr = OS_ERR_PCP_LOWER; + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + } + OS_TRACE_MUTEX_PEND_EXIT(*perr); + return; + } + if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { + mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get priority of mutex owner */ + ptcb = (OS_TCB *)(pevent->OSEventPtr); /* Point to TCB of mutex owner */ + if (ptcb->OSTCBPrio > pcp) { /* Need to promote prio of owner?*/ + if (mprio > OSTCBCur->OSTCBPrio) { + y = ptcb->OSTCBY; + if ((OSRdyTbl[y] & ptcb->OSTCBBitX) != 0u) { /* See if mutex owner is ready */ + OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Yes, Remove owner from Rdy ...*/ + if (OSRdyTbl[y] == 0u) { /* ... list at current prio */ + OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + rdy = OS_TRUE; + } else { + pevent2 = ptcb->OSTCBEventPtr; + if (pevent2 != (OS_EVENT *)0) { /* Remove from event wait list */ + y = ptcb->OSTCBY; + pevent2->OSEventTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; + if (pevent2->OSEventTbl[y] == 0u) { + pevent2->OSEventGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + } + rdy = OS_FALSE; /* No */ + } + ptcb->OSTCBPrio = pcp; /* Change owner task prio to PCP */ + + OS_TRACE_MUTEX_TASK_PRIO_INHERIT(ptcb, pcp); + +#if OS_LOWEST_PRIO <= 63u + ptcb->OSTCBY = (INT8U)( ptcb->OSTCBPrio >> 3u); + ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x07u); +#else + ptcb->OSTCBY = (INT8U)((INT8U)(ptcb->OSTCBPrio >> 4u) & 0xFFu); + ptcb->OSTCBX = (INT8U)( ptcb->OSTCBPrio & 0x0Fu); +#endif + ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY); + ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX); + + if (rdy == OS_TRUE) { /* If task was ready at owner's priority ...*/ + OSRdyGrp |= ptcb->OSTCBBitY; /* ... make it ready at new priority. */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + } else { + pevent2 = ptcb->OSTCBEventPtr; + if (pevent2 != (OS_EVENT *)0) { /* Add to event wait list */ + pevent2->OSEventGrp |= ptcb->OSTCBBitY; + pevent2->OSEventTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + } + } + OSTCBPrioTbl[pcp] = ptcb; + } + } + } + OSTCBCur->OSTCBStat |= OS_STAT_MUTEX; /* Mutex not available, pend current task */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Store timeout in current task's TCB */ + OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next highest priority task ready */ + OS_ENTER_CRITICAL(); + switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ + case OS_STAT_PEND_OK: + *perr = OS_ERR_NONE; + break; + + case OS_STAT_PEND_ABORT: + *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted getting mutex */ + break; + + case OS_STAT_PEND_TO: + default: + OS_EventTaskRemove(OSTCBCur, pevent); + *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get mutex within TO */ + break; + } + OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ + OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ +#if (OS_EVENT_MULTI_EN > 0u) + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; + OSTCBCur->OSTCBEventMultiRdy = (OS_EVENT *)0; +#endif + OS_EXIT_CRITICAL(); + + OS_TRACE_MUTEX_PEND_EXIT(*perr); +} + + +/* +********************************************************************************************************* +* POST TO A MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function signals a mutual exclusion semaphore +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* mutex. +* +* Returns : OS_ERR_NONE The call was successful and the mutex was signaled. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mutex +* OS_ERR_PEVENT_NULL 'pevent' is a NULL pointer +* OS_ERR_POST_ISR Attempted to post from an ISR (not valid for MUTEXes) +* OS_ERR_NOT_MUTEX_OWNER The task that did the post is NOT the owner of the MUTEX. +* OS_ERR_PCP_LOWER If the priority of the new task that owns the Mutex is +* HIGHER (i.e. a lower number) than the PCP. This error +* indicates that you did not set the PCP higher (lower +* number) than ALL the tasks that compete for the Mutex. +* Unfortunately, this is something that could not be +* detected when the Mutex is created because we don't know +* what tasks will be using the Mutex. +********************************************************************************************************* +*/ + +INT8U OSMutexPost (OS_EVENT *pevent) +{ + INT8U pcp; /* Priority ceiling priority */ + INT8U prio; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + return (OS_ERR_POST_ISR); /* ... can't POST mutex from an ISR */ + } +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } +#endif + + OS_TRACE_MUTEX_POST_ENTER(pevent); + + if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ + OS_TRACE_MUTEX_POST_EXIT(OS_ERR_EVENT_TYPE); + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + pcp = (INT8U)(pevent->OSEventCnt >> 8u); /* Get priority ceiling priority of mutex */ + prio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get owner's original priority */ + if (OSTCBCur != (OS_TCB *)pevent->OSEventPtr) { /* See if posting task owns the MUTEX */ + OS_EXIT_CRITICAL(); + OS_TRACE_MUTEX_POST_EXIT(OS_ERR_NOT_MUTEX_OWNER); + return (OS_ERR_NOT_MUTEX_OWNER); + } + if (pcp != OS_PRIO_MUTEX_CEIL_DIS) { + if (OSTCBCur->OSTCBPrio == pcp) { /* Did we have to raise current task's priority? */ + OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(OSTCBCur, prio); + OSMutex_RdyAtPrio(OSTCBCur, prio); /* Restore the task's original priority */ + } + OSTCBPrioTbl[pcp] = OS_TCB_RESERVED; /* Reserve table entry */ + } + if (pevent->OSEventGrp != 0u) { /* Any task waiting for the mutex? */ + /* Yes, Make HPT waiting for mutex ready */ + prio = OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX, OS_STAT_PEND_OK); + pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Save priority of mutex's new owner */ + pevent->OSEventCnt |= (INT16U)prio; + pevent->OSEventPtr = OSTCBPrioTbl[prio]; /* Link to new mutex owner's OS_TCB */ + if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) && + (prio <= pcp)) { /* PCP 'must' have a SMALLER prio ... */ + OS_EXIT_CRITICAL(); /* ... than current task! */ + OS_Sched(); /* Find highest priority task ready to run */ + OS_TRACE_MUTEX_POST_EXIT(OS_ERR_PCP_LOWER); + return (OS_ERR_PCP_LOWER); + } else { + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find highest priority task ready to run */ + OS_TRACE_MUTEX_POST_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + } + pevent->OSEventCnt |= OS_MUTEX_AVAILABLE; /* No, Mutex is now available */ + pevent->OSEventPtr = (void *)0; + OS_EXIT_CRITICAL(); + OS_TRACE_MUTEX_POST_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); +} + + +/* +********************************************************************************************************* +* QUERY A MUTUAL EXCLUSION SEMAPHORE +* +* Description: This function obtains information about a mutex +* +* Arguments : pevent is a pointer to the event control block associated with the desired mutex +* +* p_mutex_data is a pointer to a structure that will contain information about the mutex +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_QUERY_ISR If you called this function from an ISR +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_PDATA_NULL If 'p_mutex_data' is a NULL pointer +* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mutex. +********************************************************************************************************* +*/ + +#if OS_MUTEX_QUERY_EN > 0u +INT8U OSMutexQuery (OS_EVENT *pevent, + OS_MUTEX_DATA *p_mutex_data) +{ + INT8U i; + OS_PRIO *psrc; + OS_PRIO *pdest; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + return (OS_ERR_QUERY_ISR); /* ... can't QUERY mutex from an ISR */ + } +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } + if (p_mutex_data == (OS_MUTEX_DATA *)0) { /* Validate 'p_mutex_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */ + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + p_mutex_data->OSMutexPCP = (INT8U)(pevent->OSEventCnt >> 8u); + p_mutex_data->OSOwnerPrio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); + if (p_mutex_data->OSOwnerPrio == 0xFFu) { + p_mutex_data->OSValue = OS_TRUE; + } else { + p_mutex_data->OSValue = OS_FALSE; + } + p_mutex_data->OSEventGrp = pevent->OSEventGrp; /* Copy wait list */ + psrc = &pevent->OSEventTbl[0]; + pdest = &p_mutex_data->OSEventTbl[0]; + for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { + *pdest++ = *psrc++; + } + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif /* OS_MUTEX_QUERY_EN */ + + +/* +********************************************************************************************************* +* RESTORE A TASK BACK TO ITS ORIGINAL PRIORITY +* +* Description: This function makes a task ready at the specified priority +* +* Arguments : ptcb is a pointer to OS_TCB of the task to make ready +* +* prio is the desired priority +* +* Returns : none +********************************************************************************************************* +*/ + +static void OSMutex_RdyAtPrio (OS_TCB *ptcb, + INT8U prio) +{ + INT8U y; + + + y = ptcb->OSTCBY; /* Remove owner from ready list at 'pcp' */ + OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; + OS_TRACE_TASK_SUSPENDED(ptcb); + if (OSRdyTbl[y] == 0u) { + OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + ptcb->OSTCBPrio = prio; + OSPrioCur = prio; /* The current task is now at this priority */ +#if OS_LOWEST_PRIO <= 63u + ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 3u) & 0x07u); + ptcb->OSTCBX = (INT8U)(prio & 0x07u); +#else + ptcb->OSTCBY = (INT8U)((INT8U)(prio >> 4u) & 0x0Fu); + ptcb->OSTCBX = (INT8U) (prio & 0x0Fu); +#endif + ptcb->OSTCBBitY = (OS_PRIO)(1uL << ptcb->OSTCBY); + ptcb->OSTCBBitX = (OS_PRIO)(1uL << ptcb->OSTCBX); + OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready at original priority */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OSTCBPrioTbl[prio] = ptcb; + OS_TRACE_TASK_READY(ptcb); +} + + +#endif /* OS_MUTEX_EN */ +#endif /* OS_MUTEX_C */ diff --git a/Source/os_q.c b/Source/os_q.c new file mode 100644 index 0000000..17b73cd --- /dev/null +++ b/Source/os_q.c @@ -0,0 +1,964 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* MESSAGE QUEUE MANAGEMENT +* +* Filename : os_q.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_Q_C +#define OS_Q_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +/* +********************************************************************************************************* +* ACCEPT MESSAGE FROM QUEUE +* +* Description: This function checks the queue to see if a message is available. Unlike OSQPend(), +* OSQAccept() does not suspend the calling task if a message is not available. +* +* Arguments : pevent is a pointer to the event control block +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE The call was successful and your task received a +* message. +* OS_ERR_EVENT_TYPE You didn't pass a pointer to a queue +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_Q_EMPTY The queue did not contain any messages +* +* Returns : != (void *)0 is the message in the queue if one is available. The message is removed +* from the so the next time OSQAccept() is called, the queue will contain +* one less entry. +* == (void *)0 if you received a NULL pointer message +* if the queue is empty or, +* if 'pevent' is a NULL pointer or, +* if you passed an invalid event type +* +* Note(s) : As of V2.60, you can now pass NULL pointers through queues. Because of this, the argument +* 'perr' has been added to the API to tell you about the outcome of the call. +********************************************************************************************************* +*/ + +#if OS_Q_ACCEPT_EN > 0u +void *OSQAccept (OS_EVENT *pevent, + INT8U *perr) +{ + void *pmsg; + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((void *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return ((void *)0); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return ((void *)0); + } + OS_ENTER_CRITICAL(); + pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */ + if (pq->OSQEntries > 0u) { /* See if any messages in the queue */ + pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */ + pq->OSQEntries--; /* Update the number of entries in the queue */ + if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */ + pq->OSQOut = pq->OSQStart; + } + *perr = OS_ERR_NONE; + } else { + *perr = OS_ERR_Q_EMPTY; + pmsg = (void *)0; /* Queue is empty */ + } + OS_EXIT_CRITICAL(); + return (pmsg); /* Return message received (or NULL) */ +} +#endif + + +/* +********************************************************************************************************* +* CREATE A MESSAGE QUEUE +* +* Description: This function creates a message queue if free event control blocks are available. +* +* Arguments : start is a pointer to the base address of the message queue storage area. The +* storage area MUST be declared as an array of pointers to 'void' as follows +* +* void *MessageStorage[size] +* +* size is the number of elements in the storage area +* +* Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the +* created queue +* == (OS_EVENT *)0 if no event control blocks were available or an error was detected +********************************************************************************************************* +*/ + +OS_EVENT *OSQCreate (void **start, + INT16U size) +{ + OS_EVENT *pevent; + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */ + } + OS_ENTER_CRITICAL(); + pevent = OSEventFreeList; /* Get next free event control block */ + if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */ + OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; + } + OS_EXIT_CRITICAL(); + if (pevent != (OS_EVENT *)0) { /* See if we have an event control block */ + OS_ENTER_CRITICAL(); + pq = OSQFreeList; /* Get a free queue control block */ + if (pq != (OS_Q *)0) { /* Were we able to get a queue control block ? */ + OSQFreeList = OSQFreeList->OSQPtr; /* Yes, Adjust free list pointer to next free*/ + OS_EXIT_CRITICAL(); + pq->OSQStart = start; /* Initialize the queue */ + pq->OSQEnd = &start[size]; + pq->OSQIn = start; + pq->OSQOut = start; + pq->OSQSize = size; + pq->OSQEntries = 0u; + pevent->OSEventType = OS_EVENT_TYPE_Q; + pevent->OSEventCnt = 0u; + pevent->OSEventPtr = pq; +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + OS_EventWaitListInit(pevent); /* Initialize the wait list */ + + OS_TRACE_Q_CREATE(pevent, pevent->OSEventName); + } else { + pevent->OSEventPtr = (void *)OSEventFreeList; /* No, Return event control block on error */ + OSEventFreeList = pevent; + OS_EXIT_CRITICAL(); + pevent = (OS_EVENT *)0; + } + } + return (pevent); +} + + +/* +********************************************************************************************************* +* DELETE A MESSAGE QUEUE +* +* Description: This function deletes a message queue and readies all tasks pending on the queue. +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* queue. +* +* opt determines delete options as follows: +* opt == OS_DEL_NO_PEND Delete the queue ONLY if no task pending +* opt == OS_DEL_ALWAYS Deletes the queue even if tasks are waiting. +* In this case, all the tasks pending will be readied. +* +* perr is a pointer to an error code that can contain one of the following values: +* OS_ERR_NONE The call was successful and the queue was deleted +* OS_ERR_DEL_ISR If you tried to delete the queue from an ISR +* OS_ERR_ILLEGAL_DEL_RUN_TIME If you tried to delete the queue after safety +* critical operation started. +* OS_ERR_INVALID_OPT An invalid option was specified +* OS_ERR_TASK_WAITING One or more tasks were waiting on the queue +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* +* Returns : pevent upon error +* (OS_EVENT *)0 if the queue was successfully deleted. +* +* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of +* the queue MUST check the return code of OSQPend(). +* 2) OSQAccept() callers will not know that the intended queue has been deleted unless +* they check 'pevent' to see that it's a NULL pointer. +* 3) This call can potentially disable interrupts for a long time. The interrupt disable +* time is directly proportional to the number of tasks waiting on the queue. +* 4) Because ALL tasks pending on the queue will be readied, you MUST be careful in +* applications where the queue is used for mutual exclusion because the resource(s) +* will no longer be guarded by the queue. +* 5) If the storage for the message queue was allocated dynamically (i.e. using a malloc() +* type call) then your application MUST release the memory storage by call the counterpart +* call of the dynamic allocation scheme used. If the queue storage was created statically +* then, the storage can be reused. +* 6) All tasks that were waiting for the queue will be readied and returned an +* OS_ERR_PEND_ABORT if OSQDel() was called with OS_DEL_ALWAYS +********************************************************************************************************* +*/ + +#if OS_Q_DEL_EN > 0u +OS_EVENT *OSQDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr) +{ + BOOLEAN tasks_waiting; + OS_EVENT *pevent_return; + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_DEL_RUN_TIME; + return ((OS_EVENT *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (pevent); + } +#endif + + OS_TRACE_Q_DEL_ENTER(pevent, opt); + + if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_Q_DEL_EXIT(*perr); + return (pevent); + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ + OS_TRACE_Q_DEL_EXIT(*perr); + return (pevent); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on queue */ + tasks_waiting = OS_TRUE; /* Yes */ + } else { + tasks_waiting = OS_FALSE; /* No */ + } + switch (opt) { + case OS_DEL_NO_PEND: /* Delete queue only if no task waiting */ + if (tasks_waiting == OS_FALSE) { +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */ + pq->OSQPtr = OSQFreeList; + OSQFreeList = pq; + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; /* Get next free event control block */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Queue has been deleted */ + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_TASK_WAITING; + pevent_return = pevent; + } + break; + + case OS_DEL_ALWAYS: /* Always delete the queue */ + while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for queue */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT); + } +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pq = (OS_Q *)pevent->OSEventPtr; /* Return OS_Q to free list */ + pq->OSQPtr = OSQFreeList; + OSQFreeList = pq; + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; /* Get next free event control block */ + OS_EXIT_CRITICAL(); + if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ + OS_Sched(); /* Find highest priority task ready to run */ + } + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Queue has been deleted */ + break; + + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_INVALID_OPT; + pevent_return = pevent; + break; + } + + OS_TRACE_Q_DEL_EXIT(*perr); + + return (pevent_return); +} +#endif + + +/* +********************************************************************************************************* +* FLUSH QUEUE +* +* Description : This function is used to flush the contents of the message queue. +* +* Arguments : none +* +* Returns : OS_ERR_NONE upon success +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* +* WARNING : You should use this function with great care because, when to flush the queue, you LOOSE +* the references to what the queue entries are pointing to and thus, you could cause +* 'memory leaks'. In other words, the data you are pointing to that's being referenced +* by the queue entries should, most likely, need to be de-allocated (i.e. freed). +********************************************************************************************************* +*/ + +#if OS_Q_FLUSH_EN > 0u +INT8U OSQFlush (OS_EVENT *pevent) +{ + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } + if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ + return (OS_ERR_EVENT_TYPE); + } +#endif + OS_ENTER_CRITICAL(); + pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue storage structure */ + pq->OSQIn = pq->OSQStart; + pq->OSQOut = pq->OSQStart; + pq->OSQEntries = 0u; + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* PEND ON A QUEUE FOR A MESSAGE +* +* Description: This function waits for a message to be sent to a queue +* +* Arguments : pevent is a pointer to the event control block associated with the desired queue +* +* timeout is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for a message to arrive at the queue up to the amount of time +* specified by this argument. If you specify 0, however, your task will wait +* forever at the specified queue or, until a message arrives. +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE The call was successful and your task received a +* message. +* OS_ERR_TIMEOUT A message was not received within the specified 'timeout'. +* OS_ERR_PEND_ABORT The wait on the queue was aborted. +* OS_ERR_EVENT_TYPE You didn't pass a pointer to a queue +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_PEND_ISR If you called this function from an ISR and the result +* would lead to a suspension. +* OS_ERR_PEND_LOCKED If you called this function with the scheduler is locked +* +* Returns : != (void *)0 is a pointer to the message received +* == (void *)0 if you received a NULL pointer message or, +* if no message was received or, +* if 'pevent' is a NULL pointer or, +* if you didn't pass a pointer to a queue. +* +* Note(s) : As of V2.60, this function allows you to receive NULL pointer messages. +********************************************************************************************************* +*/ + +void *OSQPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr) +{ + void *pmsg; + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((void *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return ((void *)0); + } +#endif + + OS_TRACE_Q_PEND_ENTER(pevent, timeout); + + if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_Q_PEND_EXIT(*perr); + return ((void *)0); + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + OS_TRACE_Q_PEND_EXIT(*perr); + return ((void *)0); + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + OS_TRACE_Q_PEND_EXIT(*perr); + return ((void *)0); + } + OS_ENTER_CRITICAL(); + pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block */ + if (pq->OSQEntries > 0u) { /* See if any messages in the queue */ + pmsg = *pq->OSQOut++; /* Yes, extract oldest message from the queue */ + pq->OSQEntries--; /* Update the number of entries in the queue */ + if (pq->OSQOut == pq->OSQEnd) { /* Wrap OUT pointer if we are at the end of the queue */ + pq->OSQOut = pq->OSQStart; + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + OS_TRACE_Q_PEND_EXIT(*perr); + return (pmsg); /* Return message received */ + } + OSTCBCur->OSTCBStat |= OS_STAT_Q; /* Task will have to pend for a message to be posted */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Load timeout into TCB */ + OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next highest priority task ready to run */ + OS_ENTER_CRITICAL(); + switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ + case OS_STAT_PEND_OK: /* Extract message from TCB (Put there by QPost) */ + pmsg = OSTCBCur->OSTCBMsg; + *perr = OS_ERR_NONE; + break; + + case OS_STAT_PEND_ABORT: + pmsg = (void *)0; + *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ + break; + + case OS_STAT_PEND_TO: + default: + OS_EventTaskRemove(OSTCBCur, pevent); + pmsg = (void *)0; + *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ + break; + } + OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ + OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ +#if (OS_EVENT_MULTI_EN > 0u) + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; + OSTCBCur->OSTCBEventMultiRdy = (OS_EVENT *)0; +#endif + OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */ + OS_EXIT_CRITICAL(); + OS_TRACE_Q_PEND_EXIT(*perr); + + return (pmsg); /* Return received message */ +} + + +/* +********************************************************************************************************* +* ABORT WAITING ON A MESSAGE QUEUE +* +* Description: This function aborts & readies any tasks currently waiting on a queue. This function +* should be used to fault-abort the wait on the queue, rather than to normally signal +* the queue via OSQPost(), OSQPostFront() or OSQPostOpt(). +* +* Arguments : pevent is a pointer to the event control block associated with the desired queue. +* +* opt determines the type of ABORT performed: +* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the +* queue +* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the +* queue +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE No tasks were waiting on the queue. +* OS_ERR_PEND_ABORT At least one task waiting on the queue was readied +* and informed of the aborted wait; check return value +* for the number of tasks whose wait on the queue +* was aborted. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* +* Returns : == 0 if no tasks were waiting on the queue, or upon error. +* > 0 if one or more tasks waiting on the queue are now readied and informed. +********************************************************************************************************* +*/ + +#if OS_Q_PEND_ABORT_EN > 0u +INT8U OSQPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr) +{ + INT8U nbr_tasks; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task waiting on queue? */ + nbr_tasks = 0u; + switch (opt) { + case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */ + while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on queue */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT); + nbr_tasks++; + } + break; + + case OS_PEND_OPT_NONE: + default: /* No, ready HPT waiting on queue */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q, OS_STAT_PEND_ABORT); + nbr_tasks++; + break; + } + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find HPT ready to run */ + *perr = OS_ERR_PEND_ABORT; + return (nbr_tasks); + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (0u); /* No tasks waiting on queue */ +} +#endif + + +/* +********************************************************************************************************* +* POST MESSAGE TO A QUEUE +* +* Description: This function sends a message to a queue +* +* Arguments : pevent is a pointer to the event control block associated with the desired queue +* +* pmsg is a pointer to the message to send. +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* +* Note(s) : As of V2.60, this function allows you to send NULL pointer messages. +********************************************************************************************************* +*/ + +#if OS_Q_POST_EN > 0u +INT8U OSQPost (OS_EVENT *pevent, + void *pmsg) +{ + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } +#endif + + OS_TRACE_Q_POST_ENTER(pevent); + + if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ + OS_TRACE_Q_POST_EXIT(OS_ERR_EVENT_TYPE); + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task pending on queue */ + /* Ready highest priority task waiting on event */ + (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find highest priority task ready to run */ + OS_TRACE_Q_POST_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */ + if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */ + OS_EXIT_CRITICAL(); + OS_TRACE_Q_POST_EXIT(OS_ERR_Q_FULL); + return (OS_ERR_Q_FULL); + } + *pq->OSQIn++ = pmsg; /* Insert message into queue */ + pq->OSQEntries++; /* Update the nbr of entries in the queue */ + if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */ + pq->OSQIn = pq->OSQStart; + } + OS_EXIT_CRITICAL(); + OS_TRACE_Q_POST_EXIT(OS_ERR_NONE); + + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* POST MESSAGE TO THE FRONT OF A QUEUE +* +* Description: This function sends a message to a queue but unlike OSQPost(), the message is posted at +* the front instead of the end of the queue. Using OSQPostFront() allows you to send +* 'priority' messages. +* +* Arguments : pevent is a pointer to the event control block associated with the desired queue +* +* pmsg is a pointer to the message to send. +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* +* Note(s) : As of V2.60, this function allows you to send NULL pointer messages. +********************************************************************************************************* +*/ + +#if OS_Q_POST_FRONT_EN > 0u +INT8U OSQPostFront (OS_EVENT *pevent, + void *pmsg) +{ + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } +#endif + + OS_TRACE_Q_POST_FRONT_ENTER(pevent); + + if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ + OS_TRACE_Q_POST_FRONT_EXIT(OS_ERR_EVENT_TYPE); + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task pending on queue */ + /* Ready highest priority task waiting on event */ + (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find highest priority task ready to run */ + OS_TRACE_Q_POST_FRONT_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */ + if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */ + OS_EXIT_CRITICAL(); + OS_TRACE_Q_POST_FRONT_EXIT(OS_ERR_Q_FULL); + return (OS_ERR_Q_FULL); + } + if (pq->OSQOut == pq->OSQStart) { /* Wrap OUT ptr if we are at the 1st queue entry */ + pq->OSQOut = pq->OSQEnd; + } + pq->OSQOut--; + *pq->OSQOut = pmsg; /* Insert message into queue */ + pq->OSQEntries++; /* Update the nbr of entries in the queue */ + OS_EXIT_CRITICAL(); + OS_TRACE_Q_POST_FRONT_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* POST MESSAGE TO A QUEUE +* +* Description: This function sends a message to a queue. This call has been added to reduce code size +* since it can replace both OSQPost() and OSQPostFront(). Also, this function adds the +* capability to broadcast a message to ALL tasks waiting on the message queue. +* +* Arguments : pevent is a pointer to the event control block associated with the desired queue +* +* pmsg is a pointer to the message to send. +* +* opt determines the type of POST performed: +* OS_POST_OPT_NONE POST to a single waiting task +* (Identical to OSQPost()) +* OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the queue +* OS_POST_OPT_FRONT POST as LIFO (Simulates OSQPostFront()) +* OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_Q_FULL If the queue cannot accept any more messages because it is full. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a queue. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* +* Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the +* interrupt disable time is proportional to the number of tasks waiting on the queue. +********************************************************************************************************* +*/ + +#if OS_Q_POST_OPT_EN > 0u +INT8U OSQPostOpt (OS_EVENT *pevent, + void *pmsg, + INT8U opt) +{ + OS_Q *pq; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } +#endif + + OS_TRACE_Q_POST_OPT_ENTER(pevent, opt); + + if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ + OS_TRACE_Q_POST_OPT_EXIT(OS_ERR_EVENT_TYPE); + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0x00u) { /* See if any task pending on queue */ + if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */ + while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on queue */ + (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); + } + } else { /* No, Post to HPT waiting on queue */ + (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_Q, OS_STAT_PEND_OK); + } + OS_EXIT_CRITICAL(); + if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */ + OS_Sched(); /* Find highest priority task ready to run */ + } + OS_TRACE_Q_POST_OPT_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + pq = (OS_Q *)pevent->OSEventPtr; /* Point to queue control block */ + if (pq->OSQEntries >= pq->OSQSize) { /* Make sure queue is not full */ + OS_EXIT_CRITICAL(); + OS_TRACE_Q_POST_OPT_EXIT(OS_ERR_Q_FULL); + return (OS_ERR_Q_FULL); + } + if ((opt & OS_POST_OPT_FRONT) != 0x00u) { /* Do we post to the FRONT of the queue? */ + if (pq->OSQOut == pq->OSQStart) { /* Yes, Post as LIFO, Wrap OUT pointer if we ... */ + pq->OSQOut = pq->OSQEnd; /* ... are at the 1st queue entry */ + } + pq->OSQOut--; + *pq->OSQOut = pmsg; /* Insert message into queue */ + } else { /* No, Post as FIFO */ + *pq->OSQIn++ = pmsg; /* Insert message into queue */ + if (pq->OSQIn == pq->OSQEnd) { /* Wrap IN ptr if we are at end of queue */ + pq->OSQIn = pq->OSQStart; + } + } + pq->OSQEntries++; /* Update the nbr of entries in the queue */ + OS_EXIT_CRITICAL(); + OS_TRACE_Q_POST_OPT_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* QUERY A MESSAGE QUEUE +* +* Description: This function obtains information about a message queue. +* +* Arguments : pevent is a pointer to the event control block associated with the desired queue +* +* p_q_data is a pointer to a structure that will contain information about the message +* queue. +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non queue. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer +* OS_ERR_PDATA_NULL If 'p_q_data' is a NULL pointer +********************************************************************************************************* +*/ + +#if OS_Q_QUERY_EN > 0u +INT8U OSQQuery (OS_EVENT *pevent, + OS_Q_DATA *p_q_data) +{ + OS_Q *pq; + INT8U i; + OS_PRIO *psrc; + OS_PRIO *pdest; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } + if (p_q_data == (OS_Q_DATA *)0) { /* Validate 'p_q_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_Q) { /* Validate event block type */ + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + p_q_data->OSEventGrp = pevent->OSEventGrp; /* Copy message queue wait list */ + psrc = &pevent->OSEventTbl[0]; + pdest = &p_q_data->OSEventTbl[0]; + for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { + *pdest++ = *psrc++; + } + pq = (OS_Q *)pevent->OSEventPtr; + if (pq->OSQEntries > 0u) { + p_q_data->OSMsg = *pq->OSQOut; /* Get next message to return if available */ + } else { + p_q_data->OSMsg = (void *)0; + } + p_q_data->OSNMsgs = pq->OSQEntries; + p_q_data->OSQSize = pq->OSQSize; + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif /* OS_Q_QUERY_EN */ + + +/* +********************************************************************************************************* +* QUEUE MODULE INITIALIZATION +* +* Description : This function is called by uC/OS-II to initialize the message queue module. Your +* application MUST NOT call this function. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_QInit (void) +{ +#if OS_MAX_QS == 1u + OSQFreeList = &OSQTbl[0]; /* Only ONE queue! */ + OSQFreeList->OSQPtr = (OS_Q *)0; +#endif + +#if OS_MAX_QS >= 2u + INT16U ix; + INT16U ix_next; + OS_Q *pq1; + OS_Q *pq2; + + + + OS_MemClr((INT8U *)&OSQTbl[0], sizeof(OSQTbl)); /* Clear the queue table */ + for (ix = 0u; ix < (OS_MAX_QS - 1u); ix++) { /* Init. list of free QUEUE control blocks */ + ix_next = ix + 1u; + pq1 = &OSQTbl[ix]; + pq2 = &OSQTbl[ix_next]; + pq1->OSQPtr = pq2; + } + pq1 = &OSQTbl[ix]; + pq1->OSQPtr = (OS_Q *)0; + OSQFreeList = &OSQTbl[0]; +#endif +} +#endif /* OS_Q_EN */ +#endif /* OS_Q_C */ diff --git a/Source/os_sem.c b/Source/os_sem.c new file mode 100644 index 0000000..06e27cc --- /dev/null +++ b/Source/os_sem.c @@ -0,0 +1,679 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* SEMAPHORE MANAGEMENT +* +* Filename : os_sem.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_SEM_C +#define OS_SEM_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + +#if OS_SEM_EN > 0u +/* +********************************************************************************************************* +* ACCEPT SEMAPHORE +* +* Description: This function checks the semaphore to see if a resource is available or, if an event +* occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the +* resource is not available or the event did not occur. +* +* Arguments : pevent is a pointer to the event control block +* +* Returns : > 0 if the resource is available or the event did not occur the semaphore is +* decremented to obtain the resource. +* == 0 if the resource is not available or the event did not occur or, +* if 'pevent' is a NULL pointer or, +* if you didn't pass a pointer to a semaphore +********************************************************************************************************* +*/ + +#if OS_SEM_ACCEPT_EN > 0u +INT16U OSSemAccept (OS_EVENT *pevent) +{ + INT16U cnt; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (0u); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ + return (0u); + } + OS_ENTER_CRITICAL(); + cnt = pevent->OSEventCnt; + if (cnt > 0u) { /* See if resource is available */ + pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */ + } + OS_EXIT_CRITICAL(); + return (cnt); /* Return semaphore count */ +} +#endif + + +/* +********************************************************************************************************* +* CREATE A SEMAPHORE +* +* Description: This function creates a semaphore. +* +* Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is +* available (or no event has occurred). You initialize the semaphore to a +* non-zero value to specify how many resources are available (e.g. if you have +* 10 resources, you would initialize the semaphore to 10). +* +* Returns : != (void *)0 is a pointer to the event control block (OS_EVENT) associated with the +* created semaphore +* == (void *)0 if no event control blocks were available +********************************************************************************************************* +*/ + +OS_EVENT *OSSemCreate (INT16U cnt) +{ + OS_EVENT *pevent; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */ + } + OS_ENTER_CRITICAL(); + pevent = OSEventFreeList; /* Get next free event control block */ + if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */ + OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr; + } + OS_EXIT_CRITICAL(); + if (pevent != (OS_EVENT *)0) { /* Get an event control block */ + pevent->OSEventType = OS_EVENT_TYPE_SEM; + pevent->OSEventCnt = cnt; /* Set semaphore value */ + pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */ +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */ + + OS_TRACE_SEM_CREATE(pevent, pevent->OSEventName); + } + return (pevent); +} + + +/* +********************************************************************************************************* +* DELETE A SEMAPHORE +* +* Description: This function deletes a semaphore and readies all tasks pending on the semaphore. +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* semaphore. +* +* opt determines delete options as follows: +* opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending +* opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting. +* In this case, all the tasks pending will be readied. +* +* perr is a pointer to an error code that can contain one of the following values: +* OS_ERR_NONE The call was successful and the semaphore was +* deleted +* OS_ERR_DEL_ISR If you attempted to delete the semaphore from an +* ISR +* OS_ERR_ILLEGAL_DEL_RUN_TIME If you tried to delete the semaphore after +* safety critical operation started. +* OS_ERR_INVALID_OPT An invalid option was specified +* OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* +* Returns : pevent upon error +* (OS_EVENT *)0 if the semaphore was successfully deleted. +* +* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of +* the semaphore MUST check the return code of OSSemPend(). +* 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless +* they check 'pevent' to see that it's a NULL pointer. +* 3) This call can potentially disable interrupts for a long time. The interrupt disable +* time is directly proportional to the number of tasks waiting on the semaphore. +* 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in +* applications where the semaphore is used for mutual exclusion because the resource(s) +* will no longer be guarded by the semaphore. +* 5) All tasks that were waiting for the semaphore will be readied and returned an +* OS_ERR_PEND_ABORT if OSSemDel() was called with OS_DEL_ALWAYS +********************************************************************************************************* +*/ + +#if OS_SEM_DEL_EN > 0u +OS_EVENT *OSSemDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr) +{ + BOOLEAN tasks_waiting; + OS_EVENT *pevent_return; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_EVENT *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_DEL_RUN_TIME; + return ((OS_EVENT *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (pevent); + } +#endif + + OS_TRACE_SEM_DEL_ENTER(pevent, opt); + + if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_SEM_DEL_EXIT(*perr); + return (pevent); + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */ + OS_TRACE_SEM_DEL_EXIT(*perr); + return (pevent); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on semaphore */ + tasks_waiting = OS_TRUE; /* Yes */ + } else { + tasks_waiting = OS_FALSE; /* No */ + } + switch (opt) { + case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */ + if (tasks_waiting == OS_FALSE) { +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; /* Get next free event control block */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ + } else { + OS_EXIT_CRITICAL(); + *perr = OS_ERR_TASK_WAITING; + pevent_return = pevent; + } + break; + + case OS_DEL_ALWAYS: /* Always delete the semaphore */ + while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for semaphore */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT); + } +#if OS_EVENT_NAME_EN > 0u + pevent->OSEventName = (INT8U *)(void *)"?"; +#endif + pevent->OSEventType = OS_EVENT_TYPE_UNUSED; + pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */ + pevent->OSEventCnt = 0u; + OSEventFreeList = pevent; /* Get next free event control block */ + OS_EXIT_CRITICAL(); + if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */ + OS_Sched(); /* Find highest priority task ready to run */ + } + *perr = OS_ERR_NONE; + pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */ + break; + + default: + OS_EXIT_CRITICAL(); + *perr = OS_ERR_INVALID_OPT; + pevent_return = pevent; + break; + } + + OS_TRACE_SEM_DEL_EXIT(*perr); + + return (pevent_return); +} +#endif + + +/* +********************************************************************************************************* +* PEND ON SEMAPHORE +* +* Description: This function waits for a semaphore. +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* semaphore. +* +* timeout is an optional timeout period (in clock ticks). If non-zero, your task will +* wait for the resource up to the amount of time specified by this argument. +* If you specify 0, however, your task will wait forever at the specified +* semaphore or, until the resource becomes available (or the event occurs). +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE The call was successful and your task owns the resource +* or, the event you are waiting for occurred. +* OS_ERR_TIMEOUT The semaphore was not received within the specified +* 'timeout'. +* OS_ERR_PEND_ABORT The wait on the semaphore was aborted. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore. +* OS_ERR_PEND_ISR If you called this function from an ISR and the result +* would lead to a suspension. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked +* +* Returns : none +********************************************************************************************************* +*/ + +void OSSemPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return; + } +#endif + + OS_TRACE_SEM_PEND_ENTER(pevent, timeout); + + if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + OS_TRACE_SEM_PEND_EXIT(*perr); + return; + } + if (OSIntNesting > 0u) { /* See if called from ISR ... */ + *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */ + OS_TRACE_SEM_PEND_EXIT(*perr); + return; + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */ + *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */ + OS_TRACE_SEM_PEND_EXIT(*perr); + return; + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */ + pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + OS_TRACE_SEM_PEND_EXIT(*perr); + return; + } + /* Otherwise, must wait until event occurs */ + OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; + OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ + OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */ + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next highest priority task ready */ + OS_ENTER_CRITICAL(); + switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */ + case OS_STAT_PEND_OK: + *perr = OS_ERR_NONE; + break; + + case OS_STAT_PEND_ABORT: + *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */ + break; + + case OS_STAT_PEND_TO: + default: + OS_EventTaskRemove(OSTCBCur, pevent); + *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */ + break; + } + OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */ + OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */ + OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */ +#if (OS_EVENT_MULTI_EN > 0u) + OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0; + OSTCBCur->OSTCBEventMultiRdy = (OS_EVENT *)0; +#endif + OS_EXIT_CRITICAL(); + + OS_TRACE_SEM_PEND_EXIT(*perr); +} + + +/* +********************************************************************************************************* +* ABORT WAITING ON A SEMAPHORE +* +* Description: This function aborts & readies any tasks currently waiting on a semaphore. This function +* should be used to fault-abort the wait on the semaphore, rather than to normally signal +* the semaphore via OSSemPost(). +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* semaphore. +* +* opt determines the type of ABORT performed: +* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the +* semaphore +* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the +* semaphore +* +* perr is a pointer to where an error message will be deposited. Possible error +* messages are: +* +* OS_ERR_NONE No tasks were waiting on the semaphore. +* OS_ERR_PEND_ABORT At least one task waiting on the semaphore was readied +* and informed of the aborted wait; check return value +* for the number of tasks whose wait on the semaphore +* was aborted. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* +* Returns : == 0 if no tasks were waiting on the semaphore, or upon error. +* > 0 if one or more tasks waiting on the semaphore are now readied and informed. +********************************************************************************************************* +*/ + +#if OS_SEM_PEND_ABORT_EN > 0u +INT8U OSSemPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr) +{ + INT8U nbr_tasks; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return (0u); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return (0u); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task waiting on semaphore? */ + nbr_tasks = 0u; + switch (opt) { + case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */ + while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on semaphore */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT); + nbr_tasks++; + } + break; + + case OS_PEND_OPT_NONE: + default: /* No, ready HPT waiting on semaphore */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT); + nbr_tasks++; + break; + } + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find HPT ready to run */ + *perr = OS_ERR_PEND_ABORT; + return (nbr_tasks); + } + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (0u); /* No tasks waiting on semaphore */ +} +#endif + + +/* +********************************************************************************************************* +* POST TO A SEMAPHORE +* +* Description: This function signals a semaphore +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* semaphore. +* +* Returns : OS_ERR_NONE The call was successful and the semaphore was signaled. +* OS_ERR_SEM_OVF If the semaphore count exceeded its limit. In other words, you have +* signaled the semaphore more often than you waited on it with either +* OSSemAccept() or OSSemPend(). +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +********************************************************************************************************* +*/ + +INT8U OSSemPost (OS_EVENT *pevent) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } +#endif + + OS_TRACE_SEM_POST_ENTER(pevent); + + if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ + OS_TRACE_SEM_POST_EXIT(OS_ERR_EVENT_TYPE); + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + if (pevent->OSEventGrp != 0u) { /* See if any task waiting for semaphore */ + /* Ready HPT waiting on event */ + (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK); + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find HPT ready to run */ + OS_TRACE_SEM_POST_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */ + pevent->OSEventCnt++; /* Increment semaphore count to register event */ + OS_EXIT_CRITICAL(); + OS_TRACE_SEM_POST_EXIT(OS_ERR_NONE); + return (OS_ERR_NONE); + } + OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */ + OS_TRACE_SEM_POST_EXIT(OS_ERR_SEM_OVF); + + return (OS_ERR_SEM_OVF); +} + + +/* +********************************************************************************************************* +* QUERY A SEMAPHORE +* +* Description: This function obtains information about a semaphore +* +* Arguments : pevent is a pointer to the event control block associated with the desired +* semaphore +* +* p_sem_data is a pointer to a structure that will contain information about the +* semaphore. +* +* Returns : OS_ERR_NONE The call was successful and the message was sent +* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non semaphore. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* OS_ERR_PDATA_NULL If 'p_sem_data' is a NULL pointer +********************************************************************************************************* +*/ + +#if OS_SEM_QUERY_EN > 0u +INT8U OSSemQuery (OS_EVENT *pevent, + OS_SEM_DATA *p_sem_data) +{ + INT8U i; + OS_PRIO *psrc; + OS_PRIO *pdest; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + return (OS_ERR_PEVENT_NULL); + } + if (p_sem_data == (OS_SEM_DATA *)0) { /* Validate 'p_sem_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ + return (OS_ERR_EVENT_TYPE); + } + OS_ENTER_CRITICAL(); + p_sem_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */ + psrc = &pevent->OSEventTbl[0]; + pdest = &p_sem_data->OSEventTbl[0]; + for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) { + *pdest++ = *psrc++; + } + p_sem_data->OSCnt = pevent->OSEventCnt; /* Get semaphore count */ + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif /* OS_SEM_QUERY_EN */ + + +/* +********************************************************************************************************* +* SET SEMAPHORE +* +* Description: This function sets the semaphore count to the value specified as an argument. Typically, +* this value would be 0. +* +* You would typically use this function when a semaphore is used as a signaling mechanism +* and, you want to reset the count value. +* +* Arguments : pevent is a pointer to the event control block +* +* cnt is the new value for the semaphore count. You would pass 0 to reset the +* semaphore count. +* +* perr is a pointer to an error code returned by the function as follows: +* +* OS_ERR_NONE The call was successful and the semaphore value was set. +* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore. +* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer. +* OS_ERR_TASK_WAITING If tasks are waiting on the semaphore. +********************************************************************************************************* +*/ + +#if OS_SEM_SET_EN > 0u +void OSSemSet (OS_EVENT *pevent, + INT16U cnt, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */ + *perr = OS_ERR_PEVENT_NULL; + return; + } +#endif + if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ + *perr = OS_ERR_EVENT_TYPE; + return; + } + OS_ENTER_CRITICAL(); + *perr = OS_ERR_NONE; + if (pevent->OSEventCnt > 0u) { /* See if semaphore already has a count */ + pevent->OSEventCnt = cnt; /* Yes, set it to the new value specified. */ + } else { /* No */ + if (pevent->OSEventGrp == 0u) { /* See if task(s) waiting? */ + pevent->OSEventCnt = cnt; /* No, OK to set the value */ + } else { + *perr = OS_ERR_TASK_WAITING; + } + } + OS_EXIT_CRITICAL(); +} +#endif + +#endif /* OS_SEM_EN */ +#endif /* OS_SEM_C */ diff --git a/Source/os_task.c b/Source/os_task.c new file mode 100644 index 0000000..2427e87 --- /dev/null +++ b/Source/os_task.c @@ -0,0 +1,1386 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TASK MANAGEMENT +* +* Filename : os_task.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_TASK_C +#define OS_TASK_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + + +/* +********************************************************************************************************* +* CHANGE PRIORITY OF A TASK +* +* Description: This function allows you to change the priority of a task dynamically. Note that the new +* priority MUST be available. +* +* Arguments : oldp is the old priority +* +* newp is the new priority +* +* Returns : OS_ERR_NONE is the call was successful +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) +* OS_ERR_PRIO_EXIST if the new priority already exist. +* OS_ERR_PRIO there is no task with the specified OLD priority (i.e. the OLD task does +* not exist. +* OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP. +********************************************************************************************************* +*/ + +#if OS_TASK_CHANGE_PRIO_EN > 0u +INT8U OSTaskChangePrio (INT8U oldprio, + INT8U newprio) +{ +#if (OS_EVENT_EN) + OS_EVENT *pevent; +#if (OS_EVENT_MULTI_EN > 0u) + OS_EVENT **pevents; +#endif +#endif + OS_TCB *ptcb; + INT8U y_new; + INT8U x_new; + INT8U y_old; + OS_PRIO bity_new; + OS_PRIO bitx_new; + OS_PRIO bity_old; + OS_PRIO bitx_old; +#if OS_CRITICAL_METHOD == 3u + OS_CPU_SR cpu_sr = 0u; /* Storage for CPU status register */ +#endif + + +#if OS_ARG_CHK_EN > 0u + if (oldprio >= OS_LOWEST_PRIO) { + if (oldprio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } + if (newprio >= OS_LOWEST_PRIO) { + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) { /* New priority must not already exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO_EXIST); + } + if (oldprio == OS_PRIO_SELF) { /* See if changing self */ + oldprio = OSTCBCur->OSTCBPrio; /* Yes, get priority */ + } + ptcb = OSTCBPrioTbl[oldprio]; + if (ptcb == (OS_TCB *)0) { /* Does task to change exist? */ + OS_EXIT_CRITICAL(); /* No, can't change its priority! */ + return (OS_ERR_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* Is task assigned to Mutex */ + OS_EXIT_CRITICAL(); /* No, can't change its priority! */ + return (OS_ERR_TASK_NOT_EXIST); + } +#if OS_LOWEST_PRIO <= 63u + y_new = (INT8U)(newprio >> 3u); /* Yes, compute new TCB fields */ + x_new = (INT8U)(newprio & 0x07u); +#else + y_new = (INT8U)((INT8U)(newprio >> 4u) & 0x0Fu); + x_new = (INT8U)(newprio & 0x0Fu); +#endif + bity_new = (OS_PRIO)(1uL << y_new); + bitx_new = (OS_PRIO)(1uL << x_new); + + OSTCBPrioTbl[oldprio] = (OS_TCB *)0; /* Remove TCB from old priority */ + OSTCBPrioTbl[newprio] = ptcb; /* Place pointer to TCB @ new priority */ + y_old = ptcb->OSTCBY; + bity_old = ptcb->OSTCBBitY; + bitx_old = ptcb->OSTCBBitX; + if ((OSRdyTbl[y_old] & bitx_old) != 0u) { /* If task is ready make it not */ + OSRdyTbl[y_old] &= (OS_PRIO)~bitx_old; + if (OSRdyTbl[y_old] == 0u) { + OSRdyGrp &= (OS_PRIO)~bity_old; + } + OSRdyGrp |= bity_new; /* Make new priority ready to run */ + OSRdyTbl[y_new] |= bitx_new; + OS_TRACE_TASK_READY(ptcb); + } + +#if (OS_EVENT_EN) + pevent = ptcb->OSTCBEventPtr; + if (pevent != (OS_EVENT *)0) { + pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old; /* Remove old task prio from wait list */ + if (pevent->OSEventTbl[y_old] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~bity_old; + } + pevent->OSEventGrp |= bity_new; /* Add new task prio to wait list */ + pevent->OSEventTbl[y_new] |= bitx_new; + } +#if (OS_EVENT_MULTI_EN > 0u) + if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { + pevents = ptcb->OSTCBEventMultiPtr; + pevent = *pevents; + while (pevent != (OS_EVENT *)0) { + pevent->OSEventTbl[y_old] &= (OS_PRIO)~bitx_old; /* Remove old task prio from wait lists */ + if (pevent->OSEventTbl[y_old] == 0u) { + pevent->OSEventGrp &= (OS_PRIO)~bity_old; + } + pevent->OSEventGrp |= bity_new; /* Add new task prio to wait lists */ + pevent->OSEventTbl[y_new] |= bitx_new; + pevents++; + pevent = *pevents; + } + } +#endif +#endif + + ptcb->OSTCBPrio = newprio; /* Set new task priority */ + ptcb->OSTCBY = y_new; + ptcb->OSTCBX = x_new; + ptcb->OSTCBBitY = bity_new; + ptcb->OSTCBBitX = bitx_new; + OS_EXIT_CRITICAL(); + if (OSRunning == OS_TRUE) { + OS_Sched(); /* Find new highest priority task */ + } + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* CREATE A TASK +* +* Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either +* be created prior to the start of multitasking or by a running task. A task cannot be +* created by an ISR. +* +* Arguments : task is a pointer to the task's code +* +* p_arg is a pointer to an optional data area which can be used to pass parameters to +* the task when the task first executes. Where the task is concerned it thinks +* it was invoked and passed the argument 'p_arg' as follows: +* +* void Task (void *p_arg) +* { +* for (;;) { +* Task code; +* } +* } +* +* ptos is a pointer to the task's top of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'pstk' will thus point to the highest (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'pstk' will point to the +* lowest memory location of the stack and the stack will grow with increasing +* memory locations. +* +* prio is the task's priority. A unique priority MUST be assigned to each task and the +* lower the number, the higher the priority. +* +* Returns : OS_ERR_NONE if the function was successful. +* OS_ERR_PRIO_EXIST if the task priority already exist +* (each task MUST have a unique priority). +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum +* allowed (i.e. >= OS_LOWEST_PRIO) +* OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR. +* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a task after safety critical +* operation started. +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EN > 0u +INT8U OSTaskCreate (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio) +{ + OS_STK *psp; + INT8U err; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_ERR_ILLEGAL_CREATE_RUN_TIME); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_CREATE_ISR); + } + if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ + OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ + /* ... the same thing until task is created. */ + OS_EXIT_CRITICAL(); + psp = OSTaskStkInit(task, p_arg, ptos, 0u); /* Initialize the task's stack */ + err = OS_TCBInit(prio, psp, (OS_STK *)0, 0u, 0u, (void *)0, 0u); + if (err == OS_ERR_NONE) { + OS_TRACE_TASK_CREATE(OSTCBPrioTbl[prio]); + if (OSRunning == OS_TRUE) { /* Find highest priority task if multitasking has started */ + OS_Sched(); + } + } else { + OS_TRACE_TASK_CREATE_FAILED(OSTCBPrioTbl[prio]); + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = (OS_TCB *)0;/* Make this priority available to others */ + OS_EXIT_CRITICAL(); + } + return (err); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO_EXIST); +} +#endif + + +/* +********************************************************************************************************* +* CREATE A TASK (Extended Version) +* +* Description: This function is used to have uC/OS-II manage the execution of a task. Tasks can either +* be created prior to the start of multitasking or by a running task. A task cannot be +* created by an ISR. This function is similar to OSTaskCreate() except that it allows +* additional information about a task to be specified. +* +* Arguments : task is a pointer to the task's code +* +* p_arg is a pointer to an optional data area which can be used to pass parameters to +* the task when the task first executes. Where the task is concerned it thinks +* it was invoked and passed the argument 'p_arg' as follows: +* +* void Task (void *p_arg) +* { +* for (;;) { +* Task code; +* } +* } +* +* ptos is a pointer to the task's top of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'ptos' will thus point to the highest (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'ptos' will point to the +* lowest memory location of the stack and the stack will grow with increasing +* memory locations. 'ptos' MUST point to a valid 'free' data item. +* +* prio is the task's priority. A unique priority MUST be assigned to each task and the +* lower the number, the higher the priority. +* +* id is the task's ID (0..65535) +* +* pbos is a pointer to the task's bottom of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'pbos' will thus point to the LOWEST (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'pbos' will point to the +* HIGHEST memory location of the stack and the stack will grow with increasing +* memory locations. 'pbos' MUST point to a valid 'free' data item. +* +* stk_size is the size of the stack in number of elements. If OS_STK is set to INT8U, +* 'stk_size' corresponds to the number of bytes available. If OS_STK is set to +* INT16U, 'stk_size' contains the number of 16-bit entries available. Finally, if +* OS_STK is set to INT32U, 'stk_size' contains the number of 32-bit entries +* available on the stack. +* +* pext is a pointer to a user supplied memory location which is used as a TCB extension. +* For example, this user memory can hold the contents of floating-point registers +* during a context switch, the time each task takes to execute, the number of times +* the task has been switched-in, etc. +* +* opt contains additional information (or options) about the behavior of the task. The +* LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application +* specific. See OS_TASK_OPT_??? in uCOS-II.H. Current choices are: +* +* OS_TASK_OPT_STK_CHK Stack checking to be allowed for the task +* OS_TASK_OPT_STK_CLR Clear the stack when the task is created +* OS_TASK_OPT_SAVE_FP If the CPU has floating-point registers, save them +* during a context switch. +* +* Returns : OS_ERR_NONE if the function was successful. +* OS_ERR_PRIO_EXIST if the task priority already exist +* (each task MUST have a unique priority). +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum +* allowed (i.e. > OS_LOWEST_PRIO) +* OS_ERR_TASK_CREATE_ISR if you tried to create a task from an ISR. +* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a task after safety critical +* operation started. +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EXT_EN > 0u +INT8U OSTaskCreateExt (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio, + INT16U id, + OS_STK *pbos, + INT32U stk_size, + void *pext, + INT16U opt) +{ + OS_STK *psp; + INT8U err; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_ERR_ILLEGAL_CREATE_RUN_TIME); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */ + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_CREATE_ISR); + } + if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* Make sure task doesn't already exist at this priority */ + OSTCBPrioTbl[prio] = OS_TCB_RESERVED;/* Reserve the priority to prevent others from doing ... */ + /* ... the same thing until task is created. */ + OS_EXIT_CRITICAL(); + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) + OS_TaskStkClr(pbos, stk_size, opt); /* Clear the task stack (if needed) */ +#endif + + psp = OSTaskStkInit(task, p_arg, ptos, opt); /* Initialize the task's stack */ + err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt); + if (err == OS_ERR_NONE) { + OS_TRACE_TASK_CREATE(OSTCBPrioTbl[prio]); + if (OSRunning == OS_TRUE) { /* Find HPT if multitasking has started */ + OS_Sched(); + } + } else { + OS_ENTER_CRITICAL(); + OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Make this priority avail. to others */ + OS_EXIT_CRITICAL(); + } + return (err); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO_EXIST); +} +#endif + + +/* +********************************************************************************************************* +* DELETE A TASK +* +* Description: This function allows you to delete a task. The calling task can delete itself by +* its own priority number. The deleted task is returned to the dormant state and can be +* re-activated by creating the deleted task again. +* +* Arguments : prio is the priority of the task to delete. Note that you can explicitly delete +* the current task without knowing its priority level by setting 'prio' to +* OS_PRIO_SELF. +* +* Returns : OS_ERR_NONE if the call is successful +* OS_ERR_ILLEGAL_DEL_RUN_TIME if you tried to delete a task after safety critical operation +* started. +* OS_ERR_TASK_DEL_IDLE if you attempted to delete uC/OS-II's idle task +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_DEL if the task is assigned to a Mutex PIP. +* OS_ERR_TASK_NOT_EXIST if the task you want to delete does not exist. +* OS_ERR_TASK_DEL_ISR if you tried to delete a task from an ISR +* +* Notes : 1) To reduce interrupt latency, OSTaskDel() 'disables' the task: +* a) by making it not ready +* b) by removing it from any wait lists +* c) by preventing OSTimeTick() from making the task ready to run. +* The task can then be 'unlinked' from the miscellaneous structures in uC/OS-II. +* 2) The function OS_Dummy() is called after OS_EXIT_CRITICAL() because, on most processors, +* the next instruction following the enable interrupt instruction is ignored. +* 3) An ISR cannot delete a task. +* 4) The lock nesting counter is incremented because, for a brief instant, if the current +* task is being deleted, the current task would not be able to be rescheduled because it +* is removed from the ready list. Incrementing the nesting counter prevents another task +* from being schedule. This means that an ISR would return to the current task which is +* being deleted. The rest of the deletion would thus be able to be completed. +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0u +INT8U OSTaskDel (INT8U prio) +{ +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + OS_FLAG_NODE *pnode; +#endif + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_ERR_ILLEGAL_DEL_RUN_TIME); + } +#endif + + if (OSIntNesting > 0u) { /* See if trying to delete from ISR */ + return (OS_ERR_TASK_DEL_ISR); + } + if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */ + return (OS_ERR_TASK_DEL_IDLE); + } +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } +#endif + + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if requesting to delete self */ + prio = OSTCBCur->OSTCBPrio; /* Set priority to delete to current */ + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if (ptcb == OS_TCB_RESERVED) { /* Must not be assigned to Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_DEL); + } + + OSRdyTbl[ptcb->OSTCBY] &= (OS_PRIO)~ptcb->OSTCBBitX; + OS_TRACE_TASK_SUSPENDED(ptcb); + if (OSRdyTbl[ptcb->OSTCBY] == 0u) { /* Make task not ready */ + OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + +#if (OS_EVENT_EN) + if (ptcb->OSTCBEventPtr != (OS_EVENT *)0) { + OS_EventTaskRemove(ptcb, ptcb->OSTCBEventPtr); /* Remove this task from any event wait list */ + } +#if (OS_EVENT_MULTI_EN > 0u) + if (ptcb->OSTCBEventMultiPtr != (OS_EVENT **)0) { /* Remove this task from any events' wait lists*/ + OS_EventTaskRemoveMulti(ptcb, ptcb->OSTCBEventMultiPtr); + } +#endif +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + pnode = ptcb->OSTCBFlagNode; + if (pnode != (OS_FLAG_NODE *)0) { /* If task is waiting on event flag */ + OS_FlagUnlink(pnode); /* Remove from wait list */ + } +#endif + + ptcb->OSTCBDly = 0u; /* Prevent OSTimeTick() from updating */ + ptcb->OSTCBStat = OS_STAT_RDY; /* Prevent task from being resumed */ + ptcb->OSTCBStatPend = OS_STAT_PEND_OK; + if (OSLockNesting < 255u) { /* Make sure we don't context switch */ + OSLockNesting++; + } + OS_EXIT_CRITICAL(); /* Enabling INT. ignores next instruc. */ + OS_Dummy(); /* ... Dummy ensures that INTs will be */ + OS_ENTER_CRITICAL(); /* ... disabled HERE! */ + if (OSLockNesting > 0u) { /* Remove context switch lock */ + OSLockNesting--; + } + OSTaskDelHook(ptcb); /* Call user defined hook */ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + OS_TLS_TaskDel(ptcb); /* Call TLS hook */ +#endif +#endif + + OSTaskCtr--; /* One less task being managed */ + OSTCBPrioTbl[prio] = (OS_TCB *)0; /* Clear old priority entry */ + if (ptcb->OSTCBPrev == (OS_TCB *)0) { /* Remove from TCB chain */ + ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0; + OSTCBList = ptcb->OSTCBNext; + } else { + ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext; + ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev; + } + ptcb->OSTCBNext = OSTCBFreeList; /* Return TCB to free TCB list */ + OSTCBFreeList = ptcb; +#if OS_TASK_NAME_EN > 0u + ptcb->OSTCBTaskName = (INT8U *)(void *)"?"; +#endif + OS_EXIT_CRITICAL(); + if (OSRunning == OS_TRUE) { + OS_Sched(); /* Find new highest priority task */ + } + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* REQUEST THAT A TASK DELETE ITSELF +* +* Description: This function is used to: +* a) notify a task to delete itself. +* b) to see if a task requested that the current task delete itself. +* This function is a little tricky to understand. Basically, you have a task that needs +* to be deleted however, this task has resources that it has allocated (memory buffers, +* semaphores, mailboxes, queues etc.). The task cannot be deleted otherwise these +* resources would not be freed. The requesting task calls OSTaskDelReq() to indicate that +* the task needs to be deleted. Deleting of the task is however, deferred to the task to +* be deleted. For example, suppose that task #10 needs to be deleted. The requesting task +* example, task #5, would call OSTaskDelReq(10). When task #10 gets to execute, it calls +* this function by specifying OS_PRIO_SELF and monitors the returned value. If the return +* value is OS_ERR_TASK_DEL_REQ, another task requested a task delete. Task #10 would look like +* this: +* +* void Task(void *p_arg) +* { +* . +* . +* while (1) { +* OSTimeDly(1); +* if (OSTaskDelReq(OS_PRIO_SELF) == OS_ERR_TASK_DEL_REQ) { +* Release any owned resources; +* De-allocate any dynamic memory; +* OSTaskDel(OS_PRIO_SELF); +* } +* } +* } +* +* Arguments : prio is the priority of the task to request the delete from +* +* Returns : OS_ERR_NONE if the task exist and the request has been registered +* OS_ERR_ILLEGAL_DEL_RUN_TIME if you tried to delete a task after safety critical operation +* started. +* OS_ERR_TASK_NOT_EXIST if the task has been deleted. This allows the caller to know +* whether the request has been executed. +* OS_ERR_TASK_DEL if the task is assigned to a Mutex. +* OS_ERR_TASK_DEL_IDLE if you requested to delete uC/OS-II's idle task +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_DEL_REQ if a task (possibly another task) requested that the running +* task be deleted. +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0u +INT8U OSTaskDelReq (INT8U prio) +{ + INT8U stat; + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_ERR_ILLEGAL_DEL_RUN_TIME); + } +#endif + + if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to delete idle task */ + return (OS_ERR_TASK_DEL_IDLE); + } +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } +#endif + if (prio == OS_PRIO_SELF) { /* See if a task is requesting to ... */ + OS_ENTER_CRITICAL(); /* ... this task to delete itself */ + stat = OSTCBCur->OSTCBDelReq; /* Return request status to caller */ + OS_EXIT_CRITICAL(); + return (stat); + } + OS_ENTER_CRITICAL(); + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to delete must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); /* Task must already be deleted */ + } + if (ptcb == OS_TCB_RESERVED) { /* Must NOT be assigned to a Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_DEL); + } + ptcb->OSTCBDelReq = OS_ERR_TASK_DEL_REQ; /* Set flag indicating task to be DEL. */ + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* GET THE NAME OF A TASK +* +* Description: This function is called to obtain the name of a task. +* +* Arguments : prio is the priority of the task that you want to obtain the name from. +* +* pname is a pointer to a pointer to an ASCII string that will receive the name of the task. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex +* OS_ERR_PRIO_INVALID if you specified an invalid priority: +* A higher value than the idle task or not OS_PRIO_SELF. +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_NAME_GET_ISR You called this function from an ISR +* +* +* Returns : The length of the string or 0 if the task does not exist. +********************************************************************************************************* +*/ + +#if OS_TASK_NAME_EN > 0u +INT8U OSTaskNameGet (INT8U prio, + INT8U **pname, + INT8U *perr) +{ + OS_TCB *ptcb; + INT8U len; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; /* No */ + return (0u); + } + } + if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; /* Yes */ + return (0u); + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_GET_ISR; + return (0u); + } + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if caller desires it's own name */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Does task exist? */ + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TASK_NOT_EXIST; + return (0u); + } + if (ptcb == OS_TCB_RESERVED) { /* Task assigned to a Mutex? */ + OS_EXIT_CRITICAL(); /* Yes */ + *perr = OS_ERR_TASK_NOT_EXIST; + return (0u); + } + *pname = ptcb->OSTCBTaskName; + len = OS_StrLen(*pname); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (len); +} +#endif + + +/* +********************************************************************************************************* +* ASSIGN A NAME TO A TASK +* +* Description: This function is used to set the name of a task. +* +* Arguments : prio is the priority of the task that you want the assign a name to. +* +* pname is a pointer to an ASCII string that contains the name of the task. +* +* perr is a pointer to an error code that can contain one of the following values: +* +* OS_ERR_NONE if the requested task is resumed +* OS_ERR_TASK_NOT_EXIST if the task has not been created or is assigned to a Mutex +* OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' +* OS_ERR_PRIO_INVALID if you specified an invalid priority: +* A higher value than the idle task or not OS_PRIO_SELF. +* OS_ERR_NAME_SET_ISR if you called this function from an ISR +* +* Returns : None +********************************************************************************************************* +*/ +#if OS_TASK_NAME_EN > 0u +void OSTaskNameSet (INT8U prio, + INT8U *pname, + INT8U *perr) +{ + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; /* No */ + return; + } + } + if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */ + *perr = OS_ERR_PNAME_NULL; /* Yes */ + return; + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_SET_ISR; + return; + } + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if caller desires to set it's own name */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Does task exist? */ + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TASK_NOT_EXIST; + return; + } + if (ptcb == OS_TCB_RESERVED) { /* Task assigned to a Mutex? */ + OS_EXIT_CRITICAL(); /* Yes */ + *perr = OS_ERR_TASK_NOT_EXIST; + return; + } + ptcb->OSTCBTaskName = pname; + OS_TRACE_TASK_NAME_SET(ptcb); + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; +} +#endif + + +/* +********************************************************************************************************* +* RESUME A SUSPENDED TASK +* +* Description: This function is called to resume a previously suspended task. This is the only call that +* will remove an explicit task suspension. +* +* Arguments : prio is the priority of the task to resume. +* +* Returns : OS_ERR_NONE if the requested task is resumed +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) +* OS_ERR_TASK_RESUME_PRIO if the task to resume does not exist +* OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP +* OS_ERR_TASK_NOT_SUSPENDED if the task to resume has not been suspended +********************************************************************************************************* +*/ + +#if OS_TASK_SUSPEND_EN > 0u +INT8U OSTaskResume (INT8U prio) +{ + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { /* Make sure task priority is valid */ + return (OS_ERR_PRIO_INVALID); + } +#endif + OS_ENTER_CRITICAL(); + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_RESUME_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended */ + ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_SUSPEND; /* Remove suspension */ + if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) == OS_STAT_RDY) { /* See if task is now ready */ + if (ptcb->OSTCBDly == 0u) { + OSRdyGrp |= ptcb->OSTCBBitY; /* Yes, Make task ready to run */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OS_TRACE_TASK_READY(ptcb); + OS_EXIT_CRITICAL(); + if (OSRunning == OS_TRUE) { + OS_TRACE_TASK_RESUME(ptcb); + OS_Sched(); /* Find new highest priority task */ + } + } else { + OS_EXIT_CRITICAL(); + } + } else { /* Must be pending on event */ + OS_EXIT_CRITICAL(); + } + return (OS_ERR_NONE); + } + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_SUSPENDED); +} +#endif + + +/* +********************************************************************************************************* +* STACK CHECKING +* +* Description: This function is called to check the amount of free memory left on the specified task's +* stack. +* +* Arguments : prio is the task priority +* +* p_stk_data is a pointer to a data structure of type OS_STK_DATA. +* +* Returns : OS_ERR_NONE upon success +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_NOT_EXIST if the desired task has not been created or is assigned to a Mutex PIP +* OS_ERR_TASK_OPT if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created +* OS_ERR_PDATA_NULL if 'p_stk_data' is a NULL pointer +********************************************************************************************************* +*/ +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +INT8U OSTaskStkChk (INT8U prio, + OS_STK_DATA *p_stk_data) +{ + OS_TCB *ptcb; + OS_STK *pchk; + INT32U nfree; + INT32U size; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Make sure task priority is valid */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } + if (p_stk_data == (OS_STK_DATA *)0) { /* Validate 'p_stk_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + p_stk_data->OSFree = 0u; /* Assume failure, set to 0 size */ + p_stk_data->OSUsed = 0u; + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if check for SELF */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Make sure task exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if (ptcb == OS_TCB_RESERVED) { + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0u) { /* Make sure stack checking option is set */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_OPT); + } + nfree = 0u; + size = ptcb->OSTCBStkSize; + pchk = ptcb->OSTCBStkBottom; + OS_EXIT_CRITICAL(); +#if OS_STK_GROWTH == 1u + while (*pchk++ == (OS_STK)0) { /* Compute the number of zero entries on the stk */ + nfree++; + } +#else + while (*pchk-- == (OS_STK)0) { + nfree++; + } +#endif + p_stk_data->OSFree = nfree; /* Store number of free entries on the stk */ + p_stk_data->OSUsed = size - nfree; /* Compute number of entries used on the stk */ + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* SUSPEND A TASK +* +* Description: This function is called to suspend a task. The task can be the calling task if the +* priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF. +* +* Arguments : prio is the priority of the task to suspend. If you specify OS_PRIO_SELF, the +* calling task will suspend itself and rescheduling will occur. +* +* Returns : OS_ERR_NONE if the requested task is suspended +* OS_ERR_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not allowed. +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_TASK_SUSPEND_PRIO if the task to suspend does not exist +* OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP +* +* Note : You should use this function with great care. If you suspend a task that is waiting for +* an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from +* running when the event arrives. +********************************************************************************************************* +*/ + +#if OS_TASK_SUSPEND_EN > 0u +INT8U OSTaskSuspend (INT8U prio) +{ + BOOLEAN self; + OS_TCB *ptcb; + INT8U y; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (prio == OS_TASK_IDLE_PRIO) { /* Not allowed to suspend idle task */ + return (OS_ERR_TASK_SUSPEND_IDLE); + } + if (prio >= OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if suspend SELF */ + prio = OSTCBCur->OSTCBPrio; + self = OS_TRUE; + } else if (prio == OSTCBCur->OSTCBPrio) { /* See if suspending self */ + self = OS_TRUE; + } else { + self = OS_FALSE; /* No suspending another task */ + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_SUSPEND_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* See if assigned to Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + y = ptcb->OSTCBY; + OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* Make task not ready */ + if (OSRdyTbl[y] == 0u) { + OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY; + } + ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* Status of task is 'SUSPENDED' */ + OS_EXIT_CRITICAL(); + OS_TRACE_TASK_SUSPEND(ptcb); + OS_TRACE_TASK_SUSPENDED(ptcb); + if (self == OS_TRUE) { /* Context switch only if SELF */ + OS_Sched(); /* Find new highest priority task */ + } + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* QUERY A TASK +* +* Description: This function is called to obtain a copy of the desired task's TCB. +* +* Arguments : prio is the priority of the task to obtain information from. +* +* p_task_data is a pointer to where the desired task's OS_TCB will be stored. +* +* Returns : OS_ERR_NONE if the requested task is suspended +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF. +* OS_ERR_PRIO if the desired task has not been created +* OS_ERR_TASK_NOT_EXIST if the task is assigned to a Mutex PIP +* OS_ERR_PDATA_NULL if 'p_task_data' is a NULL pointer +********************************************************************************************************* +*/ + +#if OS_TASK_QUERY_EN > 0u +INT8U OSTaskQuery (INT8U prio, + OS_TCB *p_task_data) +{ + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#if OS_ARG_CHK_EN > 0u + if (prio > OS_LOWEST_PRIO) { /* Task priority valid ? */ + if (prio != OS_PRIO_SELF) { + return (OS_ERR_PRIO_INVALID); + } + } + if (p_task_data == (OS_TCB *)0) { /* Validate 'p_task_data' */ + return (OS_ERR_PDATA_NULL); + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if suspend SELF */ + prio = OSTCBCur->OSTCBPrio; + } + ptcb = OSTCBPrioTbl[prio]; + if (ptcb == (OS_TCB *)0) { /* Task to query must exist */ + OS_EXIT_CRITICAL(); + return (OS_ERR_PRIO); + } + if (ptcb == OS_TCB_RESERVED) { /* Task to query must not be assigned to a Mutex */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); + } + /* Copy TCB into user storage area */ + OS_MemCopy((INT8U *)p_task_data, (INT8U *)ptcb, sizeof(OS_TCB)); + OS_EXIT_CRITICAL(); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* GET THE CURRENT VALUE OF A TASK REGISTER +* +* Description: This function is called to obtain the current value of a task register. Task registers +* are application specific and can be used to store task specific values such as 'error +* numbers' (i.e. errno), statistics, etc. Each task register can hold a 32-bit value. +* +* Arguments : prio is the priority of the task you want to get the task register from. If you +* specify OS_PRIO_SELF then the task register of the current task will be obtained. +* +* id is the 'id' of the desired task register. Note that the 'id' must be less +* than OS_TASK_REG_TBL_SIZE +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_PRIO_INVALID if you specified an invalid priority +* OS_ERR_ID_INVALID if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1 +* +* Returns : The current value of the task's register or 0 if an error is detected. +* +* Note(s) : The maximum number of task variables is 254 +********************************************************************************************************* +*/ + +#if OS_TASK_REG_TBL_SIZE > 0u +INT32U OSTaskRegGet (INT8U prio, + INT8U id, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + INT32U value; + OS_TCB *ptcb; + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; + return (0u); + } + } + if (id >= OS_TASK_REG_TBL_SIZE) { + *perr = OS_ERR_ID_INVALID; + return (0u); + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if need to get register from current task */ + ptcb = OSTCBCur; + } else { + ptcb = OSTCBPrioTbl[prio]; + } + value = ptcb->OSTCBRegTbl[id]; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (value); +} +#endif + + +/* +************************************************************************************************************************ +* ALLOCATE THE NEXT AVAILABLE TASK REGISTER ID +* +* Description: This function is called to obtain a task register ID. This function thus allows task registers IDs to be +* allocated dynamically instead of statically. +* +* Arguments : p_err is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_NO_MORE_ID_AVAIL if you are attempting to assign more task register IDs than you +* have available through OS_TASK_REG_TBL_SIZE. +* +* Returns : The next available task register 'id' or OS_TASK_REG_TBL_SIZE if an error is detected. +************************************************************************************************************************ +*/ + +#if OS_TASK_REG_TBL_SIZE > 0u +INT8U OSTaskRegGetID (INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + INT8U id; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((INT8U)OS_TASK_REG_TBL_SIZE); + } +#endif + + OS_ENTER_CRITICAL(); + if (OSTaskRegNextAvailID >= OS_TASK_REG_TBL_SIZE) { /* See if we exceeded the number of IDs available */ + *perr = OS_ERR_NO_MORE_ID_AVAIL; /* Yes, cannot allocate more task register IDs */ + OS_EXIT_CRITICAL(); + return ((INT8U)OS_TASK_REG_TBL_SIZE); + } + + id = OSTaskRegNextAvailID; /* Assign the next available ID */ + OSTaskRegNextAvailID++; /* Increment available ID for next request */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (id); +} +#endif + + +/* +********************************************************************************************************* +* SET THE CURRENT VALUE OF A TASK VARIABLE +* +* Description: This function is called to change the current value of a task register. Task registers +* are application specific and can be used to store task specific values such as 'error +* numbers' (i.e. errno), statistics, etc. Each task register can hold a 32-bit value. +* +* Arguments : prio is the priority of the task you want to set the task register for. If you +* specify OS_PRIO_SELF then the task register of the current task will be obtained. +* +* id is the 'id' of the desired task register. Note that the 'id' must be less +* than OS_TASK_REG_TBL_SIZE +* +* value is the desired value for the task register. +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_PRIO_INVALID if you specified an invalid priority +* OS_ERR_ID_INVALID if the 'id' is not between 0 and OS_TASK_REG_TBL_SIZE-1 +* +* Returns : The current value of the task's variable or 0 if an error is detected. +* +* Note(s) : The maximum number of task variables is 254 +********************************************************************************************************* +*/ + +#if OS_TASK_REG_TBL_SIZE > 0u +void OSTaskRegSet (INT8U prio, + INT8U id, + INT32U value, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + OS_TCB *ptcb; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (prio >= OS_LOWEST_PRIO) { + if (prio != OS_PRIO_SELF) { + *perr = OS_ERR_PRIO_INVALID; + return; + } + } + if (id >= OS_TASK_REG_TBL_SIZE) { + *perr = OS_ERR_ID_INVALID; + return; + } +#endif + OS_ENTER_CRITICAL(); + if (prio == OS_PRIO_SELF) { /* See if need to get register from current task */ + ptcb = OSTCBCur; + } else { + ptcb = OSTCBPrioTbl[prio]; + } + ptcb->OSTCBRegTbl[id] = value; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; +} +#endif + + +/* +********************************************************************************************************* +* CATCH ACCIDENTAL TASK RETURN +* +* Description: This function is called if a task accidentally returns without deleting itself. In other +* words, a task should either be an infinite loop or delete itself if it's done. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_TaskReturn (void) +{ + OSTaskReturnHook(OSTCBCur); /* Call hook to let user decide on what to do */ + +#if OS_TASK_DEL_EN > 0u + (void)OSTaskDel(OS_PRIO_SELF); /* Delete task if it accidentally returns! */ +#else + for (;;) { + OSTimeDly(OS_TICKS_PER_SEC); + } +#endif +} + + +/* +********************************************************************************************************* +* CLEAR TASK STACK +* +* Description: This function is used to clear the stack of a task (i.e. write all zeros) +* +* Arguments : pbos is a pointer to the task's bottom of stack. If the configuration constant +* OS_STK_GROWTH is set to 1, the stack is assumed to grow downward (i.e. from high +* memory to low memory). 'pbos' will thus point to the lowest (valid) memory +* location of the stack. If OS_STK_GROWTH is set to 0, 'pbos' will point to the +* highest memory location of the stack and the stack will grow with increasing +* memory locations. 'pbos' MUST point to a valid 'free' data item. +* +* size is the number of 'stack elements' to clear. +* +* opt contains additional information (or options) about the behavior of the task. The +* LOWER 8-bits are reserved by uC/OS-II while the upper 8 bits can be application +* specific. See OS_TASK_OPT_??? in uCOS-II.H. +* +* Returns : none +********************************************************************************************************* +*/ +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStkClr (OS_STK *pbos, + INT32U size, + INT16U opt) +{ + if ((opt & OS_TASK_OPT_STK_CHK) != 0x0000u) { /* See if stack checking has been enabled */ + if ((opt & OS_TASK_OPT_STK_CLR) != 0x0000u) { /* See if stack needs to be cleared */ +#if OS_STK_GROWTH == 1u + while (size > 0u) { /* Stack grows from HIGH to LOW memory */ + size--; + *pbos++ = (OS_STK)0; /* Clear from bottom of stack and up! */ + } +#else + while (size > 0u) { /* Stack grows from LOW to HIGH memory */ + size--; + *pbos-- = (OS_STK)0; /* Clear from bottom of stack and down */ + } +#endif + } + } +} + +#endif +#endif /* OS_TASK_C */ diff --git a/Source/os_time.c b/Source/os_time.c new file mode 100644 index 0000000..b0f88db --- /dev/null +++ b/Source/os_time.c @@ -0,0 +1,280 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TIME MANAGEMENT +* +* Filename : os_time.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_TIME_C +#define OS_TIME_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + +/* +********************************************************************************************************* +* DELAY TASK 'n' TICKS +* +* Description: This function is called to delay execution of the currently running task until the +* specified number of system ticks expires. This, of course, directly equates to delaying +* the current task for some time to expire. No delay will result If the specified delay is +* 0. If the specified delay is greater than 0 then, a context switch will result. +* +* Arguments : ticks is the time delay that the task will be suspended in number of clock 'ticks'. +* Note that by specifying 0, the task will not be delayed. +* +* Returns : none +********************************************************************************************************* +*/ + +void OSTimeDly (INT32U ticks) +{ + INT8U y; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + return; + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked */ + return; + } + if (ticks > 0u) { /* 0 means no delay! */ + OS_ENTER_CRITICAL(); + y = OSTCBCur->OSTCBY; /* Delay current task */ + OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX; + OS_TRACE_TASK_SUSPENDED(OSTCBCur); + if (OSRdyTbl[y] == 0u) { + OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY; + } + OSTCBCur->OSTCBDly = ticks; /* Load ticks in TCB */ + OS_TRACE_TASK_DLY(ticks); + OS_EXIT_CRITICAL(); + OS_Sched(); /* Find next task to run! */ + } +} + + +/* +********************************************************************************************************* +* DELAY TASK FOR SPECIFIED TIME +* +* Description: This function is called to delay execution of the currently running task until some time +* expires. This call allows you to specify the delay time in HOURS, MINUTES, SECONDS and +* MILLISECONDS instead of ticks. +* +* Arguments : hours specifies the number of hours that the task will be delayed (max. is 255) +* minutes specifies the number of minutes (max. 59) +* seconds specifies the number of seconds (max. 59) +* ms specifies the number of milliseconds (max. 999) +* +* Returns : OS_ERR_NONE +* OS_ERR_TIME_INVALID_MINUTES +* OS_ERR_TIME_INVALID_SECONDS +* OS_ERR_TIME_INVALID_MS +* OS_ERR_TIME_ZERO_DLY +* OS_ERR_TIME_DLY_ISR +* +* Note(s) : The resolution on the milliseconds depends on the tick rate. For example, you can't do +* a 10 mS delay if the ticker interrupts every 100 mS. In this case, the delay would be +* set to 0. The actual delay is rounded to the nearest tick. +********************************************************************************************************* +*/ + +#if OS_TIME_DLY_HMSM_EN > 0u +INT8U OSTimeDlyHMSM (INT8U hours, + INT8U minutes, + INT8U seconds, + INT16U ms) +{ + INT32U ticks; + + + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + return (OS_ERR_TIME_DLY_ISR); + } + if (OSLockNesting > 0u) { /* See if called with scheduler locked */ + return (OS_ERR_SCHED_LOCKED); + } +#if OS_ARG_CHK_EN > 0u + if (hours == 0u) { + if (minutes == 0u) { + if (seconds == 0u) { + if (ms == 0u) { + return (OS_ERR_TIME_ZERO_DLY); + } + } + } + } + if (minutes > 59u) { + return (OS_ERR_TIME_INVALID_MINUTES); /* Validate arguments to be within range */ + } + if (seconds > 59u) { + return (OS_ERR_TIME_INVALID_SECONDS); + } + if (ms > 999u) { + return (OS_ERR_TIME_INVALID_MS); + } +#endif + /* Compute the total number of clock ticks required.. */ + /* .. (rounded to the nearest tick) */ + ticks = ((INT32U)hours * 3600uL + (INT32U)minutes * 60uL + (INT32U)seconds) * OS_TICKS_PER_SEC + + OS_TICKS_PER_SEC * ((INT32U)ms + 500uL / OS_TICKS_PER_SEC) / 1000uL; + OSTimeDly(ticks); + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* RESUME A DELAYED TASK +* +* Description: This function is used resume a task that has been delayed through a call to either +* OSTimeDly() or OSTimeDlyHMSM(). Note that you can call this function to resume a +* task that is waiting for an event with timeout. This would make the task look +* like a timeout occurred. +* +* Arguments : prio specifies the priority of the task to resume +* +* Returns : OS_ERR_NONE Task has been resumed +* OS_ERR_PRIO_INVALID if the priority you specify is higher that the maximum allowed +* (i.e. >= OS_LOWEST_PRIO) +* OS_ERR_TIME_NOT_DLY Task is not waiting for time to expire +* OS_ERR_TASK_NOT_EXIST The desired task has not been created or has been assigned to a Mutex. +********************************************************************************************************* +*/ + +#if OS_TIME_DLY_RESUME_EN > 0u +INT8U OSTimeDlyResume (INT8U prio) +{ + OS_TCB *ptcb; +#if OS_CRITICAL_METHOD == 3u /* Storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + if (prio >= OS_LOWEST_PRIO) { + return (OS_ERR_PRIO_INVALID); + } + OS_ENTER_CRITICAL(); + ptcb = OSTCBPrioTbl[prio]; /* Make sure that task exist */ + if (ptcb == (OS_TCB *)0) { + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */ + } + if (ptcb == OS_TCB_RESERVED) { + OS_EXIT_CRITICAL(); + return (OS_ERR_TASK_NOT_EXIST); /* The task does not exist */ + } + if (ptcb->OSTCBDly == 0u) { /* See if task is delayed */ + OS_EXIT_CRITICAL(); + return (OS_ERR_TIME_NOT_DLY); /* Indicate that task was not delayed */ + } + + ptcb->OSTCBDly = 0u; /* Clear the time delay */ + if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) { + ptcb->OSTCBStat &= ~OS_STAT_PEND_ANY; /* Yes, Clear status flag */ + ptcb->OSTCBStatPend = OS_STAT_PEND_TO; /* Indicate PEND timeout */ + } else { + ptcb->OSTCBStatPend = OS_STAT_PEND_OK; + } + if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) { /* Is task suspended? */ + OSRdyGrp |= ptcb->OSTCBBitY; /* No, Make ready */ + OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX; + OS_TRACE_TASK_READY(ptcb); + OS_EXIT_CRITICAL(); + OS_Sched(); /* See if this is new highest priority */ + } else { + OS_EXIT_CRITICAL(); /* Task may be suspended */ + } + return (OS_ERR_NONE); +} +#endif + + +/* +********************************************************************************************************* +* GET CURRENT SYSTEM TIME +* +* Description: This function is used by your application to obtain the current value of the 32-bit +* counter which keeps track of the number of clock ticks. +* +* Arguments : none +* +* Returns : The current value of OSTime +********************************************************************************************************* +*/ + +#if OS_TIME_GET_SET_EN > 0u +INT32U OSTimeGet (void) +{ + INT32U ticks; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OS_ENTER_CRITICAL(); + ticks = OSTime; + OS_EXIT_CRITICAL(); + return (ticks); +} +#endif + + +/* +********************************************************************************************************* +* SET SYSTEM CLOCK +* +* Description: This function sets the 32-bit counter which keeps track of the number of clock ticks. +* +* Arguments : ticks specifies the new value that OSTime needs to take. +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TIME_GET_SET_EN > 0u +void OSTimeSet (INT32U ticks) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OS_ENTER_CRITICAL(); + OSTime = ticks; + OS_EXIT_CRITICAL(); +} +#endif +#endif /* OS_TIME_C */ diff --git a/Source/os_tmr.c b/Source/os_tmr.c new file mode 100644 index 0000000..b0433dd --- /dev/null +++ b/Source/os_tmr.c @@ -0,0 +1,1140 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TIMER MANAGEMENT +* +* Filename : os_tmr.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_TMR_C +#define OS_TMR_C + +#define MICRIUM_SOURCE + +#ifndef OS_MASTER_FILE +#include +#endif + +/* +********************************************************************************************************* +* NOTES +* +* 1) Your application MUST define the following #define constants: +* +* OS_TASK_TMR_PRIO The priority of the Timer management task +* OS_TASK_TMR_STK_SIZE The size of the Timer management task's stack +* +* 2) You must call OSTmrSignal() to notify the Timer management task that it's time to update the timers. +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* CONSTANTS +********************************************************************************************************* +*/ + +#define OS_TMR_LINK_DLY 0u +#define OS_TMR_LINK_PERIODIC 1u + +/* +********************************************************************************************************* +* LOCAL PROTOTYPES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static OS_TMR *OSTmr_Alloc (void); +static void OSTmr_Free (OS_TMR *ptmr); +static void OSTmr_InitTask (void); +static void OSTmr_Link (OS_TMR *ptmr, INT8U type); +static void OSTmr_Unlink (OS_TMR *ptmr); +static void OSTmr_Task (void *p_arg); +#endif + + +/* +********************************************************************************************************* +* CREATE A TIMER +* +* Description: This function is called by your application code to create a timer. +* +* Arguments : dly Initial delay. +* If the timer is configured for ONE-SHOT mode, this is the timeout used. +* If the timer is configured for PERIODIC mode, this is the first timeout to +* wait for before the timer starts entering periodic mode. +* +* period The 'period' being repeated for the timer. +* If you specified 'OS_TMR_OPT_PERIODIC' as an option, when the timer +* expires, it will automatically restart with the same period. +* +* opt Specifies either: +* OS_TMR_OPT_ONE_SHOT The timer counts down only once +* OS_TMR_OPT_PERIODIC The timer counts down and then reloads itself +* +* callback Is a pointer to a callback function that will be called when the timer expires. +* The callback function must be declared as follows: +* +* void MyCallback (OS_TMR *ptmr, void *p_arg); +* +* callback_arg Is an argument (a pointer) that is passed to the callback function when it is called. +* +* pname Is a pointer to an ASCII string that is used to name the timer. Names are +* useful for debugging. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE the call was successful and the timer +* was created. +* OS_ERR_ILLEGAL_CREATE_RUN_TIME if you tried to create a timer after +* safety critical operation started. +* OS_ERR_TMR_INVALID_DLY you specified an invalid delay +* OS_ERR_TMR_INVALID_PERIOD you specified an invalid period +* OS_ERR_TMR_INVALID_OPT you specified an invalid option +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_NON_AVAIL if there are no free timers from the timer pool +* +* Returns : A pointer to an OS_TMR data structure. +* This is the 'handle' that your application will use to reference the timer created. +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +OS_TMR *OSTmrCreate (INT32U dly, + INT32U period, + INT8U opt, + OS_TMR_CALLBACK callback, + void *callback_arg, + INT8U *pname, + INT8U *perr) +{ + OS_TMR *ptmr; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_TMR *)0); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_CREATE_RUN_TIME; + return ((OS_TMR *)0); + } +#endif + +#if OS_ARG_CHK_EN > 0u + switch (opt) { /* Validate arguments */ + case OS_TMR_OPT_PERIODIC: + if (period == 0u) { + *perr = OS_ERR_TMR_INVALID_PERIOD; + return ((OS_TMR *)0); + } + break; + + case OS_TMR_OPT_ONE_SHOT: + if (dly == 0u) { + *perr = OS_ERR_TMR_INVALID_DLY; + return ((OS_TMR *)0); + } + break; + + default: + *perr = OS_ERR_TMR_INVALID_OPT; + return ((OS_TMR *)0); + } +#endif + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return ((OS_TMR *)0); + } + OSSchedLock(); + ptmr = OSTmr_Alloc(); /* Obtain a timer from the free pool */ + if (ptmr == (OS_TMR *)0) { + OSSchedUnlock(); + *perr = OS_ERR_TMR_NON_AVAIL; + return ((OS_TMR *)0); + } + ptmr->OSTmrState = OS_TMR_STATE_STOPPED; /* Indicate that timer is not running yet */ + ptmr->OSTmrDly = dly; + ptmr->OSTmrPeriod = period; + ptmr->OSTmrOpt = opt; + ptmr->OSTmrCallback = callback; + ptmr->OSTmrCallbackArg = callback_arg; +#if OS_TMR_CFG_NAME_EN > 0u + if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */ + ptmr->OSTmrName = (INT8U *)(void *)"?"; + } else { + ptmr->OSTmrName = pname; + } +#endif + OSSchedUnlock(); + OS_TRACE_TMR_CREATE(ptmr, ptmr->OSTmrName); + *perr = OS_ERR_NONE; + return (ptmr); +} +#endif + + +/* +********************************************************************************************************* +* DELETE A TIMER +* +* Description: This function is called by your application code to delete a timer. +* +* Arguments : ptmr Is a pointer to the timer to stop and delete. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE the call was successful and the timer +* was deleted. +* OS_ERR_ILLEGAL_DEL_RUN_TIME if you tried to delete a timer after safety +* critical operation started. +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the function was called from an ISR +* OS_ERR_TMR_INACTIVE if the timer was not created +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : OS_TRUE If the call was successful +* OS_FALSE If not +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +BOOLEAN OSTmrDel (OS_TMR *ptmr, + INT8U *perr) +{ +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_FALSE); + } +#endif + +#ifdef OS_SAFETY_CRITICAL_IEC61508 + if (OSSafetyCriticalStartFlag == OS_TRUE) { + OS_SAFETY_CRITICAL_EXCEPTION(); + *perr = OS_ERR_ILLEGAL_DEL_RUN_TIME; + return (OS_FALSE); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (OS_FALSE); + } +#endif + + OS_TRACE_TMR_DEL_ENTER(ptmr); + + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + OS_TRACE_TMR_DEL_EXIT(*perr); + return (OS_FALSE); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + OS_TRACE_TMR_DEL_EXIT(*perr); + return (OS_FALSE); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */ + OSTmr_Free(ptmr); /* Return timer to free list of timers */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + OS_TRACE_TMR_DEL_EXIT(*perr); + return (OS_TRUE); + + case OS_TMR_STATE_STOPPED: /* Timer has not started or ... */ + case OS_TMR_STATE_COMPLETED: /* ... timer has completed the ONE-SHOT time */ + OSTmr_Free(ptmr); /* Return timer to free list of timers */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + OS_TRACE_TMR_DEL_EXIT(*perr); + return (OS_TRUE); + + case OS_TMR_STATE_UNUSED: /* Already deleted */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + OS_TRACE_TMR_DEL_EXIT(*perr); + return (OS_FALSE); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + OS_TRACE_TMR_DEL_EXIT(*perr); + return (OS_FALSE); + } +} +#endif + + +/* +********************************************************************************************************* +* GET THE NAME OF A TIMER +* +* Description: This function is called to obtain the name of a timer. +* +* Arguments : ptmr Is a pointer to the timer to obtain the name for +* +* pdest Is a pointer to pointer to where the name of the timer will be placed. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE The call was successful +* OS_ERR_TMR_INVALID_DEST 'pdest' is a NULL pointer +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_NAME_GET_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : The length of the string or 0 if the timer does not exist. +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u && OS_TMR_CFG_NAME_EN > 0u +INT8U OSTmrNameGet (OS_TMR *ptmr, + INT8U **pdest, + INT8U *perr) +{ + INT8U len; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (pdest == (INT8U **)0) { + *perr = OS_ERR_TMR_INVALID_DEST; + return (0u); + } + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (0u); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (0u); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_NAME_GET_ISR; + return (0u); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + case OS_TMR_STATE_STOPPED: + case OS_TMR_STATE_COMPLETED: + *pdest = ptmr->OSTmrName; + len = OS_StrLen(*pdest); + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (len); + + case OS_TMR_STATE_UNUSED: /* Timer is not allocated */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + return (0u); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + return (0u); + } +} +#endif + + +/* +********************************************************************************************************* +* GET HOW MUCH TIME IS LEFT BEFORE A TIMER EXPIRES +* +* Description: This function is called to get the number of ticks before a timer times out. +* +* Arguments : ptmr Is a pointer to the timer to obtain the remaining time from. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : The time remaining for the timer to expire. The time represents 'timer' increments. +* In other words, if OSTmr_Task() is signaled every 1/10 of a second then the returned +* value represents the number of 1/10 of a second remaining before the timer expires. +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +INT32U OSTmrRemainGet (OS_TMR *ptmr, + INT8U *perr) +{ + INT32U remain; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (0u); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (0u); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return (0u); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + remain = ptmr->OSTmrMatch - OSTmrTime; /* Determine how much time is left to timeout */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (remain); + + case OS_TMR_STATE_STOPPED: /* It's assumed that the timer has not started yet */ + switch (ptmr->OSTmrOpt) { + case OS_TMR_OPT_PERIODIC: + if (ptmr->OSTmrDly == 0u) { + remain = ptmr->OSTmrPeriod; + } else { + remain = ptmr->OSTmrDly; + } + OSSchedUnlock(); + *perr = OS_ERR_NONE; + break; + + case OS_TMR_OPT_ONE_SHOT: + default: + remain = ptmr->OSTmrDly; + OSSchedUnlock(); + *perr = OS_ERR_NONE; + break; + } + return (remain); + + case OS_TMR_STATE_COMPLETED: /* Only ONE-SHOT that timed out can be in this state */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + return (0u); + + case OS_TMR_STATE_UNUSED: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + return (0u); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + return (0u); + } +} +#endif + + +/* +********************************************************************************************************* +* FIND OUT WHAT STATE A TIMER IS IN +* +* Description: This function is called to determine what state the timer is in: +* +* OS_TMR_STATE_UNUSED the timer has not been created +* OS_TMR_STATE_STOPPED the timer has been created but has not been started or has been stopped +* OS_TMR_STATE_COMPLETED the timer is in ONE-SHOT mode and has completed it's timeout +* OS_TMR_STATE_RUNNING the timer is currently running +* +* Arguments : ptmr Is a pointer to the desired timer +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE 'ptmr' points to a timer that is not active +* OS_ERR_TMR_INVALID_STATE if the timer is not in a valid state +* +* Returns : The current state of the timer (see description). +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +INT8U OSTmrStateGet (OS_TMR *ptmr, + INT8U *perr) +{ + INT8U state; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (0u); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (0u); + } +#endif + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + return (0u); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + return (0u); + } + OSSchedLock(); + state = ptmr->OSTmrState; + switch (state) { + case OS_TMR_STATE_UNUSED: + case OS_TMR_STATE_STOPPED: + case OS_TMR_STATE_COMPLETED: + case OS_TMR_STATE_RUNNING: + *perr = OS_ERR_NONE; + break; + + default: + *perr = OS_ERR_TMR_INVALID_STATE; + break; + } + OSSchedUnlock(); + return (state); +} +#endif + + +/* +********************************************************************************************************* +* START A TIMER +* +* Description: This function is called by your application code to start a timer. +* +* Arguments : ptmr Is a pointer to an OS_TMR +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the call was made from an ISR +* OS_ERR_TMR_INACTIVE if the timer was not created +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* +* Returns : OS_TRUE if the timer was started +* OS_FALSE if an error was detected +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +BOOLEAN OSTmrStart (OS_TMR *ptmr, + INT8U *perr) +{ +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_FALSE); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (OS_FALSE); + } +#endif + + OS_TRACE_TMR_START_ENTER(ptmr); + + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + OS_TRACE_TMR_START_EXIT(*perr); + return (OS_FALSE); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + OS_TRACE_TMR_START_EXIT(*perr); + return (OS_FALSE); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: /* Restart the timer */ + OSTmr_Unlink(ptmr); /* ... Stop the timer */ + OSTmr_Link(ptmr, OS_TMR_LINK_DLY); /* ... Link timer to timer wheel */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + OS_TRACE_TMR_START_EXIT(*perr); + return (OS_TRUE); + + case OS_TMR_STATE_STOPPED: /* Start the timer */ + case OS_TMR_STATE_COMPLETED: + OSTmr_Link(ptmr, OS_TMR_LINK_DLY); /* ... Link timer to timer wheel */ + OSSchedUnlock(); + *perr = OS_ERR_NONE; + OS_TRACE_TMR_START_EXIT(*perr); + return (OS_TRUE); + + case OS_TMR_STATE_UNUSED: /* Timer not created */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + OS_TRACE_TMR_START_EXIT(*perr); + return (OS_FALSE); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + OS_TRACE_TMR_START_EXIT(*perr); + return (OS_FALSE); + } +} +#endif + + +/* +********************************************************************************************************* +* STOP A TIMER +* +* Description: This function is called by your application code to stop a timer. +* +* Arguments : ptmr Is a pointer to the timer to stop. +* +* opt Allows you to specify an option to this functions which can be: +* +* OS_TMR_OPT_NONE Do nothing special but stop the timer +* OS_TMR_OPT_CALLBACK Execute the callback function, pass it the +* callback argument specified when the timer +* was created. +* OS_TMR_OPT_CALLBACK_ARG Execute the callback function, pass it the +* callback argument specified in THIS function call. +* +* callback_arg Is a pointer to a 'new' callback argument that can be passed to the callback +* function instead of the timer's callback argument. In other words, use +* 'callback_arg' passed in THIS function INSTEAD of ptmr->OSTmrCallbackArg. +* +* perr Is a pointer to an error code. '*perr' will contain one of the following: +* OS_ERR_NONE +* OS_ERR_TMR_INVALID 'ptmr' is a NULL pointer +* OS_ERR_TMR_INVALID_TYPE 'ptmr' is not pointing to an OS_TMR +* OS_ERR_TMR_ISR if the function was called from an ISR +* OS_ERR_TMR_INACTIVE if the timer was not created +* OS_ERR_TMR_INVALID_OPT if you specified an invalid option for 'opt' +* OS_ERR_TMR_STOPPED if the timer was already stopped +* OS_ERR_TMR_INVALID_STATE the timer is in an invalid state +* OS_ERR_TMR_NO_CALLBACK if the timer does not have a callback function defined +* +* Returns : OS_TRUE If we stopped the timer (if the timer is already stopped, we also return OS_TRUE) +* OS_FALSE If not +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +BOOLEAN OSTmrStop (OS_TMR *ptmr, + INT8U opt, + void *callback_arg, + INT8U *perr) +{ + OS_TMR_CALLBACK pfnct; + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return (OS_FALSE); + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (ptmr == (OS_TMR *)0) { + *perr = OS_ERR_TMR_INVALID; + return (OS_FALSE); + } +#endif + + OS_TRACE_TMR_STOP_ENTER(ptmr); + + if (ptmr->OSTmrType != OS_TMR_TYPE) { /* Validate timer structure */ + *perr = OS_ERR_TMR_INVALID_TYPE; + OS_TRACE_TMR_STOP_EXIT(*perr); + return (OS_FALSE); + } + if (OSIntNesting > 0u) { /* See if trying to call from an ISR */ + *perr = OS_ERR_TMR_ISR; + OS_TRACE_TMR_STOP_EXIT(*perr); + return (OS_FALSE); + } + OSSchedLock(); + switch (ptmr->OSTmrState) { + case OS_TMR_STATE_RUNNING: + OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */ + *perr = OS_ERR_NONE; + switch (opt) { + case OS_TMR_OPT_CALLBACK: + pfnct = ptmr->OSTmrCallback; /* Execute callback function if available ... */ + if (pfnct != (OS_TMR_CALLBACK)0) { + (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg); /* Use callback arg when timer was created */ + } else { + *perr = OS_ERR_TMR_NO_CALLBACK; + } + break; + + case OS_TMR_OPT_CALLBACK_ARG: + pfnct = ptmr->OSTmrCallback; /* Execute callback function if available ... */ + if (pfnct != (OS_TMR_CALLBACK)0) { + (*pfnct)((void *)ptmr, callback_arg); /* ... using the 'callback_arg' provided in call */ + } else { + *perr = OS_ERR_TMR_NO_CALLBACK; + } + break; + + case OS_TMR_OPT_NONE: + break; + + default: + *perr = OS_ERR_TMR_INVALID_OPT; + break; + } + OSSchedUnlock(); + OS_TRACE_TMR_STOP_EXIT(*perr); + return (OS_TRUE); + + case OS_TMR_STATE_COMPLETED: /* Timer has already completed the ONE-SHOT or ... */ + case OS_TMR_STATE_STOPPED: /* ... timer has not started yet. */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_STOPPED; + OS_TRACE_TMR_STOP_EXIT(*perr); + return (OS_TRUE); + + case OS_TMR_STATE_UNUSED: /* Timer was not created */ + OSSchedUnlock(); + *perr = OS_ERR_TMR_INACTIVE; + OS_TRACE_TMR_STOP_EXIT(*perr); + return (OS_FALSE); + + default: + OSSchedUnlock(); + *perr = OS_ERR_TMR_INVALID_STATE; + OS_TRACE_TMR_STOP_EXIT(*perr); + return (OS_FALSE); + } +} +#endif + + +/* +********************************************************************************************************* +* SIGNAL THAT IT'S TIME TO UPDATE THE TIMERS +* +* Description: This function is typically called by the ISR that occurs at the timer tick rate and is +* used to signal to OSTmr_Task() that it's time to update the timers. +* +* Arguments : none +* +* Returns : OS_ERR_NONE The call was successful and the timer task was signaled. +* OS_ERR_SEM_OVF If OSTmrSignal() was called more often than OSTmr_Task() can handle +* the timers. This would indicate that your system is heavily loaded. +* OS_ERR_EVENT_TYPE Unlikely you would get this error because the semaphore used for +* signaling is created by uC/OS-II. +* OS_ERR_PEVENT_NULL Again, unlikely you would ever get this error because the semaphore +* used for signaling is created by uC/OS-II. +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +INT8U OSTmrSignal (void) +{ + INT8U err; + + + err = OSSemPost(OSTmrSemSignal); + return (err); +} +#endif + + +/* +********************************************************************************************************* +* ALLOCATE AND FREE A TIMER +* +* Description: This function is called to allocate a timer. +* +* Arguments : none +* +* Returns : a pointer to a timer if one is available +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static OS_TMR *OSTmr_Alloc (void) +{ + OS_TMR *ptmr; + + + if (OSTmrFreeList == (OS_TMR *)0) { + return ((OS_TMR *)0); + } + ptmr = (OS_TMR *)OSTmrFreeList; + OSTmrFreeList = (OS_TMR *)ptmr->OSTmrNext; + ptmr->OSTmrNext = (OS_TCB *)0; + ptmr->OSTmrPrev = (OS_TCB *)0; + OSTmrUsed++; + OSTmrFree--; + return (ptmr); +} +#endif + + +/* +********************************************************************************************************* +* RETURN A TIMER TO THE FREE LIST +* +* Description: This function is called to return a timer object to the free list of timers. +* +* Arguments : ptmr is a pointer to the timer to free +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Free (OS_TMR *ptmr) +{ + ptmr->OSTmrState = OS_TMR_STATE_UNUSED; /* Clear timer object fields */ + ptmr->OSTmrOpt = OS_TMR_OPT_NONE; + ptmr->OSTmrPeriod = 0u; + ptmr->OSTmrMatch = 0u; + ptmr->OSTmrCallback = (OS_TMR_CALLBACK)0; + ptmr->OSTmrCallbackArg = (void *)0; +#if OS_TMR_CFG_NAME_EN > 0u + ptmr->OSTmrName = (INT8U *)(void *)"?"; +#endif + + ptmr->OSTmrPrev = (OS_TCB *)0; /* Chain timer to free list */ + ptmr->OSTmrNext = OSTmrFreeList; + OSTmrFreeList = ptmr; + + OSTmrUsed--; /* Update timer object statistics */ + OSTmrFree++; +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZATION +* INITIALIZE THE FREE LIST OF TIMERS +* +* Description: This function is called by OSInit() to initialize the free list of OS_TMRs. +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +void OSTmr_Init (void) +{ +#if OS_EVENT_NAME_EN > 0u + INT8U err; +#endif + INT16U ix; + INT16U ix_next; + OS_TMR *ptmr1; + OS_TMR *ptmr2; + + + OS_MemClr((INT8U *)&OSTmrTbl[0], sizeof(OSTmrTbl)); /* Clear all the TMRs */ + OS_MemClr((INT8U *)&OSTmrWheelTbl[0], sizeof(OSTmrWheelTbl)); /* Clear the timer wheel */ + + for (ix = 0u; ix < (OS_TMR_CFG_MAX - 1u); ix++) { /* Init. list of free TMRs */ + ix_next = ix + 1u; + ptmr1 = &OSTmrTbl[ix]; + ptmr2 = &OSTmrTbl[ix_next]; + ptmr1->OSTmrType = OS_TMR_TYPE; + ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */ + ptmr1->OSTmrNext = (void *)ptmr2; /* Link to next timer */ +#if OS_TMR_CFG_NAME_EN > 0u + ptmr1->OSTmrName = (INT8U *)(void *)"?"; +#endif + } + ptmr1 = &OSTmrTbl[ix]; + ptmr1->OSTmrType = OS_TMR_TYPE; + ptmr1->OSTmrState = OS_TMR_STATE_UNUSED; /* Indicate that timer is inactive */ + ptmr1->OSTmrNext = (void *)0; /* Last OS_TMR */ +#if OS_TMR_CFG_NAME_EN > 0u + ptmr1->OSTmrName = (INT8U *)(void *)"?"; +#endif + OSTmrTime = 0u; + OSTmrUsed = 0u; + OSTmrFree = OS_TMR_CFG_MAX; + OSTmrFreeList = &OSTmrTbl[0]; + OSTmrSem = OSSemCreate(1u); + OSTmrSemSignal = OSSemCreate(0u); + +#if OS_EVENT_NAME_EN > 0u /* Assign names to semaphores */ + OSEventNameSet(OSTmrSem, (INT8U *)(void *)"uC/OS-II TmrLock", &err); + OSEventNameSet(OSTmrSemSignal, (INT8U *)(void *)"uC/OS-II TmrSignal", &err); +#endif + + OSTmr_InitTask(); +} +#endif + + +/* +********************************************************************************************************* +* INITIALIZE THE TIMER MANAGEMENT TASK +* +* Description: This function is called by OSTmrInit() to create the timer management task. +* * Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_InitTask (void) +{ +#if OS_TASK_NAME_EN > 0u + INT8U err; +#endif + + +#if OS_TASK_CREATE_EXT_EN > 0u + #if OS_STK_GROWTH == 1u + (void)OSTaskCreateExt(OSTmr_Task, + (void *)0, /* No arguments passed to OSTmrTask() */ + &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], /* Set Top-Of-Stack */ + OS_TASK_TMR_PRIO, + OS_TASK_TMR_ID, + &OSTmrTaskStk[0], /* Set Bottom-Of-Stack */ + OS_TASK_TMR_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */ + #else + (void)OSTaskCreateExt(OSTmr_Task, + (void *)0, /* No arguments passed to OSTmrTask() */ + &OSTmrTaskStk[0], /* Set Top-Of-Stack */ + OS_TASK_TMR_PRIO, + OS_TASK_TMR_ID, + &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], /* Set Bottom-Of-Stack */ + OS_TASK_TMR_STK_SIZE, + (void *)0, /* No TCB extension */ + OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); /* Enable stack checking + clear stack */ + #endif +#else + #if OS_STK_GROWTH == 1u + (void)OSTaskCreate(OSTmr_Task, + (void *)0, + &OSTmrTaskStk[OS_TASK_TMR_STK_SIZE - 1u], + OS_TASK_TMR_PRIO); + #else + (void)OSTaskCreate(OSTmr_Task, + (void *)0, + &OSTmrTaskStk[0], + OS_TASK_TMR_PRIO); + #endif +#endif + +#if OS_TASK_NAME_EN > 0u + OSTaskNameSet(OS_TASK_TMR_PRIO, (INT8U *)(void *)"uC/OS-II Tmr", &err); +#endif +} +#endif + + +/* +********************************************************************************************************* +* INSERT A TIMER INTO THE TIMER WHEEL +* +* Description: This function is called to insert the timer into the timer wheel. The timer is always +* inserted at the beginning of the list. +* +* Arguments : ptmr Is a pointer to the timer to insert. +* +* type Is either: +* OS_TMR_LINK_PERIODIC Means to re-insert the timer after a period expired +* OS_TMR_LINK_DLY Means to insert the timer the first time +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Link (OS_TMR *ptmr, + INT8U type) +{ + OS_TMR *ptmr1; + OS_TMR_WHEEL *pspoke; + INT16U spoke; + + + ptmr->OSTmrState = OS_TMR_STATE_RUNNING; + if (type == OS_TMR_LINK_PERIODIC) { /* Determine when timer will expire */ + ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime; + } else { + if (ptmr->OSTmrDly == 0u) { + ptmr->OSTmrMatch = ptmr->OSTmrPeriod + OSTmrTime; + } else { + ptmr->OSTmrMatch = ptmr->OSTmrDly + OSTmrTime; + } + } + spoke = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE); + pspoke = &OSTmrWheelTbl[spoke]; + + if (pspoke->OSTmrFirst == (OS_TMR *)0) { /* Link into timer wheel */ + pspoke->OSTmrFirst = ptmr; + ptmr->OSTmrNext = (OS_TMR *)0; + pspoke->OSTmrEntries = 1u; + } else { + ptmr1 = pspoke->OSTmrFirst; /* Point to first timer in the spoke */ + pspoke->OSTmrFirst = ptmr; + ptmr->OSTmrNext = (void *)ptmr1; + ptmr1->OSTmrPrev = (void *)ptmr; + pspoke->OSTmrEntries++; + } + ptmr->OSTmrPrev = (void *)0; /* Timer always inserted as first node in list */ +} +#endif + + +/* +********************************************************************************************************* +* REMOVE A TIMER FROM THE TIMER WHEEL +* +* Description: This function is called to remove the timer from the timer wheel. +* +* Arguments : ptmr Is a pointer to the timer to remove. +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Unlink (OS_TMR *ptmr) +{ + OS_TMR *ptmr1; + OS_TMR *ptmr2; + OS_TMR_WHEEL *pspoke; + INT16U spoke; + + + spoke = (INT16U)(ptmr->OSTmrMatch % OS_TMR_CFG_WHEEL_SIZE); + pspoke = &OSTmrWheelTbl[spoke]; + + if (pspoke->OSTmrFirst == ptmr) { /* See if timer to remove is at the beginning of list */ + ptmr1 = (OS_TMR *)ptmr->OSTmrNext; + pspoke->OSTmrFirst = (OS_TMR *)ptmr1; + if (ptmr1 != (OS_TMR *)0) { + ptmr1->OSTmrPrev = (void *)0; + } + } else { + ptmr1 = (OS_TMR *)ptmr->OSTmrPrev; /* Remove timer from somewhere in the list */ + ptmr2 = (OS_TMR *)ptmr->OSTmrNext; + ptmr1->OSTmrNext = ptmr2; + if (ptmr2 != (OS_TMR *)0) { + ptmr2->OSTmrPrev = (void *)ptmr1; + } + } + ptmr->OSTmrState = OS_TMR_STATE_STOPPED; + ptmr->OSTmrNext = (void *)0; + ptmr->OSTmrPrev = (void *)0; + pspoke->OSTmrEntries--; +} +#endif + + +/* +********************************************************************************************************* +* TIMER MANAGEMENT TASK +* +* Description: This task is created by OSTmrInit(). +* +* Arguments : none +* +* Returns : none +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +static void OSTmr_Task (void *p_arg) +{ + INT8U err; + OS_TMR *ptmr; + OS_TMR *ptmr_next; + OS_TMR_CALLBACK pfnct; + OS_TMR_WHEEL *pspoke; + INT16U spoke; + + + p_arg = p_arg; /* Prevent compiler warning for not using 'p_arg' */ + for (;;) { + OSSemPend(OSTmrSemSignal, 0u, &err); /* Wait for signal indicating time to update timers */ + OSSchedLock(); + OSTmrTime++; /* Increment the current time */ + spoke = (INT16U)(OSTmrTime % OS_TMR_CFG_WHEEL_SIZE); /* Position on current timer wheel entry */ + pspoke = &OSTmrWheelTbl[spoke]; + ptmr = pspoke->OSTmrFirst; + while (ptmr != (OS_TMR *)0) { + ptmr_next = (OS_TMR *)ptmr->OSTmrNext; /* Point to next timer to update because current ... */ + /* ... timer could get unlinked from the wheel. */ + if (OSTmrTime == ptmr->OSTmrMatch) { /* Process each timer that expires */ + OS_TRACE_TMR_EXPIRED(ptmr); + OSTmr_Unlink(ptmr); /* Remove from current wheel spoke */ + if (ptmr->OSTmrOpt == OS_TMR_OPT_PERIODIC) { + OSTmr_Link(ptmr, OS_TMR_LINK_PERIODIC); /* Recalculate new position of timer in wheel */ + } else { + ptmr->OSTmrState = OS_TMR_STATE_COMPLETED; /* Indicate that the timer has completed */ + } + pfnct = ptmr->OSTmrCallback; /* Execute callback function if available */ + if (pfnct != (OS_TMR_CALLBACK)0) { + (*pfnct)((void *)ptmr, ptmr->OSTmrCallbackArg); + } + } + ptmr = ptmr_next; + } + OSSchedUnlock(); + } +} +#endif +#endif /* OS_TMR_C */ diff --git a/Source/os_trace.h b/Source/os_trace.h new file mode 100644 index 0000000..f3736a7 --- /dev/null +++ b/Source/os_trace.h @@ -0,0 +1,474 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* +* TRACE SUPPORT +* +* Filename : os_trace.h +* Version : V2.93.00 +********************************************************************************************************* +* Note(s) : (1) The header file os_trace_events.h is the interface between uC/OS-II and your trace +* recorder of choice. +* To support trace recording, include one of the sub-folders at uCOS-II/Trace/ into +* your project. +********************************************************************************************************* +*/ + +#ifndef OS_TRACE_H +#define OS_TRACE_H + +#include + +#if (defined(OS_TRACE_EN) && (OS_TRACE_EN > 0u)) +#include /* See Note #1. */ +#endif + + +/* +************************************************************************************************************************** +* uC/OS-II Trace Default Macros (Empty) +************************************************************************************************************************** +*/ + +#ifndef OS_TRACE_INIT +#define OS_TRACE_INIT() +#endif +#ifndef OS_TRACE_START +#define OS_TRACE_START() +#endif +#ifndef OS_TRACE_STOP +#define OS_TRACE_STOP() +#endif +#ifndef OS_TRACE_CLEAR +#define OS_TRACE_CLEAR() +#endif + +#ifndef OS_TRACE_ISR_ENTER +#define OS_TRACE_ISR_ENTER() +#endif +#ifndef OS_TRACE_ISR_EXIT +#define OS_TRACE_ISR_EXIT() +#endif +#ifndef OS_TRACE_ISR_EXIT_TO_SCHEDULER +#define OS_TRACE_ISR_EXIT_TO_SCHEDULER() +#endif + +#ifndef OS_TRACE_TICK_INCREMENT +#define OS_TRACE_TICK_INCREMENT(OSTickCtr) +#endif + +#ifndef OS_TRACE_TASK_CREATE +#define OS_TRACE_TASK_CREATE(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_CREATE_FAILED +#define OS_TRACE_TASK_CREATE_FAILED(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_DEL +#define OS_TRACE_TASK_DEL(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_READY +#define OS_TRACE_TASK_READY(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_SWITCHED_IN +#define OS_TRACE_TASK_SWITCHED_IN(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_DLY +#define OS_TRACE_TASK_DLY(dly_ticks) +#endif + +#ifndef OS_TRACE_TASK_SUSPEND +#define OS_TRACE_TASK_SUSPEND(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_SUSPENDED +#define OS_TRACE_TASK_SUSPENDED(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_RESUME +#define OS_TRACE_TASK_RESUME(p_tcb) +#endif + +#ifndef OS_TRACE_TASK_PRIO_CHANGE +#define OS_TRACE_TASK_PRIO_CHANGE(p_tcb, prio) +#endif + +#ifndef OS_TRACE_TASK_NAME_SET +#define OS_TRACE_TASK_NAME_SET(p_tcb) +#endif + +#ifndef OS_TRACE_EVENT_NAME_SET +#define OS_TRACE_EVENT_NAME_SET(p_event, p_name) +#endif + +#ifndef OS_TRACE_ISR_REGISTER +#define OS_TRACE_ISR_REGISTER(isr_id, isr_name, isr_prio) +#endif + +#ifndef OS_TRACE_ISR_BEGIN +#define OS_TRACE_ISR_BEGIN(isr_id) +#endif + +#ifndef OS_TRACE_ISR_END +#define OS_TRACE_ISR_END() +#endif + +#ifndef OS_TRACE_MBOX_CREATE +#define OS_TRACE_MBOX_CREATE(p_mbox, p_name) +#endif + +#ifndef OS_TRACE_MUTEX_CREATE +#define OS_TRACE_MUTEX_CREATE(p_mutex, p_name) +#endif + +#ifndef OS_TRACE_MUTEX_DEL +#define OS_TRACE_MUTEX_DEL(p_mutex) +#endif + +#ifndef OS_TRACE_MUTEX_POST +#define OS_TRACE_MUTEX_POST(p_mutex) +#endif + +#ifndef OS_TRACE_MUTEX_POST_FAILED +#define OS_TRACE_MUTEX_POST_FAILED(p_mutex) +#endif + +#ifndef OS_TRACE_MUTEX_PEND +#define OS_TRACE_MUTEX_PEND(p_mutex) +#endif + +#ifndef OS_TRACE_MUTEX_PEND_FAILED +#define OS_TRACE_MUTEX_PEND_FAILED(p_mutex) +#endif + +#ifndef OS_TRACE_MUTEX_PEND_BLOCK +#define OS_TRACE_MUTEX_PEND_BLOCK(p_mutex) +#endif + +#ifndef OS_TRACE_MUTEX_TASK_PRIO_INHERIT +#define OS_TRACE_MUTEX_TASK_PRIO_INHERIT(p_tcb, prio) +#endif + +#ifndef OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT +#define OS_TRACE_MUTEX_TASK_PRIO_DISINHERIT(p_tcb, prio) +#endif + +#ifndef OS_TRACE_SEM_CREATE +#define OS_TRACE_SEM_CREATE(p_sem, p_name) +#endif + +#ifndef OS_TRACE_SEM_DEL +#define OS_TRACE_SEM_DEL(p_sem) +#endif + +#ifndef OS_TRACE_SEM_POST +#define OS_TRACE_SEM_POST(p_sem) +#endif + +#ifndef OS_TRACE_SEM_POST_FAILED +#define OS_TRACE_SEM_POST_FAILED(p_sem) +#endif + +#ifndef OS_TRACE_SEM_PEND +#define OS_TRACE_SEM_PEND(p_sem) +#endif + +#ifndef OS_TRACE_SEM_PEND_FAILED +#define OS_TRACE_SEM_PEND_FAILED(p_sem) +#endif + +#ifndef OS_TRACE_SEM_PEND_BLOCK +#define OS_TRACE_SEM_PEND_BLOCK(p_sem) +#endif + +#ifndef OS_TRACE_Q_CREATE +#define OS_TRACE_Q_CREATE(p_q, p_name) +#endif + +#ifndef OS_TRACE_Q_DEL +#define OS_TRACE_Q_DEL(p_q) +#endif + +#ifndef OS_TRACE_Q_POST +#define OS_TRACE_Q_POST(p_q) +#endif + +#ifndef OS_TRACE_Q_POST_FAILED +#define OS_TRACE_Q_POST_FAILED(p_q) +#endif + +#ifndef OS_TRACE_Q_PEND +#define OS_TRACE_Q_PEND(p_q) +#endif + +#ifndef OS_TRACE_Q_PEND_FAILED +#define OS_TRACE_Q_PEND_FAILED(p_q) +#endif + +#ifndef OS_TRACE_Q_PEND_BLOCK +#define OS_TRACE_Q_PEND_BLOCK(p_q) +#endif + +#ifndef OS_TRACE_FLAG_CREATE +#define OS_TRACE_FLAG_CREATE(p_grp, p_name) +#endif + +#ifndef OS_TRACE_FLAG_DEL +#define OS_TRACE_FLAG_DEL(p_grp) +#endif + +#ifndef OS_TRACE_FLAG_POST +#define OS_TRACE_FLAG_POST(p_grp) +#endif + +#ifndef OS_TRACE_FLAG_POST_FAILED +#define OS_TRACE_FLAG_POST_FAILED(p_grp) +#endif + +#ifndef OS_TRACE_FLAG_PEND +#define OS_TRACE_FLAG_PEND(p_grp) +#endif + +#ifndef OS_TRACE_FLAG_PEND_FAILED +#define OS_TRACE_FLAG_PEND_FAILED(p_grp) +#endif + +#ifndef OS_TRACE_FLAG_PEND_BLOCK +#define OS_TRACE_FLAG_PEND_BLOCK(p_grp) +#endif + +#ifndef OS_TRACE_MEM_CREATE +#define OS_TRACE_MEM_CREATE(p_mem) +#endif + +#ifndef OS_TRACE_MEM_PUT +#define OS_TRACE_MEM_PUT(p_mem) +#endif + +#ifndef OS_TRACE_MEM_PUT_FAILED +#define OS_TRACE_MEM_PUT_FAILED(p_mem) +#endif + +#ifndef OS_TRACE_MEM_GET +#define OS_TRACE_MEM_GET(p_mem) +#endif + +#ifndef OS_TRACE_MEM_GET_FAILED +#define OS_TRACE_MEM_GET_FAILED(p_mem) +#endif + +#ifndef OS_TRACE_TMR_CREATE +#define OS_TRACE_TMR_CREATE(p_tmr, p_name) +#endif + + + +#ifndef OS_TRACE_MBOX_DEL_ENTER +#define OS_TRACE_MBOX_DEL_ENTER(p_mbox, opt) +#endif + +#ifndef OS_TRACE_MBOX_POST_ENTER +#define OS_TRACE_MBOX_POST_ENTER(p_mbox) +#endif + +#ifndef OS_TRACE_MBOX_POST_OPT_ENTER +#define OS_TRACE_MBOX_POST_OPT_ENTER(p_mbox, opt) +#endif + +#ifndef OS_TRACE_MBOX_PEND_ENTER +#define OS_TRACE_MBOX_PEND_ENTER(p_mbox, timeout) +#endif + +#ifndef OS_TRACE_MUTEX_DEL_ENTER +#define OS_TRACE_MUTEX_DEL_ENTER(p_mutex, opt) +#endif + +#ifndef OS_TRACE_MUTEX_POST_ENTER +#define OS_TRACE_MUTEX_POST_ENTER(p_mutex) +#endif + +#ifndef OS_TRACE_MUTEX_PEND_ENTER +#define OS_TRACE_MUTEX_PEND_ENTER(p_mutex, timeout) +#endif + +#ifndef OS_TRACE_SEM_DEL_ENTER +#define OS_TRACE_SEM_DEL_ENTER(p_sem, opt) +#endif + +#ifndef OS_TRACE_SEM_POST_ENTER +#define OS_TRACE_SEM_POST_ENTER(p_sem) +#endif + +#ifndef OS_TRACE_SEM_PEND_ENTER +#define OS_TRACE_SEM_PEND_ENTER(p_sem, timeout) +#endif + +#ifndef OS_TRACE_Q_DEL_ENTER +#define OS_TRACE_Q_DEL_ENTER(p_q, opt) +#endif + +#ifndef OS_TRACE_Q_POST_ENTER +#define OS_TRACE_Q_POST_ENTER(p_q) +#endif + +#ifndef OS_TRACE_Q_POST_FRONT_ENTER +#define OS_TRACE_Q_POST_FRONT_ENTER(p_q) +#endif + +#ifndef OS_TRACE_Q_POST_OPT_ENTER +#define OS_TRACE_Q_POST_OPT_ENTER(p_q, opt) +#endif + +#ifndef OS_TRACE_Q_PEND_ENTER +#define OS_TRACE_Q_PEND_ENTER(p_q, timeout) +#endif + +#ifndef OS_TRACE_FLAG_DEL_ENTER +#define OS_TRACE_FLAG_DEL_ENTER(p_grp, opt) +#endif + +#ifndef OS_TRACE_TMR_DEL_ENTER +#define OS_TRACE_TMR_DEL_ENTER(p_tmr) +#endif + +#ifndef OS_TRACE_TMR_START_ENTER +#define OS_TRACE_TMR_START_ENTER(p_tmr) +#endif + +#ifndef OS_TRACE_TMR_STOP_ENTER +#define OS_TRACE_TMR_STOP_ENTER(p_tmr) +#endif + +#ifndef OS_TRACE_TMR_EXPIRED +#define OS_TRACE_TMR_EXPIRED(p_tmr) +#endif + +#ifndef OS_TRACE_FLAG_POST_ENTER +#define OS_TRACE_FLAG_POST_ENTER(p_grp, flags, opt) +#endif + +#ifndef OS_TRACE_FLAG_PEND_ENTER +#define OS_TRACE_FLAG_PEND_ENTER(p_grp, flags, timeout, opt) +#endif + +#ifndef OS_TRACE_MEM_PUT_ENTER +#define OS_TRACE_MEM_PUT_ENTER(p_mem, p_blk) +#endif + +#ifndef OS_TRACE_MEM_GET_ENTER +#define OS_TRACE_MEM_GET_ENTER(p_mem) +#endif + +#ifndef OS_TRACE_MBOX_DEL_EXIT +#define OS_TRACE_MBOX_DEL_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MBOX_POST_EXIT +#define OS_TRACE_MBOX_POST_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MBOX_POST_OPT_EXIT +#define OS_TRACE_MBOX_POST_OPT_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MBOX_PEND_EXIT +#define OS_TRACE_MBOX_PEND_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MUTEX_DEL_EXIT +#define OS_TRACE_MUTEX_DEL_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MUTEX_POST_EXIT +#define OS_TRACE_MUTEX_POST_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MUTEX_PEND_EXIT +#define OS_TRACE_MUTEX_PEND_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_SEM_DEL_EXIT +#define OS_TRACE_SEM_DEL_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_SEM_POST_EXIT +#define OS_TRACE_SEM_POST_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_SEM_PEND_EXIT +#define OS_TRACE_SEM_PEND_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_Q_DEL_EXIT +#define OS_TRACE_Q_DEL_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_Q_POST_EXIT +#define OS_TRACE_Q_POST_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_Q_POST_FRONT_EXIT +#define OS_TRACE_Q_POST_FRONT_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_Q_POST_OPT_EXIT +#define OS_TRACE_Q_POST_OPT_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_Q_PEND_EXIT +#define OS_TRACE_Q_PEND_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_FLAG_DEL_EXIT +#define OS_TRACE_FLAG_DEL_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_FLAG_POST_EXIT +#define OS_TRACE_FLAG_POST_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_FLAG_PEND_EXIT +#define OS_TRACE_FLAG_PEND_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MEM_PUT_EXIT +#define OS_TRACE_MEM_PUT_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_MEM_GET_EXIT +#define OS_TRACE_MEM_GET_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_TMR_DEL_EXIT +#define OS_TRACE_TMR_DEL_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_TMR_START_EXIT +#define OS_TRACE_TMR_START_EXIT(RetVal) +#endif + +#ifndef OS_TRACE_TMR_STOP_EXIT +#define OS_TRACE_TMR_STOP_EXIT(RetVal) +#endif + +#endif diff --git a/Source/ucos_ii.c b/Source/ucos_ii.c new file mode 100644 index 0000000..6e46601 --- /dev/null +++ b/Source/ucos_ii.c @@ -0,0 +1,39 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + + +/* +********************************************************************************************************* +* Filename : ucos_ii.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define OS_GLOBALS /* Declare GLOBAL variables */ +#include + + +#define OS_MASTER_FILE /* Prevent the following files from including includes.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/Source/ucos_ii.h b/Source/ucos_ii.h new file mode 100644 index 0000000..3944225 --- /dev/null +++ b/Source/ucos_ii.h @@ -0,0 +1,1987 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* Filename : ucos_ii.h +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#ifndef OS_uCOS_II_H +#define OS_uCOS_II_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* +********************************************************************************************************* +* uC/OS-II VERSION NUMBER +********************************************************************************************************* +*/ + +#define OS_VERSION 29300u /* Version of uC/OS-II (Vx.yy mult. by 10000) */ + +/* +********************************************************************************************************* +* INCLUDE HEADER FILES +********************************************************************************************************* +*/ + +#include +#include +#include +#include "os_trace.h" + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#ifdef OS_GLOBALS +#define OS_EXT +#else +#define OS_EXT extern +#endif + +#ifndef OS_FALSE +#define OS_FALSE 0u +#endif + +#ifndef OS_TRUE +#define OS_TRUE 1u +#endif + +#define OS_ASCII_NUL (INT8U)0 + +#define OS_PRIO_SELF 0xFFu /* Indicate SELF priority */ +#define OS_PRIO_MUTEX_CEIL_DIS 0xFFu /* Disable mutex priority ceiling promotion */ + +#if OS_TASK_STAT_EN > 0u +#define OS_N_SYS_TASKS 2u /* Number of system tasks */ +#else +#define OS_N_SYS_TASKS 1u +#endif + +#define OS_TASK_STAT_PRIO (OS_LOWEST_PRIO - 1u) /* Statistic task priority */ +#define OS_TASK_IDLE_PRIO (OS_LOWEST_PRIO) /* IDLE task priority */ + +#if OS_LOWEST_PRIO <= 63u +#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 8u + 1u) /* Size of event table */ +#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 8u + 1u) /* Size of ready table */ +#else +#define OS_EVENT_TBL_SIZE ((OS_LOWEST_PRIO) / 16u + 1u)/* Size of event table */ +#define OS_RDY_TBL_SIZE ((OS_LOWEST_PRIO) / 16u + 1u)/* Size of ready table */ +#endif + +#define OS_TASK_IDLE_ID 65535u /* ID numbers for Idle, Stat and Timer tasks */ +#define OS_TASK_STAT_ID 65534u +#define OS_TASK_TMR_ID 65533u + +#define OS_EVENT_EN (((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) || (OS_SEM_EN > 0u) || (OS_MUTEX_EN > 0u)) + +#define OS_TCB_RESERVED ((OS_TCB *)1) + +/* +********************************************************************************************************* +* TASK STATUS (Bit definition for OSTCBStat) +********************************************************************************************************* +*/ +#define OS_STAT_RDY 0x00u /* Ready to run */ +#define OS_STAT_SEM 0x01u /* Pending on semaphore */ +#define OS_STAT_MBOX 0x02u /* Pending on mailbox */ +#define OS_STAT_Q 0x04u /* Pending on queue */ +#define OS_STAT_SUSPEND 0x08u /* Task is suspended */ +#define OS_STAT_MUTEX 0x10u /* Pending on mutual exclusion semaphore */ +#define OS_STAT_FLAG 0x20u /* Pending on event flag group */ +#define OS_STAT_MULTI 0x80u /* Pending on multiple events */ + +#define OS_STAT_PEND_ANY (OS_STAT_SEM | OS_STAT_MBOX | OS_STAT_Q | OS_STAT_MUTEX | OS_STAT_FLAG) + +/* +********************************************************************************************************* +* TASK PEND STATUS (Status codes for OSTCBStatPend) +********************************************************************************************************* +*/ +#define OS_STAT_PEND_OK 0u /* Pending status OK, not pending, or pending complete */ +#define OS_STAT_PEND_TO 1u /* Pending timed out */ +#define OS_STAT_PEND_ABORT 2u /* Pending aborted */ + +/* +********************************************************************************************************* +* OS_EVENT types +********************************************************************************************************* +*/ +#define OS_EVENT_TYPE_UNUSED 0u +#define OS_EVENT_TYPE_MBOX 1u +#define OS_EVENT_TYPE_Q 2u +#define OS_EVENT_TYPE_SEM 3u +#define OS_EVENT_TYPE_MUTEX 4u +#define OS_EVENT_TYPE_FLAG 5u + +#define OS_TMR_TYPE 100u /* Used to identify Timers ... */ + /* ... (Must be different value than OS_EVENT_TYPE_xxx) */ + +/* +********************************************************************************************************* +* EVENT FLAGS +********************************************************************************************************* +*/ +#define OS_FLAG_WAIT_CLR_ALL 0u /* Wait for ALL the bits specified to be CLR (i.e. 0) */ +#define OS_FLAG_WAIT_CLR_AND 0u + +#define OS_FLAG_WAIT_CLR_ANY 1u /* Wait for ANY of the bits specified to be CLR (i.e. 0) */ +#define OS_FLAG_WAIT_CLR_OR 1u + +#define OS_FLAG_WAIT_SET_ALL 2u /* Wait for ALL the bits specified to be SET (i.e. 1) */ +#define OS_FLAG_WAIT_SET_AND 2u + +#define OS_FLAG_WAIT_SET_ANY 3u /* Wait for ANY of the bits specified to be SET (i.e. 1) */ +#define OS_FLAG_WAIT_SET_OR 3u + + +#define OS_FLAG_CONSUME 0x80u /* Consume the flags if condition(s) satisfied */ + + +#define OS_FLAG_CLR 0u +#define OS_FLAG_SET 1u + +/* +********************************************************************************************************* +* Values for OSTickStepState +* +* Note(s): This feature is used by uC/OS-View. +********************************************************************************************************* +*/ + +#if OS_TICK_STEP_EN > 0u +#define OS_TICK_STEP_DIS 0u /* Stepping is disabled, tick runs as normal */ +#define OS_TICK_STEP_WAIT 1u /* Waiting for uC/OS-View to set OSTickStepState to _ONCE */ +#define OS_TICK_STEP_ONCE 2u /* Process tick once and wait for next cmd from uC/OS-View */ +#endif + +/* +********************************************************************************************************* +* Possible values for 'opt' argument of OSSemDel(), OSMboxDel(), OSQDel() and OSMutexDel() +********************************************************************************************************* +*/ +#define OS_DEL_NO_PEND 0u +#define OS_DEL_ALWAYS 1u + +/* +********************************************************************************************************* +* OS???Pend() OPTIONS +* +* These #defines are used to establish the options for OS???PendAbort(). +********************************************************************************************************* +*/ +#define OS_PEND_OPT_NONE 0u /* NO option selected */ +#define OS_PEND_OPT_BROADCAST 1u /* Broadcast action to ALL tasks waiting */ + +/* +********************************************************************************************************* +* OS???PostOpt() OPTIONS +* +* These #defines are used to establish the options for OSMboxPostOpt() and OSQPostOpt(). +********************************************************************************************************* +*/ +#define OS_POST_OPT_NONE 0x00u /* NO option selected */ +#define OS_POST_OPT_BROADCAST 0x01u /* Broadcast message to ALL tasks waiting */ +#define OS_POST_OPT_FRONT 0x02u /* Post to highest priority task waiting */ +#define OS_POST_OPT_NO_SCHED 0x04u /* Do not call the scheduler if this option is selected */ + +/* +********************************************************************************************************* +* TASK OPTIONS (see OSTaskCreateExt()) +********************************************************************************************************* +*/ +#define OS_TASK_OPT_NONE 0x0000u /* NO option selected */ +#define OS_TASK_OPT_STK_CHK 0x0001u /* Enable stack checking for the task */ +#define OS_TASK_OPT_STK_CLR 0x0002u /* Clear the stack when the task is create */ +#define OS_TASK_OPT_SAVE_FP 0x0004u /* Save the contents of any floating-point registers */ +#define OS_TASK_OPT_NO_TLS 0x0008u /* Specify that task doesn't needs TLS */ + +/* +********************************************************************************************************* +* TIMER OPTIONS (see OSTmrStart() and OSTmrStop()) +********************************************************************************************************* +*/ +#define OS_TMR_OPT_NONE 0u /* No option selected */ + +#define OS_TMR_OPT_ONE_SHOT 1u /* Timer will not automatically restart when it expires */ +#define OS_TMR_OPT_PERIODIC 2u /* Timer will automatically restart when it expires */ + +#define OS_TMR_OPT_CALLBACK 3u /* OSTmrStop() option to call 'callback' w/ timer arg. */ +#define OS_TMR_OPT_CALLBACK_ARG 4u /* OSTmrStop() option to call 'callback' w/ new arg. */ + +/* +********************************************************************************************************* +* TIMER STATES +********************************************************************************************************* +*/ +#define OS_TMR_STATE_UNUSED 0u +#define OS_TMR_STATE_STOPPED 1u +#define OS_TMR_STATE_COMPLETED 2u +#define OS_TMR_STATE_RUNNING 3u + +/* +********************************************************************************************************* +* ERROR CODES +********************************************************************************************************* +*/ +#define OS_ERR_NONE 0u + +#define OS_ERR_EVENT_TYPE 1u +#define OS_ERR_PEND_ISR 2u +#define OS_ERR_POST_NULL_PTR 3u +#define OS_ERR_PEVENT_NULL 4u +#define OS_ERR_POST_ISR 5u +#define OS_ERR_QUERY_ISR 6u +#define OS_ERR_INVALID_OPT 7u +#define OS_ERR_ID_INVALID 8u +#define OS_ERR_PDATA_NULL 9u + +#define OS_ERR_TIMEOUT 10u +#define OS_ERR_EVENT_NAME_TOO_LONG 11u +#define OS_ERR_PNAME_NULL 12u +#define OS_ERR_PEND_LOCKED 13u +#define OS_ERR_PEND_ABORT 14u +#define OS_ERR_DEL_ISR 15u +#define OS_ERR_CREATE_ISR 16u +#define OS_ERR_NAME_GET_ISR 17u +#define OS_ERR_NAME_SET_ISR 18u +#define OS_ERR_ILLEGAL_CREATE_RUN_TIME 19u + +#define OS_ERR_MBOX_FULL 20u +#define OS_ERR_ILLEGAL_DEL_RUN_TIME 21u + +#define OS_ERR_Q_FULL 30u +#define OS_ERR_Q_EMPTY 31u + +#define OS_ERR_PRIO_EXIST 40u +#define OS_ERR_PRIO 41u +#define OS_ERR_PRIO_INVALID 42u + +#define OS_ERR_SCHED_LOCKED 50u +#define OS_ERR_SEM_OVF 51u + +#define OS_ERR_TASK_CREATE_ISR 60u +#define OS_ERR_TASK_DEL 61u +#define OS_ERR_TASK_DEL_IDLE 62u +#define OS_ERR_TASK_DEL_REQ 63u +#define OS_ERR_TASK_DEL_ISR 64u +#define OS_ERR_TASK_NAME_TOO_LONG 65u +#define OS_ERR_TASK_NO_MORE_TCB 66u +#define OS_ERR_TASK_NOT_EXIST 67u +#define OS_ERR_TASK_NOT_SUSPENDED 68u +#define OS_ERR_TASK_OPT 69u +#define OS_ERR_TASK_RESUME_PRIO 70u +#define OS_ERR_TASK_SUSPEND_IDLE 71u +#define OS_ERR_TASK_SUSPEND_PRIO 72u +#define OS_ERR_TASK_WAITING 73u + +#define OS_ERR_TIME_NOT_DLY 80u +#define OS_ERR_TIME_INVALID_MINUTES 81u +#define OS_ERR_TIME_INVALID_SECONDS 82u +#define OS_ERR_TIME_INVALID_MS 83u +#define OS_ERR_TIME_ZERO_DLY 84u +#define OS_ERR_TIME_DLY_ISR 85u + +#define OS_ERR_MEM_INVALID_PART 90u +#define OS_ERR_MEM_INVALID_BLKS 91u +#define OS_ERR_MEM_INVALID_SIZE 92u +#define OS_ERR_MEM_NO_FREE_BLKS 93u +#define OS_ERR_MEM_FULL 94u +#define OS_ERR_MEM_INVALID_PBLK 95u +#define OS_ERR_MEM_INVALID_PMEM 96u +#define OS_ERR_MEM_INVALID_PDATA 97u +#define OS_ERR_MEM_INVALID_ADDR 98u +#define OS_ERR_MEM_NAME_TOO_LONG 99u + +#define OS_ERR_NOT_MUTEX_OWNER 100u + +#define OS_ERR_FLAG_INVALID_PGRP 110u +#define OS_ERR_FLAG_WAIT_TYPE 111u +#define OS_ERR_FLAG_NOT_RDY 112u +#define OS_ERR_FLAG_INVALID_OPT 113u +#define OS_ERR_FLAG_GRP_DEPLETED 114u +#define OS_ERR_FLAG_NAME_TOO_LONG 115u + +#define OS_ERR_PCP_LOWER 120u + +#define OS_ERR_TMR_INVALID_DLY 130u +#define OS_ERR_TMR_INVALID_PERIOD 131u +#define OS_ERR_TMR_INVALID_OPT 132u +#define OS_ERR_TMR_INVALID_NAME 133u +#define OS_ERR_TMR_NON_AVAIL 134u +#define OS_ERR_TMR_INACTIVE 135u +#define OS_ERR_TMR_INVALID_DEST 136u +#define OS_ERR_TMR_INVALID_TYPE 137u +#define OS_ERR_TMR_INVALID 138u +#define OS_ERR_TMR_ISR 139u +#define OS_ERR_TMR_NAME_TOO_LONG 140u +#define OS_ERR_TMR_INVALID_STATE 141u +#define OS_ERR_TMR_STOPPED 142u +#define OS_ERR_TMR_NO_CALLBACK 143u + +#define OS_ERR_NO_MORE_ID_AVAIL 150u + +#define OS_ERR_TLS_NO_MORE_AVAIL 160u +#define OS_ERR_TLS_ID_INVALID 161u +#define OS_ERR_TLS_NOT_EN 162u +#define OS_ERR_TLS_DESTRUCT_ASSIGNED 163u +#define OS_ERR_OS_NOT_RUNNING 164u + + +/* +********************************************************************************************************* +* THREAD LOCAL STORAGE (TLS) +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) +typedef void *OS_TLS; + +typedef INT8U OS_TLS_ID; +#endif +#endif + +/* +********************************************************************************************************* +* EVENT CONTROL BLOCK +********************************************************************************************************* +*/ + +#if OS_LOWEST_PRIO <= 63u +typedef INT8U OS_PRIO; +#else +typedef INT16U OS_PRIO; +#endif + +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +typedef struct os_event { + INT8U OSEventType; /* Type of event control block (see OS_EVENT_TYPE_xxxx) */ + void *OSEventPtr; /* Pointer to message or queue structure */ + INT16U OSEventCnt; /* Semaphore Count (not used if other EVENT type) */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + +#if OS_EVENT_NAME_EN > 0u + INT8U *OSEventName; +#endif +} OS_EVENT; +#endif + + +/* +********************************************************************************************************* +* EVENT FLAGS CONTROL BLOCK +********************************************************************************************************* +*/ + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + +#if OS_FLAGS_NBITS == 8u /* Determine the size of OS_FLAGS (8, 16 or 32 bits) */ +typedef INT8U OS_FLAGS; +#endif + +#if OS_FLAGS_NBITS == 16u +typedef INT16U OS_FLAGS; +#endif + +#if OS_FLAGS_NBITS == 32u +typedef INT32U OS_FLAGS; +#endif + + +typedef struct os_flag_grp { /* Event Flag Group */ + INT8U OSFlagType; /* Should be set to OS_EVENT_TYPE_FLAG */ + void *OSFlagWaitList; /* Pointer to first NODE of task waiting on event flag */ + OS_FLAGS OSFlagFlags; /* 8, 16 or 32 bit flags */ +#if OS_FLAG_NAME_EN > 0u + INT8U *OSFlagName; +#endif +} OS_FLAG_GRP; + + + +typedef struct os_flag_node { /* Event Flag Wait List Node */ + void *OSFlagNodeNext; /* Pointer to next NODE in wait list */ + void *OSFlagNodePrev; /* Pointer to previous NODE in wait list */ + void *OSFlagNodeTCB; /* Pointer to TCB of waiting task */ + void *OSFlagNodeFlagGrp; /* Pointer to Event Flag Group */ + OS_FLAGS OSFlagNodeFlags; /* Event flag to wait on */ + INT8U OSFlagNodeWaitType; /* Type of wait: */ + /* OS_FLAG_WAIT_AND */ + /* OS_FLAG_WAIT_ALL */ + /* OS_FLAG_WAIT_OR */ + /* OS_FLAG_WAIT_ANY */ +} OS_FLAG_NODE; +#endif + + +/* +********************************************************************************************************* +* MESSAGE MAILBOX DATA +********************************************************************************************************* +*/ + +#if OS_MBOX_EN > 0u +typedef struct os_mbox_data { + void *OSMsg; /* Pointer to message in mailbox */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_MBOX_DATA; +#endif + +/* +********************************************************************************************************* +* MEMORY PARTITION DATA STRUCTURES +********************************************************************************************************* +*/ + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +typedef struct os_mem { /* MEMORY CONTROL BLOCK */ + void *OSMemAddr; /* Pointer to beginning of memory partition */ + void *OSMemFreeList; /* Pointer to list of free memory blocks */ + INT32U OSMemBlkSize; /* Size (in bytes) of each block of memory */ + INT32U OSMemNBlks; /* Total number of blocks in this partition */ + INT32U OSMemNFree; /* Number of memory blocks remaining in this partition */ +#if OS_MEM_NAME_EN > 0u + INT8U *OSMemName; /* Memory partition name */ +#endif +} OS_MEM; + + +typedef struct os_mem_data { + void *OSAddr; /* Ptr to the beginning address of the memory partition */ + void *OSFreeList; /* Ptr to the beginning of the free list of memory blocks */ + INT32U OSBlkSize; /* Size (in bytes) of each memory block */ + INT32U OSNBlks; /* Total number of blocks in the partition */ + INT32U OSNFree; /* Number of memory blocks free */ + INT32U OSNUsed; /* Number of memory blocks used */ +} OS_MEM_DATA; +#endif + + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORE DATA +********************************************************************************************************* +*/ + +#if OS_MUTEX_EN > 0u +typedef struct os_mutex_data { + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ + BOOLEAN OSValue; /* Mutex value (OS_FALSE = used, OS_TRUE = available) */ + INT8U OSOwnerPrio; /* Mutex owner's task priority or 0xFF if no owner */ + INT8U OSMutexPCP; /* Priority Ceiling Priority or 0xFF if PCP disabled */ +} OS_MUTEX_DATA; +#endif + +/* +********************************************************************************************************* +* MESSAGE QUEUE DATA +********************************************************************************************************* +*/ + +#if OS_Q_EN > 0u +typedef struct os_q { /* QUEUE CONTROL BLOCK */ + struct os_q *OSQPtr; /* Link to next queue control block in list of free blocks */ + void **OSQStart; /* Ptr to start of queue data */ + void **OSQEnd; /* Ptr to end of queue data */ + void **OSQIn; /* Ptr to where next message will be inserted in the Q */ + void **OSQOut; /* Ptr to where next message will be extracted from the Q */ + INT16U OSQSize; /* Size of queue (maximum number of entries) */ + INT16U OSQEntries; /* Current number of entries in the queue */ +} OS_Q; + + +typedef struct os_q_data { + void *OSMsg; /* Pointer to next message to be extracted from queue */ + INT16U OSNMsgs; /* Number of messages in message queue */ + INT16U OSQSize; /* Size of message queue */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_Q_DATA; +#endif + +/* +********************************************************************************************************* +* SEMAPHORE DATA +********************************************************************************************************* +*/ + +#if OS_SEM_EN > 0u +typedef struct os_sem_data { + INT16U OSCnt; /* Semaphore count */ + OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */ + OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */ +} OS_SEM_DATA; +#endif + +/* +********************************************************************************************************* +* TASK STACK DATA +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EXT_EN > 0u +typedef struct os_stk_data { + INT32U OSFree; /* Number of free entries on the stack */ + INT32U OSUsed; /* Number of entries used on the stack */ +} OS_STK_DATA; +#endif + + +/* +********************************************************************************************************* +* TASK CONTROL BLOCK +********************************************************************************************************* +*/ + +typedef struct os_tcb { + OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */ + +#if OS_TASK_CREATE_EXT_EN > 0u + void *OSTCBExtPtr; /* Pointer to user definable data for TCB extension */ + OS_STK *OSTCBStkBottom; /* Pointer to bottom of stack */ + INT32U OSTCBStkSize; /* Size of task stack (in number of stack elements) */ + INT16U OSTCBOpt; /* Task options as passed by OSTaskCreateExt() */ + INT16U OSTCBId; /* Task ID (0..65535) */ +#endif + + struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */ + struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + OS_TLS OSTCBTLSTbl[OS_TLS_TBL_SIZE]; +#endif +#endif + +#if (OS_EVENT_EN) + OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */ +#endif + +#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0u) + OS_EVENT **OSTCBEventMultiPtr; /* Pointer to multiple event control blocks */ + OS_EVENT *OSTCBEventMultiRdy; /* Pointer to the first event control block readied */ +#endif + +#if ((OS_Q_EN > 0u) && (OS_MAX_QS > 0u)) || (OS_MBOX_EN > 0u) + void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */ +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +#if OS_TASK_DEL_EN > 0u + OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */ +#endif + OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run */ +#endif + + INT32U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event */ + INT8U OSTCBStat; /* Task status */ + INT8U OSTCBStatPend; /* Task PEND status */ + INT8U OSTCBPrio; /* Task priority (0 == highest) */ + + INT8U OSTCBX; /* Bit position in group corresponding to task priority */ + INT8U OSTCBY; /* Index into ready table corresponding to task priority */ + OS_PRIO OSTCBBitX; /* Bit mask to access bit position in ready table */ + OS_PRIO OSTCBBitY; /* Bit mask to access bit position in ready group */ + +#if OS_TASK_DEL_EN > 0u + INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */ +#endif + +#if OS_TASK_PROFILE_EN > 0u + INT32U OSTCBCtxSwCtr; /* Number of time the task was switched in */ + INT32U OSTCBCyclesTot; /* Total number of clock cycles the task has been running */ + INT32U OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption */ + OS_STK *OSTCBStkBase; /* Pointer to the beginning of the task stack */ + INT32U OSTCBStkUsed; /* Number of bytes used from the stack */ +#endif + +#if OS_TASK_NAME_EN > 0u + INT8U *OSTCBTaskName; +#endif + +#if OS_TASK_REG_TBL_SIZE > 0u + INT32U OSTCBRegTbl[OS_TASK_REG_TBL_SIZE]; +#endif +} OS_TCB; + + +/* +********************************************************************************************************* +* TIMER DATA TYPES +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +typedef void (*OS_TMR_CALLBACK)(void *ptmr, void *parg); + + + +typedef struct os_tmr { + INT8U OSTmrType; /* Should be set to OS_TMR_TYPE */ + OS_TMR_CALLBACK OSTmrCallback; /* Function to call when timer expires */ + void *OSTmrCallbackArg; /* Argument to pass to function when timer expires */ + void *OSTmrNext; /* Double link list pointers */ + void *OSTmrPrev; + INT32U OSTmrMatch; /* Timer expires when OSTmrTime == OSTmrMatch */ + INT32U OSTmrDly; /* Delay time before periodic update starts */ + INT32U OSTmrPeriod; /* Period to repeat timer */ +#if OS_TMR_CFG_NAME_EN > 0u + INT8U *OSTmrName; /* Name to give the timer */ +#endif + INT8U OSTmrOpt; /* Options (see OS_TMR_OPT_xxx) */ + INT8U OSTmrState; /* Indicates the state of the timer: */ + /* OS_TMR_STATE_UNUSED */ + /* OS_TMR_STATE_RUNNING */ + /* OS_TMR_STATE_STOPPED */ +} OS_TMR; + + + +typedef struct os_tmr_wheel { + OS_TMR *OSTmrFirst; /* Pointer to first timer in linked list */ + INT16U OSTmrEntries; +} OS_TMR_WHEEL; +#endif + + +/* +********************************************************************************************************* +* THREAD LOCAL STORAGE (TLS) +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) +typedef void (*OS_TLS_DESTRUCT_PTR)(OS_TCB *ptcb, + OS_TLS_ID id, + OS_TLS value); +#endif +#endif + +/* +********************************************************************************************************* +* GLOBAL VARIABLES +********************************************************************************************************* +*/ + +OS_EXT INT32U OSCtxSwCtr; /* Counter of number of context switches */ + +#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) +OS_EXT OS_EVENT *OSEventFreeList; /* Pointer to list of free EVENT control blocks */ +OS_EXT OS_EVENT OSEventTbl[OS_MAX_EVENTS];/* Table of EVENT control blocks */ +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +OS_EXT OS_FLAG_GRP OSFlagTbl[OS_MAX_FLAGS]; /* Table containing event flag groups */ +OS_EXT OS_FLAG_GRP *OSFlagFreeList; /* Pointer to free list of event flag groups */ +#endif + +#if OS_TASK_STAT_EN > 0u +OS_EXT INT8U OSCPUUsage; /* Percentage of CPU used */ +OS_EXT INT32U OSIdleCtrMax; /* Max. value that idle ctr can take in 1 sec. */ +OS_EXT INT32U OSIdleCtrRun; /* Val. reached by idle ctr at run time in 1 sec. */ +OS_EXT BOOLEAN OSStatRdy; /* Flag indicating that the statistic task is rdy */ +OS_EXT OS_STK OSTaskStatStk[OS_TASK_STAT_STK_SIZE]; /* Statistics task stack */ +#endif + +OS_EXT INT8U OSIntNesting; /* Interrupt nesting level */ + +OS_EXT INT8U OSLockNesting; /* Multitasking lock nesting level */ + +OS_EXT INT8U OSPrioCur; /* Priority of current task */ +OS_EXT INT8U OSPrioHighRdy; /* Priority of highest priority task */ + +OS_EXT OS_PRIO OSRdyGrp; /* Ready list group */ +OS_EXT OS_PRIO OSRdyTbl[OS_RDY_TBL_SIZE]; /* Table of tasks which are ready to run */ + +OS_EXT BOOLEAN OSRunning; /* Flag indicating that kernel is running */ + +OS_EXT INT8U OSTaskCtr; /* Number of tasks created */ + +OS_EXT volatile INT32U OSIdleCtr; /* Idle counter */ + +#ifdef OS_SAFETY_CRITICAL_IEC61508 +OS_EXT BOOLEAN OSSafetyCriticalStartFlag; +#endif + +OS_EXT OS_STK OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE]; /* Idle task stack */ + + +OS_EXT OS_TCB *OSTCBCur; /* Pointer to currently running TCB */ +OS_EXT OS_TCB *OSTCBFreeList; /* Pointer to list of free TCBs */ +OS_EXT OS_TCB *OSTCBHighRdy; /* Pointer to highest priority TCB R-to-R */ +OS_EXT OS_TCB *OSTCBList; /* Pointer to doubly linked list of TCBs */ +OS_EXT OS_TCB *OSTCBPrioTbl[OS_LOWEST_PRIO + 1u]; /* Table of pointers to created TCBs */ +OS_EXT OS_TCB OSTCBTbl[OS_MAX_TASKS + OS_N_SYS_TASKS]; /* Table of TCBs */ + +#if OS_TICK_STEP_EN > 0u +OS_EXT INT8U OSTickStepState; /* Indicates the state of the tick step feature */ +#endif + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +OS_EXT OS_MEM *OSMemFreeList; /* Pointer to free list of memory partitions */ +OS_EXT OS_MEM OSMemTbl[OS_MAX_MEM_PART];/* Storage for memory partition manager */ +#endif + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) +OS_EXT OS_Q *OSQFreeList; /* Pointer to list of free QUEUE control blocks */ +OS_EXT OS_Q OSQTbl[OS_MAX_QS]; /* Table of QUEUE control blocks */ +#endif + +#if OS_TASK_REG_TBL_SIZE > 0u +OS_EXT INT8U OSTaskRegNextAvailID; /* Next available Task register ID */ +#endif + +#if OS_TIME_GET_SET_EN > 0u +OS_EXT volatile INT32U OSTime; /* Current value of system time (in ticks) */ +#endif + +#if OS_TMR_EN > 0u +OS_EXT INT16U OSTmrFree; /* Number of free entries in the timer pool */ +OS_EXT INT16U OSTmrUsed; /* Number of timers used */ +OS_EXT INT32U OSTmrTime; /* Current timer time */ + +OS_EXT OS_EVENT *OSTmrSem; /* Sem. used to gain exclusive access to timers */ +OS_EXT OS_EVENT *OSTmrSemSignal; /* Sem. used to signal the update of timers */ + +OS_EXT OS_TMR OSTmrTbl[OS_TMR_CFG_MAX]; /* Table containing pool of timers */ +OS_EXT OS_TMR *OSTmrFreeList; /* Pointer to free list of timers */ +OS_EXT OS_STK OSTmrTaskStk[OS_TASK_TMR_STK_SIZE]; + +OS_EXT OS_TMR_WHEEL OSTmrWheelTbl[OS_TMR_CFG_WHEEL_SIZE]; +#endif + +extern INT8U const OSUnMapTbl[256]; /* Priority->Index lookup table */ + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Target Independent Functions) +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#if (OS_EVENT_EN) + +#if (OS_EVENT_NAME_EN > 0u) +INT8U OSEventNameGet (OS_EVENT *pevent, + INT8U **pname, + INT8U *perr); + +void OSEventNameSet (OS_EVENT *pevent, + INT8U *pname, + INT8U *perr); +#endif + +#if (OS_EVENT_MULTI_EN > 0u) +INT16U OSEventPendMulti (OS_EVENT **pevents_pend, + OS_EVENT **pevents_rdy, + void **pmsgs_rdy, + INT32U timeout, + INT8U *perr); +#endif + +#endif + +/* +********************************************************************************************************* +* TASK LOCAL STORAGE (TLS) SUPPORT +********************************************************************************************************* +*/ + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + +OS_TLS_ID OS_TLS_GetID (INT8U *perr); + +OS_TLS OS_TLS_GetValue (OS_TCB *ptcb, + OS_TLS_ID id, + INT8U *perr); + +void OS_TLS_Init (INT8U *perr); + +void OS_TLS_SetValue (OS_TCB *ptcb, + OS_TLS_ID id, + OS_TLS value, + INT8U *perr); + +void OS_TLS_SetDestruct (OS_TLS_ID id, + OS_TLS_DESTRUCT_PTR pdestruct, + INT8U *perr); + +void OS_TLS_TaskCreate (OS_TCB *ptcb); + +void OS_TLS_TaskDel (OS_TCB *ptcb); + +void OS_TLS_TaskSw (void); + +#endif +#endif + + +/* +********************************************************************************************************* +* EVENT FLAGS MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) + +#if OS_FLAG_ACCEPT_EN > 0u +OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT8U *perr); +#endif + +OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, + INT8U *perr); + +#if OS_FLAG_DEL_EN > 0u +OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp, + INT8U opt, + INT8U *perr); +#endif + +#if (OS_FLAG_EN > 0u) && (OS_FLAG_NAME_EN > 0u) +INT8U OSFlagNameGet (OS_FLAG_GRP *pgrp, + INT8U **pname, + INT8U *perr); + +void OSFlagNameSet (OS_FLAG_GRP *pgrp, + INT8U *pname, + INT8U *perr); +#endif + +OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U wait_type, + INT32U timeout, + INT8U *perr); + +OS_FLAGS OSFlagPendGetFlagsRdy (void); +OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, + OS_FLAGS flags, + INT8U opt, + INT8U *perr); + +#if OS_FLAG_QUERY_EN > 0u +OS_FLAGS OSFlagQuery (OS_FLAG_GRP *pgrp, + INT8U *perr); +#endif +#endif + +/* +********************************************************************************************************* +* MESSAGE MAILBOX MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_MBOX_EN > 0u + +#if OS_MBOX_ACCEPT_EN > 0u +void *OSMboxAccept (OS_EVENT *pevent); +#endif + +OS_EVENT *OSMboxCreate (void *pmsg); + +#if OS_MBOX_DEL_EN > 0u +OS_EVENT *OSMboxDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +void *OSMboxPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +#if OS_MBOX_PEND_ABORT_EN > 0u +INT8U OSMboxPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +#if OS_MBOX_POST_EN > 0u +INT8U OSMboxPost (OS_EVENT *pevent, + void *pmsg); +#endif + +#if OS_MBOX_POST_OPT_EN > 0u +INT8U OSMboxPostOpt (OS_EVENT *pevent, + void *pmsg, + INT8U opt); +#endif + +#if OS_MBOX_QUERY_EN > 0u +INT8U OSMboxQuery (OS_EVENT *pevent, + OS_MBOX_DATA *p_mbox_data); +#endif +#endif + +/* +********************************************************************************************************* +* MEMORY MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) + +OS_MEM *OSMemCreate (void *addr, + INT32U nblks, + INT32U blksize, + INT8U *perr); + +void *OSMemGet (OS_MEM *pmem, + INT8U *perr); +#if OS_MEM_NAME_EN > 0u +INT8U OSMemNameGet (OS_MEM *pmem, + INT8U **pname, + INT8U *perr); + +void OSMemNameSet (OS_MEM *pmem, + INT8U *pname, + INT8U *perr); +#endif +INT8U OSMemPut (OS_MEM *pmem, + void *pblk); + +#if OS_MEM_QUERY_EN > 0u +INT8U OSMemQuery (OS_MEM *pmem, + OS_MEM_DATA *p_mem_data); +#endif + +#endif + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORE MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_MUTEX_EN > 0u + +#if OS_MUTEX_ACCEPT_EN > 0u +BOOLEAN OSMutexAccept (OS_EVENT *pevent, + INT8U *perr); +#endif + +OS_EVENT *OSMutexCreate (INT8U prio, + INT8U *perr); + +#if OS_MUTEX_DEL_EN > 0u +OS_EVENT *OSMutexDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +void OSMutexPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +INT8U OSMutexPost (OS_EVENT *pevent); + +#if OS_MUTEX_QUERY_EN > 0u +INT8U OSMutexQuery (OS_EVENT *pevent, + OS_MUTEX_DATA *p_mutex_data); +#endif + +#endif + + +/* +********************************************************************************************************* +* MESSAGE QUEUE MANAGEMENT +********************************************************************************************************* +*/ + +#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u) + +#if OS_Q_ACCEPT_EN > 0u +void *OSQAccept (OS_EVENT *pevent, + INT8U *perr); +#endif + +OS_EVENT *OSQCreate (void **start, + INT16U size); + +#if OS_Q_DEL_EN > 0u +OS_EVENT *OSQDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +#if OS_Q_FLUSH_EN > 0u +INT8U OSQFlush (OS_EVENT *pevent); +#endif + +void *OSQPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +#if OS_Q_PEND_ABORT_EN > 0u +INT8U OSQPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +#if OS_Q_POST_EN > 0u +INT8U OSQPost (OS_EVENT *pevent, + void *pmsg); +#endif + +#if OS_Q_POST_FRONT_EN > 0u +INT8U OSQPostFront (OS_EVENT *pevent, + void *pmsg); +#endif + +#if OS_Q_POST_OPT_EN > 0u +INT8U OSQPostOpt (OS_EVENT *pevent, + void *pmsg, + INT8U opt); +#endif + +#if OS_Q_QUERY_EN > 0u +INT8U OSQQuery (OS_EVENT *pevent, + OS_Q_DATA *p_q_data); +#endif + +#endif + + +/* +********************************************************************************************************* +* SEMAPHORE MANAGEMENT +********************************************************************************************************* +*/ +#if OS_SEM_EN > 0u + +#if OS_SEM_ACCEPT_EN > 0u +INT16U OSSemAccept (OS_EVENT *pevent); +#endif + +OS_EVENT *OSSemCreate (INT16U cnt); + +#if OS_SEM_DEL_EN > 0u +OS_EVENT *OSSemDel (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +void OSSemPend (OS_EVENT *pevent, + INT32U timeout, + INT8U *perr); + +#if OS_SEM_PEND_ABORT_EN > 0u +INT8U OSSemPendAbort (OS_EVENT *pevent, + INT8U opt, + INT8U *perr); +#endif + +INT8U OSSemPost (OS_EVENT *pevent); + +#if OS_SEM_QUERY_EN > 0u +INT8U OSSemQuery (OS_EVENT *pevent, + OS_SEM_DATA *p_sem_data); +#endif + +#if OS_SEM_SET_EN > 0u +void OSSemSet (OS_EVENT *pevent, + INT16U cnt, + INT8U *perr); +#endif + +#endif + + +/* +********************************************************************************************************* +* TASK MANAGEMENT +********************************************************************************************************* +*/ +#if OS_TASK_CHANGE_PRIO_EN > 0u +INT8U OSTaskChangePrio (INT8U oldprio, + INT8U newprio); +#endif + +#if OS_TASK_CREATE_EN > 0u +INT8U OSTaskCreate (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio); +#endif + +#if OS_TASK_CREATE_EXT_EN > 0u +INT8U OSTaskCreateExt (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT8U prio, + INT16U id, + OS_STK *pbos, + INT32U stk_size, + void *pext, + INT16U opt); +#endif + +#if OS_TASK_DEL_EN > 0u +INT8U OSTaskDel (INT8U prio); +INT8U OSTaskDelReq (INT8U prio); +#endif + +#if OS_TASK_NAME_EN > 0u +INT8U OSTaskNameGet (INT8U prio, + INT8U **pname, + INT8U *perr); + +void OSTaskNameSet (INT8U prio, + INT8U *pname, + INT8U *perr); +#endif + +#if OS_TASK_SUSPEND_EN > 0u +INT8U OSTaskResume (INT8U prio); +INT8U OSTaskSuspend (INT8U prio); +#endif + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +INT8U OSTaskStkChk (INT8U prio, + OS_STK_DATA *p_stk_data); +#endif + +#if OS_TASK_QUERY_EN > 0u +INT8U OSTaskQuery (INT8U prio, + OS_TCB *p_task_data); +#endif + + + +#if OS_TASK_REG_TBL_SIZE > 0u +INT32U OSTaskRegGet (INT8U prio, + INT8U id, + INT8U *perr); + +INT8U OSTaskRegGetID (INT8U *perr); + +void OSTaskRegSet (INT8U prio, + INT8U id, + INT32U value, + INT8U *perr); +#endif + + +/* +********************************************************************************************************* +* TIME MANAGEMENT +********************************************************************************************************* +*/ + +void OSTimeDly (INT32U ticks); + +#if OS_TIME_DLY_HMSM_EN > 0u +INT8U OSTimeDlyHMSM (INT8U hours, + INT8U minutes, + INT8U seconds, + INT16U ms); +#endif + +#if OS_TIME_DLY_RESUME_EN > 0u +INT8U OSTimeDlyResume (INT8U prio); +#endif + +#if OS_TIME_GET_SET_EN > 0u +INT32U OSTimeGet (void); +void OSTimeSet (INT32U ticks); +#endif + +void OSTimeTick (void); + +/* +********************************************************************************************************* +* TIMER MANAGEMENT +********************************************************************************************************* +*/ + +#if OS_TMR_EN > 0u +OS_TMR *OSTmrCreate (INT32U dly, + INT32U period, + INT8U opt, + OS_TMR_CALLBACK callback, + void *callback_arg, + INT8U *pname, + INT8U *perr); + +BOOLEAN OSTmrDel (OS_TMR *ptmr, + INT8U *perr); + +#if OS_TMR_CFG_NAME_EN > 0u +INT8U OSTmrNameGet (OS_TMR *ptmr, + INT8U **pdest, + INT8U *perr); +#endif +INT32U OSTmrRemainGet (OS_TMR *ptmr, + INT8U *perr); + +INT8U OSTmrStateGet (OS_TMR *ptmr, + INT8U *perr); + +BOOLEAN OSTmrStart (OS_TMR *ptmr, + INT8U *perr); + +BOOLEAN OSTmrStop (OS_TMR *ptmr, + INT8U opt, + void *callback_arg, + INT8U *perr); + +INT8U OSTmrSignal (void); +#endif + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +void OSInit (void); + +void OSIntEnter (void); +void OSIntExit (void); + +#ifdef OS_SAFETY_CRITICAL_IEC61508 +void OSSafetyCriticalStart (void); +#endif + +#if OS_SCHED_LOCK_EN > 0u +void OSSchedLock (void); +void OSSchedUnlock (void); +#endif + +void OSStart (void); + +void OSStatInit (void); + +INT16U OSVersion (void); + + +/* +********************************************************************************************************* +* INTERNAL FUNCTION PROTOTYPES +* (Your application MUST NOT call these functions) +********************************************************************************************************* +*/ + +#if OS_TASK_DEL_EN > 0u +void OS_Dummy (void); +#endif + +#if (OS_EVENT_EN) +INT8U OS_EventTaskRdy (OS_EVENT *pevent, + void *pmsg, + INT8U msk, + INT8U pend_stat); + +void OS_EventTaskWait (OS_EVENT *pevent); + +void OS_EventTaskRemove (OS_TCB *ptcb, + OS_EVENT *pevent); + +#if (OS_EVENT_MULTI_EN > 0u) +void OS_EventTaskWaitMulti (OS_EVENT **pevents_wait); + +void OS_EventTaskRemoveMulti (OS_TCB *ptcb, + OS_EVENT **pevents_multi); +#endif + +void OS_EventWaitListInit (OS_EVENT *pevent); +#endif + +#if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u) +void OS_FlagInit (void); +void OS_FlagUnlink (OS_FLAG_NODE *pnode); +#endif + +void OS_MemClr (INT8U *pdest, + INT16U size); + +void OS_MemCopy (INT8U *pdest, + INT8U *psrc, + INT16U size); + +#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) +void OS_MemInit (void); +#endif + +#if OS_Q_EN > 0u +void OS_QInit (void); +#endif + +void OS_Sched (void); + +#if (OS_EVENT_NAME_EN > 0u) || (OS_FLAG_NAME_EN > 0u) || (OS_MEM_NAME_EN > 0u) || (OS_TASK_NAME_EN > 0u) +INT8U OS_StrLen (INT8U *psrc); +#endif + +void OS_TaskIdle (void *p_arg); + +void OS_TaskReturn (void); + +#if OS_TASK_STAT_EN > 0u +void OS_TaskStat (void *p_arg); +#endif + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStkClr (OS_STK *pbos, + INT32U size, + INT16U opt); +#endif + +#if (OS_TASK_STAT_STK_CHK_EN > 0u) && (OS_TASK_CREATE_EXT_EN > 0u) +void OS_TaskStatStkChk (void); +#endif + +INT8U OS_TCBInit (INT8U prio, + OS_STK *ptos, + OS_STK *pbos, + INT16U id, + INT32U stk_size, + void *pext, + INT16U opt); + +#if OS_TMR_EN > 0u +void OSTmr_Init (void); +#endif + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Target Specific Functions) +********************************************************************************************************* +*/ + +#if OS_DEBUG_EN > 0u +void OSDebugInit (void); +#endif + +void OSInitHookBegin (void); +void OSInitHookEnd (void); + +void OSTaskCreateHook (OS_TCB *ptcb); +void OSTaskDelHook (OS_TCB *ptcb); + +void OSTaskIdleHook (void); + +void OSTaskReturnHook (OS_TCB *ptcb); + +void OSTaskStatHook (void); +OS_STK *OSTaskStkInit (void (*task)(void *p_arg), + void *p_arg, + OS_STK *ptos, + INT16U opt); + +#if OS_TASK_SW_HOOK_EN > 0u +void OSTaskSwHook (void); +#endif + +void OSTCBInitHook (OS_TCB *ptcb); + +#if OS_TIME_TICK_HOOK_EN > 0u +void OSTimeTickHook (void); +#endif + + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* (Application Specific Functions) +********************************************************************************************************* +*/ + +#if OS_APP_HOOKS_EN > 0u +void App_TaskCreateHook (OS_TCB *ptcb); +void App_TaskDelHook (OS_TCB *ptcb); +void App_TaskIdleHook (void); + +void App_TaskReturnHook (OS_TCB *ptcb); + +void App_TaskStatHook (void); + +#if OS_TASK_SW_HOOK_EN > 0u +void App_TaskSwHook (void); +#endif + +void App_TCBInitHook (OS_TCB *ptcb); + +#if OS_TIME_TICK_HOOK_EN > 0u +void App_TimeTickHook (void); +#endif +#endif + +/* +********************************************************************************************************* +* FUNCTION PROTOTYPES +* +* IMPORTANT: These prototypes MUST be placed in OS_CPU.H +********************************************************************************************************* +*/ + +#if 0 +void OSStartHighRdy (void); +void OSIntCtxSw (void); +void OSCtxSw (void); +#endif + + +/* +********************************************************************************************************* +* LOOK FOR MISSING #define CONSTANTS +* +* This section is used to generate ERROR messages at compile time if certain #define constants are +* MISSING in OS_CFG.H. This allows you to quickly determine the source of the error. +* +* You SHOULD NOT change this section UNLESS you would like to add more comments as to the source of the +* compile time error. +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* EVENT FLAGS +********************************************************************************************************* +*/ + +#ifndef OS_FLAG_EN +#error "OS_CFG.H, Missing OS_FLAG_EN: Enable (1) or Disable (0) code generation for Event Flags" +#else + #ifndef OS_MAX_FLAGS + #error "OS_CFG.H, Missing OS_MAX_FLAGS: Max. number of Event Flag Groups in your application" + #else + #if OS_MAX_FLAGS > 65500u + #error "OS_CFG.H, OS_MAX_FLAGS must be <= 65500" + #endif + #endif + + #ifndef OS_FLAGS_NBITS + #error "OS_CFG.H, Missing OS_FLAGS_NBITS: Determine #bits used for event flags, MUST be either 8, 16 or 32" + #endif + + #ifndef OS_FLAG_WAIT_CLR_EN + #error "OS_CFG.H, Missing OS_FLAG_WAIT_CLR_EN: Include code for Wait on Clear EVENT FLAGS" + #endif + + #ifndef OS_FLAG_ACCEPT_EN + #error "OS_CFG.H, Missing OS_FLAG_ACCEPT_EN: Include code for OSFlagAccept()" + #endif + + #ifndef OS_FLAG_DEL_EN + #error "OS_CFG.H, Missing OS_FLAG_DEL_EN: Include code for OSFlagDel()" + #endif + + #ifndef OS_FLAG_NAME_EN + #error "OS_CFG.H, Missing OS_FLAG_NAME_EN: Enable flag group names" + #endif + + #ifndef OS_FLAG_QUERY_EN + #error "OS_CFG.H, Missing OS_FLAG_QUERY_EN: Include code for OSFlagQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MESSAGE MAILBOXES +********************************************************************************************************* +*/ + +#ifndef OS_MBOX_EN +#error "OS_CFG.H, Missing OS_MBOX_EN: Enable (1) or Disable (0) code generation for MAILBOXES" +#else + #ifndef OS_MBOX_ACCEPT_EN + #error "OS_CFG.H, Missing OS_MBOX_ACCEPT_EN: Include code for OSMboxAccept()" + #endif + + #ifndef OS_MBOX_DEL_EN + #error "OS_CFG.H, Missing OS_MBOX_DEL_EN: Include code for OSMboxDel()" + #endif + + #ifndef OS_MBOX_PEND_ABORT_EN + #error "OS_CFG.H, Missing OS_MBOX_PEND_ABORT_EN: Include code for OSMboxPendAbort()" + #endif + + #ifndef OS_MBOX_POST_EN + #error "OS_CFG.H, Missing OS_MBOX_POST_EN: Include code for OSMboxPost()" + #endif + + #ifndef OS_MBOX_POST_OPT_EN + #error "OS_CFG.H, Missing OS_MBOX_POST_OPT_EN: Include code for OSMboxPostOpt()" + #endif + + #ifndef OS_MBOX_QUERY_EN + #error "OS_CFG.H, Missing OS_MBOX_QUERY_EN: Include code for OSMboxQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MEMORY MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_MEM_EN +#error "OS_CFG.H, Missing OS_MEM_EN: Enable (1) or Disable (0) code generation for MEMORY MANAGER" +#else + #ifndef OS_MAX_MEM_PART + #error "OS_CFG.H, Missing OS_MAX_MEM_PART: Max. number of memory partitions" + #else + #if OS_MAX_MEM_PART > 65500u + #error "OS_CFG.H, OS_MAX_MEM_PART must be <= 65500" + #endif + #endif + + #ifndef OS_MEM_NAME_EN + #error "OS_CFG.H, Missing OS_MEM_NAME_EN: Enable memory partition names" + #endif + + #ifndef OS_MEM_QUERY_EN + #error "OS_CFG.H, Missing OS_MEM_QUERY_EN: Include code for OSMemQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MUTUAL EXCLUSION SEMAPHORES +********************************************************************************************************* +*/ + +#ifndef OS_MUTEX_EN +#error "OS_CFG.H, Missing OS_MUTEX_EN: Enable (1) or Disable (0) code generation for MUTEX" +#else + #ifndef OS_MUTEX_ACCEPT_EN + #error "OS_CFG.H, Missing OS_MUTEX_ACCEPT_EN: Include code for OSMutexAccept()" + #endif + + #ifndef OS_MUTEX_DEL_EN + #error "OS_CFG.H, Missing OS_MUTEX_DEL_EN: Include code for OSMutexDel()" + #endif + + #ifndef OS_MUTEX_QUERY_EN + #error "OS_CFG.H, Missing OS_MUTEX_QUERY_EN: Include code for OSMutexQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* MESSAGE QUEUES +********************************************************************************************************* +*/ + +#ifndef OS_Q_EN +#error "OS_CFG.H, Missing OS_Q_EN: Enable (1) or Disable (0) code generation for QUEUES" +#else + #ifndef OS_MAX_QS + #error "OS_CFG.H, Missing OS_MAX_QS: Max. number of queue control blocks" + #else + #if OS_MAX_QS > 65500u + #error "OS_CFG.H, OS_MAX_QS must be <= 65500" + #endif + #endif + + #ifndef OS_Q_ACCEPT_EN + #error "OS_CFG.H, Missing OS_Q_ACCEPT_EN: Include code for OSQAccept()" + #endif + + #ifndef OS_Q_DEL_EN + #error "OS_CFG.H, Missing OS_Q_DEL_EN: Include code for OSQDel()" + #endif + + #ifndef OS_Q_FLUSH_EN + #error "OS_CFG.H, Missing OS_Q_FLUSH_EN: Include code for OSQFlush()" + #endif + + #ifndef OS_Q_PEND_ABORT_EN + #error "OS_CFG.H, Missing OS_Q_PEND_ABORT_EN: Include code for OSQPendAbort()" + #endif + + #ifndef OS_Q_POST_EN + #error "OS_CFG.H, Missing OS_Q_POST_EN: Include code for OSQPost()" + #endif + + #ifndef OS_Q_POST_FRONT_EN + #error "OS_CFG.H, Missing OS_Q_POST_FRONT_EN: Include code for OSQPostFront()" + #endif + + #ifndef OS_Q_POST_OPT_EN + #error "OS_CFG.H, Missing OS_Q_POST_OPT_EN: Include code for OSQPostOpt()" + #endif + + #ifndef OS_Q_QUERY_EN + #error "OS_CFG.H, Missing OS_Q_QUERY_EN: Include code for OSQQuery()" + #endif +#endif + +/* +********************************************************************************************************* +* SEMAPHORES +********************************************************************************************************* +*/ + +#ifndef OS_SEM_EN +#error "OS_CFG.H, Missing OS_SEM_EN: Enable (1) or Disable (0) code generation for SEMAPHORES" +#else + #ifndef OS_SEM_ACCEPT_EN + #error "OS_CFG.H, Missing OS_SEM_ACCEPT_EN: Include code for OSSemAccept()" + #endif + + #ifndef OS_SEM_DEL_EN + #error "OS_CFG.H, Missing OS_SEM_DEL_EN: Include code for OSSemDel()" + #endif + + #ifndef OS_SEM_PEND_ABORT_EN + #error "OS_CFG.H, Missing OS_SEM_PEND_ABORT_EN: Include code for OSSemPendAbort()" + #endif + + #ifndef OS_SEM_QUERY_EN + #error "OS_CFG.H, Missing OS_SEM_QUERY_EN: Include code for OSSemQuery()" + #endif + + #ifndef OS_SEM_SET_EN + #error "OS_CFG.H, Missing OS_SEM_SET_EN: Include code for OSSemSet()" + #endif +#endif + +/* +********************************************************************************************************* +* TASK MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_MAX_TASKS +#error "OS_CFG.H, Missing OS_MAX_TASKS: Max. number of tasks in your application" +#else + #if OS_MAX_TASKS < 2u + #error "OS_CFG.H, OS_MAX_TASKS must be >= 2" + #endif + + #if OS_MAX_TASKS > ((OS_LOWEST_PRIO - OS_N_SYS_TASKS) + 1u) + #error "OS_CFG.H, OS_MAX_TASKS must be <= OS_LOWEST_PRIO - OS_N_SYS_TASKS + 1" + #endif + +#endif + +#if OS_LOWEST_PRIO > 254u +#error "OS_CFG.H, OS_LOWEST_PRIO must be <= 254 in V2.8x and higher" +#endif + +#ifndef OS_TASK_IDLE_STK_SIZE +#error "OS_CFG.H, Missing OS_TASK_IDLE_STK_SIZE: Idle task stack size" +#endif + +#ifndef OS_TASK_STAT_EN +#error "OS_CFG.H, Missing OS_TASK_STAT_EN: Enable (1) or Disable(0) the statistics task" +#endif + +#ifndef OS_TASK_STAT_STK_SIZE +#error "OS_CFG.H, Missing OS_TASK_STAT_STK_SIZE: Statistics task stack size" +#endif + +#ifndef OS_TASK_STAT_STK_CHK_EN +#error "OS_CFG.H, Missing OS_TASK_STAT_STK_CHK_EN: Check task stacks from statistics task" +#endif + +#ifndef OS_TASK_CHANGE_PRIO_EN +#error "OS_CFG.H, Missing OS_TASK_CHANGE_PRIO_EN: Include code for OSTaskChangePrio()" +#endif + +#ifndef OS_TASK_CREATE_EN +#error "OS_CFG.H, Missing OS_TASK_CREATE_EN: Include code for OSTaskCreate()" +#endif + +#ifndef OS_TASK_CREATE_EXT_EN +#error "OS_CFG.H, Missing OS_TASK_CREATE_EXT_EN: Include code for OSTaskCreateExt()" +#else + #if (OS_TASK_CREATE_EXT_EN == 0u) && (OS_TASK_CREATE_EN == 0u) + #error "OS_CFG.H, OS_TASK_CREATE_EXT_EN or OS_TASK_CREATE_EN must be Enable (1)" + #endif +#endif + +#ifndef OS_TASK_DEL_EN +#error "OS_CFG.H, Missing OS_TASK_DEL_EN: Include code for OSTaskDel()" +#endif + +#ifndef OS_TASK_NAME_EN +#error "OS_CFG.H, Missing OS_TASK_NAME_EN: Enable task names" +#endif + +#ifndef OS_TASK_SUSPEND_EN +#error "OS_CFG.H, Missing OS_TASK_SUSPEND_EN: Include code for OSTaskSuspend() and OSTaskResume()" +#endif + +#ifndef OS_TASK_QUERY_EN +#error "OS_CFG.H, Missing OS_TASK_QUERY_EN: Include code for OSTaskQuery()" +#endif + +#ifndef OS_TASK_REG_TBL_SIZE +#error "OS_CFG.H, Missing OS_TASK_REG_TBL_SIZE: Include code for task specific registers" +#else + #if OS_TASK_REG_TBL_SIZE > 255u + #error "OS_CFG.H, OS_TASK_REG_TBL_SIZE must be <= 255" + #endif +#endif + +/* +********************************************************************************************************* +* TIME MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_TICKS_PER_SEC +#error "OS_CFG.H, Missing OS_TICKS_PER_SEC: Sets the number of ticks in one second" +#endif + +#ifndef OS_TIME_DLY_HMSM_EN +#error "OS_CFG.H, Missing OS_TIME_DLY_HMSM_EN: Include code for OSTimeDlyHMSM()" +#endif + +#ifndef OS_TIME_DLY_RESUME_EN +#error "OS_CFG.H, Missing OS_TIME_DLY_RESUME_EN: Include code for OSTimeDlyResume()" +#endif + +#ifndef OS_TIME_GET_SET_EN +#error "OS_CFG.H, Missing OS_TIME_GET_SET_EN: Include code for OSTimeGet() and OSTimeSet()" +#endif + +/* +********************************************************************************************************* +* TIMER MANAGEMENT +********************************************************************************************************* +*/ + +#ifndef OS_TMR_EN +#error "OS_CFG.H, Missing OS_TMR_EN: When (1) enables code generation for Timer Management" +#elif OS_TMR_EN > 0u + #if OS_SEM_EN == 0u + #error "OS_CFG.H, Semaphore management is required (set OS_SEM_EN to 1) when enabling Timer Management." + #error " Timer management require TWO semaphores." + #endif + + #ifndef OS_TMR_CFG_MAX + #error "OS_CFG.H, Missing OS_TMR_CFG_MAX: Determines the total number of timers in an application (2 .. 65500)" + #else + #if OS_TMR_CFG_MAX < 2u + #error "OS_CFG.H, OS_TMR_CFG_MAX should be between 2 and 65500" + #endif + + #if OS_TMR_CFG_MAX > 65500u + #error "OS_CFG.H, OS_TMR_CFG_MAX should be between 2 and 65500" + #endif + #endif + + #ifndef OS_TMR_CFG_WHEEL_SIZE + #error "OS_CFG.H, Missing OS_TMR_CFG_WHEEL_SIZE: Sets the size of the timer wheel (1 .. 1023)" + #else + #if OS_TMR_CFG_WHEEL_SIZE < 2u + #error "OS_CFG.H, OS_TMR_CFG_WHEEL_SIZE should be between 2 and 1024" + #endif + + #if OS_TMR_CFG_WHEEL_SIZE > 1024u + #error "OS_CFG.H, OS_TMR_CFG_WHEEL_SIZE should be between 2 and 1024" + #endif + #endif + + #ifndef OS_TMR_CFG_NAME_EN + #error "OS_CFG.H, Missing OS_TMR_CFG_NAME_EN: Enable Timer names" + #endif + + #ifndef OS_TMR_CFG_TICKS_PER_SEC + #error "OS_CFG.H, Missing OS_TMR_CFG_TICKS_PER_SEC: Determines the rate at which the timer management task will run (Hz)" + #endif + + #ifndef OS_TASK_TMR_STK_SIZE + #error "OS_CFG.H, Missing OS_TASK_TMR_STK_SIZE: Determines the size of the Timer Task's stack" + #endif +#endif + + +/* +********************************************************************************************************* +* MISCELLANEOUS +********************************************************************************************************* +*/ + +#ifndef OS_ARG_CHK_EN +#error "OS_CFG.H, Missing OS_ARG_CHK_EN: Enable (1) or Disable (0) argument checking" +#endif + + +#ifndef OS_CPU_HOOKS_EN +#error "OS_CFG.H, Missing OS_CPU_HOOKS_EN: uC/OS-II hooks are found in the processor port files when 1" +#endif + + +#ifndef OS_APP_HOOKS_EN +#error "OS_CFG.H, Missing OS_APP_HOOKS_EN: Application-defined hooks are called from the uC/OS-II hooks" +#endif + + +#ifndef OS_DEBUG_EN +#error "OS_CFG.H, Missing OS_DEBUG_EN: Allows you to include variables for debugging or not" +#endif + + +#ifndef OS_LOWEST_PRIO +#error "OS_CFG.H, Missing OS_LOWEST_PRIO: Defines the lowest priority that can be assigned" +#endif + + +#ifndef OS_MAX_EVENTS +#error "OS_CFG.H, Missing OS_MAX_EVENTS: Max. number of event control blocks in your application" +#else + #if OS_MAX_EVENTS > 65500u + #error "OS_CFG.H, OS_MAX_EVENTS must be <= 65500" + #endif +#endif + + +#ifndef OS_SCHED_LOCK_EN +#error "OS_CFG.H, Missing OS_SCHED_LOCK_EN: Include code for OSSchedLock() and OSSchedUnlock()" +#endif + + +#ifndef OS_EVENT_MULTI_EN +#error "OS_CFG.H, Missing OS_EVENT_MULTI_EN: Include code for OSEventPendMulti()" +#endif + + +#ifndef OS_TASK_PROFILE_EN +#error "OS_CFG.H, Missing OS_TASK_PROFILE_EN: Include data structure for run-time task profiling" +#endif + + +#ifndef OS_TASK_SW_HOOK_EN +#error "OS_CFG.H, Missing OS_TASK_SW_HOOK_EN: Allows you to include the code for OSTaskSwHook() or not" +#endif + + +#ifndef OS_TICK_STEP_EN +#error "OS_CFG.H, Missing OS_TICK_STEP_EN: Allows to 'step' one tick at a time with uC/OS-View" +#endif + + +#ifndef OS_TIME_TICK_HOOK_EN +#error "OS_CFG.H, Missing OS_TIME_TICK_HOOK_EN: Allows you to include the code for OSTimeTickHook() or not" +#endif + +/* +********************************************************************************************************* +* SAFETY CRITICAL USE +********************************************************************************************************* +*/ + +#ifdef SAFETY_CRITICAL_RELEASE + +#if OS_ARG_CHK_EN < 1u +#error "OS_CFG.H, OS_ARG_CHK_EN must be enabled for safety-critical release code" +#endif + +#if OS_APP_HOOKS_EN > 0u +#error "OS_CFG.H, OS_APP_HOOKS_EN must be disabled for safety-critical release code" +#endif + +#if OS_DEBUG_EN > 0u +#error "OS_CFG.H, OS_DEBUG_EN must be disabled for safety-critical release code" +#endif + +#ifdef CANTATA +#error "OS_CFG.H, CANTATA must be disabled for safety-critical release code" +#endif + +#if OS_TMR_EN < 1u + #if OS_SCHED_LOCK_EN > 0u + #error "OS_CFG.H, OS_SCHED_LOCK_EN must be disabled for safety-critical release code if OS_TMR_EN is disabled" + #endif +#endif + +#ifdef VSC_VALIDATION_MODE +#error "OS_CFG.H, VSC_VALIDATION_MODE must be disabled for safety-critical release code" +#endif + +#if OS_TASK_STAT_EN > 0u +#error "OS_CFG.H, OS_TASK_STAT_EN must be disabled for safety-critical release code" +#endif + +#if OS_TICK_STEP_EN > 0u +#error "OS_CFG.H, OS_TICK_STEP_EN must be disabled for safety-critical release code" +#endif + +#if OS_FLAG_EN > 0u + #if OS_FLAG_DEL_EN > 0 + #error "OS_CFG.H, OS_FLAG_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_MBOX_EN > 0u + #if OS_MBOX_DEL_EN > 0u + #error "OS_CFG.H, OS_MBOX_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_MUTEX_EN > 0u + #if OS_MUTEX_DEL_EN > 0u + #error "OS_CFG.H, OS_MUTEX_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_Q_EN > 0u + #if OS_Q_DEL_EN > 0u + #error "OS_CFG.H, OS_Q_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_SEM_EN > 0u + #if OS_SEM_DEL_EN > 0u + #error "OS_CFG.H, OS_SEM_DEL_EN must be disabled for safety-critical release code" + #endif +#endif + +#if OS_TASK_DEL_EN > 0u +#error "OS_CFG.H, OS_TASK_DEL_EN must be disabled for safety-critical release code" +#endif + +#if OS_CRITICAL_METHOD != 3u +#error "OS_CPU.H, OS_CRITICAL_METHOD must be type 3 for safety-critical release code" +#endif + +#endif /* ------------------------ SAFETY_CRITICAL_RELEASE ------------------------ */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/TLS/CCES/os_tls.c b/TLS/CCES/os_tls.c new file mode 100644 index 0000000..303852c --- /dev/null +++ b/TLS/CCES/os_tls.c @@ -0,0 +1,425 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* THREAD LOCAL STORAGE (TLS) MANAGEMENT +* Cross Core Embedded Studio (CCES) IMPLEMENTATION +* +* Filename : os_tls.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define MICRIUM_SOURCE +#include + +#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES +const char *os_tls__c = "$Id: $"; +#endif + +#if OS_TASK_CREATE_EXT_EN > 0u +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) + +/* +************************************************************************************************************************ +* LOCAL VARIABLES +************************************************************************************************************************ +*/ + +static OS_TLS_ID OS_TLS_NextAvailID; /* Next available TLS ID */ +static OS_TLS_DESTRUCT_PTR OS_TLS_DestructPtrTbl[OS_TLS_TBL_SIZE]; + +/* +************************************************************************************************************************ +* ALLOCATE THE NEXT AVAILABLE TLS ID +* +* Description: This function is called to obtain the ID of the next free TLS (Task Local Storage) register 'id' +* +* Arguments : perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_TLS_NO_MORE_AVAIL if you are attempting to assign more TLS than you declared +* available through OS_TLS_TBL_SIZE. +* +* Returns : The next available TLS 'id' or OS_TLS_TBL_SIZE if an error is detected. +************************************************************************************************************************ +*/ + +OS_TLS_ID OS_TLS_GetID (INT8U *perr) +{ + OS_TLS_ID id; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_TLS_ID)OS_TLS_TBL_SIZE); + } +#endif + + OS_ENTER_CRITICAL(); + if (OS_TLS_NextAvailID >= OS_TLS_TBL_SIZE) { /* See if we exceeded the number of IDs available */ + *perr = OS_ERR_TLS_NO_MORE_AVAIL; /* Yes, cannot allocate more TLS */ + OS_EXIT_CRITICAL(); + return ((OS_TLS_ID)OS_TLS_TBL_SIZE); + } + + id = OS_TLS_NextAvailID; + OS_TLS_NextAvailID++; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (id); +} + +/* +************************************************************************************************************************ +* GET THE CURRENT VALUE OF A TLS REGISTER +* +* Description: This function is called to obtain the current value of a TLS register +* +* Arguments : ptcb is a pointer to the OS_TCB of the task you want to read the TLS register from. If 'ptcb' is +* a NULL pointer then you will get the TLS register of the current task. +* +* id is the 'id' of the desired TLS register. Note that the 'id' must be less than +* 'OS_TLS_NextAvailID' +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_OS_NOT_RUNNING if the kernel has not started yet +* OS_ERR_TLS_ID_INVALID if the 'id' is greater or equal to OS_TLS_NextAvailID +* OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not +* needed for the task +* +* Returns : The current value of the task's TLS register or 0 if an error is detected. +* +* Note(s) : 1) ptcb->OSTCBOpt contains options passed to OSTaskCreateExt(). One of these options (OS_OPT_TASK_NO_TLS) +* is used to specify that the user doesn't want TLS support for the task being created. In other words, +* by default, TLS support is enabled if OS_TLS_TBL_SIZE is defined and > 0 so the user must +* specifically indicate that he/she doesn't want TLS supported for a task. +************************************************************************************************************************ +*/ + +OS_TLS OS_TLS_GetValue (OS_TCB *ptcb, + OS_TLS_ID id, + INT8U *perr) +{ + OS_TLS value; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_TLS)0); + } +#endif + + +#if OS_ARG_CHK_EN > 0u + if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */ + *perr = OS_ERR_TLS_ID_INVALID; + return ((OS_TLS)0); + } +#endif + + OS_ENTER_CRITICAL(); + if (ptcb == (OS_TCB *)0) { /* Does caller want to use current task's TCB? */ + ptcb = OSTCBCur; /* Yes */ + if (OSTCBCur == (OS_TCB *)0) { /* Is the kernel running? */ + OS_EXIT_CRITICAL(); /* No, then caller cannot specify NULL */ + *perr = OS_ERR_OS_NOT_RUNNING; + return ((OS_TLS)0); + } + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) {/* See if TLS is available for this task */ + value = ptcb->OSTCBTLSTbl[id]; /* Yes */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return ((OS_TLS)value); + } else { + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TLS_NOT_EN; + return ((OS_TLS)0); + } +} + +/* +************************************************************************************************************************ +* DEFINE TLS DESTRUCTOR FUNCTION +* +* Description: This function is called by the user to assign a 'destructor' function to a specific TLS. When a task is +* deleted, all the destructors are called for all the task's TLS for which there is a destructor function +* defined. In other when a task is deleted, all the non-NULL functions present in OS_TLS_DestructPtrTbl[] +* will be called. +* +* Arguments : id is the ID of the TLS destructor to set +* +* pdestruct is a pointer to a function that is associated with a specific TLS register and is called when +* a task is deleted. The prototype of such functions is: +* +* void MyDestructFunction (OS_TCB *ptcb, +* OS_TLS_ID id, +* OS_TLS value); +* +* you can specify a NULL pointer if you don't want to have a fucntion associated with a TLS +* register. A NULL pointer (i.e. no function associated with a TLS register) is the default +* value placed in OS_TLS_DestructPtrTbl[]. +* +* perr is a pointer to an error return code. The possible values are: +* +* OS_ERR_NONE The call was successful. +* OS_ERR_TLS_ID_INVALID You you specified an invalid TLS ID +* OS_ERR_TLS_DESTRUCT_ASSIGNED If a destructor has already been assigned to the TLS ID +* +* Returns : none +* +* Note : none +************************************************************************************************************************ +*/ + +void OS_TLS_SetDestruct (OS_TLS_ID id, + OS_TLS_DESTRUCT_PTR pdestruct, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + + if (id >= OS_TLS_NextAvailID) { /* See if we exceeded the number of TLS IDs available */ + *perr = OS_ERR_TLS_ID_INVALID; + return; + } + + if (OS_TLS_DestructPtrTbl[id] != (OS_TLS_DESTRUCT_PTR)0) { /* Can only assign a destructor once */ + *perr = OS_ERR_TLS_DESTRUCT_ASSIGNED; + return; + } + + OS_ENTER_CRITICAL(); + OS_TLS_DestructPtrTbl[id] = pdestruct; + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; +} + +/* +************************************************************************************************************************ +* SET THE CURRENT VALUE OF A TASK TLS REGISTER +* +* Description: This function is called to change the current value of a task TLS register. +* +* Arguments : ptcb is a pointer to the OS_TCB of the task you want to set the task's TLS register for. If 'ptcb' +* is a NULL pointer then you will change the TLS register of the current task. +* +* id is the 'id' of the desired task TLS register. Note that the 'id' must be less than +* 'OS_TLS_NextAvailID' +* +* value is the desired value for the task TLS register. +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_OS_NOT_RUNNING if the kernel has not started yet +* OS_ERR_TLS_ID_INVALID if you specified an invalid TLS ID +* OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not +* needed for the task +* +* Returns : none +* +* Note(s) : 1) ptcb->OSTCBOpt contains options passed to OSTaskCreateExt(). One of these options (OS_TASK_OPT_NO_TLS) is +* used to specify that the user doesn't want TLS support for the task being created. In other words, +* by default, TLS support is enabled if OS_TLS_TBL_SIZE is defined and > 0 so the user must +* specifically indicate that he/she doesn't want TLS supported for a task. +************************************************************************************************************************ +*/ + +void OS_TLS_SetValue (OS_TCB *ptcb, + OS_TLS_ID id, + OS_TLS value, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */ + *perr = OS_ERR_TLS_ID_INVALID; + return; + } +#endif + + OS_ENTER_CRITICAL(); /* Does caller want to use current task's TCB? */ + if (ptcb == (OS_TCB *)0) { /* Yes */ + ptcb = OSTCBCur; /* Is the kernel running? */ + if (OSTCBCur == (OS_TCB *)0) { /* No, then caller cannot specify NULL */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_OS_NOT_RUNNING; + return; + } + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + ptcb->OSTCBTLSTbl[id] = value; /* Yes */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + } else { + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TLS_NOT_EN; + } +} + +/* +************************************************************************************************************************ +************************************************************************************************************************ +* uC/OS-III INTERNAL FUNCTIONS +* DO NOT CALL FROM THE APPLICATION CODE +************************************************************************************************************************ +************************************************************************************************************************ +*/ + +/* +************************************************************************************************************************ +* INITIALIZE THE TASK LOCAL STORAGE SERVICES +* +* Description: This function is called by uC/OS-III to initialize the TLS id allocator. +* +* This function also initializes an array containing function pointers. There is one function associated +* to each task TLS register and all the functions (assuming non-NULL) will be called when the task is +* deleted. +* +* Arguments : perr is a pointer to an error return value. Current error can be: +* +* OS_ERR_NONE if the call was successful +* +* Returns : none +* +* Note : This function is INTERNAL to uC/OS-III and your application should not call it. +************************************************************************************************************************ +*/ + +void OS_TLS_Init (INT8U *perr) +{ + OS_TLS_ID i; + + + + OS_TLS_NextAvailID = 0u; + + for (i = 0u; i < OS_TLS_TBL_SIZE; i++) { + OS_TLS_DestructPtrTbl[i] = (OS_TLS_DESTRUCT_PTR)0; + } + *perr = OS_ERR_NONE; +} + +/* +************************************************************************************************************************ +* TASK CREATE HOOK +* +* Description: This function is called by OSTaskCreateExt() +* +* Arguments : ptcb is a pointer to the OS_TCB of the task being created. +* +* Returns : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it. +* +* 2) OSTaskCreateExt() clears all entries in ptcb->OSTCBTLSTbl[] before calling OS_TLS_TaskCreate() so no +* need to this here. +************************************************************************************************************************ +*/ + +void OS_TLS_TaskCreate (OS_TCB *ptcb) +{ + (void)&ptcb; +} + +/* +************************************************************************************************************************ +* TASK DELETE HOOK +* +* Description: This function is called by OSTaskDel() +* +* Arguments : ptcb is a pointer to the OS_TCB of the task being deleted. +* +* Returns : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it. +************************************************************************************************************************ +*/ + +void OS_TLS_TaskDel (OS_TCB *ptcb) +{ + OS_TLS_ID id; + OS_TLS_DESTRUCT_PTR *p_tbl; + + + for (id = 0; id < OS_TLS_NextAvailID; id++) { /* Call all the destructors associated with the TLS IDs */ + p_tbl = &OS_TLS_DestructPtrTbl[id]; + if (*p_tbl != (OS_TLS_DESTRUCT_PTR)0) { + (*p_tbl)(ptcb, id, ptcb->OSTCBTLSTbl[id]); + } + } +} + +/* +************************************************************************************************************************ +* TASK SWITCH HOOK +* +* Description: This function is called by OSSched() and OSIntExit() just prior to calling the context switch code +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it. +* +* 2) It's assumed that OSTCBCur points to the task being switched out and OSTCBHighRdyPtr points to the +* task being switched in. +************************************************************************************************************************ +*/ + +void OS_TLS_TaskSw (void) +{ +} +#endif +#endif + diff --git a/TLS/IAR/os_tls.c b/TLS/IAR/os_tls.c new file mode 100644 index 0000000..c647c56 --- /dev/null +++ b/TLS/IAR/os_tls.c @@ -0,0 +1,822 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* THREAD LOCAL STORAGE (TLS) MANAGEMENT +* IAR IMPLEMENTATION +* +* Filename : os_tls.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define MICRIUM_SOURCE +#include +#include +#include +#include + + +#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES +const char *os_tls__c = "$Id: $"; +#endif + +#if defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u) +#if OS_TASK_CREATE_EXT_EN > 0u + +/* +************************************************************************************************************************ +* LOCAL DEFINES +************************************************************************************************************************ +*/ + + +#if (_DLIB_FILE_DESCRIPTOR > 0) && (_FILE_OP_LOCKS > 0) +#define OS_TLS_LOCK_MAX ((_MAX_LOCK) + (FOPEN_MAX)) /* _MAX_LOCK and _FOPEN_MAX defined by IAR */ +#else +#define OS_TLS_LOCK_MAX (_MAX_LOCK) +#endif + +/* +************************************************************************************************************************ +* LOCAL DATA TYPES +************************************************************************************************************************ +*/ + +typedef struct os_tls_lock OS_TLS_LOCK; + + +struct os_tls_lock { + OS_EVENT *Sem; /* OS semaphore object. */ + OS_TLS_LOCK *NextPtr; /* Pointer to the next object in the pool. */ +}; + +/* +************************************************************************************************************************ +* LOCAL VARIABLES +************************************************************************************************************************ +*/ + +static INT8U OS_TLS_NextAvailID; /* Next available TLS ID */ + +static OS_TLS_ID OS_TLS_LibID; /* ID used to store library space pointer */ + +static OS_TLS_LOCK OS_TLS_LockPoolTbl[OS_TLS_LOCK_MAX]; +static OS_TLS_LOCK *OS_TLS_LockPoolListPtr = (OS_TLS_LOCK *)0; /* Pointer to head of 'OS_TLS_LOCK' list */ + +/* +************************************************************************************************************************ +* LOCAL FUNCTIONS +************************************************************************************************************************ +*/ + +static void OS_TLS_LockCreate (void **p_lock); +static void OS_TLS_LockDel (void *p_lock); +static void OS_TLS_LockAcquire (void *p_lock); +static void OS_TLS_LockRelease (void *p_lock); + +/* +************************************************************************************************************************ +* ALLOCATE THE NEXT AVAILABLE TLS ID +* +* Description: This function is called to obtain the ID of the next free TLS (Task Local Storage) register 'id' +* +* Arguments : perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_TLS_NO_MORE_AVAIL if you are attempting to assign more TLS than you declared +* available through OS_TLS_TBL_SIZE. +* +* Returns : The next available TLS 'id' or OS_TLS_TBL_SIZE if an error is detected. +************************************************************************************************************************ +*/ + +OS_TLS_ID OS_TLS_GetID (INT8U *perr) +{ + OS_TLS_ID id; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_TLS_ID)OS_TLS_TBL_SIZE); + } +#endif + + OS_ENTER_CRITICAL(); + if (OS_TLS_NextAvailID >= OS_TLS_TBL_SIZE) { /* See if we exceeded the number of IDs available */ + *perr = OS_ERR_TLS_NO_MORE_AVAIL; /* Yes, cannot allocate more TLS */ + OS_EXIT_CRITICAL(); + return ((OS_TLS_ID)OS_TLS_TBL_SIZE); + } + + id = OS_TLS_NextAvailID; /* Assign the next available ID */ + OS_TLS_NextAvailID++; /* Increment available ID for next request */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (id); +} + +/* +************************************************************************************************************************ +* GET THE CURRENT VALUE OF A TLS REGISTER +* +* Description: This function is called to obtain the current value of a TLS register +* +* Arguments : ptcb is a pointer to the OS_TCB of the task you want to read the TLS register from. If 'ptcb' is +* a NULL pointer then you will get the TLS register of the current task. +* +* id is the 'id' of the desired TLS register. Note that the 'id' must be less than +* 'OS_TLS_NextAvailID' +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_OS_NOT_RUNNING if the kernel has not started yet +* OS_ERR_TLS_ID_INVALID if the 'id' is greater or equal to OS_TLS_NextAvailID +* OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not +* needed for the task +* +* Returns : The current value of the task's TLS register or 0 if an error is detected. +* +* Note(s) : 1) ptcb->OSTCBOpt contains options passed to OSTaskCreate(). One of these options (OS_TASK_OPT_NO_TLS) +* is used to specify that the user doesn't want TLS support for the task being created. In other words, +* by default, TLS support is enabled if OS_TLS_TBL_SIZE is defined and > 0 so the user must +* specifically indicate that he/she doesn't want TLS supported for a task. +************************************************************************************************************************ +*/ + +OS_TLS OS_TLS_GetValue (OS_TCB *ptcb, + OS_TLS_ID id, + INT8U *perr) +{ + OS_TLS value; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_TLS)0); + } +#endif + + +#if OS_ARG_CHK_EN > 0u + if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */ + *perr = OS_ERR_TLS_ID_INVALID; + return ((OS_TLS)0); + } +#endif + + OS_ENTER_CRITICAL(); + if (ptcb == (OS_TCB *)0) { /* Does caller want to use current task's TCB? */ + ptcb = OSTCBCur; /* Yes */ + if (OSTCBCur == (OS_TCB *)0) { /* Is the kernel running? */ + OS_EXIT_CRITICAL(); /* No, then caller cannot specify NULL */ + *perr = OS_ERR_OS_NOT_RUNNING; + return ((OS_TLS)0); + } + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + value = ptcb->OSTCBTLSTbl[id]; /* Yes */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return ((OS_TLS)value); + } else { + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TLS_NOT_EN; + return ((OS_TLS)0); + } +} + +/* +************************************************************************************************************************ +* DEFINE TLS DESTRUCTOR FUNCTION +* +* Description: This function is called by the user to assign a 'destructor' function to a specific TLS. When a task is +* deleted, all the destructors are called for all the task's TLS for which there is a destructor function +* defined. In other when a task is deleted, all the non-NULL functions present in OS_TLS_DestructPtrTbl[] +* will be called. +* +* Arguments : id is the ID of the TLS destructor to set +* +* pdestruct is a pointer to a function that is associated with a specific TLS register and is called when +* a task is deleted. The prototype of such functions is: +* +* void MyDestructFunction (OS_TCB *ptcb, +* OS_TLS_ID id, +* OS_TLS value); +* +* you can specify a NULL pointer if you don't want to have a fucntion associated with a TLS +* register. A NULL pointer (i.e. no function associated with a TLS register) is the default +* value placed in OS_TLS_DestructPtrTbl[]. +* +* perr is a pointer to an error return code. The possible values are: +* +* OS_ERR_NONE The call was successful. +* OS_ERR_TLS_ID_INVALID You you specified an invalid TLS ID +* +* Returns : none +* +* Note : none +************************************************************************************************************************ +*/ + +void OS_TLS_SetDestruct (OS_TLS_ID id, + OS_TLS_DESTRUCT_PTR pdestruct, + INT8U *perr) +{ + *perr = OS_ERR_NONE; +} + +/* +************************************************************************************************************************ +* SET THE CURRENT VALUE OF A TASK TLS REGISTER +* +* Description: This function is called to change the current value of a task TLS register. +* +* Arguments : ptcb is a pointer to the OS_TCB of the task you want to set the task's TLS register for. If 'ptcb' +* is a NULL pointer then you will change the TLS register of the current task. +* +* id is the 'id' of the desired task TLS register. Note that the 'id' must be less than +* 'OS_TLS_NextAvailID' +* +* value is the desired value for the task TLS register. +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_OS_NOT_RUNNING if the kernel has not started yet +* OS_ERR_TLS_ID_INVALID if you specified an invalid TLS ID +* OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not +* needed for the task +* +* Returns : none +* +* Note(s) : 1) ptcb->OSTCBOpt contains options passed to OSTaskCreate(). One of these options (OS_TASK_OPT_NO_TLS) +* is used to specify that the user doesn't want TLS support for the task being created. In other words, +* by default, TLS support is enabled if OS_TLS_TBL_SIZE is defined and > 0 so the user must +* specifically indicate that he/she doesn't want TLS supported for a task. +************************************************************************************************************************ +*/ + +void OS_TLS_SetValue (OS_TCB *ptcb, + OS_TLS_ID id, + OS_TLS value, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */ + *perr = OS_ERR_TLS_ID_INVALID; + return; + } +#endif + + OS_ENTER_CRITICAL(); /* Does caller want to use current task's TCB? */ + if (ptcb == (OS_TCB *)0) { /* Yes */ + ptcb = OSTCBCur; /* Is the kernel running? */ + if (OSTCBCur == (OS_TCB *)0) { /* No, then caller cannot specify NULL */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_OS_NOT_RUNNING; + return; + } + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + ptcb->OSTCBTLSTbl[id] = value; /* Yes */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + } else { + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TLS_NOT_EN; + } +} + +/* +************************************************************************************************************************ +************************************************************************************************************************ +* uC/OS-III INTERNAL FUNCTIONS +* DO NOT CALL FROM THE APPLICATION CODE +************************************************************************************************************************ +************************************************************************************************************************ +*/ + +/* +************************************************************************************************************************ +* INITIALIZE THE TASK LOCAL STORAGE SERVICES +* +* Description: This function is called by uC/OS-III to initialize the TLS id allocator. +* +* This function also initializes an array containing function pointers. There is one function associated +* to each task TLS register and all the functions (assuming non-NULL) will be called when the task is +* deleted. +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it. +************************************************************************************************************************ +*/ + +void OS_TLS_Init (INT8U *perr) +{ + INT16U ix; + OS_TLS_LOCK *p_lock; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + + OS_TLS_NextAvailID = 0u; + OS_TLS_LibID = OS_TLS_GetID(perr); + + OS_ENTER_CRITICAL(); + /* Create the link list of OS_TLS_LOCK objects. */ + for (ix = 0u; ix < (OS_TLS_LOCK_MAX - 1u); ix++) { + p_lock = &OS_TLS_LockPoolTbl[ix]; + p_lock->NextPtr = &OS_TLS_LockPoolTbl[ix + 1u]; + } + + p_lock = &OS_TLS_LockPoolTbl[OS_TLS_LOCK_MAX - 1u]; + p_lock->NextPtr = (OS_TLS_LOCK *)0; /* Last node points to 'NULL' */ + + OS_TLS_LockPoolListPtr = &OS_TLS_LockPoolTbl[0]; /* Initialize the list head pointer. */ + + OS_EXIT_CRITICAL(); +} + +/* +************************************************************************************************************************ +* TASK CREATE HOOK +* +* Description: This function is called by OSTaskCreate() +* +* Arguments : ptcb is a pointer to the OS_TCB of the task being created. +* +* Returns : none +* +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it. +* +* 2) OSTaskCreate() clears all entries in ptcb->OSTCBTLSTbl[] before calling OS_TLS_TaskCreate() so no need +* to this here. +************************************************************************************************************************ +*/ + +void OS_TLS_TaskCreate (OS_TCB *ptcb) +{ + OS_TLS p_tls; + + + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + /* Get TLS segment from the HEAP. */ + p_tls = (OS_TLS)__iar_dlib_perthread_allocate(); + __iar_dlib_perthread_initialize(p_tls); /* Initialize the TLS segment. */ + ptcb->OSTCBTLSTbl[OS_TLS_LibID] = p_tls; /* Set the TLS segment pointer in the task. */ + } +} + +/* +************************************************************************************************************************ +* TASK DELETE HOOK +* +* Description: This function is called by OSTaskDel() +* +* Arguments : ptcb is a pointer to the OS_TCB of the task being deleted. +* +* Returns : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it. +************************************************************************************************************************ +*/ + +void OS_TLS_TaskDel (OS_TCB *ptcb) +{ + OS_TLS p_tls; + + + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + p_tls = ptcb->OSTCBTLSTbl[OS_TLS_LibID]; + __iar_dlib_perthread_destroy(); + __iar_dlib_perthread_deallocate((void *)p_tls); /* De-allocate the TLS segment. */ + ptcb->OSTCBTLSTbl[OS_TLS_LibID] = (OS_TLS)0; /* Remove the TLS segment pointer from the task. */ + } +} + +/* +************************************************************************************************************************ +* TASK SWITCH HOOK +* +* Description: This function is called by OSSched() and OSIntExit() just prior to calling the context switch code +* +* Arguments : none +* +* Returns : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it. +* +* 2) It's assumed that OSTCBCur points to the task being switched out and OSTCBHighRdy points to the +* task being switched in. +************************************************************************************************************************ +*/ + +void OS_TLS_TaskSw (void) +{ + if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + } +} + +/* +************************************************************************************************************************ +************************************************************************************************************************ +* uC/OS-III MUTEX IMPLEMENTATION +************************************************************************************************************************ +************************************************************************************************************************ +*/ + +/* +************************************************************************************************************************ +* OS LOCK CREATE +* +* Description : Allocate a new 'OS_TLS_LOCK' object from the free pool and create a 'OS_SEM' in the kernel. +* +* Argument(s) : p_lock Pointer to the DLIB lock handler. +* +* Return(s) : None. +* +* Note(s) : None. +************************************************************************************************************************ +*/ + +static void OS_TLS_LockCreate (void **p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + OS_EVENT *psem; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + if (p_lock == (void **)0) { + return; + } + + if (OS_TLS_LockPoolListPtr == (OS_TLS_LOCK *)0) { /* If 'OS_TLS_LOCK' object pool is empty? */ + *p_lock = (void *)0; /* return a 'NULL' pointer. */ + return; + } + + p_tls_lock = OS_TLS_LockPoolListPtr; /* Get the first object in the list. */ + + psem = OSSemCreate(1); /* Create the semaphore in the kernel. */ + + if (psem == (OS_EVENT *)0) { /* If the semaphore create funtion failed ... */ + *p_lock = (void *)0; /* ... return a 'NULL' pointer. */ + return; + } + + p_tls_lock->Sem = psem; + + OS_ENTER_CRITICAL(); + OS_TLS_LockPoolListPtr = p_tls_lock->NextPtr; /* Move HEAD pointer to the next object in the list.*/ + OS_EXIT_CRITICAL(); + + *p_lock = (void *)p_tls_lock; /* Return the new 'OS_TLS_LOCK' object pointer. */ +} + + +/* +************************************************************************************************************************ +* OS LOCK DELETE +* +* Description : Delete a 'OS_MUTEX' from the kernel and return the allocated 'OS_TLS_LOCK' +* to the free pool. +* +* Argument(s) : p_lock DLIB lock handler. +* +* Return(s) : Return the current task TLS pointer. +* +* Note(s) : None. +************************************************************************************************************************ +*/ + +static void OS_TLS_LockDel (void *p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + INT8U err; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + if (p_lock == (void *)0) { + return; + } + + p_tls_lock = (OS_TLS_LOCK *)p_lock; + + (void)OSSemDel(p_tls_lock->Sem, + OS_DEL_ALWAYS, + &err); + + OS_ENTER_CRITICAL(); + /* Return the OS_TLS_LOCK in front of the list */ + if (OS_TLS_LockPoolListPtr == (OS_TLS_LOCK *)0) { + p_tls_lock->NextPtr = (OS_TLS_LOCK *)0; + } else { + p_tls_lock->NextPtr = OS_TLS_LockPoolListPtr; + } + OS_TLS_LockPoolListPtr = p_tls_lock; + + OS_EXIT_CRITICAL(); +} + + +/* +************************************************************************************************************************ +* OS LOCK PEND +* +* Description : Wait indefinitely until the lock become available +* +* Arguments : p_lock DLIB lock handler. +* +* Return(s) : Return the current task TLS pointer. +* +* Note(s) : None. +************************************************************************************************************************ +*/ + +static void OS_TLS_LockAcquire (void *p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + INT8U err; + + + if ((p_lock == (void *)0 ) || /* Return if the lock handler is 'NULL' or the ... */ + (OSRunning != OS_TRUE)) { /* ... kernel is not running. */ + return; + } + + p_tls_lock = (OS_TLS_LOCK *)p_lock; + OSSemPend(p_tls_lock->Sem, + 0u, + &err); +} + + +/* +************************************************************************************************************************ +* OS LOCK POST +* +* Description : Signal the lock. +* +* Argument(s) : p_lock DLIB lock handler. +* +* Return(s) : Return the current task TLS pointer. +* +* Note(s) : None. +************************************************************************************************************************ +*/ + +static void OS_TLS_LockRelease (void *p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + + + if ((p_lock == (void *)0 ) || /* Return if the lock handler is 'NULL' or the ... */ + (OSRunning != OS_TRUE)) { /* ... kernel is not running. */ + return; + } + + p_tls_lock = (OS_TLS_LOCK *)p_lock; + (void)OSSemPost(p_tls_lock->Sem); +} + +_STD_BEGIN +/* +************************************************************************************************************************ +************************************************************************************************************************ +* IAR FUNCTIONS IMPLEMENTATIONS +************************************************************************************************************************ +************************************************************************************************************************ +*/ + +/* +************************************************************************************************************************ +* SYSTEM LOCK INITIALIZATION +* +* Description: Initialize a system lock. +* +* Arguments : p_lock Pointer to the lock info object pointer. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_system_Mtxinit (__iar_Rmtx *p_lock) +{ + OS_TLS_LockCreate((void **)p_lock); +} + + +/* +************************************************************************************************************************ +* SYSTEM LOCK DELETE +* +* Description: Delete a system lock. +* +* Arguments : p_lock Pointer to the lock info object. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_system_Mtxdst(__iar_Rmtx *p_lock) +{ + OS_TLS_LockDel((void *)*p_lock); +} + + +/* +************************************************************************************************************************ +* SYSTEM LOCK PEND +* +* Description: Pend on a system lock. +* +* Arguments : p_lock Pointer to the lock info object. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_system_Mtxlock(__iar_Rmtx *p_lock) +{ + OS_TLS_LockAcquire((void *)*p_lock); +} + + +/* +************************************************************************************************************************ +* SYSTEM LOCK POST +* +* Description: Signal a system lock. +* +* Arguments : p_lock Pointer to the lock info object. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_system_Mtxunlock(__iar_Rmtx *p_lock) +{ + OS_TLS_LockRelease((void *)*p_lock); +} + +/* +************************************************************************************************************************ +* FILE LOCK INITIALIZATION +* +* Description: Initialize a file lock. +* +* Arguments : p_lock Pointer to the lock info object pointer. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_file_Mtxinit (__iar_Rmtx *p_lock) +{ + OS_TLS_LockCreate((void **)p_lock); +} + + +/* +************************************************************************************************************************ +* FILE LOCK DELETE +* +* Description: Delete a system lock. +* +* Arguments : p_lock Pointer to the lock info object. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_file_Mtxdst(__iar_Rmtx *p_lock) +{ + OS_TLS_LockDel((void *)*p_lock); +} + + +/* +************************************************************************************************************************ +* FILE LOCK PEND +* +* Description: Pend on a file lock. +* +* Arguments : p_lock Pointer to the lock info object. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_file_Mtxlock(__iar_Rmtx *p_lock) +{ + OS_TLS_LockAcquire((void *)*p_lock); +} + + +/* +************************************************************************************************************************ +* FILE LOCK POST +* +* Description: Signal in a file lock. +* +* Arguments : p_lock Pointer to the lock info object. +* +* Note(s) : none. +************************************************************************************************************************ +*/ + +void __iar_file_Mtxunlock(__iar_Rmtx *p_lock) +{ + OS_TLS_LockRelease((void *)*p_lock); +} + + + +/* +************************************************************************************************************************ +* GET CURRENT TLS POINTER +* +* Description : Get the current TLS pointer. +* +* Argument(s) : symbp Pointer to the symbol in the segment. +* +* Return(s) : Returns symbol address in the current TLS segment. +* +* Note(s) : None. +************************************************************************************************************************ +*/ + +void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access (void _DLIB_TLS_MEMORY *symbp) +{ + void _DLIB_TLS_MEMORY *p_tls; + uintptr_t tls_start; + uintptr_t tls_offset; + + + + if (OSRunning != OS_TRUE) { /* If the kernel is not running yet? */ + p_tls = (OS_TLS)__segment_begin("__DLIB_PERTHREAD"); /* ... return the pointer to the main TLS segment. */ + } else { + p_tls = (void *)OSTCBCur->OSTCBTLSTbl[OS_TLS_LibID]; /* Get the pointer to the TLS for the task */ + } + + tls_start = (uintptr_t)(p_tls); + tls_offset = (uintptr_t)(__IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp)); + p_tls = (void _DLIB_TLS_MEMORY *)(tls_start + tls_offset); + + return (p_tls); +} + +_STD_END +#endif +#endif diff --git a/TLS/IAR/os_tls_v8.c b/TLS/IAR/os_tls_v8.c new file mode 100644 index 0000000..b71c690 --- /dev/null +++ b/TLS/IAR/os_tls_v8.c @@ -0,0 +1,847 @@ +/* +********************************************************************************************************* +* uC/OS-II +* The Real-Time Kernel +* +* Copyright 1992-2020 Silicon Laboratories Inc. www.silabs.com +* +* SPDX-License-Identifier: APACHE-2.0 +* +* This software is subject to an open source license and is distributed by +* Silicon Laboratories Inc. pursuant to the terms of the Apache License, +* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. +* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* +* THREAD LOCAL STORAGE (TLS) MANAGEMENT +* EWARM V8 IMPLEMENTATION +* +* Filename : os_tls.c +* Version : V2.93.00 +********************************************************************************************************* +*/ + +#define MICRIUM_SOURCE +#include +#include +#include + + +#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES +const char *os_tls_v8__c = "$Id: $"; +#endif + +#if (defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)) +#if (OS_TASK_CREATE_EXT_EN > 0u) + + +/* +********************************************************************************************************* +* LOCAL DEFINES +********************************************************************************************************* +*/ + +#pragma section="__iar_tls$$DATA" + +#if ((_DLIB_FILE_DESCRIPTOR > 0) && (defined(FOPEN_MAX))) +#define OS_TLS_LOCK_MAX ((_MAX_LOCK) + (FOPEN_MAX)) /* _MAX_LOCK and _FOPEN_MAX defined by IAR */ +#else +#define OS_TLS_LOCK_MAX (_MAX_LOCK) +#endif + + +/* +********************************************************************************************************* +* LOCAL DATA TYPES +********************************************************************************************************* +*/ + +typedef struct os_tls_lock OS_TLS_LOCK; + + +struct os_tls_lock { + OS_EVENT *Sem; /* OS semaphore object. */ + OS_TLS_LOCK *NextPtr; /* Pointer to the next object in the pool. */ +}; + + +/* +********************************************************************************************************* +* LOCAL VARIABLES +********************************************************************************************************* +*/ + +static INT8U OS_TLS_NextAvailID; /* Next available TLS ID */ + +static OS_TLS_ID OS_TLS_LibID; /* ID used to store library space pointer */ + +static OS_TLS_LOCK OS_TLS_LockPoolTbl[OS_TLS_LOCK_MAX]; +static OS_TLS_LOCK *OS_TLS_LockPoolListPtr; /* Pointer to head of 'OS_TLS_LOCK' list */ + + +/* +********************************************************************************************************* +* LOCAL FUNCTIONS +********************************************************************************************************* +*/ + +static void OS_TLS_LockCreate (void **p_lock); +static void OS_TLS_LockDel (void *p_lock); +static void OS_TLS_LockAcquire(void *p_lock); +static void OS_TLS_LockRelease(void *p_lock); + + +/* +********************************************************************************************************* +* ALLOCATE THE NEXT AVAILABLE TLS ID +* +* Description : This function is called to obtain the ID of the next free TLS (Task Local Storage) +* register 'id' +* +* Argument(s) : perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_TLS_NO_MORE_AVAIL if you are attempting to assign more TLS segments +* than were specified by OS_TLS_TBL_SIZE +* +* Return(s) : The next available TLS 'id' or OS_TLS_TBL_SIZE if an error is detected. +********************************************************************************************************* +*/ + +OS_TLS_ID OS_TLS_GetID (INT8U *perr) +{ + OS_TLS_ID id; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_TLS_ID)OS_TLS_TBL_SIZE); + } +#endif + + OS_ENTER_CRITICAL(); + if (OS_TLS_NextAvailID >= OS_TLS_TBL_SIZE) { /* See if we exceeded the number of IDs available */ + *perr = OS_ERR_TLS_NO_MORE_AVAIL; /* Yes, cannot allocate more TLS */ + OS_EXIT_CRITICAL(); + return ((OS_TLS_ID)OS_TLS_TBL_SIZE); + } + + id = OS_TLS_NextAvailID; /* Assign the next available ID */ + OS_TLS_NextAvailID++; /* Increment available ID for next request */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return (id); +} + + +/* +********************************************************************************************************* +* GET THE CURRENT VALUE OF A TLS REGISTER +* +* Description : This function is called to obtain the current value of a TLS register +* +* Argument(s) : ptcb is a pointer to the OS_TCB of the task you want to read the TLS register from. +* If 'ptcb' is a NULL pointer then you will get the TLS register of the current +* task. +* +* id is the 'id' of the desired TLS register. Note that the 'id' must be less than +* 'OS_TLS_NextAvailID' +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_OS_NOT_RUNNING if the kernel has not started yet +* OS_ERR_TLS_ID_INVALID if the 'id' is greater or equal to +* OS_TLS_NextAvailID +* OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS +* support was not needed +* +* Return(s) : The current value of the task's TLS register or 0 if an error is detected. +* +* Note(s) : 1) ptcb->OSTCBOpt contains options passed to OSTaskCreate(). One of these options +* (OS_TASK_OPT_NO_TLS) is used to specify that the user doesn't want TLS support for the +* task being created. In other words, by default, TLS support is enabled if +* OS_TLS_TBL_SIZE is defined and > 0, so the user must specifically indicate that he/she +* doesn't want TLS supported for a task. +********************************************************************************************************* +*/ + +OS_TLS OS_TLS_GetValue (OS_TCB *ptcb, + OS_TLS_ID id, + INT8U *perr) +{ + OS_TLS value; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return ((OS_TLS)0); + } +#endif + + +#if OS_ARG_CHK_EN > 0u + if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */ + *perr = OS_ERR_TLS_ID_INVALID; + return ((OS_TLS)0); + } +#endif + + OS_ENTER_CRITICAL(); + if (ptcb == (OS_TCB *)0) { /* Does caller want to use current task's TCB? */ + ptcb = OSTCBCur; /* Yes */ + if (OSTCBCur == (OS_TCB *)0) { /* Is the kernel running? */ + OS_EXIT_CRITICAL(); /* No, then caller cannot specify NULL */ + *perr = OS_ERR_OS_NOT_RUNNING; + return ((OS_TLS)0); + } + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + value = ptcb->OSTCBTLSTbl[id]; /* Yes */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + return ((OS_TLS)value); + } else { + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TLS_NOT_EN; + return ((OS_TLS)0); + } +} + + +/* +********************************************************************************************************* +* DEFINE TLS DESTRUCTOR FUNCTION +* +* Description : This function is called by the user to assign a 'destructor' function to a specific TLS. +* When a task is deleted, all the destructors are called for all the task's TLS for which +* there is a destructor function defined. When a task is deleted, all the non-NULL +* functions present in OS_TLS_DestructPtrTbl[] will be called. +* +* Argument(s) : id is the ID of the TLS destructor to set +* +* pdestruct is a pointer to a function that is associated with a specific TLS register +* and is called when a task is deleted. The prototype of such functions is: +* +* void MyDestructFunction (OS_TCB *ptcb, +* OS_TLS_ID id, +* OS_TLS value); +* +* you can specify a NULL pointer if you don't want to have a function +* associated with a TLS register. A NULL pointer (i.e. no function associated +* with a TLS register) is the default value placed in OS_TLS_DestructPtrTbl[]. +* +* perr is a pointer to an error return code. The possible values are: +* +* OS_ERR_NONE The call was successful. +* OS_ERR_TLS_ID_INVALID You you specified an invalid TLS ID +* +* Return(s) : none +* +* Note(s) : none +********************************************************************************************************* +*/ + +void OS_TLS_SetDestruct (OS_TLS_ID id, + OS_TLS_DESTRUCT_PTR pdestruct, + INT8U *perr) +{ + (void)id; + (void)pdestruct; + *perr = OS_ERR_NONE; +} + + +/* +********************************************************************************************************* +* SET THE CURRENT VALUE OF A TASK TLS REGISTER +* +* Description : This function is called to change the current value of a task TLS register. +* +* Argument(s) : ptcb is a pointer to the OS_TCB of the task you for which you want to set the TLS +* register. If 'ptcb' is a NULL pointer then you will change the TLS register of +* the current task. +* +* id is the 'id' of the desired task TLS register. Note that the 'id' must be less +* than 'OS_TLS_NextAvailID' +* +* value is the desired value for the task TLS register. +* +* perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_OS_NOT_RUNNING if the kernel has not started yet +* OS_ERR_TLS_ID_INVALID if the 'id' is greater or equal to + OS_TLS_NextAvailID +* OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS +* support was not needed +* +* Return(s) : The current value of the task's TLS register or 0 if an error is detected. +* +* Note(s) : 1) ptcb->OSTCBOpt contains options passed to OSTaskCreate(). One of these options +* (OS_TASK_OPT_NO_TLS) is used to specify that the user doesn't want TLS support for the +* task being created. In other words, by default, TLS support is enabled if +* OS_TLS_TBL_SIZE is defined and > 0, so the user must specifically indicate that he/she +* doesn't want TLS supported for a task. +********************************************************************************************************* +*/ + +void OS_TLS_SetValue (OS_TCB *ptcb, + OS_TLS_ID id, + OS_TLS value, + INT8U *perr) +{ +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + +#ifdef OS_SAFETY_CRITICAL + if (perr == (INT8U *)0) { + OS_SAFETY_CRITICAL_EXCEPTION(); + return; + } +#endif + +#if OS_ARG_CHK_EN > 0u + if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */ + *perr = OS_ERR_TLS_ID_INVALID; + return; + } +#endif + + OS_ENTER_CRITICAL(); /* Does caller want to use current task's TCB? */ + if (ptcb == (OS_TCB *)0) { /* Yes */ + ptcb = OSTCBCur; /* Is the kernel running? */ + if (OSTCBCur == (OS_TCB *)0) { /* No, then caller cannot specify NULL */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_OS_NOT_RUNNING; + return; + } + } + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + ptcb->OSTCBTLSTbl[id] = value; /* Yes */ + OS_EXIT_CRITICAL(); + *perr = OS_ERR_NONE; + } else { + OS_EXIT_CRITICAL(); /* No */ + *perr = OS_ERR_TLS_NOT_EN; + } +} + + +/* +********************************************************************************************************* +********************************************************************************************************* +* uC/OS-II INTERNAL FUNCTIONS +* DO NOT CALL FROM THE APPLICATION CODE +********************************************************************************************************* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* INITIALIZE THE TASK LOCAL STORAGE SERVICES +* +* Description : This function is called by uC/OS-II to initialize the TLS id allocator. +* This function also initializes an array containing function pointers. +* There is one function associated to each task TLS register and all the functions +* (assuming non-NULL) will be called when the task is deleted. +* +* Argument(s) : perr is a pointer to a variable that will hold an error code related to this call. +* +* OS_ERR_NONE if the call was successful +* OS_ERR_TLS_NO_MORE_AVAIL if you are attempting to assign more TLS segments +* than were specified by OS_TLS_TBL_SIZE +* +* Return(s) : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_TLS_Init (INT8U *perr) +{ + INT16U ix; + OS_TLS_LOCK *p_lock; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + OS_TLS_NextAvailID = 0u; + OS_TLS_LibID = OS_TLS_GetID(perr); + + OS_ENTER_CRITICAL(); + /* Create the link list of OS_TLS_LOCK objects. */ + for (ix = 0u; ix < (OS_TLS_LOCK_MAX - 1u); ix++) { + p_lock = &OS_TLS_LockPoolTbl[ix]; + p_lock->NextPtr = &OS_TLS_LockPoolTbl[ix + 1u]; + } + + p_lock = &OS_TLS_LockPoolTbl[OS_TLS_LOCK_MAX - 1u]; + p_lock->NextPtr = (OS_TLS_LOCK *)0; /* Last node points to 'NULL' */ + OS_TLS_LockPoolListPtr = &OS_TLS_LockPoolTbl[0]; /* Initialize the list head pointer. */ + + __iar_Initlocks(); /* Initialize the DLib Thread Locks. */ + + OS_EXIT_CRITICAL(); +} + + +/* +********************************************************************************************************* +* TASK CREATE HOOK +* +* Description : This function is called by OSTaskCreate() +* +* Argument(s) : ptcb is a pointer to the OS_TCB of the task being created. +* +* Return(s) : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* +* 2) OSTaskCreate() clears all entries in ptcb->OSTCBTLSTbl[] before calling +* OS_TLS_TaskCreate() so no need to do this here. +********************************************************************************************************* +*/ + +void OS_TLS_TaskCreate (OS_TCB *ptcb) +{ + OS_TLS p_tls; + + + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + p_tls = malloc(__iar_tls_size()); /* Get TLS segment from the HEAP. */ + __iar_tls_init(p_tls); /* Initialize the TLS segment. */ + ptcb->OSTCBTLSTbl[OS_TLS_LibID] = p_tls; /* Set the TLS segment pointer in the task. */ + } +} + + +/* +********************************************************************************************************* +* TASK DELETE HOOK +* +* Description : This function is called by OSTaskDel() +* +* Argument(s) : ptcb is a pointer to the OS_TCB of the task being deleted. +* +* Return(s) : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +********************************************************************************************************* +*/ + +void OS_TLS_TaskDel (OS_TCB *ptcb) +{ + OS_TLS p_tls; + + + if ((ptcb->OSTCBOpt & OS_TASK_OPT_NO_TLS) == OS_TASK_OPT_NONE) { /* See if TLS is available for this task */ + p_tls = ptcb->OSTCBTLSTbl[OS_TLS_LibID]; + __call_thread_dtors(); + free(p_tls); /* De-allocate the TLS segment. */ + ptcb->OSTCBTLSTbl[OS_TLS_LibID] = (OS_TLS)0; /* Remove the TLS segment pointer from the task. */ + } +} + + +/* +********************************************************************************************************* +* TASK SWITCH HOOK +* +* Description : This function is called by OSSched() and OSIntExit() just prior to calling the +* context switch code +* +* Argument(s) : none +* +* Return(s) : none +* +* Note(s) : 1) This function is INTERNAL to uC/OS-II and your application should not call it. +* +* 2) It's assumed that OSTCBCur points to the task being switched out and OSTCBHighRdy +* points to the task being switched in. +********************************************************************************************************* +*/ + +void OS_TLS_TaskSw (void) +{ + /* No action required here for this port. */ +} + + +/* +********************************************************************************************************* +********************************************************************************************************* +* uC/OS-II MUTEX IMPLEMENTATION +********************************************************************************************************* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* OS TLS LOCK CREATE +* +* Description : Allocate a new 'OS_TLS_LOCK' object from the free pool and create an 'OS_EVENT' +* in the kernel. +* +* Argument(s) : p_lock Pointer to the DLIB lock handler. +* +* Return(s) : None. +* +* Note(s) : None. +********************************************************************************************************* +*/ + +static void OS_TLS_LockCreate (void **p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + OS_EVENT *psem; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + if (p_lock == (void **)0) { + return; + } + + if (OS_TLS_LockPoolListPtr == (OS_TLS_LOCK *)0) { /* If 'OS_TLS_LOCK' object pool is empty? */ + *p_lock = (void *)0; /* return a 'NULL' pointer. */ + return; + } + + p_tls_lock = OS_TLS_LockPoolListPtr; /* Get the first object in the list. */ + psem = OSSemCreate(1); /* Create the semaphore in the kernel. */ + + if (psem == (OS_EVENT *)0) { /* If the semaphore create funtion failed ... */ + *p_lock = (void *)0; /* ... return a 'NULL' pointer. */ + return; + } + + p_tls_lock->Sem = psem; + + OS_ENTER_CRITICAL(); + OS_TLS_LockPoolListPtr = p_tls_lock->NextPtr; /* Move HEAD pointer to the next object in the list. */ + OS_EXIT_CRITICAL(); + + *p_lock = (void *)p_tls_lock; /* Return the new 'OS_TLS_LOCK' object pointer. */ +} + + +/* +********************************************************************************************************* +* OS TLS LOCK DELETE +* +* Description : Delete an 'OS_EVENT' from the kernel and return the allocated 'OS_TLS_LOCK' +* to the free pool. +* +* Argument(s) : p_lock DLIB lock handler. +* +* Return(s) : Return the current task TLS pointer. +* +* Note(s) : None. +********************************************************************************************************* +*/ + +static void OS_TLS_LockDel (void *p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + INT8U err; +#if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */ + OS_CPU_SR cpu_sr = 0u; +#endif + + + if (p_lock == (void *)0) { + return; + } + + p_tls_lock = (OS_TLS_LOCK *)p_lock; + + (void)OSSemDel( p_tls_lock->Sem, + OS_DEL_ALWAYS, + &err); + + OS_ENTER_CRITICAL(); + /* Return the OS_TLS_LOCK in front of the list */ + if (OS_TLS_LockPoolListPtr == (OS_TLS_LOCK *)0) { + p_tls_lock->NextPtr = (OS_TLS_LOCK *)0; + } else { + p_tls_lock->NextPtr = OS_TLS_LockPoolListPtr; + } + OS_TLS_LockPoolListPtr = p_tls_lock; + + OS_EXIT_CRITICAL(); +} + + +/* +********************************************************************************************************* +* OS TLS LOCK ACQUIRE +* +* Description : Wait indefinitely until the lock becomes available +* +* Argument(s) : p_lock DLIB lock handler. +* +* Return(s) : Return the current task TLS pointer. +* +* Note(s) : None. +********************************************************************************************************* +*/ + +static void OS_TLS_LockAcquire (void *p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + INT8U err; + + + if ((p_lock == (void *)0) || /* Return if the lock handler is 'NULL' or the ... */ + (OSRunning != OS_TRUE)) { /* ... kernel is not running. */ + return; + } + + p_tls_lock = (OS_TLS_LOCK *)p_lock; + OSSemPend( p_tls_lock->Sem, + 0u, + &err); +} + + +/* +********************************************************************************************************* +* OS TLS LOCK RELEASE +* +* Description : Signal the lock. +* +* Argument(s) : p_lock DLIB lock handler. +* +* Return(s) : Return the current task TLS pointer. +* +* Note(s) : None. +********************************************************************************************************* +*/ + +static void OS_TLS_LockRelease (void *p_lock) +{ + OS_TLS_LOCK *p_tls_lock; + + + if ((p_lock == (void *)0) || /* Return if the lock handler is 'NULL' or the ... */ + (OSRunning != OS_TRUE)) { /* ... kernel is not running. */ + return; + } + + p_tls_lock = (OS_TLS_LOCK *)p_lock; + (void)OSSemPost(p_tls_lock->Sem); +} + + +#if defined(__cplusplus) +extern "C" { +namespace std { +#endif + + +/* +********************************************************************************************************* +********************************************************************************************************* +* IAR FUNCTION IMPLEMENTATIONS +********************************************************************************************************* +********************************************************************************************************* +*/ + +/* +********************************************************************************************************* +* GET CURRENT TLS POINTER +* +* Description : Get the current TLS pointer. +* +* Argument(s) : none. +* +* Return(s) : Returns address of the current TLS segment. +* +* Note(s) : None. +********************************************************************************************************* +*/ + +void *__aeabi_read_tp (void) +{ + void *p_tls; + + + if (OSRunning != OS_TRUE) { + p_tls = __section_begin("__iar_tls$$DATA"); + } else { + p_tls = (void *)OSTCBCur->OSTCBTLSTbl[OS_TLS_LibID]; + } + + return (p_tls); +} + + +/* +********************************************************************************************************* +* SYSTEM LOCK INITIALIZATION +* +* Description : Initialize a system lock. +* +* Argument(s) : p_lock Pointer to the lock info object pointer. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_system_Mtxinit (__iar_Rmtx *p_lock) +{ + OS_TLS_LockCreate((void **)p_lock); +} + + +/* +********************************************************************************************************* +* SYSTEM LOCK DELETE +* +* Description : Delete a system lock. +* +* Argument(s) : p_lock Pointer to the lock info object. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_system_Mtxdst (__iar_Rmtx *p_lock) +{ + OS_TLS_LockDel((void *)*p_lock); +} + + +/* +********************************************************************************************************* +* SYSTEM LOCK PEND +* +* Description : Pend on a system lock. +* +* Argument(s) : p_lock Pointer to the lock info object. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_system_Mtxlock (__iar_Rmtx *p_lock) +{ + OS_TLS_LockAcquire((void *)*p_lock); +} + + +/* +********************************************************************************************************* +* SYSTEM LOCK POST +* +* Description : Signal a system lock. +* +* Argument(s) : p_lock Pointer to the lock info object. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_system_Mtxunlock (__iar_Rmtx *p_lock) +{ + OS_TLS_LockRelease((void *)*p_lock); +} + + +/* +********************************************************************************************************* +* FILE LOCK INITIALIZATION +* +* Description : Initialize a file lock. +* +* Argument(s) : p_lock Pointer to the lock info object pointer. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_file_Mtxinit (__iar_Rmtx *p_lock) +{ + OS_TLS_LockCreate((void **)p_lock); +} + + +/* +********************************************************************************************************* +* FILE LOCK DELETE +* +* Description : Delete a system lock. +* +* Argument(s) : p_lock Pointer to the lock info object. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_file_Mtxdst (__iar_Rmtx *p_lock) +{ + OS_TLS_LockDel((void *)*p_lock); +} + + +/* +********************************************************************************************************* +* FILE LOCK PEND +* +* Description : Pend on a file lock. +* +* Argument(s) : p_lock Pointer to the lock info object. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_file_Mtxlock (__iar_Rmtx *p_lock) +{ + OS_TLS_LockAcquire((void *)*p_lock); +} + + +/* +********************************************************************************************************* +* FILE LOCK POST +* +* Description : Signal in a file lock. +* +* Argument(s) : p_lock Pointer to the lock info object. +* +* Note(s) : none. +********************************************************************************************************* +*/ + +void __iar_file_Mtxunlock (__iar_Rmtx *p_lock) +{ + OS_TLS_LockRelease((void *)*p_lock); +} + +#if defined(__cplusplus) +} +} +#endif + +#endif /* #if (OS_TASK_CREATE_EXT_EN > 0u) */ +#endif /* #if (defined(OS_TLS_TBL_SIZE) && (OS_TLS_TBL_SIZE > 0u)) */ + diff --git a/Trace/readme.txt b/Trace/readme.txt new file mode 100644 index 0000000..178f2ed --- /dev/null +++ b/Trace/readme.txt @@ -0,0 +1,9 @@ +The following trace tools are supported: + +##################################################################################### +SEGGER SystemView for uC/OS-III + +Download the embedded target code to support Segger's SystemView for uC/OS-III +from the following website https://www.segger.com/downloads/free_tools#SystemView +and place the files in this folder. +##################################################################################### \ No newline at end of file diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..4242d40 --- /dev/null +++ b/license.txt @@ -0,0 +1,29 @@ +ATTENTION ALL USERS OF THIS REPOSITORY: + +The original work found in this repository is provided by Silicon Labs under the +Apache License, Version 2.0. + +Any third party may contribute derivative works to the original work in which +modifications are clearly identified as being licensed under: + + (1) the Apache License, Version 2.0 or a compatible open source license; or + (2) under a proprietary license with a copy of such license deposited. + +All posted derivative works must clearly identify which license choice has been +elected. + +No such posted derivative works will be considered to be a “Contribution” under +the Apache License, Version 2.0. + +SILICON LABS MAKES NO WARRANTY WITH RESPECT TO ALL POSTED THIRD PARTY CONTENT +AND DISCLAIMS ALL OTHER WARRANTIES OR LIABILITIES, INCLUDING ALL WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, OWNERSHIP, +NON-INFRINGEMENT, AND NON-MISAPPROPRIATION. + +In the event a derivative work is desired to be submitted to Silicon Labs as a +“Contribution” under the Apache License, Version 2.0, a “Contributor” must give +written email notice to micrium@weston-embedded.com. Unless an email response in +the affirmative to accept the derivative work as a “Contribution”, such email +submission should be considered to have not been incorporated into the original +work. + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..c8e5d0c --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +# uC/OS-II + +μC/OS-II is a portable, ROMable, scalable, preemptive, real-time deterministic multitasking kernel for microprocessors, microcontrollers and DSPs. +Offering unprecedented ease-of-use, μC/OS-II is delivered with complete 100% ANSI C source code and in-depth documentation. μC/OS-II runs on the largest number of processor architectures, with ports available for download from the Micrium Web site. + +## For the complete documentation, visit https://doc.micrium.com/display/ucos/ \ No newline at end of file