add event-driven framework

see examples/event_driven_at_module and examples/event_driven_hello_world, demo project: TencentOS-tiny\board\TencentOS_tiny_EVB_MX\KEIL\event_driven_hello_world
This commit is contained in:
SheldonDai
2019-09-24 17:21:58 +08:00
parent 97be1b9e93
commit 9727512631
45 changed files with 16682 additions and 7 deletions

View File

@@ -40,6 +40,7 @@
#define __PURE__ __attribute__((__pure__))
#define __CONST__ __attribute__((__const__))
#define __NO_RETURN__ __attribute__((__noreturn__))
#define __WEAK__ __attribute__((weak))
/*------------------ ARM Compiler V6 -------------------*/
#elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
@@ -61,7 +62,7 @@
#define __CONST__ __attribute__((__const__))
#define __NO_RETURN__ __attribute__((__noreturn__))
#define __NAKED__ __attribute__((naked))
#define __WEAK__ __attribute__((weak))
/*------------------ ICC Compiler ----------------------*/
#elif defined(__ICCARM__)
@@ -82,6 +83,8 @@
#define __CONST__
#define __NO_RETURN__
#define __NAKED__
#define __WEAK__ __weak
/*------------------ GNU Compiler ----------------------*/
#elif defined(__GNUC__)
@@ -103,6 +106,7 @@
#define __CONST__ __attribute__((__const__))
#define __NO_RETURN__ __attribute__((__noreturn__))
#define __NAKED__ __attribute__((naked))
#define __WEAK__ __attribute__((weak))
#endif

View File

@@ -1,6 +1,18 @@
#ifndef _TOS_CONFIG_CHECK_H_
#define _TOS_CONFIG_CHECK_H_
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
#if TOS_CFG_MMHEAP_EN == 0u
#error "INVALID config, must enable tos_mmheap to use event-driven"
#endif
#if TOS_CFG_TICKLESS_EN == 1u
#error "INVALID config, tickless not supported in event-driven yet"
#endif
#else /* TOS_CFG_EVENT_DRIVEN_EN */
#if TOS_CFG_TASK_PRIO_MAX < 8u
#error "INVALID config, TOS_CFG_TASK_PRIO_MAX must be >= 8"
#endif
@@ -57,5 +69,7 @@
#error "INVALID config, TOS_CFG_CPU_DATA_SIZE"
#endif
#endif /* _TOS_CHECK_CONFIG_H_ */
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_CONFIG_CHECK_H_ */

View File

