### Introduction In embedded development, many devices nowadays run specific operating systems like Linux, RT-Thread, FreeRTOS, uC/OS, etc. However, there are still quite a number of devices that don't use an operating system and instead operate in a "bare-metal" mode (also known as a foreground-background system). In software development for such systems without an operating system, a common approach is to put all the functions to be executed in a loop and execute each function sequentially in the loop. And if there are requirements for the execution period of functions, timers can be used to determine how often a certain function should be executed. But when it comes to managing multiple such functions, this programming method becomes rather redundant and cumbersome, and it's not convenient for us to manage. Here, a kernel for managing timed tasks has been developed. The only hardware resource it requires is a timer (used to obtain time slices). Of course, it can also run on a computer as long as it can obtain time slices. The main function of this kernel is to achieve the periodic invocation of functions. In other words, this kernel realizes the function of a software timer. ### Interface #### Kernel Initialization ```c int kern_init(kern_tick_t tick_func, unsigned short time_slice); ``` Before task scheduling, the kernel must be initialized first. The initialization is quite simple. Pass in the clock function `tick_func` that can obtain time slices and the specific clock period `time_slice` of the clock function (usually in milliseconds). If the initialization is successful, it will return `KE_OK`; otherwise, it will return other values indicating failure. #### Task Creation and Deletion ```c task_t task_create(unsigned short period, task_handler_t handler); int task_delete(task_t task); ``` Task creation is straightforward. One needs to pass in the period `period` of the task (the unit is the time slice passed in during kernel initialization) and the execution function `handler` of the task. If the creation is successful, it will return the unique ID of the task; otherwise, it will return 0. For deletion, just pass in the task ID. If the deletion is successful, it will return `KE_OK`; otherwise, it will return other values indicating failure. #### Task Scheduling ```c void kern_schedule(void); ``` After initializing the kernel, the kernel scheduling function can be called. However, there will be no tasks at this time. Generally, tasks are created first and then scheduled. This scheduling function has no exit and will keep running until the program ends. Therefore, the code after the scheduling function won't be executed. So don't write code after the scheduling function. #### Running Task ```c task_t task_running(void); ``` Different tasks can have the same execution function. This function is used to distinguish which task is calling the execution function. ### Example ```c static unsigned int get_msec(void) { struct timeval mstime; unsigned int ms = 0; gettimeofday(&mstime, NULL); ms = mstime.tv_sec * 1000 + mstime.tv_usec / 1000; return ms; } void task1(void) { static int count = 0; printf("task1 running! %d\r\n", ++count); } void task2(void) { static int count = 0; printf("task2 running! %d\r\n", ++count); } int main(int argc, char *argv[]) { if (kern_init(get_msec, 1) == KE_OK) { printf("kern init success!\r\n"); } else { printf("*** kern init fail!\r\n"); return; } printf("create task %d\r\n", task_create(1000, task1)); printf("create task %d\r\n", task_create(500, task2)); kern_schedule(); return 0; } ``` **Running Results**: ``` kern init success! create task 1 create task 2 task1 running! 1 task2 running! 1 task2 running! 2 task1 running! 2 task2 running! 3 task2 running! 4 task1 running! 3 task2 running! 5 task2 running! 6 task1 running! 4 task2 running! 7 task2 running! 8 ``` Task 2 has run 2 times while the corresponding Task 1 has run 1 time.