فهرست منبع

Start working on docs.

Taiga Develop 2 هفته پیش
والد
کامیت
77fd093e31

+ 2 - 1
build-wch-riscv/zivuos.mk

@@ -2,6 +2,7 @@ ZIVUOS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))/..)
 ZIVUOS_SOURCES := $(wildcard  $(ZIVUOS_DIR)/sources/*.c)
 ZIVUOS_CFLAGS += -I$(ZIVUOS_DIR)/headers/
 ZIVUOS_CFLAGS += -DZIVUOS_PLATFORM_WCH_RISCV
+ZIVUOS_CFLAGS += -DZIVUOS_USE_32BIT_TIME
 
-CFLAGS += $(ZIVUOS_CFLAGS)
+EXTRA_CFLAGS += $(ZIVUOS_CFLAGS)
 ADDITIONAL_C_FILES += $(ZIVUOS_SOURCES)

+ 2 - 0
headers/zivuos.h

@@ -9,5 +9,7 @@
 #include "zivuos/kernel.h"
 #include "zivuos/scheduler.h"
 #include "zivuos/zv_time.h"
+#include "zivuos/platform.h"
+#include "zivuos/idle.h"
 
 #endif

+ 151 - 3
headers/zivuos/event.h

@@ -5,37 +5,185 @@
 #include "event_type.h"
 #include "zv_time.h"
 
+/**
+ * @brief List of event types.
+ * 
+ * That enum is used to store type of the event. Default event is empty,
+ * which mean that no event occur.
+ */
+typedef enum zv_event_type_e {
+    
+    /* That mean no event occur. */
+    ZV_EVENT_EMPTY,
+
+    /* That mean event is timer, whose waiting time has already expired. */
+    ZV_EVENT_TIMER,
+    
+    /* 
+     * That mean timer event is waiting in first phrase, it is used by 
+     * scheduler for timer processing.
+     */
+    ZV_EVENT_TIMER_PHRASE_FIRST,
+
+    /* 
+     * That mean timer event is waiting in second phrase, it is used by 
+     * scheduler for timer processing.
+     */
+    ZV_EVENT_TIMER_PHRASE_SECOND,
+
+    /* That mean event with data occured. */
+    ZV_EVENT_DATA,
+
+    /* That mean event with unsigned data occured. */
+    ZV_EVENT_UDATA,
+
+    /* That mean event with object pointer occured. */
+    ZV_EVENT_OBJECT,
+
+} zv_event_type_t;
+
+
+/**
+ * @brief That store content of the event.
+ * 
+ * That union store content of event. Event could store pointer to any
+ * object, number or time. How to interpret content of that union depends
+ * on type of the event.
+ */
 typedef union zv_event_content_u {
+    
+    /* Pointer to any object. */
     void *object;
+
+    /* Time after which task would be ready. */
     zv_time_t time;
-    uint64_t unumber;
-    int64_t number;
+
+    /* Unsigned number. */
+    uintptr_t unumber;
+
+    /* Signed number. */
+    intptr_t number;
+
 } zv_event_content_t;
 
+/**
+ * @brief That is event container. Do not modify without API function.
+ * 
+ * That is event container. Store type of the event and its content.
+ * Type could also being empty, which mean that event did not occur.
+ */
 typedef struct zv_event_s {
+    
+    /* Type of the event. */
     zv_event_type_t type;
+
+    /* Content of the event. */
     zv_event_content_t content;
+
 } zv_event_t;
 
+/**
+ * That would return true, when event is timer in any phrase. Software
+ * timers are supported by scheduler, and it is used to determinate which
+ * event must being updated by scheduler every task selection loop.
+ */
+#define __zv_event_is_working_timer(X) (\
+    X.type == ZV_EVENT_TIMER_PHRASE_FIRST \
+    || X.type == ZV_EVENT_TIMER_PHRASE_SECOND \
+)
+
+/** 
+ * That return true, when any event occur. It is used to determinate
+ * chech if the process should be updated to ZV_TASK_READY state.
+ */
+#define __zv_event_is_set(X) ( \
+    X.type != ZV_EVENT_EMPTY \
+    && !__zv_event_is_working_timer(X) \
+)
+
+/**
+ * That function clean event. After call it, target event would return to
+ * default empty state with empty content.
+ *
+ * @param target Pointer to target event.
+ */
+static inline void __zv_event_clear(zv_event_t *target) {
+    target->type = ZV_EVENT_EMPTY;
+    target->content = (zv_event_content_t) { .unumber = 0x00 };
+}
 
+/** 
+ * @brief That function send event with number.
+ *
+ * That function would trigger event with number content for choosen task.
+ * 
+ * @param self Kernel object to work on.
+ * @param target Target task TID.
+ * @param content Content of event to push.
+ * @return True when operation end with success. False when operation
+ *         could not being finalized, for example task not exists or 
+ *         event already in use.
+ */
 bool zv_event_push_number(
     struct zv_kernel_s *self,
     zv_tid_t target,
     int64_t content
 );
 