@@ -1,6 +1,136 @@
#ifndef _TOS_CONFIG_DEFAULT_H_
#define _TOS_CONFIG_DEFAULT_H_
#ifndef TOS_CFG_EVENT_DRIVEN_EN
#define TOS_CFG_EVENT_DRIVEN_EN 0u
#endif
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
/////////////////////////////////////////
// disable round robin
#ifdef TOS_CFG_ROUND_ROBIN_EN
#undef TOS_CFG_ROUND_ROBIN_EN
#endif
#define TOS_CFG_ROUND_ROBIN_EN 0u
/////////////////////////////////////////
/////////////////////////////////////////
// disable event
#ifdef TOS_CFG_EVENT_EN
#undef TOS_CFG_EVENT_EN
#endif
#define TOS_CFG_EVENT_EN 0u
/////////////////////////////////////////
/////////////////////////////////////////
// disable mutex
#ifdef TOS_CFG_MUTEX_EN
#undef TOS_CFG_MUTEX_EN
#endif
#define TOS_CFG_MUTEX_EN 0u
/////////////////////////////////////////
/////////////////////////////////////////
// disable queue
#ifdef TOS_CFG_QUEUE_EN
#undef TOS_CFG_QUEUE_EN
#endif
#define TOS_CFG_QUEUE_EN 0u
/////////////////////////////////////////
/////////////////////////////////////////
// disable semaphore
#ifdef TOS_CFG_SEM_EN
#undef TOS_CFG_SEM_EN
#endif
#define TOS_CFG_SEM_EN 0u
/////////////////////////////////////////
/////////////////////////////////////////
// disable the "traditional" timer
#ifdef TOS_CFG_TIMER_EN
#undef TOS_CFG_TIMER_EN
#endif
#define TOS_CFG_TIMER_EN 0u
/////////////////////////////////////////
/////////////////////////////////////////
// disable stack draught depth detact
#ifdef TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN
#undef TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN
#endif
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 0u
/////////////////////////////////////////
/////////////////////////////////////////
// enable mmheap
#ifndef TOS_CFG_MMHEAP_EN
#define TOS_CFG_MMHEAP_EN 1u
#endif
#if (TOS_CFG_MMHEAP_EN > 0u) && !defined(TOS_CFG_MMHEAP_POOL_SIZE)
#define TOS_CFG_MMHEAP_POOL_SIZE 0x1000
#endif
/////////////////////////////////////////
/////////////////////////////////////////
// disable default
#ifndef TOS_CFG_MMBLK_EN
#define TOS_CFG_MMBLK_EN 0u
#endif
/////////////////////////////////////////
/////////////////////////////////////////
// disable default
#ifndef TOS_CFG_FAULT_BACKTRACE_EN
#define TOS_CFG_FAULT_BACKTRACE_EN 0u
#endif
/////////////////////////////////////////
/////////////////////////////////////////
#ifndef TOS_CFG_CPU_SYSTICK_PRIO
#define TOS_CFG_CPU_SYSTICK_PRIO 0u
#endif
/////////////////////////////////////////
/////////////////////////////////////////
// disable default
#ifndef TOS_CFG_PWR_MGR_EN
#define TOS_CFG_PWR_MGR_EN 0u
#endif
#ifndef TOS_CFG_TICKLESS_EN
#define TOS_CFG_TICKLESS_EN 0u
#endif
/////////////////////////////////////////
// we donot really need these, it's a compromise to the compiler.
#ifndef TOS_CFG_TASK_PRIO_MAX
#define TOS_CFG_TASK_PRIO_MAX 8u
#endif
#ifndef TOS_CFG_IDLE_TASK_STK_SIZE
#define TOS_CFG_IDLE_TASK_STK_SIZE 128u
#endif
/////////////////////////////////////////
/////////////////////////////////////////
#else /* TOS_CFG_EVENT_DRIVEN_EN */
#ifndef TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 0u
#endif
@@ -13,10 +143,6 @@
#define TOS_CFG_EVENT_EN 0u
#endif
#ifndef TOS_CFG_MMHEAP_EN
#define TOS_CFG_MMHEAP_EN 0u
#endif
#ifndef TOS_CFG_MUTEX_EN
#define TOS_CFG_MUTEX_EN 0u
#endif
@@ -29,6 +155,10 @@
#define TOS_CFG_SEM_EN 0u
#endif
#ifndef TOS_CFG_MMHEAP_EN
#define TOS_CFG_MMHEAP_EN 0u
#endif
#if (TOS_CFG_QUEUE_EN > 0u) && !defined(TOS_CFG_MSG_EN)
#define TOS_CFG_MSG_EN 1u
#elif (TOS_CFG_QUEUE_EN == 0u) && !defined(TOS_CFG_MSG_EN)
@@ -76,7 +206,7 @@
#endif
#ifndef TOS_CFG_TASK_PRIO_MAX
#define TOS_CFG_TASK_PRIO_MAX 10u
#define TOS_CFG_TASK_PRIO_MAX 8u
#endif
#ifndef TOS_CFG_MMBLK_EN
@@ -110,5 +240,7 @@
#define TOS_CFG_FAULT_BACKTRACE_EN 0u
#endif
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_CONFIG_DEFAULT_H_ */

View File

@@ -0,0 +1,16 @@
#ifndef _TOS_EVTDRV_H_
#define _TOS_EVTDRV_H_
#include "tos.h"
#include "tos_evtdrv_err.h"
#include "tos_evtdrv_types.h"
#include "tos_evtdrv_event.h"
#include "tos_evtdrv_msg.h"
#include "tos_evtdrv_timer.h"
#include "tos_evtdrv_task.h"
#include "tos_evtdrv_tick.h"
#include "tos_evtdrv_sys.h"
#include "tos_evtdrv_global.h"
#endif

View File

@@ -0,0 +1,20 @@
#ifndef _TOS_EVTDRV_ERR_H_
#define _TOS_EVTDRV_ERR_H_
typedef enum evtdrv_err_en {
EVTDRV_ERR_NONE = 0x0u,
EVTDRV_ERR_MEM_ALLOC_FAILED = 0x1u,
EVTDRV_ERR_PTR_NULL = 0x2u,
EVTDRV_ERR_MSG_BUSY = 0x3u,
EVTDRV_ERR_TASK_INVALID = 0x4u,
EVTDRV_ERR_MMHEAP_NOT_ENABLED = 0x5u,
EVTDRV_ERR_EVENT_INVALID = 0x10u,
EVTDRV_ERR_EVENT_OVERFLOW = 0x11u,
EVTDRV_ERR_TIMER_ALREADY_EXIST = 0x20u,
EVTDRV_ERR_TIMER_INACTIVE = 0x21u,
} evtdrv_err_t;
#endif

View File

