ICARUS OS (Intelligent Cooperative Architecture for Real-time Unified Systems) 0.1.0
Preemptive Real-Time Operating System for ARM Cortex-M7
Loading...
Searching...
No Matches
kernel.c
Go to the documentation of this file.
1
16#include "icarus/kernel.h"
17#include "icarus/task.h"
18#include "icarus/scheduler.h"
19#include "bsp/display.h"
20#include "bsp/led.h"
21
22#include <string.h>
23
24/* ============================================================================
25 * SECTION PLACEMENT MACROS
26 * ========================================================================= */
27
28/* Defined centrally in icarus/config.h — included via icarus/kernel.h */
29
30/* ============================================================================
31 * COMPILE-TIME STRUCTURE VALIDATION
32 * ========================================================================= */
33
34#ifndef SKIP_STATIC_ASSERTS
35#include <stddef.h>
36_Static_assert(offsetof(icarus_task_t, stack_pointer) == 12,
37 "TCB stack_pointer offset mismatch - update context_switch.s");
38_Static_assert(offsetof(icarus_task_t, task_state) == 16,
39 "TCB task_state offset mismatch - update context_switch.s");
40_Static_assert(offsetof(icarus_task_t, global_tick_paused) == 20,
41 "TCB global_tick_paused offset mismatch - update context_switch.s");
42_Static_assert(offsetof(icarus_task_t, ticks_to_pause) == 24,
43 "TCB ticks_to_pause offset mismatch - update context_switch.s");
44#endif
45
46/* ============================================================================
47 * KERNEL DATA STRUCTURES (DTCM_PRIV - privileged-only, zero wait state)
48 * ========================================================================= */
49
53
58
59/* ============================================================================
60 * SCHEDULER STATE (DTCM_PRIV - privileged-only, zero wait state)
61 * ========================================================================= */
62
69DTCM_DATA_PRIV volatile uint32_t os_tick_count;
70DTCM_DATA_PRIV volatile uint8_t os_running;
74
75/* ============================================================================
76 * STACK POOL (RAM_D1)
77 * ========================================================================= */
78
80
81
82/* ============================================================================
83 * DATA POOL (RAM_D2 - isolated from RAM_D1 for MPU protection)
84 * ========================================================================= */
85
86/* Each task's data pool must be aligned to 2KB (MPU region size requirement) */
87/* Placed in RAM_D2 so Region 6 (RAM_D1) doesn't grant default access */
88#ifndef HOST_TEST
90 __attribute__((aligned(2048)))
91 __attribute__((section(".ram_d2")));
92#else
94 __attribute__((aligned(2048)));
95#endif
96
97/* Data pool allocation offsets — kernel metadata, protected in DTCM */
99
100/* ============================================================================
101 * EXTERNAL ASSEMBLY FUNCTIONS
102 * ========================================================================= */
103
105
106/* ============================================================================
107 * CRITICAL SECTION MANAGEMENT
108 * ========================================================================= */
109
115{
116 scheduler_enabled = false;
118}
119
125{
126 if (--critical_stack_depth == 0) {
127 scheduler_enabled = true;
128 }
129}
130
131/* ============================================================================
132 * INTERNAL HELPER FUNCTIONS
133 * ========================================================================= */
134
135static inline ITCM_FUNC void __init_sem(uint8_t semaphore_idx, uint32_t semaphore_count,
136 bool should_engage)
137{
138 semaphore_list[semaphore_idx]->count = semaphore_count;
139 semaphore_list[semaphore_idx]->max_count = semaphore_count;
141 semaphore_list[semaphore_idx]->engaged = should_engage;
142}
143
144static inline ITCM_FUNC void __init_pipe(uint8_t message_pipe_idx, uint16_t max_messages,
145 bool should_engage)
146{
147 message_pipe_list[message_pipe_idx]->count = 0;
148 message_pipe_list[message_pipe_idx]->max_count = max_messages;
149 message_pipe_list[message_pipe_idx]->enqueue_idx = 0;
150 message_pipe_list[message_pipe_idx]->dequeue_idx = 0;
152 message_pipe_list[message_pipe_idx]->engaged = should_engage;
153
154 for (uint16_t i = 0u; i < (uint16_t)ICARUS_MAX_MESSAGE_BYTES; i++) {
155 message_pipe_list[message_pipe_idx]->buffer[i] = 0;
156 }
157}
158
159/* ============================================================================
160 * SYSTEM TASKS
161 * ========================================================================= */
162
163static void os_idle_task(void)
164{
165 // Simplified display_init for DTCM protection testing
166 // printf("ICARUS OS - DTCM Protection Test\r\n");
167 // fflush(stdout);
168 display_init();
169 while (1) {
170 os_yield();
171 }
172}
173
174static void os_heartbeat_task(void) __attribute__((unused));
175static void os_heartbeat_task(void)
176{
177#if ICARUS_ENABLE_HEARTBEAT_VIS
178 const char* task_name = os_get_current_task_name();
179#endif
180
181 while (1 != 0) {
182 if (os_is_running() != 0u) {
183#if ICARUS_ENABLE_HEARTBEAT_VIS
184 display_render_banner(ROW_HEARTBEAT, task_name, true);
185 (void)task_active_sleep(8);
186 LED_On();
188 display_render_banner(ROW_HEARTBEAT, task_name, false);
189 (void)task_active_sleep(8);
190 LED_Off();
192#else
194#endif
195 } else {
196#if ICARUS_ENABLE_HEARTBEAT_VIS
197 display_render_banner(ROW_HEARTBEAT, task_name, false);
198#endif
199 (void)task_active_sleep(100);
200 }
201 }
202}
203
204/* ============================================================================
205 * KERNEL INITIALIZATION
206 * ========================================================================= */
207
213{
214 uint8_t i;
215
216 os_running = 0;
222
223 for (i = 0u; i < (uint8_t)ICARUS_MAX_TASKS; i++) {
224 task_list[i] = &task_pool[i];
225 cleanup_task_idx[i] = -1;
227 }
228
229 for (i = 0u; i < (uint8_t)ICARUS_MAX_SEMAPHORES; i++) {
231 __init_sem(i, 0, false);
232 }
233
234 for (i = 0u; i < (uint8_t)ICARUS_MAX_MESSAGE_QUEUES; i++) {
236 __init_pipe(i, 0, false);
237 }
238
239 for (i = 0u; i < 16u; i++) {
240 cpu_vregisters[i] = 0;
241 }
242
243 __os_register_task(os_idle_task, "ICARUS_KEEPALIVE_TASK");
244 // __os_register_task(os_heartbeat_task, ">ICARUS_HEARTBEAT<"); // Disabled for interactive demo
245
246 scheduler_enabled = true;
247}
248
254{
255 if ((num_created_tasks == 0u) || (num_created_tasks > (uint8_t)ICARUS_MAX_TASKS)) {
256 return;
257 }
259}
260
261/* ============================================================================
262 * STACK POOL ACCESS (for task.c)
263 * ========================================================================= */
264
269ITCM_FUNC uint32_t* __kernel_get_stack(uint8_t task_idx)
270{
271 return stack_pool[task_idx];
272}
273
274/* ============================================================================
275 * DATA POOL ACCESS (for task.c)
276 * ========================================================================= */
277
282ITCM_FUNC uint32_t* __kernel_get_data(uint8_t task_idx)
283{
284 return data_pool[task_idx];
285}
286
287
288
289
295ITCM_FUNC void* __kernel_protected_data(uint16_t num_words) {
296 if (((data_pool_word_offsets[current_task_index] + num_words) > (uint16_t)ICARUS_DATA_WORDS) || (num_words == 0u)) {
297 return NULL;
298 }
299 uint16_t current_offset = data_pool_word_offsets[current_task_index];
301 uint32_t *ret_ptr = &data_pool[current_task_index][current_offset];
302 return (void*) ret_ptr;
303}
304
305/* ============================================================================
306 * TASK METADATA READ GATES (for display/diagnostics)
307 * ========================================================================= */
308
315ITCM_FUNC const char* __os_get_task_name(uint8_t task_idx) {
316 /* Static buffer in RAM_D1 (not DTCM) for unprivileged access */
317#ifndef HOST_TEST
318 static char name_buffer[ICARUS_MAX_TASK_NAME_LEN] __attribute__((section(".ram_d1")));
319#else
320 static char name_buffer[ICARUS_MAX_TASK_NAME_LEN];
321#endif
322
323 if ((task_idx >= num_created_tasks) || (task_list[task_idx] == NULL)) {
324 return NULL;
325 }
326
327 /* Copy name from DTCM to RAM_D1 buffer */
328 const char* src = task_list[task_idx]->name;
329 for (uint8_t i = 0u; i < (uint8_t)ICARUS_MAX_TASK_NAME_LEN; i++) {
330 name_buffer[i] = src[i];
331 if (src[i] == '\0') {
332 break;
333 }
334 }
335 name_buffer[ICARUS_MAX_TASK_NAME_LEN - 1] = '\0'; /* Ensure null termination */
336
337 return name_buffer;
338}
339
348
355 return os_running;
356}
357
364 if ((task_idx >= num_created_tasks) || (task_list[task_idx] == NULL)) {
365 return TASK_STATE_FINISHED;
366 }
367 return task_list[task_idx]->task_state;
368}
369
375ITCM_FUNC uint32_t __os_get_task_dispatch_count(uint8_t task_idx) {
376 if ((task_idx >= num_created_tasks) || (task_list[task_idx] == NULL)) {
377 return 0;
378 }
379 return task_list[task_idx]->dispatch_count;
380}
381
387ITCM_FUNC uint32_t __os_get_stack_watermark(uint8_t task_idx) {
388 if ((task_idx >= num_created_tasks) || (task_list[task_idx] == NULL)) {
389 return 0;
390 }
391 return task_list[task_idx]->stack_watermark;
392}
393
400 if ((task_idx >= num_created_tasks) || (task_list[task_idx] == NULL)) {
401 return;
402 }
403 icarus_task_t *t = task_list[task_idx];
404 uint32_t free_words = 0;
405 for (uint32_t i = 0; i < t->stack_size; i++) {
406 if (t->stack_base[i] == 0xDEADC0DEu) {
407 free_words++;
408 } else {
409 break;
410 }
411 }
412 if (free_words < t->stack_watermark) {
413 t->stack_watermark = free_words;
414 }
415}
void display_render_banner(uint8_t row, const char *task_name, bool is_on)
Render a simple flashing banner (on/off indicator)
Definition display.c:306
void display_init(void)
Initialize terminal display - clear screen and print header.
Definition display.c:654
#define ROW_HEARTBEAT
Definition display.h:29
#define ICARUS_HEARTBEAT_ON_TICKS
Heartbeat LED on duration in ticks.
Definition config.h:217
#define ICARUS_HEARTBEAT_OFF_TICKS
Heartbeat LED off duration in ticks.
Definition config.h:222
#define ICARUS_MAX_TASK_NAME_LEN
Maximum length of task name string (including null terminator)
Definition config.h:102
#define ICARUS_MAX_SEMAPHORES
Maximum number of semaphores.
Definition config.h:61
#define ICARUS_MAX_TASKS
Maximum number of concurrent tasks.
Definition config.h:54
#define ICARUS_MAX_MESSAGE_BYTES
Maximum bytes per message pipe buffer.
Definition config.h:76
#define ICARUS_TICKS_PER_TASK
Number of SysTick interrupts per task time slice.
Definition config.h:97
#define ICARUS_DATA_WORDS
Data region size per task in 32-bit words.
Definition config.h:91
#define ICARUS_MAX_MESSAGE_QUEUES
Maximum number of message queues (pipes)
Definition config.h:68
#define ICARUS_STACK_WORDS
Stack size per task in 32-bit words.
Definition config.h:84
#define DTCM_DATA_PRIV
Definition config.h:156
#define ITCM_FUNC
Definition config.h:155
static uint32_t data_pool[128][512]
Definition kernel.c:91
void * __kernel_protected_data(uint16_t num_words)
Privileged implementation of kernel_protected_data.
Definition kernel.c:295
uint8_t num_created_tasks
Total number of created tasks.
Definition kernel.c:65
volatile uint32_t current_task_ticks_remaining
Ticks remaining in current task's time slice.
Definition kernel.c:66
void start_cold_task(icarus_task_t *task)
void __exit_critical(void)
Privileged implementation of exit_critical.
Definition kernel.c:124
uint8_t running_task_count
Count of tasks in active states.
Definition kernel.c:64
uint8_t current_task_index
Index of currently executing task.
Definition kernel.c:63
static uint16_t data_pool_word_offsets[128]
Definition kernel.c:98
uint8_t __os_get_num_created_tasks(void)
Privileged implementation of os_get_num_created_tasks.
Definition kernel.c:345
icarus_pipe_t * message_pipe_list[64]
Array of pointers to all message pipes.
Definition kernel.c:52
volatile uint8_t os_running
Flag indicating OS is running.
Definition kernel.c:70
icarus_task_t * task_list[128]
Array of pointers to all task control blocks.
Definition kernel.c:50
int8_t current_cleanup_task_idx
Current cleanup queue write index.
Definition kernel.c:73
void __os_init(void)
Privileged implementation of os_init.
Definition kernel.c:212
icarus_task_state_t __os_get_task_state(uint8_t task_idx)
Privileged implementation of os_get_task_state.
Definition kernel.c:363
static void __init_pipe(uint8_t message_pipe_idx, uint16_t max_messages, bool should_engage)
Definition kernel.c:144
void __enter_critical(void)
Privileged implementation of enter_critical.
Definition kernel.c:114
static void os_idle_task(void)
Definition kernel.c:163
volatile uint8_t critical_stack_depth
Definition kernel.c:71
static icarus_pipe_t message_pipe_pool[64]
Definition kernel.c:56
static icarus_task_t task_pool[128]
Definition kernel.c:54
uint8_t __os_is_running(void)
Privileged implementation of os_is_running.
Definition kernel.c:354
static icarus_semaphore_t semaphore_pool[64]
Definition kernel.c:55
static void __init_sem(uint8_t semaphore_idx, uint32_t semaphore_count, bool should_engage)
Definition kernel.c:135
uint32_t * __kernel_get_data(uint8_t task_idx)
Privileged implementation of kernel_get_data.
Definition kernel.c:282
void __os_start(void)
Privileged implementation of os_start.
Definition kernel.c:253
uint32_t __os_get_task_dispatch_count(uint8_t task_idx)
Privileged implementation of os_get_task_dispatch_count.
Definition kernel.c:375
const char * __os_get_task_name(uint8_t task_idx)
Privileged implementation of os_get_task_name.
Definition kernel.c:315
icarus_semaphore_t * semaphore_list[64]
Array of pointers to all semaphores.
Definition kernel.c:51
int8_t cleanup_task_idx[128]
Cleanup task index queue.
Definition kernel.c:57
volatile uint32_t os_tick_count
System tick counter.
Definition kernel.c:69
uint32_t cpu_vregisters[16]
Definition kernel.c:68
uint32_t * __kernel_get_stack(uint8_t task_idx)
Privileged implementation of kernel_get_stack.
Definition kernel.c:269
void __os_update_stack_watermark(uint8_t task_idx)
Scan a task's stack from the base upward for the sentinel pattern (0xDEADC0DE) and update the waterma...
Definition kernel.c:399
uint32_t __os_get_stack_watermark(uint8_t task_idx)
Privileged implementation of os_get_stack_watermark.
Definition kernel.c:387
volatile uint32_t ticks_per_task
Configured ticks per time slice.
Definition kernel.c:67
volatile bool scheduler_enabled
Scheduler enable flag.
Definition kernel.c:72
static uint32_t stack_pool[128][512]
Definition kernel.c:79
static void os_heartbeat_task(void)
Definition kernel.c:175
ICARUS Kernel Core - State and Initialization.
void os_yield(void)
Voluntarily yield CPU to scheduler.
Definition svc.c:511
const char * os_get_current_task_name(void)
Get name of currently executing task.
Definition svc.c:575
uint32_t task_active_sleep(uint32_t ticks)
Sleep for specified ticks (cooperative, via SVC)
Definition svc.c:522
void LED_On(void)
Turn LED on.
void LED_Blink(uint32_t on_ticks, uint32_t off_ticks)
Blink LED with specified timing.
void LED_Off(void)
Turn LED off.
ICARUS Scheduler - Task Scheduling and Timing.
uint8_t os_is_running(void)
Check if OS is running (safe from unprivileged mode)
Definition svc.c:1166
Message Pipe (Queue)
Definition types.h:169
uint16_t count
Current number of bytes in buffer.
Definition types.h:171
uint16_t dequeue_idx
Read index (circular)
Definition types.h:174
uint16_t max_count
Maximum buffer capacity in bytes.
Definition types.h:172
uint16_t enqueue_idx
Write index (circular)
Definition types.h:173
uint8_t buffer[512]
Circular message buffer.
Definition types.h:176
uint32_t tick_updated_at
Last modification timestamp.
Definition types.h:175
bool engaged
true if pipe is initialized and active
Definition types.h:170
Counting Semaphore.
Definition types.h:151
uint32_t tick_updated_at
Last modification timestamp (for debugging)
Definition types.h:155
uint32_t max_count
Maximum count (initial value)
Definition types.h:154
bool engaged
true if semaphore is initialized and active
Definition types.h:152
uint32_t count
Current semaphore count.
Definition types.h:153
Task Control Block (TCB)
Definition types.h:115
char name[32]
Human-readable task name.
Definition types.h:131
icarus_task_state_t task_state
Current task state (offset 16)
Definition types.h:123
uint32_t dispatch_count
Times this task has been dispatched.
Definition types.h:132
uint32_t * stack_base
Base address of task stack.
Definition types.h:118
uint32_t stack_size
Stack size in 32-bit words.
Definition types.h:119
uint32_t stack_watermark
Minimum free stack words observed.
Definition types.h:133
ICARUS Task Management - Creation and Lifecycle.
void __os_register_task(void(*function)(void), const char *name)
Privileged implementation of os_register_task.
Definition task.c:74
icarus_task_state_t
Task state enumeration.
Definition types.h:75
@ TASK_STATE_FINISHED
Task completed execution normally.
Definition types.h:81