+/**
+ * @brief That function send event with unsigned number.
+ *
+ * That function would trigger event with unsigned number content 
+ * for choosen task.
+ * 
+ * @param self Kernel object to work on.
+ * @param target Target task TID.
+ * @param content Content of event to push.
+ * @return True when operation end with success. False when operation
+ *         could not being finalized, for example task not exists or 
+ *         event already in use.
+ */
 bool zv_event_push_unumber(
     struct zv_kernel_s *self,
     zv_tid_t target,
     uint64_t content
 );
 
+/**
+ * @brief That function set software timer for task.
+ * 
+ * That function would use event to set software timer. It use event 
+ * to store timestamp after which time event would be triggered. Timestamp
+ * would be calculated automatically by delay time.
+ * 
+ * @param self Kernel object to work on.
+ * @param target Target task TID.
+ * @param delay_time Time after which timer event would be triggered 
+ *                   is ms. For example 500 for 500ms.
+ * @return True when operation end with success. False when operation
+ *         could not being finalized, for example task not exists or 
+ *         event already in use.
+ */
 bool zv_event_set_timer(
     struct zv_kernel_s *self,
     zv_tid_t target,
-    zv_time_t time
+    zv_time_t delay_time
 );
 
+/**
+ * @brief That function send event with pointer to any data type.
+ *
+ * That function would trigger event with pointer to object as content.
+ * Pointer is void type, which mean that data type must be known by 
+ * event receiver.
+ * 
+ * @param self Kernel object to work on.
+ * @param target Target task TID.
+ * @param content Pointer to target data.
+ * @return True when operation end with success. False when operation
+ *         could not being finalized, for example task not exists or 
+ *         event already in use.
+ */
 bool zv_event_push_object(
     struct zv_kernel_s *self,
     zv_tid_t target,

+ 0 - 12
headers/zivuos/event_type.h

@@ -1,12 +0,0 @@
-#ifndef CX_ZIVUOS_EVENT_TYPE_H_INCLUDED
-#define CX_ZIVUOS_EVENT_TYPE_H_INCLUDED
-
-typedef enum zv_event_type_e {
-    ZV_EVENT_EMPTY,
-    ZV_EVENT_TIMER,
-    ZV_EVENT_DATA,
-    ZV_EVENT_OBJECT
-} zv_event_type_t;
-
-#endif
-

+ 34 - 0
headers/zivuos/idle.h

@@ -0,0 +1,34 @@
+#ifndef CX_ZIVUOS_IDLE_H_INCLUDED
+#define CX_ZIVUOS_IDLE_H_INCLUDED
+
+#include "zv_types.h"
+
+/** 
+ * That is type of IDLE worker function. It is called when all other
+ * tasks are in waiting (not ready) state.
+ * That function must analyze tasks stack, and check that any task 
+ * exists. If all task slots are empty, then IDLE worker would 
+ * return false. When tasks exists, but are not in ready state it
+ * must return true.
+ * 
+ * @param self Kernel to work on.
+ * @return True when any task exists, false if not.
+ */
+typedef bool (*zv_idle_worker_t) (struct zv_kernel_s *); 
+
+/** 
+ * That is default IDLE worker function. That check if any task exists on
+ * task stack. It must be called from custom IDLE worker, if any custom 
+ * IDLE worker had been selected.
+ *
+ * @param self Kernel to work on.
+ * @return True when any task exists, false when not.
+ */
+bool zv_idle_worker_check_tasks(struct zv_kernel_s *self);
+
+/**
+ * Select zv_idle_worker_check_tasks as default IDLE worker.
+ */
+#define zv_idle_worker_default zv_idle_worker_check_tasks
+
+#endif

+ 72 - 6
headers/zivuos/kernel.h

@@ -6,16 +6,21 @@
 
 #include "zv_types.h"
 #include "task.h"
+#include "idle.h"
 
 /**
  * @brief That return number of tasks from tasks array (x for zv_task_t [x]).
- * Usefull for zv_kernel_init
+ * Usefull for zv_kernel_init.
+ * 
+ * @param X Tasks stack.
+ * @return Tasks count on tasks stack.
  */
 #define ZV_COUNT_TASKS(X) (sizeof(X) / sizeof(zv_task_t))
 
 /**
- * @brief That is main kernel structure. 
- * It store pointer to tasks stack, and size of that stack.
+ * @brief That is main kernel structure. Do not modify without API.
+ * 
+ * It store pointer to tasks stack, size of that stack and idle worker.
  */
 typedef struct zv_kernel_s {
     
@@ -25,24 +30,53 @@ typedef struct zv_kernel_s {
     /** Size of tasks stack. */
     zv_tid_t tasks_count;
 
+    /** That is idle worker. By default do nothing. Could be replaced. */
+    zv_idle_worker_t idle_worker;
+
 } zv_kernel_t;
 
 /**
  * @brief That initialize kernel structure.
+ * 
+ * That function initialize kernel structure. It must be called to initialize
+ * kernel. 
+ * Kernel initialization require tasks stack and kernel structure which is
+ * NULL pointers, and tasks stack count which must be greater than 0.
+ *
  * @param self Pointer to kernel structure to work on.
  * @param tasks Pointer to tasks stack.
  * @param count Number of tasks slots on stack.
+ * @return True when kernel initialize success, false if cannot initialize it.
  */
-void zv_kernel_init(zv_kernel_t *self, zv_task_t *tasks, zv_tid_t count);
+bool zv_kernel_init(zv_kernel_t *self, zv_task_t *tasks, zv_tid_t count);
 
 /** 
  * @brief That boot OS. It return when task stack is empty.
+ * 
+ * That is main kernel loop. By default it would not return. 
+ * It could be break only when tasks stack is empty, or when any task
+ * raise error.
+ *
  * @return True when everything is executed, and all tasks had been killed.
  *         False when something went wrong.
  */
 bool zv_kernel_boot(zv_kernel_t *self);
 
-
+/**
+ * @brief That function create process.
+ * 
+ * That function create process, require process worker, process priority
+ * and process param. Process param is pointer to any data or number as 
+ * intptr_r or uintptr_t. It return task ID or ZV_TID_NULL when can not
+ * create process. Process creation fails when worker is NULL pointer or
+ * when tasks stack is full.
+ *
+ * @param self Kernel to work on.
+ * @param worker Worker of the process.
+ * @param priority Priority of the process. Greater number is bigger priority.
+ * @param param Param of the process.
+ * @return Task ID on success, ZV_TID_NULL on fail.
+ */
 zv_tid_t zv_kernel_create_process(
     zv_kernel_t *self,
     zv_worker_t worker,
@@ -50,13 +84,45 @@ zv_tid_t zv_kernel_create_process(
     void *param
 );
 
-void zv_kernel_kill_process(
+/** 
+ * @brief That function kill process.
+ * 
+ * That function kill process. Process can not being killed when not exists.
+ * 
+ * @param self Kernel to work on.
+ * @param target Task ID of task to kill.
+ * @return True when task killed successfull, false when failed.
+ */
+bool zv_kernel_kill_process(
     zv_kernel_t *self,
     zv_tid_t target
 );
 
+/**
+ * That function return first empty slot TID or ZV_TID_NULL when tasks stack
+ * is full.
+ * 
+ * @param self Kernel to work on.
+ * @return First empty task slot TID or ZV_TID_NULL when tasks stack is full.
+ */
 zv_tid_t __zv_kernel_get_empty_slot(zv_kernel_t *self);
+
+/**
+ * That function return pointer to task based on task ID.
+ * 
+ * @param self Kernel to work on.
+ * @param target Task ID to get pointer.
+ * @return Pointer to task with given ID or NULL when task slot not exists.
+ */
 zv_task_t * __zv_kernel_get_task(zv_kernel_t *self, zv_tid_t target);
+
+/**
+ * That function return task ID based on pointer to task on task stack.
+ * 
+ * @param self Kernel to work on.
+ * @param target Pointer to task.
+ * @return Task ID of that task.
+ */
 zv_tid_t __zv_kernel_get_tid(zv_kernel_t *self, zv_task_t *target);
 
 #endif

+ 31 - 0
headers/zivuos/platform.h

@@ -0,0 +1,31 @@
+#ifndef CX_ZIVUOS_PLATFORM_H_INCLUDED
+#define CX_ZIVUOS_PLATFORM_H_INCLUDED
+
+/**
+ * @brief That initialize plarform for ZivuOS.
+ *
+ * That do initialization of the platform required for ZivuOS to property 
+ * work. A lot of initialization process touches SysTick, which is used to
+ * generate software timers.
+ */
+void zv_platform_init(void);
+
+/** 
+ * That return time of the system in miliseconds. That is 32 or 64 bit
+ * number, used in software timers. It is low-level ZivuOS function, 
+ * use API functions to get time of the system.
+ *
+ * @return Time of the system in miliseconds.
+ */
+zv_time_t __zv_platform_get_time_ms(void);
+
+/**
+ * That return time of the system in microseconds. That is 32 bit number
+ * and it could return to zero after +/- 100 seconds. Use API functions
+ * to generate small delays.
+ * 
+ * @return Time of the system in microseconds.
+ */
+zv_ticks_t __zv_platform_get_time_us(void);
+
+#endif

+ 9 - 3
headers/zivuos/scheduler.h

@@ -4,9 +4,15 @@
 #include "kernel.h"
 #include "task.h"
 
-void __zv_scheduler_update_tasks(zv_kernel_t *self);
-zv_task_t * __zv_scheduler_find_task(zv_kernel_t *self);
-void __zv_scheduler_run_task(zv_kernel_t *self, zv_task_t *target);
+/**
+ * That is single loop of the scheduler. It is low-level ZivuOS function, do
+ * not use it in app.
+ * That return true when any task had been executed, or false if all tasks
+ * are in waiting state.
+ *
+ * @return True when any task executed, false when all tasks waiting.
+ */
+bool __zv_scheduler_single_loop(zv_kernel_t *self);
 
 #endif
 

+ 40 - 3
headers/zivuos/state.h

@@ -1,14 +1,51 @@
 #ifndef CX_ZIVUOS_STATE_H_INCLUDED
 #define CX_ZIVUOS_STATE_H_INCLUDED
 
+/**
+ * @brief States of the task.
+ *
+ * That is current task state. It is used also to mark empty tasks
+ * slots. Worker also uses that type to mark new state of the task.
+ */
 typedef enum zv_state_e {
+
+    /* That state mark task slot as empty. */
     ZV_TASK_EMPTY,
+
+    /* That mean task is ready, and wait to be executed. */
     ZV_TASK_READY,
+
+    /* That mean task is now executed. */
     ZV_TASK_RUNNING,
-    ZV_TASK_ANY_EVENT_WAIT,
-    ZV_TASK_TIMER_EVENT_WAIT,
-    ZV_TASK_DATA_EVENT_WAIT
+
+    /* 
+     * That mean task is waiting for any event. When any event 
+     * had been received, task state would be update to ZV_TASK_READY 
+     * by scheduler.
+    */
+    ZV_TASK_EVENT_WAIT,
+
+    /* 
+     * That mean task is waiting for timer event. System timers are 
+     * processed by scheduler, when target time had elapsed, scheduler
+     * would update task state to ZV_TASK_READY.
+     */
+    ZV_TASK_TIMER_WAIT,
+
+    /*
+     * That state could be used by worker. When worker return that state,
+     * task would be killed.
+     */
+    ZV_TASK_KILLED,
+
 } zv_state_t;
 
+/**
+ * That would return true when task is supported by scheduler timer.
+ */
+#define __zv_state_is_timer(X) ( \
+    X == ZV_TASK_TIMER_WAIT \
+)
+
 #endif
 

+ 10 - 0
headers/zivuos/task.h

@@ -5,6 +5,11 @@
 #include "state.h"
 #include "event.h"
 
+/** 
+ * @brief That structure store single stack.
+ *
+ * 
+ */
 typedef struct zv_task_s {
     zv_state_t state;
     void *param;
@@ -14,5 +19,10 @@ typedef struct zv_task_s {
     zv_priority_t priority;
 } zv_task_t;
 
+#define __zv_task_mark_running(X) (X->state = ZV_TASK_RUNNING)
+#define __zv_task_clear_age(X) (X->age = 0)
+#define __zv_task_is_ready(X) (X->state == ZV_TASK_READY)
+#define __zv_task_calc_priority(X) ((X->priority) + (X->age))
+
 #endif
 

+ 27 - 4
headers/zivuos/zv_time.h

@@ -3,12 +3,35 @@
 
 #include "zv_types.h"
 
+#ifndef ZIVUOS_USE_32BIT_TIME
+
+/** System time in ms. */
 typedef uint64_t zv_time_t;
+
+#else
+
+/** System time in ms. */
+typedef uint32_t zv_time_t;
+
+#endif
+
+/** System time for precission delays and measurments */
 typedef uint32_t zv_ticks_t;
 
-void zv_platform_init(void);
-zv_time_t zv_platform_get_time(void);
-zv_ticks_t zv_platform_get_ticks(void);
-zv_ticks_t zv_platform_get_time_us(void);
+#define ZV_TIME_MAX ((zv_time_t) -1)
+#define ZV_TICKS_MAX ((zv_ticks_t) -1)
+
+#define zv_time_get_ticks __zv_platform_get_time_us
+#define zv_time_get_time __zv_platform_get_time_ms
+
+#define zv_time_remaining(X, Y) ((zv_time_t) (Y - X))
+#define zv_ticks_remaining(X, Y) ((zv_ticks_t) (Y - X))
+
+#define zv_time_after(X, Y) ((zv_time_t) (X + Y))
+#define zv_ticks_after(X, Y) ((zv_ticks_t) (X + Y))
+
+#define zv_time_get_time_after(X) (zv_time_get_time() + X)
+void zv_time_ticks_delay(zv_ticks_t delay);
+void __zv_time_process_timer(struct zv_event_s *);
 
 #endif

+ 87 - 0
sources/event.c

@@ -0,0 +1,87 @@
+#include <zivuos.h>
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+static inline bool __zv_event_already_set(zv_event_t *target) {
+    return target->type != ZV_EVENT_EMPTY;
+}
+
+static bool __zv_event_push_content(
+    zv_kernel_t *self,
+    zv_tid_t target_tid,
+    zv_event_type_t type,
+    zv_event_content_t content
+) {
+    zv_task_t *target_task = __zv_kernel_get_task(self, target_tid);
+
+    if (target_task == NULL) {
+        return false;
+    }
+
+    zv_event_t *target_event = &target_task->event;
+
+    if (__zv_event_already_set(target_event)) {
+        return false;
+    }   
+
+    target_event->content = content;
+    target_event->type = type;
+
+    return true;
+}
+
+bool zv_event_push_number(
+    struct zv_kernel_s *self,
+    zv_tid_t target,
+    int64_t content
+) {
+    return __zv_event_push_content(
+        self,
+        target,
+        ZV_EVENT_DATA,
+        (zv_event_content_t) {.number = content}
+    );
+}
+
+bool zv_event_push_unumber(
+    struct zv_kernel_s *self,
+    zv_tid_t target,
+    uint64_t content
+) {
+    return __zv_event_push_content(
+        self,
+        target,
+        ZV_EVENT_UDATA,
+        (zv_event_content_t) {.unumber = content}
+    );
+}
+
+bool zv_event_set_timer(
+    struct zv_kernel_s *self,
+    zv_tid_t target,
+    zv_time_t delay
+) {
+    zv_time_t result_time = zv_time_after(zv_time_get_time(), delay);
+
+    return __zv_event_push_content(
+        self,
+        target,
+        ZV_EVENT_TIMER_PHRASE_FIRST,
+        (zv_event_content_t) {.time = result_time}
+    );
+}
+
+bool zv_event_push_object(
+    struct zv_kernel_s *self,
+    zv_tid_t target,
+    void *content
+) {
+    return __zv_event_push_content(
+        self,
+        target,
+        ZV_EVENT_OBJECT,
+        (zv_event_content_t) {.object = content}
+    );
+}

+ 0 - 90
sources/event.c.bak

@@ -1,90 +0,0 @@
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-#include "zivuos/zv_types.h"
-#include "zivuos/kernel.h"
-#include "zivuos/task.h"
-#include "zivuos/event.h"
-#include "zivuos/zv_time.h"
-
-static inline bool __zv_event_empty(zv_event_t *self) {
-    return self->type == ZV_EVENT_EMPTY;
-}
-
-bool zv_event_push_number(
-    struct zv_kernel_s *self,
-    zv_tid_t target,
-    int64_t content
-) {
-    zv_task_t *task = __zv_kernel_get_task(self, target);
-    zv_event_t *event = &task->event;
-
-    if (!__zv_event_empty(event)) {
-        return false;
-    }
-
-    event->type = ZV_EVENT_DATA;
-    event->content.number = content;
-
-    return true;
-}
-
-bool zv_event_push_unumber(
-    struct zv_kernel_s *self,
-    zv_tid_t target,
-    uint64_t content
-) {
-    zv_task_t *task = __zv_kernel_get_task(self, target);
-    zv_event_t *event = &task->event;
-
-    if (!__zv_event_empty(event)) {
-        return false;
-    }
-
-    event->type = ZV_EVENT_DATA;
-    event->content.unumber = content;
-
-    return true;
-}
-
-bool zv_event_set_timer(
-    struct zv_kernel_s *self,
-    zv_tid_t target,
-    zv_time_t time
-) {
-    zv_task_t *task = __zv_kernel_get_task(self, target);
-    zv_event_t *event = &task->event;
-
-    if (!__zv_event_empty(event)) {
-        return false;
-    }
-
-    zv_time_t current_time = zv_platform_get_time();
-    zv_time_t final_time = current_time + time;
-
-    event->type = ZV_EVENT_TIMER;
-    event->content.time = final_time;
-    return true;
-}
-
-bool zv_event_push_object(
-    struct zv_kernel_s *self,
-    zv_tid_t target,
-    void *content
-) {
-    if (content == NULL) {
-        return false;
-    }
-
-    zv_task_t *task = __zv_kernel_get_task(self, target);
-    zv_event_t *event = &task->event;
-
-    if (!__zv_event_empty(event)) {
-        return false;
-    }
-
-    event->type = ZV_EVENT_OBJECT;
-    event->content.object = content;
-    return true;
-}

+ 12 - 0
sources/idle.c

@@ -0,0 +1,12 @@
+#include <zivuos.h>
+
+bool zv_idle_worker_check_tasks(zv_kernel_t *self) {
+    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
+        if (__zv_kernel_get_task(self, count)->state != ZV_TASK_EMPTY) {
+            return true;
+        }
+    }
+
+    return false;
+}
+

+ 42 - 7
sources/kernel.c

@@ -1,14 +1,37 @@
 #include <zivuos.h>
+#include <stddef.h>
+
+static inline void __zv_kernel_init_task(zv_task_t *target) {
+    target->state = ZV_TASK_EMPTY;
+    target->param = NULL;
+    target->event.type = ZV_EVENT_EMPTY;
+    target->event.content.unumber = 0;
+    target->age = 0;
+    target->priority = 0;
+    target->worker = NULL;
+}
 
 /**
  * @brief That initialize kernel structure.
  * @param self Pointer to kernel structure to work on.
  * @param tasks Pointer to tasks stack.
  * @param count Number of tasks slots on stack.
+ * @return True when kernel initialized success or false when not.
  */
-void zv_kernel_init(zv_kernel_t *self, zv_task_t *tasks, zv_tid_t count) {
+bool zv_kernel_init(zv_kernel_t *self, zv_task_t *tasks, zv_tid_t count) {
+    if (self == NULL || tasks == NULL || count < 2) {
+        return false;
+    }
+
     self->tasks = tasks;
     self->tasks_count = count;
+    self->idle_worker = zv_idle_worker_default;
+
+    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
+        __zv_kernel_init_task(self->tasks + count);
+    }
+
+    return true;
 }
 
 /** 
@@ -18,8 +41,14 @@ void zv_kernel_init(zv_kernel_t *self, zv_task_t *tasks, zv_tid_t count) {
  */
 bool zv_kernel_boot(zv_kernel_t *self) {
     while (true) {
-         
+        bool any_task_exists = __zv_scheduler_single_loop(self);
+
+        if (!any_task_exists) {
+            return true;
+        }
     }
+
+    return false;
 }
 
 
@@ -32,10 +61,10 @@ zv_tid_t zv_kernel_create_process(
     zv_tid_t slot = __zv_kernel_get_empty_slot(self);
 
     if (slot == ZV_TID_NULL) {
-        return false;
+        return ZV_TID_NULL;
     }
 
-    zv_task_t target = self->tasks + slot;
+    zv_task_t *target = self->tasks + slot;
 
     target->param = param;
     target->worker = worker;
@@ -46,17 +75,23 @@ zv_tid_t zv_kernel_create_process(
     return slot;
 }
 
-void zv_kernel_kill_process(
+bool zv_kernel_kill_process(
     zv_kernel_t *self,
     zv_tid_t target
 ) {
-    zv_task_t current = self->tasks + target; 
+    zv_task_t *current = self->tasks + target; 
+    
+    if (current->state == ZV_TASK_EMPTY) {
+        return false;
+    }
+
     current->state = ZV_TASK_EMPTY;
+    return true;
 }
 
 zv_tid_t __zv_kernel_get_empty_slot(zv_kernel_t *self) {
     for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
-        zv_task_t current = self->tasks + count;
+        zv_task_t *current = self->tasks + count;
 
         if (current->state == ZV_TASK_EMPTY) {
             return count;

+ 0 - 113
sources/kernel.c.bak

@@ -1,113 +0,0 @@
-#include <stddef.h>
-#include <stdint.h>
-
-#include "zivuos/task.h"
-#include "zivuos/kernel.h"
-#include "zivuos/scheduler.h"
-
-bool zv_kernel_init(zv_kernel_t *self, zv_task_t *tasks, zv_tid_t count) {
-    if (self == NULL || tasks == NULL || count < 1) {
-        return false;
-    }
-
-    self->tasks = tasks;
-    self->tasks_count = count;
-    self->scheduler = ZV_SCHEDULER_PRIORITY_AGING;
-
-    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
-        zv_task_t *current = self->tasks + count;
-        current->state = ZV_TASK_EMPTY;
-    }
-    
-    return true;
-}
-
-
-bool zv_kernel_boot(zv_kernel_t *self) {
-    if (self == NULL || self->tasks == NULL || self->tasks_count < 1) {
-        return false;
-    }
-
-    while (true) {
-        __zv_scheduler_update_tasks(self);
-        zv_task_t *next = __zv_scheduler_find_task(self);
-
-        if (next == NULL) {
-            break;
-        }
-
-        __zv_scheduler_run_task(self, next);
-    }   
-    
-    return true;
-}
-
-zv_tid_t __zv_kernel_get_empty_slot(zv_kernel_t *self) {
-    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
-        zv_task_t *current = self->tasks + count;
-        
-        if (current->state == ZV_TASK_EMPTY) {
-            return count;
-        }
-    }
-
-    return ZV_TID_NULL;
-}
-
-zv_task_t *__zv_kernel_get_task(zv_kernel_t *self, zv_tid_t target) {
-    if (self->tasks_count <= target) {
-        return NULL;
-    }
-
-    return self->tasks + target;
-}
-
-zv_tid_t zv_kernel_create_process(
-    zv_kernel_t *self,
-    zv_worker_t worker,
-    zv_priority_t priority,
-    void *param
-) {
-    if (self == NULL || worker == NULL) {
-        return ZV_TID_NULL;
-    }
-
-    zv_tid_t target_tid = __zv_kernel_get_empty_slot(self);
-    zv_task_t *target = __zv_kernel_get_task(self, target_tid);
-
-    if (target == NULL) {
-        return ZV_TID_NULL;
-    }
-
-    target->worker = worker;
-    target->param = param;
-    target->priority = priority;
-    
-    target->event.type = ZV_EVENT_EMPTY;
-    target->event.content.unumber = 0x00;
-    
-    target->state = ZV_TASK_READY;
-    return target_tid;
-}
-
-bool zv_kernel_kill_process(
-    zv_kernel_t *self,
-    zv_tid_t target_tid
-) {
-    if (self == NULL) {
-        return false;
-    }
-
-    zv_task_t *target = __zv_kernel_get_task(self, target_tid);
-
-    if (target == NULL) {
-        return false;
-    }
-
-    target->state = ZV_TASK_EMPTY;
-    return true;
-}
-
-zv_tid_t __zv_kernel_get_tid(zv_kernel_t *self, zv_task_t *target) {
-    return target - self->tasks;
-}

+ 2 - 2
sources/platform_linux.c.bak → sources/platform_linux.c

@@ -14,7 +14,7 @@ void zv_platform_init(void) {
     
 }
 
-zv_time_t zv_platform_get_time(void) {
+zv_time_t __zv_platform_get_time_ms(void) {
     struct timespec current_time;
 
     clock_gettime(CLOCK_REALTIME, &current_time);
@@ -41,7 +41,7 @@ zv_ticks_t zv_platform_get_ticks(void) {
     return current_time.tv_nsec;
 }   
 
-zv_ticks_t zv_platform_get_time_us(void) {
+zv_ticks_t __zv_platform_get_time_us(void) {
     return zv_platform_get_ticks() / 1000; 
 }
 

+ 4 - 10
sources/platform_wch_riscv.c.bak → sources/platform_wch_riscv.c

@@ -5,9 +5,7 @@
 #include <stdbool.h>
 
 #include <ch32fun.h>
-
-#include "zivuos/zv_types.h"
-#include "zivuos/zv_time.h"
+#include <zivuos.h>
 
 #ifndef FUNCONF_SYSTEM_CORE_CLOCK
 #error "MCU core clock (FUNCONF_SYSTEM_CORE_CLOCK) not defined."
@@ -16,7 +14,7 @@
 #define ZV_TICKS_PER_US ((uint32_t) FUNCONF_SYSTEM_CORE_CLOCK / 1000000)
 #define ZV_TICKS_PER_MS ((uint32_t) FUNCONF_SYSTEM_CORE_CLOCK / 1000)
 
-volatile uint32_t __zv_current_time_miliseconds;
+volatile zv_time_t __zv_current_time_miliseconds;
 
 void zv_platform_init(void) {
     __zv_current_time_miliseconds = 0;
@@ -41,15 +39,11 @@ void SysTick_Handler(void) {
     ++__zv_current_time_miliseconds;
 }
 
-zv_time_t zv_platform_get_time(void) {
+zv_time_t __zv_platform_get_time_ms(void) {
     return __zv_current_time_miliseconds;
 }
 
-zv_ticks_t zv_platform_get_ticks(void) {
-    return SysTick->CNT;
-}
-
-zv_ticks_t zv_platform_get_time_us(void) {
+zv_ticks_t __zv_platform_get_time_us(void) {
     return SysTick->CNT / ZV_TICKS_PER_US;
 }
 

+ 86 - 0
sources/scheduler.c

@@ -0,0 +1,86 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <zivuos.h>
+
+static void __zv_scheduler_update_task(zv_task_t *target) {
+    if (__zv_event_is_working_timer(target->event)) {
+        __zv_time_process_timer(&target->event);
+    }   
+
+    if (__zv_event_is_set(target->event)) {
+        target->state = ZV_TASK_READY;
+    }
+
+    if (target->state == ZV_TASK_READY) {
+        ++target->age;
+    }
+}
+
+static void __zv_scheduler_run_task(zv_kernel_t *self, zv_tid_t target_tid) {
+    zv_task_t *target = __zv_kernel_get_task(self, target_tid);
+    zv_event_t event_copy = target->event;
+    
+    __zv_task_mark_running(target);
+    __zv_task_clear_age(target);
+    __zv_event_clear(&target->event);
+
+    zv_state_t exit_state = target->worker(
+        self,
+        &event_copy,
+        target_tid,
+        target->param
+    );
+
+    if (exit_state == ZV_TASK_RUNNING) {
+        exit_state = ZV_TASK_READY;
+    }
+
+    if (exit_state == ZV_TASK_EMPTY || exit_state == ZV_TASK_KILLED) {
+        zv_kernel_kill_process(self, target_tid);
+        return;
+    }
+
+    target->state = exit_state;
+}
+
+static zv_tid_t __zv_scheduler_select_next_task(zv_kernel_t *self) {
+    zv_tid_t selected = ZV_TID_NULL;
+    zv_priority_t selected_priority = 0;
+
+    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
+        zv_task_t *current = __zv_kernel_get_task(self, count);
+
+        __zv_scheduler_update_task(current);
+
+        if (!__zv_task_is_ready(current)) {
+            continue;
+        }
+
+        zv_priority_t current_priority = __zv_task_calc_priority(current);
+
+        if (selected == ZV_TID_NULL || current_priority > selected_priority) {
+            selected = count;
+            selected_priority = current_priority;
+        }
+    }
+
+    return selected;
+}  
+
+bool __zv_scheduler_single_loop(zv_kernel_t *self) {
+    zv_tid_t next_task = __zv_scheduler_select_next_task(self);
+
+    if (next_task == ZV_TID_NULL) {
+        if (!self->idle_worker(self)) {
+            return false;
+        }       
+
+        return true;
+    }
+
+    __zv_scheduler_run_task(self, next_task);
+    return true;
+}

+ 0 - 136
sources/scheduler.c.bak

@@ -1,136 +0,0 @@
-#include <stddef.h>
-#include <stdint.h>
-
-#include "zivuos/task.h"
-#include "zivuos/kernel.h"
-#include "zivuos/scheduler.h"
-#include "zivuos/zv_time.h"
-
-static bool __zv_scheduler_event_ready(
-    zv_kernel_t *kernel,
-    zv_task_t *target
-) {
-    zv_event_t *event = &target->event;
-
-    if (event->type == ZV_EVENT_OBJECT || event->type == ZV_EVENT_DATA) {
-        return true;
-    }
-
-    if (event->type == ZV_EVENT_TIMER) {
-        zv_time_t current_time = zv_platform_get_time();
-
-        if (event->content.time <= current_time) {
-            return true;
-        }
-    }
-
-    return false;
-}
-
-static void __zv_scheduler_update_single_task(
-    zv_kernel_t *self, 
-    zv_task_t *target
-) {
-    if (__zv_scheduler_event_ready(self, target)) {
-        target->state = ZV_TASK_READY;
-    }
-
-    if (target->state == ZV_TASK_READY) {
-        ++target->age;
-    }
-}
-
-void __zv_scheduler_update_tasks(zv_kernel_t *self) {
-    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
-        __zv_scheduler_update_single_task(self, self->tasks + count);
-    }
-}
-
-static zv_task_t * __zv_scheduler_basic(zv_kernel_t *self) {
-    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
-        zv_task_t *current = self->tasks + count;
-
-        if (current->state == ZV_TASK_READY) {
-            return current;
-        }
-    }
-
-    return NULL;
-}
-
-static zv_task_t * __zv_scheduler_priority_strict(zv_kernel_t *self) {
-    zv_task_t *found = NULL;
-
-    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
-        zv_task_t *current = self->tasks + count;
-        
-        if (current->state != ZV_TASK_READY) {
-            continue;
-        }
-
-        if (found == NULL) {
-            found = current;
-            continue;
-        }
-        
-        if (found->priority < current->priority) {
-            found = current;
-            continue;
-        }
-    }
-
-    return found;
-}*/
-
-static zv_task_t * __zv_scheduler_priority_aging(zv_kernel_t *self) {
-    zv_task_t *found = NULL;
-    zv_priority_t found_priority;
-
-    for (zv_tid_t count = 0; count < self->tasks_count; ++count) {
-        zv_task_t *current = self->tasks + count;
-        
-        if (current->state != ZV_TASK_READY) {
-            continue;
-        }
-
-        if (found == NULL) {
-            found = current;
-            found_priority = found->priority + found->age;
-            continue;
-        }
-        
-        if (found_priority < (current->priority + current->age)) {
-            found = current;
-            found_priority = found->priority + found->age;
-            continue;
-        }
-    }
-
-    return found;
-}
-
-zv_task_t * __zv_scheduler_find_task(zv_kernel_t *self) {
-    return __zv_scheduler_priority_aging(self);
-}
-
-void __zv_scheduler_run_task(zv_kernel_t *self, zv_task_t *target) {
-    target->state = ZV_TASK_RUNNING;
-    zv_event_t event_copy = target->event;
-    
-    target->event.type = ZV_EVENT_EMPTY;
-    target->event.content.unumber = 0;
-
-    zv_state_t result = target->worker(
-        self,
-        &event_copy,
-        __zv_kernel_get_tid(self, target),
-        target->param
-    );
-
-    if (result == ZV_TASK_READY || result == ZV_TASK_RUNNING) {
-        result = ZV_TASK_READY;
-    }
-
-    target->state = result;
-    target->age = 0x00;
-}

+ 26 - 0
sources/time.c

@@ -0,0 +1,26 @@
+#include <zivuos.h>
+
+void zv_time_ticks_delay(zv_ticks_t delay) {
+    zv_ticks_t start_time = zv_time_get_ticks();
+    zv_ticks_t end_time = start_time + delay;
+
+    while (zv_time_get_ticks() < end_time) ;
+    while (zv_time_get_ticks() >= end_time) ;
+}   
+
+void __zv_time_process_timer(zv_event_t *target) {
+    zv_time_t current_time = zv_time_get_time();
+    zv_time_t end_time = target->content.time;
+
+    if (target->type == ZV_EVENT_TIMER_PHRASE_FIRST) {
+        if (current_time < end_time) {
+            target->type = ZV_EVENT_TIMER_PHRASE_SECOND;
+        }
+    }
+
+    if (target->type == ZV_EVENT_TIMER_PHRASE_SECOND) {
+        if (current_time >= end_time) {
+            target->type = ZV_EVENT_TIMER;
+        }
+    }
+}

+ 7 - 5
tests/001-first_boot/testing.c

@@ -15,23 +15,25 @@ int main() {
     zv_kernel_t kernel[1];
     zv_task_t tasks[10];
 
-    if (zv_kernel_init(kernel, tasks, ZV_COUNT_TASKS(tasks)) == false) {
-        puts("KERNEL INIT ERROR.");
+    if (!zv_kernel_init(kernel, tasks, ZV_COUNT_TASKS(tasks))) {
+        puts("KERNEL INIT FAIL.");
     }
 
-    if (zv_kernel_create_process(
+    zv_tid_t first_tid = zv_kernel_create_process(
         kernel, 
         task_worker, 
         0x02, 
         NULL
-    ) == ZV_TID_NULL) {
+    );
+
+    if (first_tid == ZV_TID_NULL) {
         puts("CREATE PROCESS ERROR.");
     }
     
     if (zv_kernel_create_process(
         kernel, 
         task_worker, 
-        0x01, 
+        0x03, 
         NULL
     ) == ZV_TID_NULL) {
         puts("CREATE PROCESS ERROR.");

+ 8 - 11
tests/002-event/testing.c

@@ -7,19 +7,17 @@ zv_state_t task_worker(
     zv_tid_t self,
     void *param
 ) {
-    printf("Current time: %li\n", zv_platform_get_time());
+    static uint8_t counts = 10;
+    printf("Current time: %li\n", zv_time_get_time());
 
     zv_event_set_timer(kernel, self, 500);
-    return ZV_TASK_ANY_EVENT_WAIT;
-}
+    --counts;
 
-zv_state_t task_idle(
-    zv_kernel_t *,
-    zv_event_t *,
-    zv_tid_t,
-    void *
-) {
-    return ZV_TASK_READY;
+    if (counts == 0) {
+        return ZV_TASK_KILLED;
+    }
+
+    return ZV_TASK_EVENT_WAIT;
 }
 
 int main() {
@@ -30,7 +28,6 @@ int main() {
 
     zv_kernel_init(kernel, tasks, ZV_COUNT_TASKS(tasks));
     zv_kernel_create_process(kernel, task_worker, 0x01, NULL);
-    zv_kernel_create_process(kernel, task_idle, 0x00, NULL);
 
     zv_kernel_boot(kernel);