@@ -0,0 +1,71 @@
#ifndef _TOS_EVTDRV_EVENT_H_
#define _TOS_EVTDRV_EVENT_H_
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
typedef uint16_t evtdrv_event_flag_t;
typedef uint16_t evtdrv_event_nesting_t;
#define EVTDRV_SYS_EVENT_MASK (evtdrv_event_flag_t)(0x3 << (sizeof(evtdrv_event_flag_t) * 8 - 2))
#define EVTDRV_USR_EVENT_MASK (evtdrv_event_flag_t)(~(EVTDRV_SYS_EVENT_MASK))
/* highest two bits are reserved for system event
0x8000 init all tasks
0x4000 msg received
*/
#define TOS_EVTDRV_EVENT_NONE (evtdrv_event_flag_t)0x0u
#define TOS_EVTDRV_SYS_EVENT_INIT (evtdrv_event_flag_t)(0x2 << (sizeof(evtdrv_event_flag_t) * 8 - 2))
#define TOS_EVTDRV_SYS_EVENT_MSG (evtdrv_event_flag_t)(0x1 << (sizeof(evtdrv_event_flag_t) * 8 - 2))
typedef struct evtdrv_event_st {
evtdrv_event_flag_t flags;
evtdrv_event_nesting_t nesting[sizeof(evtdrv_event_flag_t) * 8];
} evtdrv_event_t;
/**
* @brief Set event to the target task.
* Set event to the target task, next time the target task is "scheduled", the task will handle the event.
*
* @attention None
*
* @param[in] task_id id of the target task.
* @param[in] event_flags the event flags set to the task
*
* @return errcode
* @retval #EVTDRV_ERR_TASK_INVALID task id is invalid.
* @retval #EVTDRV_ERR_NONE return successfully.
*/
__API__ evtdrv_err_t tos_evtdrv_event_set(evtdrv_task_id_t task_id, evtdrv_event_flag_t event_flags);
/**
* @brief Reset the event of the target task.
*
* @attention None
*
* @param[in] task_id id of the target task.
* @param[in] event_flags the event flags reset of the task
*
* @return errcode
* @retval #EVTDRV_ERR_TASK_INVALID task id is invalid.
* @retval #EVTDRV_ERR_NONE return successfully.
*/
__API__ evtdrv_err_t tos_evtdrv_event_reset(evtdrv_task_id_t task_id, evtdrv_event_flag_t event_flags);
__KERNEL__ evtdrv_err_t evtdrv_event_init(void);
__KERNEL__ evtdrv_event_flag_t evtdrv_event_fetch(evtdrv_task_id_t *task_id);
__STATIC_INLINE__ evtdrv_bool_t evtdrv_event_is_usr(evtdrv_event_flag_t event_flag)
{
return event_flag & EVTDRV_USR_EVENT_MASK;
}
__STATIC_INLINE__ evtdrv_bool_t evtdrv_event_is_sys(evtdrv_event_flag_t event_flag)
{
return event_flag & EVTDRV_SYS_EVENT_MASK;
}
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_EVTDRV_EVENT_H_ */

View File

@@ -0,0 +1,24 @@
#ifndef _TOS_EVTDRV_GLOBAL_H_
#define _TOS_EVTDRV_GLOBAL_H_
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
extern evtdrv_task_entry_t *evtdrv_task_table;
extern evtdrv_ttb_sz_t evtdrv_task_table_size;
extern evtdrv_task_id_t evtdrv_curr_task;
extern evtdrv_event_t *evtdrv_events;
extern k_list_t evtdrv_msg_list;
extern k_list_t evtdrv_timer_list;
extern k_evtdrv_poll_t evtdrv_poll;
extern evtdrv_tick_t evtdrv_tick_count;
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_EVTDRV_GLOBAL_H_ */

View File

@@ -0,0 +1,69 @@
#ifndef _TOS_EVTDRV_MSG_H_
#define _TOS_EVTDRV_MSG_H_
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
typedef uint16_t evtdrv_msg_len_t;
typedef uint8_t *evtdrv_msg_body_t;
typedef struct evtdrv_message_header_st {
k_list_t list;
evtdrv_task_id_t dst_task_id; // destination task id
evtdrv_msg_len_t len;
} evtdrv_msg_hdr_t;
#define EVTDRV_MSG_BODY2HDR(msg_body) ((evtdrv_msg_hdr_t *)((uint8_t *)msg_body - sizeof(evtdrv_msg_hdr_t)))
#define EVTDRV_MSG_LEN(msg_len) (sizeof(evtdrv_msg_hdr_t) + msg_len)
#define EVTDRV_MSG_HDR2BODY(msg_hdr) ((evtdrv_msg_body_t)((evtdrv_msg_hdr_t *)msg_hdr + 1))
/**
* @brief Allocate a message body.
* Allocate a message body as a payload to hold the message content.
*
* @attention None
*
* @param[in] msg_len the length of the message payload.
*
* @return the message body allocated.
* @retval #NULL allocate failed.
* @retval #NO-NULL allocate successfully.
*/
__API__ evtdrv_msg_body_t tos_evtdrv_msg_alloc(evtdrv_msg_len_t msg_len);
/**
* @brief Free a message body.
*
* @attention if you wanna free a message body, the message must be "dequeued"(already received by the target task)
*
* @param[in] msg_body message body to free.
*
* @return errcode
* @retval #EVTDRV_ERR_PTR_NULL message body is NULL.
* @retval #EVTDRV_ERR_MSG_BUSY message is still in the message queue(not received).
* @retval #EVTDRV_ERR_NONE free successfully.
*/
__API__ evtdrv_err_t tos_evtdrv_msg_free(evtdrv_msg_body_t msg_body);
/**
* @brief Send a message to the target task.
*
* @attention next time the target task should be "wakeup" by the event of TOS_EVTDRV_SYS_EVENT_MSG.
*
* @param[in] task_id id of the target task.
* @param[in] msg_body message body to send.
*
* @return errcode
* @retval #EVTDRV_ERR_PTR_NULL message body is NULL.
* @retval #EVTDRV_ERR_TASK_INVALID target task id is invalid.
* @retval #EVTDRV_ERR_NONE send successfully.
*/
__API__ evtdrv_err_t tos_evtdrv_msg_send(evtdrv_task_id_t dst_task_id, evtdrv_msg_body_t msg_body);
__API__ evtdrv_msg_body_t tos_evtdrv_msg_recv(void);
__KERNEL__ void evtdrv_msg_init(void);
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_EVTDRV_MSG_H_ */

View File

@@ -0,0 +1,37 @@
#ifndef _TOS_EVTDRV_SYS_H_
#define _TOS_EVTDRV_SYS_H_
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
typedef void (*k_evtdrv_poll_t)(void);
/**
* @brief Initialize the event-driven system.
*
* @attention event-driven is a simplified schedule model to support the none-context-swith-based multi-task programming.("the big while 1")
* must enable TOS_CFG_MMHEAP_EN to use event-driven.
*
* @param[in] tasks array of the tasks.
* @param[in] task_table_size size of the tasks.
* @param[in] poll the user defined poll function.
*
* @return errcode
* @retval #EVTDRV_ERR_MMHEAP_NOT_ENABLED mmheap is not enabled.
* @retval #EVTDRV_ERR_MEM_ALLOC_FAILED memory allocate failed.
* @retval #EVTDRV_ERR_NONE initialize successfully.
*/
__API__ evtdrv_err_t tos_evtdrv_sys_init(evtdrv_task_entry_t tasks[], evtdrv_ttb_sz_t task_table_size, k_evtdrv_poll_t poll);
/**
* @brief Start the event-driven system.
*
* @attention start the event-driven multi-task "schedule".
*
* @return None
*/
__API__ void tos_evtdrv_sys_start(void);
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_EVTDRV_SYS_H_ */

View File

@@ -0,0 +1,31 @@
#ifndef _TOS_EVTDRV_TASK_H_
#define _TOS_EVTDRV_TASK_H_
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
#define TOS_EVTDRV_TASK_ID_NONE ((evtdrv_task_id_t)-1)
// return event handled
typedef evtdrv_event_flag_t (*evtdrv_task_entry_t)(evtdrv_event_flag_t event_flags);
#define EVTDRV_TASK_ID2TASK(task_id) (evtdrv_task_entry_t)(evtdrv_task_table[task_id])
/**
* @brief Get the actived("running") task id.
*
* @attention
*
* @return the actived("running") task id.
*/
__API__ evtdrv_task_id_t tos_evtdrv_task_self(void);
__KERNEL__ evtdrv_bool_t evtdrv_task_id_is_invalid(evtdrv_task_id_t task_id);
__KERNEL__ evtdrv_bool_t evtdrv_task_is_self(evtdrv_task_id_t task_id);
__KERNEL__ void evtdrv_task_init(void);
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_EVTDRV_TASK_H_ */

View File

@@ -0,0 +1,45 @@
#ifndef _TOS_EVTDRV_TICK_H_
#define _TOS_EVTDRV_TICK_H_
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
/**
* @brief Get the current systick cout.
*
* @attention
*
* @return current systick count.
*/
__API__ evtdrv_tick_t tos_evtdrv_systick_get(void);
/**
* @brief tick interrupt handler.
*
* @attention if you wanna use event-driven timer, you must deal with the tick.
*
* @return None.
*/
__API__ void tos_evtdrv_tick_handler(void);
/**
* @brief Convert tick count to milli-seconds.
*
* @attention
*
* @return the milli-seconds equals to the tick count.
*/
__API__ evtdrv_time_t tos_evtdrv_tick2millisec(evtdrv_tick_t tick);
/**
* @brief Convert milli-seconds to tick count.
*
* @attention
*
* @return the tick count equals to the tick count.
*/
__API__ evtdrv_tick_t tos_evtdrv_millisec2tick(evtdrv_time_t ms);
#endif /* TOS_CFG_EVENT_DRIVEN_EN */
#endif /* _TOS_EVTDRV_TICK_H_ */

View File

@@ -0,0 +1,82 @@
#ifndef _TOS_EVTDRV_TIMER_H_
#define _TOS_EVTDRV_TIMER_H_
#define EVTDRV_TIME_MILLISEC_PER_SEC (1000u)
typedef enum evtdrv_timer_option_en {
EVTDRV_TIMER_OPT_ONESHOT,
EVTDRV_TIMER_OPT_PERIODIC,
} evtdrv_timer_opt_t;
typedef void (*evtdrv_timer_callback_t)(void *arg);
typedef struct evtdrv_timer_st {
evtdrv_timer_callback_t cb;
void *cb_arg;
k_list_t list;
evtdrv_tick_t expires;
evtdrv_tick_t period;
evtdrv_timer_opt_t opt;
} evtdrv_timer_t;
typedef struct evtdrv_timer_control_st {
evtdrv_tick_t next_expires;
evtdrv_tick_t list;
} evtdrv_timer_ctl_t;
/**
* @brief Create a timer.
* Create a timer.
*
* @attention
*
* @param[in] tmr pointer to the handler of the timer.
* @param[in] callback callback function called when the timer expires.
* @param[in] cb_arg argument for the callback.
* @param[in] opt option for the function call.
*
* @return errcode
* @retval #EVTDRV_ERR_PTR_NULL task_id is invalid.
* @retval #EVTDRV_ERR_NONE event_flags is not valid for user use.
*/
__API__ evtdrv_err_t tos_evtdrv_timer_create(evtdrv_timer_t *tmr,
evtdrv_timer_callback_t callback,
void *cb_arg,
evtdrv_timer_opt_t opt);
/**
* @brief Start a timer.
* Start the timer to run.
*
* @attention None
*
* @param[in] tmr pointer to the handler of the timer.
*
* @return errcode
* @retval #EVTDRV_ERR_PTR_NULL tmr is a NULL pointer.
* @retval #EVTDRV_ERR_TIMER_ALREADY_EXIST tmr is already exist.
* @retval #EVTDRV_ERR_NONE return successfully.
*/
__API__ evtdrv_err_t tos_evtdrv_timer_start(evtdrv_timer_t *tmr, evtdrv_tick_t timeout);
/**
* @brief Stop a timer.
* Stop the timer from running.
*
* @attention None
*
* @param[in] tmr pointer to the handler of the timer.
*
* @return errcode
* @retval #EVTDRV_ERR_PTR_NULL tmr is a NULL pointer.
* @retval #EVTDRV_ERR_TIMER_INACTIVE the timer is not active yet.
* @retval #EVTDRV_ERR_NONE return successfully.
*/
__API__ evtdrv_err_t tos_evtdrv_timer_stop(evtdrv_timer_t *tmr);
__KERNEL__ void evtdrv_timer_update(void);
#endif /* _TOS_EVTDRV_TIMER_H_ */

View File

@@ -0,0 +1,11 @@
#ifndef _TOS_EVTDRV_TYPES_H_
#define _TOS_EVTDRV_TYPES_H_
typedef int8_t evtdrv_bool_t;
typedef uint8_t evtdrv_task_id_t; // task id type
typedef uint8_t evtdrv_ttb_sz_t; // task table size type
typedef uint64_t evtdrv_tick_t;
typedef uint32_t evtdrv_time_t;
#endif

View File

@@ -0,0 +1,111 @@
#include "tos_evtdrv.h"
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
__API__ evtdrv_err_t tos_evtdrv_event_set(evtdrv_task_id_t task_id, evtdrv_event_flag_t event_flags)
{
TOS_CPU_CPSR_ALLOC();
uint8_t i = 0;
evtdrv_event_t *event;
evtdrv_event_flag_t flag;
if (evtdrv_task_id_is_invalid(task_id)) {
return EVTDRV_ERR_TASK_INVALID;
}
TOS_CPU_INT_DISABLE();
event = &evtdrv_events[task_id];
for (i = 0; i < sizeof(evtdrv_event_flag_t) * 8; ++i) {
flag = (1 << i);
if (event_flags & flag) {
if (event->nesting[i] == (evtdrv_event_nesting_t)-1) {
continue;
}
++event->nesting[i];
event->flags |= flag;
}
}
TOS_CPU_INT_ENABLE();
return EVTDRV_ERR_NONE;
}
__API__ evtdrv_err_t tos_evtdrv_event_reset(evtdrv_task_id_t task_id, evtdrv_event_flag_t event_flags)
{
TOS_CPU_CPSR_ALLOC();
uint8_t i = 0;
evtdrv_event_t *event;
evtdrv_event_flag_t flag;
if (evtdrv_task_id_is_invalid(task_id)) {
return EVTDRV_ERR_TASK_INVALID;
}
TOS_CPU_INT_DISABLE();
event = &evtdrv_events[task_id];
for (i = 0; i < sizeof(evtdrv_event_flag_t) * 8; ++i) {
flag = (1 << i);
if (event_flags & flag) {
if (!(event->flags & flag)) {
continue;
}
if (event->nesting[i] > (evtdrv_event_nesting_t)0u) {
--event->nesting[i];
}
if (event->nesting[i] == (evtdrv_event_nesting_t)0u) {
event->flags &= ~flag;
}
}
}
TOS_CPU_INT_ENABLE();
return EVTDRV_ERR_NONE;
}
__KERNEL__ evtdrv_err_t evtdrv_event_init(void)
{
evtdrv_task_id_t i;
evtdrv_event_t *event;
evtdrv_events = (evtdrv_event_t *)tos_mmheap_calloc(evtdrv_task_table_size, sizeof(evtdrv_event_t));
if (!evtdrv_events) {
return EVTDRV_ERR_MEM_ALLOC_FAILED;
}
for (i = 0; i < evtdrv_task_table_size; ++i) {
event = &evtdrv_events[i];
event->flags = TOS_EVTDRV_EVENT_NONE;
}
return EVTDRV_ERR_NONE;
}
__KERNEL__ evtdrv_event_flag_t evtdrv_event_fetch(evtdrv_task_id_t *task_id)
{
evtdrv_task_id_t i;
evtdrv_event_t *event;
for (i = 0; i < evtdrv_task_table_size; ++i) {
event = &evtdrv_events[i];
if (event->flags != TOS_EVTDRV_EVENT_NONE) {
if (task_id) {
*task_id = i;
}
return event->flags;
}
}
return TOS_EVTDRV_EVENT_NONE;
}
#endif

View File

@@ -0,0 +1,21 @@
#include "tos_evtdrv.h"
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
evtdrv_task_entry_t *evtdrv_task_table = K_NULL;
evtdrv_ttb_sz_t evtdrv_task_table_size = 0;
evtdrv_task_id_t evtdrv_curr_task = TOS_EVTDRV_TASK_ID_NONE;
evtdrv_event_t *evtdrv_events = K_NULL;
k_evtdrv_poll_t evtdrv_poll = K_NULL;
evtdrv_tick_t evtdrv_tick_count = (evtdrv_tick_t)0u;
TOS_LIST_DEFINE(evtdrv_msg_list);
TOS_LIST_DEFINE(evtdrv_timer_list);
#endif

View File

@@ -0,0 +1,106 @@
#include "tos_evtdrv.h"
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
__API__ evtdrv_msg_body_t tos_evtdrv_msg_alloc(evtdrv_msg_len_t msg_len)
{
evtdrv_msg_hdr_t *msg_hdr = K_NULL;
if (!msg_len) {
return K_NULL;
}
msg_hdr = (evtdrv_msg_hdr_t *)tos_mmheap_alloc(EVTDRV_MSG_LEN(msg_len));
if (!msg_hdr) {
return K_NULL;
}
tos_list_init(&msg_hdr->list);
msg_hdr->len = msg_len;
msg_hdr->dst_task_id = TOS_EVTDRV_TASK_ID_NONE;
return EVTDRV_MSG_HDR2BODY(msg_hdr);
}
__API__ evtdrv_err_t tos_evtdrv_msg_free(evtdrv_msg_body_t msg_body)
{
evtdrv_msg_hdr_t *msg_hdr = K_NULL;
if (!msg_body) {
return EVTDRV_ERR_PTR_NULL;
}
msg_hdr = EVTDRV_MSG_BODY2HDR(msg_body);
if (msg_hdr->dst_task_id != TOS_EVTDRV_TASK_ID_NONE ||
!tos_list_empty(&msg_hdr->list)) {
return EVTDRV_ERR_MSG_BUSY;
}
tos_mmheap_free(msg_hdr);
return EVTDRV_ERR_NONE;
}
__API__ evtdrv_err_t tos_evtdrv_msg_send(evtdrv_task_id_t dst_task_id, evtdrv_msg_body_t msg_body)
{
evtdrv_msg_hdr_t *msg_hdr = K_NULL;
if (!msg_body) {
return EVTDRV_ERR_PTR_NULL;
}
if (evtdrv_task_id_is_invalid(dst_task_id)) {
tos_evtdrv_msg_free(msg_body);
return EVTDRV_ERR_TASK_INVALID;
}
msg_hdr = EVTDRV_MSG_BODY2HDR(msg_body);
msg_hdr->dst_task_id = dst_task_id;
tos_list_add(&msg_hdr->list, &evtdrv_msg_list);
tos_evtdrv_event_set(dst_task_id, TOS_EVTDRV_SYS_EVENT_MSG);
return EVTDRV_ERR_NONE;
}
__STATIC_INLINE__ void evtdrv_msg_prepare4use(evtdrv_msg_hdr_t *msg_hdr)
{
tos_list_del_init(&msg_hdr->list);
msg_hdr->dst_task_id = TOS_EVTDRV_TASK_ID_NONE;
}
__API__ evtdrv_msg_body_t tos_evtdrv_msg_recv(void)
{
TOS_CPU_CPSR_ALLOC();
k_list_t *curr, *next;
evtdrv_msg_hdr_t *msg_hdr = K_NULL;
TOS_CPU_INT_DISABLE();
TOS_LIST_FOR_EACH_SAFE(curr, next, &evtdrv_msg_list) {
msg_hdr = TOS_LIST_ENTRY(curr, evtdrv_msg_hdr_t, list);
if (!evtdrv_task_is_self(msg_hdr->dst_task_id)) {
continue;
}
evtdrv_msg_prepare4use(msg_hdr);
tos_evtdrv_event_set(tos_evtdrv_task_self(), TOS_EVTDRV_SYS_EVENT_MSG);
TOS_CPU_INT_ENABLE();
return EVTDRV_MSG_HDR2BODY(msg_hdr);
}
TOS_CPU_INT_ENABLE();
tos_evtdrv_event_reset(tos_evtdrv_task_self(), TOS_EVTDRV_SYS_EVENT_MSG);
return K_NULL;
}
__KERNEL__ void evtdrv_msg_init(void)
{
tos_list_init(&evtdrv_msg_list);
}
#endif

View File

@@ -0,0 +1,66 @@
#include "tos_evtdrv.h"
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
__API__ evtdrv_err_t tos_evtdrv_sys_init(evtdrv_task_entry_t tasks[], evtdrv_ttb_sz_t task_table_size, k_evtdrv_poll_t poll)
{
evtdrv_err_t err;
evtdrv_task_table = &tasks[0];
evtdrv_task_table_size = task_table_size;
evtdrv_poll = poll;
#if TOS_CFG_MMHEAP_EN > 0
mmheap_init(k_mmheap_pool, TOS_CFG_MMHEAP_POOL_SIZE);
#else
return EVTDRV_ERR_MMHEAP_NOT_ENABLED;
#endif
err = evtdrv_event_init();
if (err != EVTDRV_ERR_NONE) {
return err;
}
evtdrv_msg_init();
evtdrv_task_init();
return EVTDRV_ERR_NONE;
}
__STATIC__ void evtdrv_sys_run(void)
{
evtdrv_event_flag_t event_flag = TOS_EVTDRV_EVENT_NONE;
evtdrv_task_id_t task_id = TOS_EVTDRV_TASK_ID_NONE;
evtdrv_timer_update();
if (evtdrv_poll) {
evtdrv_poll();
}
event_flag = evtdrv_event_fetch(&task_id);
if (event_flag != TOS_EVTDRV_EVENT_NONE) {
evtdrv_curr_task = task_id;
event_flag = (EVTDRV_TASK_ID2TASK(task_id))(event_flag);
evtdrv_curr_task = TOS_EVTDRV_TASK_ID_NONE;
// after task process, event that the task handled is returned.
tos_evtdrv_event_reset(task_id, event_flag);
} else {
#if TOS_CFG_PWR_MGR_EN > 0u
pm_power_manager();
#endif
}
}
__API__ void tos_evtdrv_sys_start(void)
{
while (K_TRUE) {
evtdrv_sys_run();
}
}
#endif

View File

@@ -0,0 +1,30 @@
#include "tos_evtdrv.h"
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
__API__ evtdrv_task_id_t tos_evtdrv_task_self(void)
{
return evtdrv_curr_task;
}
__KERNEL__ evtdrv_bool_t evtdrv_task_id_is_invalid(evtdrv_task_id_t task_id)
{
return task_id >= evtdrv_task_table_size;
}
__KERNEL__ evtdrv_bool_t evtdrv_task_is_self(evtdrv_task_id_t task_id)
{
return task_id == evtdrv_curr_task;
}
__KERNEL__ void evtdrv_task_init(void)
{
evtdrv_task_id_t i;
for (i = 0; i < evtdrv_task_table_size; ++i) {
(evtdrv_task_table[i])(TOS_EVTDRV_SYS_EVENT_INIT);
}
}
#endif

View File

@@ -0,0 +1,36 @@
#include "tos_evtdrv.h"
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
__API__ evtdrv_time_t tos_evtdrv_tick2millisec(evtdrv_tick_t tick)
{
return (evtdrv_time_t)(tick * EVTDRV_TIME_MILLISEC_PER_SEC / TOS_CFG_CPU_TICK_PER_SECOND);
}
__API__ evtdrv_tick_t tos_evtdrv_millisec2tick(evtdrv_time_t ms)
{
return ((evtdrv_tick_t)ms * TOS_CFG_CPU_TICK_PER_SECOND / EVTDRV_TIME_MILLISEC_PER_SEC);
}
__API__ evtdrv_tick_t tos_evtdrv_systick_get(void)
{
TOS_CPU_CPSR_ALLOC();
evtdrv_tick_t tick;
TOS_CPU_INT_DISABLE();
tick = evtdrv_tick_count;
TOS_CPU_INT_ENABLE();
return tick;
}
__API__ void tos_evtdrv_tick_handler(void)
{
TOS_CPU_CPSR_ALLOC();
TOS_CPU_INT_DISABLE();
++evtdrv_tick_count;
TOS_CPU_INT_ENABLE();
}
#endif

View File

@@ -0,0 +1,114 @@
#include "tos_evtdrv.h"
#if TOS_CFG_EVENT_DRIVEN_EN > 0u
__STATIC__ void evtdrv_timer_place(evtdrv_timer_t *tmr, evtdrv_tick_t timeout)
{
TOS_CPU_CPSR_ALLOC();
k_list_t *curr;
evtdrv_timer_t *curr_tmr;
TOS_CPU_INT_DISABLE();
tmr->expires = tos_evtdrv_systick_get() + timeout;
TOS_LIST_FOR_EACH(curr, &evtdrv_timer_list) {
curr_tmr = TOS_LIST_ENTRY(curr, evtdrv_timer_t, list);
if (tmr->expires < curr_tmr->expires) {
break;
}
}
tos_list_add_tail(&tmr->list, curr);
TOS_CPU_INT_ENABLE();
}
__STATIC__ void evtdrv_timer_takeoff(evtdrv_timer_t *tmr)
{
TOS_CPU_CPSR_ALLOC();
TOS_CPU_INT_DISABLE();
tos_list_del(&tmr->list);
TOS_CPU_INT_ENABLE();
}
__API__ evtdrv_err_t tos_evtdrv_timer_create(evtdrv_timer_t *tmr,
evtdrv_timer_callback_t callback,
void *cb_arg,
evtdrv_timer_opt_t opt)
{
if (!tmr || !callback) {
return EVTDRV_ERR_PTR_NULL;
}
tmr->cb = callback;
tmr->opt = opt;
tos_list_init(&tmr->list);
return EVTDRV_ERR_NONE;
}
__API__ evtdrv_err_t tos_evtdrv_timer_start(evtdrv_timer_t *tmr, evtdrv_tick_t timeout)
{
if (!tmr) {
return EVTDRV_ERR_PTR_NULL;
}
if (!tos_list_empty(&tmr->list)) {
return EVTDRV_ERR_TIMER_ALREADY_EXIST;
}
evtdrv_timer_place(tmr, timeout);
if (tmr->opt == EVTDRV_TIMER_OPT_PERIODIC) {
tmr->period = timeout;
}
return EVTDRV_ERR_NONE;
}
__API__ evtdrv_err_t tos_evtdrv_timer_stop(evtdrv_timer_t *tmr)
{
if (!tmr) {
return EVTDRV_ERR_PTR_NULL;
}
if (tos_list_empty(&tmr->list)) {
return EVTDRV_ERR_TIMER_INACTIVE;
}
evtdrv_timer_takeoff(tmr);
return EVTDRV_ERR_NONE;
}
__KERNEL__ void evtdrv_timer_update(void)
{
TOS_CPU_CPSR_ALLOC();
evtdrv_timer_t *tmr;
k_list_t *curr, *next;
TOS_CPU_INT_DISABLE();
TOS_LIST_FOR_EACH_SAFE(curr, next, &evtdrv_timer_list) {
tmr = TOS_LIST_ENTRY(curr, evtdrv_timer_t, list);
if (tmr->expires > tos_evtdrv_systick_get()) {
break;
}
// time's up
evtdrv_timer_takeoff(tmr);
if (tmr->opt == EVTDRV_TIMER_OPT_PERIODIC) {
evtdrv_timer_place(tmr, tmr->period);
} else {
evtdrv_timer_takeoff(tmr);
}
(*tmr->cb)(tmr->cb_arg);
}
TOS_CPU_INT_ENABLE();
}
#endif /* TOS_CFG_EVENT_DRIVEN_EN */