From 32ec5ff04ebcb240a2d5e5b21b0df9dbe1e8a671 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B6=E4=B8=AD=E6=96=AD=E5=BB=B6=E8=BF=9F=E7=9A=84RTOS?= Date: Sun, 1 Mar 2026 09:05:14 +0000 Subject: [PATCH] =?UTF-8?q?update=20=E5=86=85=E6=A0=B8=E6=96=87=E4=BB=B6.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 零中断延迟的RTOS --- System/CosyOS.H | 28 + System/os_api.h | 313 +++++++ System/os_handler.c | 688 +++++++++++++++ System/os_taskmgr.c | 635 ++++++++++++++ System/sv_int_fifo.c | 579 +++++++++++++ System/sv_int_fifo.h | 181 ++++ System/sv_pend.h | 38 + System/ur_api.h | 1973 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 4435 insertions(+) create mode 100644 System/CosyOS.H create mode 100644 System/os_api.h create mode 100644 System/os_handler.c create mode 100644 System/os_taskmgr.c create mode 100644 System/sv_int_fifo.c create mode 100644 System/sv_int_fifo.h create mode 100644 System/sv_pend.h create mode 100644 System/ur_api.h diff --git a/System/CosyOS.H b/System/CosyOS.H new file mode 100644 index 0000000..88f498d --- /dev/null +++ b/System/CosyOS.H @@ -0,0 +1,28 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file CosyOS.H + * @brief 系统链接头文件 + * @details 用户的各个c文件中应包含此文件。 + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#ifndef __COSYOS_H +#define __COSYOS_H + +#include "os_var.h" +#include "os_api.h" +#include "sv_com.h" +#include "sv_create.h" +#include "sv_int_fifo.h" +#include "sv_int_loc.h" +#include "sv_pend.h" +#include "sv_task.h" +#include "sv_tick.h" +#include "ur_api.h" +#include "ur_eapi.h" + + + +#endif diff --git a/System/os_api.h b/System/os_api.h new file mode 100644 index 0000000..3da5100 --- /dev/null +++ b/System/os_api.h @@ -0,0 +1,313 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file os_api.h + * @brief 系统内核专用API + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#ifndef __OS_API_H +#define __OS_API_H + + +/* + * 引用.标准库函数 + */ + +#define s_init_mempool init_mempool +#define s_malloc malloc +#define s_calloc calloc +#define s_realloc realloc +#define s_free free +#define s_memcpy memcpy +#define s_memcmp memcmp +#define s_strcpy strcpy +#define s_strcmp strcmp +#define s_strlen strlen + + +/* + * 操作.定时中断/查询 + */ + +/** 启动定时中断任务 */ +#define sStartTask_TimInt(tmid) \ + sUSV_StartTask_0(s_timint_handle[tmid]->hookorhand.hand, OS_STATUS_SUSPENDED) + +/** 启动定时查询任务 */ +#define sStartTask_TimQry(tmid) \ + sUSV_StartTask_0(s_timqry_handle[tmid]->hookorhand.hand, OS_STATUS_SUSPENDED) + +/** 恢复定时中断任务 */ +#define sResumeTask_TimInt(tmid) \ + sTSV_ResumeTask(*(s_timint_handle[tmid]->hookorhand.hand)->dualhandle) + +/** 恢复定时查询任务 */ +#define sResumeTask_TimQry(tmid) \ + sTSV_ResumeTask(*(s_timqry_handle[tmid]->hookorhand.hand)->dualhandle) + +/** 调用定时中断钩子 */ +#define sCallHook_TimInt(tmid) \ + (*s_timint_handle[tmid]->hookorhand.hook)() + +/** 调用定时查询钩子 */ +#define sCallHook_TimQry(tmid) \ + (*s_timqry_handle[tmid]->hookorhand.hook)() + + +/* + * 事件标志组 - 写标志位 + */ + +#define stWriteFlagBits_1(g, v, b0) \ + g.b0 = v + +#define stWriteFlagBits_2(g, v, b0, b1) \ + g.b0 = g.b1 = v + +#define stWriteFlagBits_3(g, v, b0, b1, b2) \ + g.b0 = g.b1 = g.b2 = v + +#define stWriteFlagBits_4(g, v, b0, b1, b2, b3) \ + g.b0 = g.b1 = g.b2 = g.b3 = v + +#define stWriteFlagBits_5(g, v, b0, b1, b2, b3, b4) \ + g.b0 = g.b1 = g.b2 = g.b3 = g.b4 = v + +#define stWriteFlagBits_6(g, v, b0, b1, b2, b3, b4, b5) \ + g.b0 = g.b1 = g.b2 = g.b3 = g.b4 = g.b5 = v + +#define stWriteFlagBits_7(g, v, b0, b1, b2, b3, b4, b5, b6) \ + g.b0 = g.b1 = g.b2 = g.b3 = g.b4 = g.b5 = g.b6 = v + +#define stWriteFlagBits_8(g, v, b0, b1, b2, b3, b4, b5, b6, b7) \ + g.b0 = g.b1 = g.b2 = g.b3 = g.b4 = g.b5 = g.b6 = g.b7 = v + +#define suWriteFlagBits_1(g, v, b0) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_1(g, v, b0); \ + su_kernel_unlocks(); \ +}while(false) + +#define suWriteFlagBits_2(g, v, b0, b1) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_2(g, v, b0, b1); \ + su_kernel_unlocks(); \ +}while(false) + +#define suWriteFlagBits_3(g, v, b0, b1, b2) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_3(g, v, b0, b1, b2); \ + su_kernel_unlocks(); \ +}while(false) + +#define suWriteFlagBits_4(g, v, b0, b1, b2, b3) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_4(g, v, b0, b1, b2, b3); \ + su_kernel_unlocks(); \ +}while(false) + +#define suWriteFlagBits_5(g, v, b0, b1, b2, b3, b4) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_5(g, v, b0, b1, b2, b3, b4); \ + su_kernel_unlocks(); \ +}while(false) + +#define suWriteFlagBits_6(g, v, b0, b1, b2, b3, b4, b5) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_6(g, v, b0, b1, b2, b3, b4, b5); \ + su_kernel_unlocks(); \ +}while(false) + +#define suWriteFlagBits_7(g, v, b0, b1, b2, b3, b4, b5, b6) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_7(g, v, b0, b1, b2, b3, b4, b5, b6); \ + su_kernel_unlocks(); \ +}while(false) + +#define suWriteFlagBits_8(g, v, b0, b1, b2, b3, b4, b5, b6, b7) \ +do{ \ + su_kernel_locks(); \ + stWriteFlagBits_8(g, v, b0, b1, b2, b3, b4, b5, b6, b7); \ + su_kernel_unlocks(); \ +}while(false) + +#define siWriteFlagBits_1(b0) \ + stWriteFlagBits_1(u_grp, true, b0); \ + siWriteFlagBits() + +#define siWriteFlagBits_2(b0, b1) \ + stWriteFlagBits_2(u_grp, true, b0, b1); \ + siWriteFlagBits() + +#define siWriteFlagBits_3(b0, b1, b2) \ + stWriteFlagBits_3(u_grp, true, b0, b1, b2); \ + siWriteFlagBits() + +#define siWriteFlagBits_4(b0, b1, b2, b3) \ + stWriteFlagBits_4(u_grp, true, b0, b1, b2, b3); \ + siWriteFlagBits() + +#define siWriteFlagBits_5(b0, b1, b2, b3, b4) \ + stWriteFlagBits_5(u_grp, true, b0, b1, b2, b3, b4); \ + siWriteFlagBits() + +#define siWriteFlagBits_6(b0, b1, b2, b3, b4, b5) \ + stWriteFlagBits_6(u_grp, true, b0, b1, b2, b3, b4, b5); \ + siWriteFlagBits() + +#define siWriteFlagBits_7(b0, b1, b2, b3, b4, b5, b6) \ + stWriteFlagBits_7(u_grp, true, b0, b1, b2, b3, b4, b5, b6); \ + siWriteFlagBits() + +#define siWriteFlagBits_8(b0, b1, b2, b3, b4, b5, b6, b7) \ + stWriteFlagBits_8(u_grp, true, b0, b1, b2, b3, b4, b5, b6, b7); \ + siWriteFlagBits() + +#define siWriteFlagBits() \ + u_psv.value = ( \ + sizeof(u_grp) == 1 ? *(s_u8_t *)&u_grp \ + : sizeof(u_grp) == 2 ? *(s_u16_t *)&u_grp \ + : sizeof(u_grp) == 4 ? *(s_u32_t *)&u_grp \ + : 0 \ + ); \ + } \ + mPendSV_FIFOLoad(); \ +}while(false) + + +/* + * 私信 - 创建信箱 + */ + +#define sTaskMsg_Init_1(g) \ +tm1##g = tm1_##g + +#define sTaskMsg_Init_2(g) \ +sTaskMsg_Init_1(g); \ +tm2##g = tm2_##g + +#define sTaskMsg_Init_3(g) \ +sTaskMsg_Init_2(g); \ +tm3##g = tm3_##g + +#define sTaskMsg_Init_4(g) \ +sTaskMsg_Init_3(g); \ +tm4##g = tm4_##g + +#define sTaskMsg_Init_5(g) \ +sTaskMsg_Init_4(g); \ +tm5##g = tm5_##g + +#define sTaskMsg_Init_6(g) \ +sTaskMsg_Init_5(g); \ +tm6##g = tm6_##g + +#define sTaskMsg_Init_7(g) \ +sTaskMsg_Init_6(g); \ +tm7##g = tm7_##g + +#define sTaskMsg_Init_8(g) \ +sTaskMsg_Init_7(g); \ +tm8##g = tm8_##g + +#define sTaskMsg_Init(n) \ +static volatile s_u8_t u_tmrf = 0; \ +if(s_taskmsg_sign){ \ + u_tmrf = 1; \ + sTaskMsg_Init_##n(_); \ + if(--s_taskmsg_sign){ \ + s_taskmsg_sign = 0; \ + su_kernel_unlocks(); \ + } \ + return; \ +} \ +if(u_tmrf == 2){ \ + u_tmrf = 0; \ + sTaskMsg_Init_##n( ); \ + return; \ +} + +#define sCreateTaskMsg_0_1(m1) \ +(m1##__) \ +{ \ + static m1##_; \ + static m1 ; \ + sTaskMsg_Init(1); \ + do + +#define sCreateTaskMsg_0_2(m1, m2) \ +(m1##__, m2##__) \ +{ \ + static m1##_; static m2##_; \ + static m1 ; static m2 ; \ + sTaskMsg_Init(2); \ + do + +#define sCreateTaskMsg_0_3(m1, m2, m3) \ +(m1##__, m2##__, m3##__) \ +{ \ + static m1##_; static m2##_; static m3##_; \ + static m1 ; static m2 ; static m3 ; \ + sTaskMsg_Init(3); \ + do + +#define sCreateTaskMsg_0_4(m1, m2, m3, m4) \ +(m1##__, m2##__, m3##__, m4##__) \ +{ \ + static m1##_; static m2##_; static m3##_; static m4##_; \ + static m1 ; static m2 ; static m3 ; static m4 ; \ + sTaskMsg_Init(4); \ + do + +#define sCreateTaskMsg_0_5(m1, m2, m3, m4, m5) \ +(m1##__, m2##__, m3##__, m4##__, m5##__) \ +{ \ + static m1##_; static m2##_; static m3##_; static m4##_; static m5##_; \ + static m1 ; static m2 ; static m3 ; static m4 ; static m5 ; \ + sTaskMsg_Init(5); \ + do + +#define sCreateTaskMsg_0_6(m1, m2, m3, m4, m5, m6) \ +(m1##__, m2##__, m3##__, m4##__, m5##__, m6##__) \ +{ \ + static m1##_; static m2##_; static m3##_; static m4##_; static m5##_; static m6##_; \ + static m1 ; static m2 ; static m3 ; static m4 ; static m5 ; static m6 ; \ + sTaskMsg_Init(6); \ + do + +#define sCreateTaskMsg_0_7(m1, m2, m3, m4, m5, m6, m7) \ +(m1##__, m2##__, m3##__, m4##__, m5##__, m6##__, m7##__) \ +{ \ + static m1##_; static m2##_; static m3##_; static m4##_; static m5##_; static m6##_; static m7##_; \ + static m1 ; static m2 ; static m3 ; static m4 ; static m5 ; static m6 ; static m7 ; \ + sTaskMsg_Init(7); \ + do + +#define sCreateTaskMsg_0_8(m1, m2, m3, m4, m5, m6, m7, m8) \ +(m1##__, m2##__, m3##__, m4##__, m5##__, m6##__, m7##__, m8##__) \ +{ \ + static m1##_; static m2##_; static m3##_; static m4##_; static m5##_; static m6##_; static m7##_; static m8##_; \ + static m1 ; static m2 ; static m3 ; static m4 ; static m5 ; static m6 ; static m7 ; static m8 ; \ + sTaskMsg_Init(8); \ + do + +#define sCreateTaskMsg_1(m1) sCreateTaskMsg_0_1(m1) +#define sCreateTaskMsg_2(m1, m2) sCreateTaskMsg_0_2(m1, m2) +#define sCreateTaskMsg_3(m1, m2, m3) sCreateTaskMsg_0_3(m1, m2, m3) +#define sCreateTaskMsg_4(m1, m2, m3, m4) sCreateTaskMsg_0_4(m1, m2, m3, m4) +#define sCreateTaskMsg_5(m1, m2, m3, m4, m5) sCreateTaskMsg_0_5(m1, m2, m3, m4, m5) +#define sCreateTaskMsg_6(m1, m2, m3, m4, m5, m6) sCreateTaskMsg_0_6(m1, m2, m3, m4, m5, m6) +#define sCreateTaskMsg_7(m1, m2, m3, m4, m5, m6, m7) sCreateTaskMsg_0_7(m1, m2, m3, m4, m5, m6, m7) +#define sCreateTaskMsg_8(m1, m2, m3, m4, m5, m6, m7, m8) sCreateTaskMsg_0_8(m1, m2, m3, m4, m5, m6, m7, m8) + + +#endif diff --git a/System/os_handler.c b/System/os_handler.c new file mode 100644 index 0000000..a170432 --- /dev/null +++ b/System/os_handler.c @@ -0,0 +1,688 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file os_handler.c + * @brief tCosyTick_Handler and sPendSV_Handler + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#include "os_var.h" +#include "os_api.h" +#include "sv_com.h" +#include "sv_create.h" +#include "sv_tick.h" +#include "ur_api.h" +#include "ur_eapi.h" + +#if defined ( __ICCARM__ ) +#define __IAR_WEAK __WEAK +#else +#define __IAR_WEAK +#endif + +#if defined ( __GNUC__ ) +#define sKill_W(p) p +#else +#define sKill_W(p) +#endif + +sCat2Str(SYSCFG_STARTERCREATE, ExternTask(Starter)); +#if (SYSCFG_DEBUGGING == __ENABLED__) +__IAR_WEAK s_u32_t usedtime[2]/**/sZeroInstall_Group; +__IAR_WEAK m_stacklen_t _SYS_MEM_ s_taskstacklen; +#endif + +__IAR_WEAK void tCosyTick_Handler(void) MCUCFG_SYSTICK_ATTRIBUTE +{ + #if (OS_TIMINTTOTAL > 0 || OS_TIMQRYTOTAL > 0) + s_u8_t _SYS_REG_ i; + #endif + #if (SYSCFG_SYSTICKTIME_COUNT == __ENABLED__) + m_tick_t ticktemp_s sKill_W(=0); + #endif + s_tasknode_tsp _SYS_REG_ htask; + + /* 清除中断标志位 */ + mSysTick_Clear(); + + if(s_task_current == OS_NULL) return; + + /* 系统滴答开始时刻 */// 此刻定义为系统滴答开始时刻 for 系统滴答时间统计。 + #if (SYSCFG_SYSTICKTIME_COUNT == __ENABLED__) + if(s_taskmgr_sign){ + ticktemp_s = MCUCFG_SYSTICK_CURRVALUE; + } + #endif + + /* 软件RTC */ + #if (SYSCFG_SOFTRTC == __ENABLED__) + #define counter s_rtc_counter + if(true){ + if(counter < 1000000UL / SYSCFG_SYSTICK_CYCLE - 1){ + counter++; + if(counter == 1000000UL / SYSCFG_SYSTICK_CYCLE / 2){ + s_sign_every.halfsec = true; + } + } + else{ + counter = 0; + s_sign_every.halfsec = true; + s_sign_every.second = true; + if(s_rtc.second < 59) s_rtc.second++; + else{ + s_rtc.second = 0; + s_sign_every.minute = true; + if(s_rtc.minute < 59) s_rtc.minute++; + else{ + s_rtc.minute = 0; + s_sign_every.hour = true; + if(s_rtc.hour < 23) s_rtc.hour++; + else{ + s_rtc.hour = 0; + s_sign_every.day = true; + if(s_rtc.day < 7) s_rtc.day++; + else s_rtc.day = 1; + if(s_rtc.date < (s_rtc.month == 2 ? s_month2day : s_month0day[s_rtc.month])) s_rtc.date++; + else{ + s_rtc.date = 1; + s_sign_every.month = true; + if(s_rtc.month < 12) s_rtc.month++; + else{ + s_rtc.month = 1; + s_sign_every.year = true; + if(s_rtc.year < 99) s_rtc.year++; + else{ + s_rtc.year = 0; + s_rtc.yeah++; + } + } + } + } + } + } + } + } + #undef counter + #endif + + /* 运行时间统计 */ + #if (SYSCFG_RUNTIME_COUNT == __ENABLED__) + if(true){ + static m_rtccount_t _SYS_MEM_ counter = 0; + if(counter < 1000000UL / SYSCFG_SYSTICK_CYCLE - 1){ + counter++; + } + else{ + counter = 0; + if(s_runtime.second < 59) s_runtime.second++; + else{ + s_runtime.second = 0; + if(s_runtime.minute < 59) s_runtime.minute++; + else{ + s_runtime.minute = 0; + if(s_runtime.hour < 23) s_runtime.hour++; + else{ + s_runtime.hour = 0; + s_runtime.day++; + } + } + } + } + } + #endif + + /* 滴答钩子 */ + #if (SYSCFG_TICKHOOK == __ENABLED__) + if(true){ + void tick_hook(void); + tick_hook(); + } + #endif + + /* 任务管理器 */ + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_debug_recvlen){ + void os_debug_recv(void); + os_debug_recv(); + s_debug_recvlen = 0; + } + if(s_debug_sendsign){ + s_debug_sendsign = false; + tTimQry_ms(OS_TMID_DEBUGGER, 10); + } + #endif + + /* 定时中断 */ + #if (OS_TIMINTTOTAL > 0) + i = OS_TIMINTTOTAL; + while(i--){ + if(s_timint_handle[i]->timer){ + s_timint_handle[i]->timer--; + if(!s_timint_handle[i]->timer){ + if(s_timint_handle[i]->autoreload){ + s_timint_handle[i]->timer = s_timint_handle[i]->reload; + } + if(s_timint_handle[i]->hookortask){ + sResumeTask_TimInt(i); + } + else{ + sCallHook_TimInt(i); + } + } + } + } + #endif + + /* 定时查询 */ + #if (OS_TIMQRYTOTAL > 0) + i = OS_TIMQRYTOTAL; + while(i--){ + if(s_timqry_handle[i]->timer && s_timqry_handle[i]->timer < (s_timqry_t)~0){ + s_timqry_handle[i]->timer--; + } + if(!s_timqry_handle[i]->timer){ + if((*s_timqry_handle[i]->event)()){ + if(s_timqry_handle[i]->autoreload){ + s_timqry_handle[i]->timer = s_timqry_handle[i]->reload; + } + else{ + s_timqry_handle[i]->timer = ~0; + } + if(s_timqry_handle[i]->hookortask){ + sResumeTask_TimQry(i); + } + else{ + sCallHook_TimQry(i); + } + } + } + } + #endif + + /* 任务定时器 */// 定时器链表中的任务状态:就绪、浮动、阻塞、挂起。 + if(true){ + s_timer_pointer = (s_timer_pointer + 1) & (OS_TIMESLOTNUM - 1UL); + htask = s_timer_list[s_timer_pointer]; + if(htask != OS_NULL){ + bool loop_sign = true; + s_tasknode_tsp _SYS_REG_ hnext sKill_W(=OS_NULL); + s_tasknode_tsp _SYS_REG_ htail = htask->last_t; + __TIMER_LOOP: + if(htask == htail){ + loop_sign = false; + } + else{ + hnext = htask->next_t; + } + if(htask->status < OS_STATUS_SUSPENDED){ + if( htask->timer.cycle){ + htask->timer.cycle--; + } + else if(htask->status == OS_STATUS_READY){ + sa_remove_timerlist(htask); + s_sign_delay = false; + } + else{ + sa_clear_block(htask); + } + } + if(loop_sign){ + htask = hnext; + goto __TIMER_LOOP; + } + } + } + + /* 时间片 */ + #if (SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__) + if(s_task_current->tc_counter < OS_TIMESHARING(s_task_current)){ + s_task_current->tc_counter++; + } + else{ + s_sign_schedule.every[1] = false; + } + #endif + + /* 安全运行时 */// 超时链表中的任务状态:超时、超时|挂起、停止、删除。 + #if (SYSCFG_SAFERUNTIME == __ENABLED__) + if(!s_timeout_sign){ + htask = s_timeout_list; + while(htask != OS_VOID){ + if(htask->status == OS_STATUS_TIMEOUT){ + htask->srt_counter = 0; + sa_add_ready(htask); + htask->status = OS_STATUS_READY; + } + else if(htask->status & OS_STATUS_SUSPENDED){ + htask->srt_counter = 0; + htask->status = OS_STATUS_READY | OS_STATUS_SUSPENDED; + } + else if(htask->status == OS_STATUS_DELETED){ + if(htask->create){ + sa_free_task(htask); + } + } + s_timeout_list = htask->next_o; + htask->next_o = OS_NULL; + htask = s_timeout_list; + } + } + htask = s_task_current; + if(htask->pri && htask->saferuntime){ + htask->srt_counter++; + if(htask->srt_counter > htask->saferuntime){ + if(htask->status == OS_STATUS_READY){ + htask->next_o = s_timeout_list; + s_timeout_list = htask; + sa_remove_ready(htask); + htask->status = OS_STATUS_TIMEOUT; + s_timeout_sign = true; + #if (SYSCFG_DEBUGGING == __ENABLED__) + s_alarm.timeout_saferuntime = true; + #endif + } + } + } + #endif + + /* 任务管理器 */ + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_taskmgr_sign){ + /* CPU使用时间计数 */ + usedtime[0]++; + s_taskmgr_upspeed++; + /* 系统滴答时间统计 */// 此刻定义为系统滴答结束时刻。 + #if (SYSCFG_SYSTICKTIME_COUNT == __ENABLED__) + if(true){ + m_tick_t ticktemp_e = MCUCFG_SYSTICK_CURRVALUE; + #if (MCUCFG_SYSTICK_COUNTMODE == 1 || MCUCFG_SYSTICK_COUNTMODE == 3) + if(ticktemp_e > ticktemp_s){ + s_tick_count1 += ticktemp_e - ticktemp_s; + } + #elif (MCUCFG_SYSTICK_COUNTMODE == 2 || MCUCFG_SYSTICK_COUNTMODE == 4) + if(ticktemp_s > ticktemp_e){ + s_tick_count1 += ticktemp_s - ticktemp_e; + } + #endif + s_tick_count2++; + } + #endif + } + #endif + + /* 触发PendSV */ + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(true){ + mPendSV_Set(); + } + #else + if(!s_sign_schedule.total){ + mPendSV_Set(); + } + #endif +} + +#if (SYSCFG_DEBUGGING == __ENABLED__) +__IAR_WEAK void _cpu_usedtime_(m_tick_t ticktemp_0) MCUCFG_OSIT_ATTRIBUTE +{ + #if (MCUCFG_SYSTICK_COUNTMODE == 1 || MCUCFG_SYSTICK_COUNTMODE == 3) + if(usedtime[0]){ + s_task_current->usedtime[0] += usedtime[0] - 1; + usedtime[0] = 0; + usedtime[1] = (MCUCFG_SYSTICK_MAXVALUE - usedtime[1]) + (ticktemp_0 - MCUCFG_SYSTICK_MINVALUE); + } + else if(ticktemp_0 < usedtime[1]){ + usedtime[0] = ~0; + usedtime[1] = (MCUCFG_SYSTICK_MAXVALUE - usedtime[1]) + (ticktemp_0 - MCUCFG_SYSTICK_MINVALUE); + } + else{ + usedtime[1] = (ticktemp_0 - usedtime[1]); + } + #elif (MCUCFG_SYSTICK_COUNTMODE == 2 || MCUCFG_SYSTICK_COUNTMODE == 4) + if(usedtime[0]){ + s_task_current->usedtime[0] += usedtime[0] - 1; + usedtime[0] = 0; + usedtime[1] = (usedtime[1] - MCUCFG_SYSTICK_MINVALUE) + (MCUCFG_SYSTICK_MAXVALUE - ticktemp_0); + } + else if(usedtime[1] < ticktemp_0){ + usedtime[0] = ~0; + usedtime[1] = (usedtime[1] - MCUCFG_SYSTICK_MINVALUE) + (MCUCFG_SYSTICK_MAXVALUE - ticktemp_0); + } + else{ + usedtime[1] = (usedtime[1] - ticktemp_0); + } + #endif + s_task_current->usedtime[0] += (s_task_current->usedtime[1] + usedtime[1]) / MCUCFG_SYSTICK_COUNT1CYC; + s_task_current->usedtime[1] = (s_task_current->usedtime[1] + usedtime[1]) % MCUCFG_SYSTICK_COUNT1CYC; +} +#endif + +__IAR_WEAK void _float_to_ready_(s_tasknode_tsp htask) MCUCFG_OSIT_ATTRIBUTE +{ + htask->status = OS_STATUS_READY; +// if(htask->next_b != OS_NULL){ + sa_remove_blocklist(htask); +// } + if(htask->next_t != OS_NULL){ + sa_remove_timerlist(htask); + } +} + +__IAR_WEAK s_tasknode_tsp _SYS_MEM_ s_task_news/**/sZeroInstall; + +__IAR_WEAK s_u8_t _start_task_(void) MCUCFG_OSIT_ATTRIBUTE +{ + s_tasknode_tsp _SYS_REG_ node_news; + /* 静态创建 */ + if(*s_task_starter->dualhandle != OS_NULL){ + node_news = (s_tasknode_tsp)s_task_starter; + if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){ + #if (SYSCFG_DEBUGGING == __ENABLED__) + s_fault.failed_startuptask = true; + s_fault.overflow_taskstack = true; + #endif + s_startup_ecode = OS_ECODE_OVERFLOW_TASKSTACK; + goto __STARTUP_END; + } + else{ + mTaskStack_INIT(); + } + } + /* 动态创建 */ + else{ + node_news = OS_NULL; + node_news = (s_tasknode_tsp)s_malloc(sizeof(s_tasknode_ts)); + if(node_news != OS_NULL){ + node_news->stacksize = s_task_starter->stacksize; + if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){ + node_news->stacksize = MCUCFG_BASICSTACKSIZE; + node_news->create = 2; + } + else{ + node_news->create = 1; + } + node_news->bsp = OS_NULL; + node_news->bsp = (s_u8_t _MALLOC_MEM_ *)s_malloc(node_news->stacksize); + if(node_news->bsp != OS_NULL){ + mTaskStack_INIT(); + node_news->opri = s_task_starter->opri; + node_news->dualhandle = s_task_starter->dualhandle; + *node_news->dualhandle = node_news; + node_news->entry = s_task_starter->entry; + #if (SYSCFG_DEBUGGING == __ENABLED__) + node_news->name = s_task_starter->name; + #endif + #if (SYSCFG_SAFERUNTIME == __ENABLED__) + node_news->saferuntime = s_task_starter->saferuntime; + #endif + } + else{ + s_free(node_news); + #if (SYSCFG_DEBUGGING == __ENABLED__) + s_fault.failed_startuptask = true; + s_fault.mallocfailed_taskstack = true; + #endif + s_startup_ecode = OS_ECODE_MALLOCFAIL_TASKSTACK; + goto __STARTUP_END; + } + } + else{ + #if (SYSCFG_DEBUGGING == __ENABLED__) + s_fault.failed_startuptask = true; + s_fault.mallocfailed_tasknode = true; + #endif + s_startup_ecode = OS_ECODE_MALLOCFAIL_TASKNODE; + goto __STARTUP_END; + } + } + /* 公共部分 */ + if(node_news->opri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){ + node_news->pri = node_news->opri; + } + else{ + node_news->pri = SYSCFG_TASKPRIORITY - 1; + #if (SYSCFG_DEBUGGING == __ENABLED__) + s_alarm.outrange_taskpriority = true; + #endif + } + node_news->status = s_task_status0; + node_news->blocktype = 0; + node_news->timer.slots = 0; + node_news->timer.cycle = 0; + node_news->handle = OS_NULL; + #if (SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__) + node_news->tc_counter = 0; + #endif + #if (SYSCFG_DEBUGGING == __ENABLED__) + node_news->usedtime[0] = 0; + node_news->usedtime[1] = 0; + node_news->stacklen_max = MCUCFG_BASICSTACKSIZE; + #endif + #if (SYSCFG_SAFERUNTIME == __ENABLED__) + node_news->srt_counter = 0; + node_news->next_o = OS_NULL; + #endif + node_news->last_b = OS_NULL; + node_news->next_b = OS_NULL; + node_news->last_t = OS_NULL; + node_news->next_t = OS_NULL; + #if (SYSCFG_SAMEPRISCHEDULE && SYSCFG_MUTEX == __ENABLED__) + node_news->link = OS_NULL; + #endif + sa_insert_taskque(node_news); + s_task_queue_count++; + if(s_task_status0 == OS_STATUS_READY){ + sa_add_ready(node_news); + } + s_startup_ecode = OS_ECODE_NOERROR; + __STARTUP_END: + s_task_starter = OS_NULL; + if(node_news == Starter){ + if(s_startup_ecode == OS_ECODE_NOERROR){ + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_taskmgr_sign){ + usedtime[1] = MCUCFG_SYSTICK_CURRVALUE; + } + #endif + mUserReg_RESc(); + s_task_news = Starter; + return 1; + } + else return 0; + } + else return 2; +} + +void pendsv_hook(void); +#if (SYSCFG_MCUCORE == 80251) +#pragma functions(static) +#endif +__IAR_WEAK s_u8_t sPendSV_Handler(void) MCUCFG_OSIT_ATTRIBUTE +{ + /* 中断FIFO服务 */ + #if (MCUCFG_PENDSVFIFO_DEPTH > 0) + mPendSV_FIFOHandle(); + #endif + + /* 中断FLAG服务 */ + #if (SYSCFG_PENDSVHOOK == __ENABLED__) + pendsv_hook(); + #endif + + /* 每监控(假定入栈)*/ + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_task_current != OS_NULL){ + mTaskStack_LEN(); + if(s_task_current->stacklen_max < s_taskstacklen){ + s_task_current->stacklen_max = s_taskstacklen; + if(s_task_current->stacksize < s_taskstacklen){ + s_alarm.overflow_taskstack = true; + } + } + } + #endif + + /* 任务启动 */ + if(!s_sign_startup){ + s_sign_startup = true; + if(s_task_starter != OS_NULL){ + s_u8_t r = _start_task_(); + if(r < 2) return r; + } + } + + /* 任务调度 */ + if(s_sign_schedule.total) return 0; + else{ + #if (SYSCFG_DEBUGGING == __ENABLED__) + m_tick_t _SYS_REG_ ticktemp_0 sKill_W(=0); + m_bit_t push_sign = false; /*!< 入栈信号 */ + #else + #define push_sign true + #endif + s_u8_t _SYS_REG_ pri; + s_tasknode_tsp _SYS_REG_ node_news; + s_sign_schedule.every[1] = true; + + /* 抢占式调度(选择就绪)*/ + if(true){ + #if (SYSCFG_TASKPRIORITY > 64) + s_u8_t table_index = s_task_pickmap[s_task_table_index >> (SYSCFG_TASKPICKBITMAP & 1)]; + s_u8_t bytes_index = s_task_pickmap[s_task_bytes_index[table_index] >> (SYSCFG_TASKPICKBITMAP & 1)]; + s_u8_t bit_index = s_task_pickmap[s_task_ready_table[table_index][bytes_index] >> (SYSCFG_TASKPICKBITMAP & 1)]; + pri = (table_index << 6) + (bytes_index << 3) + bit_index; + #elif (SYSCFG_TASKPRIORITY > 8) + s_u8_t bytes_index = s_task_pickmap[s_task_bytes_index >> (SYSCFG_TASKPICKBITMAP & 1)]; + s_u8_t bit_index = s_task_pickmap[s_task_ready_table[bytes_index] >> (SYSCFG_TASKPICKBITMAP & 1)]; + pri = (bytes_index << 3) + bit_index; + #else + pri = s_task_pickmap[s_task_ready_table >> (SYSCFG_TASKPICKBITMAP & 1)]; + #endif + node_news = s_task_queue[pri]; + } + + /* 协作式调度 */ + #if (SYSCFG_SAMEPRISCHEDULE == __COOPERATIVE__) + while(true){ + if(node_news->status <= OS_STATUS_FLOATING){ + break; + } + node_news = node_news->next; + } + + /* 时间片轮转调度 */ + #elif (SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__) + while(true){ + s_tasknode_tsp _SYS_REG_ node_temp sKill_W(=OS_NULL); + if(node_news->status <= OS_STATUS_FLOATING){ + if(node_news->tc_counter < OS_TIMESHARING(node_news)){ /* 时间片未到期 */ + break; + } + else{ /* 时间片已到期 */ + node_news->tc_counter = 0; + node_temp = node_news; + } + } + if(node_news != s_task_queue[pri]->last){ + node_news = node_news->next; + } + else{ /* 在该优先级组中,未能找到时间片未到期的就绪任务,继续已到期的就绪任务 */ + node_news = node_temp; + break; + } + } + #endif + + /* 新任务为事件阻塞 */ + if(node_news->blocktype){ + node_news->blocktype = 0; + if(node_news->status == OS_STATUS_FLOATING){ /* 浮动变就绪 */ + _float_to_ready_(node_news); + } + mSysIRQ_Disable(); /* 内核上锁 */// 使服务层临界区连续。 + } + + /* 新任务仍为当前任务 -> 返回 */ + if(node_news == s_task_current){ + return 0; + } + + /* 新任务轮转至其优先级组首节点 */ + #if (SYSCFG_SAMEPRISCHEDULE) + if(node_news != s_task_queue[pri]){ + s_task_queue[pri] = node_news; + } + #endif + + /* 入栈监控 */ + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_task_current->status < OS_STATUS_STOPPED){ + if(s_task_current->stacksize < s_taskstacklen){ + #if (MCUCFG_TASKSTACK_REALLOC == __ENABLED__) + if(s_task_current->create){ + s_task_current->stacksize = s_taskstacklen + SYSCFG_TASKSTACK_REALLOCINC; + s_free(s_task_current->bsp); + s_task_current->bsp = OS_NULL; + s_task_current->bsp = (s_u8_t _MALLOC_MEM_ *)s_malloc(s_task_current->stacksize); + if(s_task_current->bsp != OS_NULL){ + push_sign = true; + s_task_current->create = 2; + s_alarm.realloc_taskstack = true; + } + else{ + sa_stop_task(s_task_current); + s_fault.reallocfailed_taskstack = true; + } + } + else{ + sa_stop_task(s_task_current); + s_fault.overflow_taskstack = true; + } + #else + sa_stop_task(s_task_current); + s_fault.overflow_taskstack = true; + #endif + } + else{ + push_sign = true; + } + } + #endif + + /* 任务切换时刻 */// 此刻定义为任务切换时刻 for CPU使用率统计。 + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_taskmgr_sign){ + ticktemp_0 = MCUCFG_SYSTICK_CURRVALUE; + } + #endif + + /* 当前任务入栈-预处理 */ + if(push_sign){ + #if (SYSCFG_SAFERUNTIME == __ENABLED__) + if(s_task_current->pri > node_news->pri){ + s_task_current->srt_counter = 0; + } + #endif + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_taskmgr_sign){ + _cpu_usedtime_(ticktemp_0); + } + #endif + mUserReg_SAVEc(); + } + + /* 新任务出栈-预处理 */ + if(true){ + #if (SYSCFG_DEBUGGING == __ENABLED__) + if(s_taskmgr_sign){ + usedtime[1] = ticktemp_0; + } + #endif + mUserReg_RESc(); + s_task_news = node_news; + } + + return (s_u8_t)push_sign + 1; + } +} diff --git a/System/os_taskmgr.c b/System/os_taskmgr.c new file mode 100644 index 0000000..a1415c6 --- /dev/null +++ b/System/os_taskmgr.c @@ -0,0 +1,635 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file os_taskmgr.c + * @brief 任务管理器(Taskmgr) + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#include "os_var.h" +#if (SYSCFG_DEBUGGING == __ENABLED__) +#include "os_api.h" +#include "sv_com.h" +#include "sv_create.h" +#include "sv_task.h" +#include "ur_api.h" +#include + +/** + \brief 字符串内存 + \details 字符串缓存 str[8] 的内存存储域。 + \note 对于 8051/251 来说,用户可自定义该内存,以寻求在性能和资源之间取得平衡。 + 该内存默认被定义为 _SYS_MEM_,即 DATA 存储区,以实现高性能。 + */ +#define _STR_MEM_ _SYS_MEM_ + +static char _STR_MEM_ str[8]; /*!< 字符串缓存 */ +static char _XDATA_MEM_ * _SYS_MEM_ mptr; /*!< 指向任务管理器发送缓存的可移动指针 */ + +/** + \brief 字符拷贝 + \param[in] c 字符 + \return 无 + */ +#define _chrcpy_(c) *mptr++ = c + +/** + \brief 字符n拷贝 + \param[in] c 字符 + \param[in] n 字符的数量 + \return 无 + */ +static void _chrncpy_(const char c, s_u8_t n) +{ + do{ + *mptr++ = c; + }while(--n); +} + +/** + \brief 空格拷贝 + \param[in] n 空格的数量 + \return 无 + */ +static void _spccpy_(s_u8_t n) +{ + do{ + *mptr++ = ' '; + }while(--n); +} + +/** + \brief 字符串拷贝 + \param[in] s 字符串指针 + \return 无 + */ +static void _strcpy_(const char *s) +{ + while(*s){ + *mptr++ = *s++; + } +} + +/** + \brief 字符串长度 + \param[in] s 字符串指针 + \return 字符串长度 + */ +static s_u8_t _strlen_(const char *s) +{ + s_u8_t i = 0; + while(*s++){ + i++; + } + return i; +} + +/** + \brief u8转字符串 + \param[in] var u8型数据 + \return 无 + */ +static void _u8str_(const s_u8_t var) +{ + char _STR_MEM_ *ptr = str; + if(var >= 100){ + *ptr++ = var / 100 + '0'; + goto Lable_2; + } + if(var >= 10){ + *ptr++ = var / 10 + '0'; + goto Lable_1; + } + else{ + *ptr++ = var /**/+ '0'; + goto Lable_0; + } + Lable_2: *ptr++ = (var % 100) / 10 + '0'; + Lable_1: *ptr++ = (var % 10) /**/+ '0'; + Lable_0: *ptr = '\0'; +} + +/** + \brief u16转字符串 + \param[in] var u16型数据 + \return 无 + */ +static void _u16str_(const s_u16_t var) +{ + char _STR_MEM_ *ptr = str; + if(var >= 10000){ + *ptr++ = var / 10000 + '0'; + goto Lable_4; + } + if(var >= 1000){ + *ptr++ = var / 1000 + '0'; + goto Lable_3; + } + if(var >= 100){ + *ptr++ = var / 100 + '0'; + goto Lable_2; + } + if(var >= 10){ + *ptr++ = var / 10 + '0'; + goto Lable_1; + } + else{ + *ptr++ = var /**/+ '0'; + goto Lable_0; + } + Lable_4: *ptr++ = (var % 10000) / 1000 + '0'; + Lable_3: *ptr++ = (var % 1000) / 100 + '0'; + Lable_2: *ptr++ = (var % 100) / 10 + '0'; + Lable_1: *ptr++ = (var % 10) /**/+ '0'; + Lable_0: *ptr = '\0'; +} + +/** + \brief u16长度 + \param[in] var u16型数据 + \return 长度 + */ +static s_u8_t _u16len_(const s_u16_t var) +{ + if(var >= 10000) return 5; + if(var >= 1000) return 4; + if(var >= 100) return 3; + if(var >= 10) return 2; + return 1; +} + +/** + \brief cpu使用率 + \param[in] num 分子(分母:10000) + \return 无 + */ +static void _used_ratio_(const s_u16_t num) +{ + s_u8_t i; + if(!num){ + str[0] = '0'; + str[1] = '\0'; + i = 2; + } + else{ + _u16str_(num); + i = _strlen_(str); + if(i > 2){ + str[i-0] = str[i-1]; + str[i-1] = str[i-2]; + str[i-2] = '.'; + str[i+1] = '\0'; + i += 2; + } + else{ + if(i == 1){ + str[2] = '0'; + str[3] = str[0]; + } + else{ + str[2] = str[0]; + str[3] = str[1]; + } + str[0] = '0'; + str[1] = '.'; + str[4] = '\0'; + i = 5; + } + } + _spccpy_((s_u8_t)(OS_TASKMGR_LEN_CPU - i)); + _strcpy_(str); + _chrcpy_('%'); +} + +#if (SYSCFG_TASKPC_MONITOR == __ENABLED__) +/** + \brief u8转十六进制字符串 + \param[in] var u8型数据 + \return 无 + \note 用于输出任务PC,十六进制字母为大写。 + */ +static void _u8str16_(const s_u8_t var) +{ + str[0] = (var >> 4) + '0'; + str[1] = (var & 0x0F) + '0'; + if(str[0] > '9') str[0] += 0x07; + if(str[1] > '9') str[1] += 0x07; + *mptr++ = str[0]; + *mptr++ = str[1]; +} +#endif + +/** + \brief 任务管理器 + \param[in] 定时器ID OS_TMID_TASKMGR + \param[in] 定时查询事件 s_sign_taskmgr + \param[in] 自动重装载 true + \param[in] 任务名称 Taskmgr + \param[in] 任务优先级 SYSCFG_TASKPRIORITY - 2 + \param[in] 任务栈大小 SYSCFG_STACKSIZE_TASKMGR + \param[in] 安全运行时 0 + \param[in] 任务名称文本 遗产模式:"Taskmgr",标准/兼容模式:"任务管理器" + \return 无 + \note 定时查询任务 + */ +#define _taskname "\xC8\xCE\xCE\xF1\xB9\xDC\xC0\xED\xC6\xF7" /*!< "任务管理器" */ +uCreateTask_TimQry +( + OS_TMID_TASKMGR, s_taskmgr_sign, true, + Taskmgr, SYSCFG_TASKPRIORITY - 2, SYSCFG_STACKSIZE_TASKMGR, 0, _taskname +) +{ + static char _XDATA_MEM_ *p[2]; + mptr = s_taskmgr_sendbuff; + /* 标题1 */ + _strcpy_("\xC8\xCE\xCE\xF1\xB9\xDC\xC0\xED\xC6\xF7"); /*!< "任务管理器" */ + _spccpy_(OS_TASKMGR_LEN_LINE - OS_TASKMGR_LEN_CPU - OS_TASKMGR_LEN_RAM - 10); + p[0] = mptr; /*!< 缓存CPU总使用率开始指针 */ + _spccpy_(OS_TASKMGR_LEN_CPU + OS_TASKMGR_LEN_RAM - 8); + _strcpy_("CosyOS-3"); + _strcpy_("\r\n"); + /* 标题2 */ + _strcpy_("\xC3\xFB\xB3\xC6"); /*!< "名称" */ + _spccpy_(SYSCFG_TASKNAMELEN_MAX - 4); + _strcpy_("\xD3\xC5\xCF\xC8\xBC\xB6"); /*!< "优先级" */ + _spccpy_(OS_TASKMGR_LEN_STA - 4); + _strcpy_("\xD7\xB4\xCC\xAC"); /*!< "状态" */ + _spccpy_(OS_TASKMGR_LEN_CPU - 3); + _strcpy_("CPU"); /*!< "CPU" */ + _spccpy_(OS_TASKMGR_LEN_RAM - 4); + _strcpy_("\xC4\xDA\xB4\xE6"); /*!< "内存" */ + _strcpy_("\r\n"); + /* - */ + _chrncpy_('-', OS_TASKMGR_LEN_LINE); + _strcpy_("\r\n"); + /* 正文 */ + p[1] = mptr; /*!< 缓存正文开始指针 */ + while(true){ + #if (SYSCFG_TASKPC_MONITOR == __ENABLED__) + m_pc_t pc = s_pc; + #endif + s_u8_t i = (s_u8_t)(SYSCFG_TASKPRIORITY); + s_u16_t numerator1 = 10000; + s_u32_t upspeed; + s_tasknode_tsp node_curr; + static s_tasknode_ts node_temp; + + mptr = p[1]; + mSysIRQ_Disable(); + upspeed = s_taskmgr_upspeed; + s_taskmgr_upspeed = 0; + mSysIRQ_Enable(); + + __TASKQUE_NEXT: + do{ + node_curr = s_task_queue[--i]; + }while(node_curr == OS_NULL); + while(true){ + s_u16_t numerator2; + mSysIRQ_Disable(); + s_memcpy(&node_temp, node_curr, sizeof(s_tasknode_ts)); + node_curr->usedtime[0] = 0; + node_curr->usedtime[1] = 0; + mSysIRQ_Enable(); + /* 名称 */ + _strcpy_(node_temp.name); + if(SYSCFG_TASKNAMELEN_MAX > _strlen_(node_temp.name)){ + _spccpy_((s_u8_t)(SYSCFG_TASKNAMELEN_MAX - _strlen_(node_temp.name))); + } + /* 优先级 */ + _u8str_ (node_temp.pri); + _spccpy_((s_u8_t)(OS_TASKMGR_LEN_PRI - _strlen_(str))); + _strcpy_(str); + /* 状态 */ + if(node_temp.status == OS_STATUS_READY){ + _spccpy_(OS_TASKMGR_LEN_STA); + } + else if(node_temp.status == OS_STATUS_FLOATING || node_temp.status == OS_STATUS_BLOCKED){ + _spccpy_(OS_TASKMGR_LEN_STA - 4); + if(node_temp.status == OS_STATUS_FLOATING){ + _chrcpy_('~'); + } + else{ + _chrcpy_(' '); + } + switch(node_temp.blocktype){ + case OS_BLOCKED_DELAY: _strcpy_("dly"); break; + case OS_BLOCKED_BINARY: _strcpy_("bin"); break; + case OS_BLOCKED_MUTEX: _strcpy_("mut"); break; + case OS_BLOCKED_SEMAPHORE: _strcpy_("sem"); break; + case OS_BLOCKED_TASKMSG: _strcpy_(" tm"); break; + case OS_BLOCKED_FETION: _strcpy_("fet"); break; + case OS_BLOCKED_MAIL: _strcpy_("mal"); break; + case OS_BLOCKED_MSG: _strcpy_("msg"); break; + case 1: _strcpy_("gro"); break; + case 2: _strcpy_("gro"); break; + case 4: _strcpy_("gro"); break; + } + } + else{ + _spccpy_(OS_TASKMGR_LEN_STA - 1); + if(node_temp.status == OS_STATUS_TIMEOUT){ + _chrcpy_('O'); + } + else if(node_temp.status & OS_STATUS_SUSPENDED){ + _chrcpy_('^'); + } + else if(node_temp.status == OS_STATUS_STOPPED){ + _chrcpy_('!'); + } + else{ + _chrcpy_('X'); + } + } + /* CPU */ + numerator2 = ( + ((node_temp.usedtime[0] * 10000UL) / upspeed) + + ((node_temp.usedtime[1] * 10000UL) / upspeed / MCUCFG_SYSTICK_COUNT1CYC) + ); + _used_ratio_(numerator2); + if(!node_temp.pri){ + numerator1 -= numerator2; + } + /* 内存 */ + _spccpy_( + (s_u8_t)( + OS_TASKMGR_LEN_RAM - 4 + - _u16len_((s_u16_t)node_temp.stacklen_max) + - _u16len_((s_u16_t)node_temp.stacksize) + ) + ); + _u16str_(node_temp.stacklen_max); + _strcpy_(str); + _strcpy_("B/"); + switch(node_temp.create){ + case 0: _chrcpy_('s'); break; + case 1: _chrcpy_('m'); break; + case 2: _chrcpy_('r'); break; + } + _u16str_(node_temp.stacksize); + _strcpy_(str); + _chrcpy_('B'); + _strcpy_("\r\n"); + /* 下一任务 */ + #if (SYSCFG_SAMEPRISCHEDULE) + if(node_curr == s_task_queue[i]->last){ + if(!i) break; + goto __TASKQUE_NEXT; + } + else{ + node_curr = node_temp.next; + } + #else + if(true){ + if(!i) break; + goto __TASKQUE_NEXT; + } + #endif + } + /* CPU总使用率 */ + if(true){ + char _XDATA_MEM_ *p0 = mptr; + mptr = p[0]; + _used_ratio_(numerator1); + mptr = p0; + } + + _strcpy_("\r\n"); /*!< null-line */ + /* PSV-FIFO */ + _strcpy_("PSV-FIFO: "); + #if (SYSCFG_PENDSVFIFO_MONITOR == __ENABLED__) + if(mPendSV_FIFO_DepthMAX > MCUCFG_PENDSVFIFO_DEPTH){ + s_fault.overflow_pendsvfifo = true; + } + _u16str_(mPendSV_FIFO_DepthMAX); + _strcpy_(str); + _strcpy_("/"); + _u16str_(MCUCFG_PENDSVFIFO_DEPTH); + _strcpy_(str); + _strcpy_(","); + _u16str_(mPendSV_FIFO_CountMAX); + _strcpy_(str); + _strcpy_("/"); + _u16str_(MCUCFG_PENDSVFIFO_COUNT); + _strcpy_(str); + _spccpy_( + (s_u8_t)( + OS_TASKMGR_LEN_LINE - 20 - 10 - 3 + - _u16len_((s_u16_t)mPendSV_FIFO_DepthMAX) + - _u16len_((s_u16_t)MCUCFG_PENDSVFIFO_DEPTH) + - _u16len_((s_u16_t)mPendSV_FIFO_CountMAX) + - _u16len_((s_u16_t)MCUCFG_PENDSVFIFO_COUNT) + ) + ); + #else + _strcpy_("null"); + _spccpy_(OS_TASKMGR_LEN_LINE - 20 - 10 - 4); + #endif + _strcpy_("| "); + /* 任务pc值 */ + _strcpy_("\xC8\xCE\xCE\xF1pc\xD6\xB5: "); + #if (SYSCFG_TASKPC_MONITOR == __ENABLED__) + #if (MCUCFG_PCLEN > 2) + _u8str16_((s_u8_t)(pc >> 24)); + _u8str16_((s_u8_t)(pc >> 16)); + #endif + _u8str16_((s_u8_t)(pc >> 8)); + _u8str16_((s_u8_t)(pc)); + #else + _strcpy_("null"); + #endif + _strcpy_("\r\n"); + /* 运行时间 */ + _strcpy_("\xD4\xCB\xD0\xD0\xCA\xB1\xBC\xE4: "); + #if (SYSCFG_RUNTIME_COUNT == __ENABLED__) + if(true){ + s_runtime_ts runtime; + mSysIRQ_Disable(); + runtime = s_runtime; + mSysIRQ_Enable(); + _u16str_(runtime.day); + _strcpy_(str); + _chrcpy_('-'); + if(runtime.hour < 10) _chrcpy_('0'); + _u8str_(runtime.hour); + _strcpy_(str); + _chrcpy_(':'); + if(runtime.minute < 10) _chrcpy_('0'); + _u8str_(runtime.minute); + _strcpy_(str); + _chrcpy_(':'); + if(runtime.second < 10) _chrcpy_('0'); + _u8str_(runtime.second); + _strcpy_(str); + _spccpy_((s_u8_t)(OS_TASKMGR_LEN_LINE - 20 - 10 - 9 - _u16len_(runtime.day))); + } + #else + _strcpy_("null"); + _spccpy_(OS_TASKMGR_LEN_LINE - 20 - 10 - 4); + #endif + _strcpy_("| "); + /* 滴答时间 */ + _strcpy_("\xB5\xCE\xB4\xF0\xCA\xB1\xBC\xE4: "); + #if (SYSCFG_SYSTICKTIME_COUNT == __ENABLED__) + mSysIRQ_Disable(); + if(s_tick_count2){ + s_u32_t counter1 = s_tick_count1; + s_u32_t counter2 = s_tick_count2; + s_tick_count1 = 0; + s_tick_count2 = 0; + mSysIRQ_Enable(); + counter2 = (counter1 * 100) / counter2; + #if defined (MCUCFG_SYSCLK) && (MCUCFG_SYSCLK > 0) \ + && defined (MCUCFG_SYSTICK_CLKDIV) && (MCUCFG_SYSTICK_CLKDIV > 0) + counter2 = (counter2 * MCUCFG_SYSTICK_CLKDIV) / MCUCFG_SYSCLK; + #elif defined (MCUCFG_SYSTICK_CLK) && (MCUCFG_SYSTICK_CLK > 0) + counter2 = counter2 / MCUCFG_SYSTICK_CLK; + #else + #error SysTick CLK undefined! + #endif + _u16str_((s_u16_t)(counter2 / 100)); + _strcpy_(str); + _chrcpy_('.'); + _u8str_((s_u8_t)((counter2 % 100) / 10)); + _strcpy_(str); + _u8str_((s_u8_t)(counter2 % 10)); + _strcpy_(str); + _strcpy_("us"); + } + else{ + mSysIRQ_Enable(); + } + #else + _strcpy_("null"); + #endif + _strcpy_("\r\n"); + /* 系统警告 */ + _strcpy_("\xCF\xB5\xCD\xB3\xBE\xAF\xB8\xE6: "); + if(*(s_u8_t *)&s_alarm){ + if(s_alarm.overflow_msgqueue){ + _strcpy_("omq, "); + } + if(s_alarm.timeout_saferuntime){ + _strcpy_("srt, "); + } + if(s_alarm.outrange_taskpriority){ + _strcpy_("otp, "); + } + if(s_alarm.realloc_taskstack){ + _strcpy_("rts, "); + } + if(s_alarm.overflow_taskstack){ + _strcpy_("ots, "); + } + mptr -= 2; + } + else{ + _strcpy_("\xCE\xDE"); + } + _strcpy_("\r\n"); + /* 系统异常 */ + _strcpy_("\xCF\xB5\xCD\xB3\xD2\xEC\xB3\xA3: "); + if(*(s_u8_t *)&s_fault){ + if(s_fault.mallocfailed_msgnode){ + _strcpy_("mmn, "); + } + if(s_fault.mallocfailed_tasknode){ + _strcpy_("mtn, "); + } + if(s_fault.mallocfailed_taskstack){ + _strcpy_("mts, "); + } + if(s_fault.reallocfailed_taskstack){ + _strcpy_("rts, "); + } + if(s_fault.overflow_taskstack){ + _strcpy_("ots, "); + } + if(s_fault.failed_startuptask){ + _strcpy_("fst, "); + } + if(s_fault.error_recvmsg_int){ + _strcpy_("erm, "); + } + #if (SYSCFG_PENDSVFIFO_MONITOR == __ENABLED__) + if(s_fault.overflow_pendsvfifo){ + _strcpy_("opd, "); + } + #endif + mptr -= 2; + } + else{ + _strcpy_("\xCE\xDE"); + } + _strcpy_("\r\n"); + /* 当前时间 */ + #if (SYSCFG_RTC_SHOW == __ENABLED__) + if(true){ + s_rtc_ts rtc; + mSysIRQ_Disable(); + if(true){ + #if (SYSCFG_SOFTRTC == __ENABLED__) + rtc = s_rtc; + #else + void rtc_hook(s_rtc_ts *t); + rtc_hook(&rtc); + #endif + } + mSysIRQ_Enable(); + _spccpy_(OS_TASKMGR_LEN_LINE - 24); + _u8str_(rtc.yeah); + _strcpy_(str); + if(rtc.year < 10) _chrcpy_('0'); + _u8str_(rtc.year); + _strcpy_(str); + _chrcpy_('.'); + if(rtc.month < 10) _chrcpy_('0'); + _u8str_(rtc.month); + _strcpy_(str); + _chrcpy_('.'); + if(rtc.date < 10) _chrcpy_('0'); + _u8str_(rtc.date); + _strcpy_(str); + _chrcpy_('-'); + if(rtc.hour < 10) _chrcpy_('0'); + _u8str_(rtc.hour); + _strcpy_(str); + _chrcpy_(':'); + if(rtc.minute < 10) _chrcpy_('0'); + _u8str_(rtc.minute); + _strcpy_(str); + _chrcpy_(':'); + if(rtc.second < 10) _chrcpy_('0'); + _u8str_(rtc.second); + _strcpy_(str); + _chrcpy_(' '); + _strcpy_("\xD6\xDC"); + switch(rtc.day){ + case 1: _strcpy_("\xD2\xBB"); break; + case 2: _strcpy_("\xB6\xFE"); break; + case 3: _strcpy_("\xC8\xFD"); break; + case 4: _strcpy_("\xCB\xC4"); break; + case 5: _strcpy_("\xCE\xE5"); break; + case 6: _strcpy_("\xC1\xF9"); break; + case 7: _strcpy_("\xC8\xD5"); break; + } + _strcpy_("\r\n"); + } + #endif + + _strcpy_("\r\n"); /*!< null-line */ + _chrcpy_('\0'); /*!< string-tail */ + /* - */ + mSysIRQ_Disable(); + s_debug_sendtype |= OS_DEBUG_SEND_TASKMGR; + #if (SYSCFG_DEBUG_SENDLEN == __ENABLED__) + s_taskmgr_sendlen = (s_u16_t)(mptr - s_taskmgr_sendbuff - 1); + #endif + sa_suspend_task(s_task_current); + su_kernel_unlock0_psv(); + } +} +#undef _taskname + +#endif diff --git a/System/sv_int_fifo.c b/System/sv_int_fifo.c new file mode 100644 index 0000000..23dfb40 --- /dev/null +++ b/System/sv_int_fifo.c @@ -0,0 +1,579 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file sv_int_fifo.c + * @brief 中断FIFO服务-执行函数 + * @details 仅在 PendSV中断 中由系统调用并执行。 + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#include "os_var.h" +#if (MCUCFG_PENDSVFIFO_DEPTH > 0) +#include "os_api.h" +#include "sv_com.h" +#include "ur_api.h" + +/** + @addtogroup 中断FIFO服务 + @{ + *//** + \defgroup 中断FIFO服务-执行函数 + @{ + */ + +/** + \page 手动裁剪说明: + + \li 本页中的各个执行函数,任何编译器都无法自动移除未使用,原因是
+ 它们是通过函数指针间接调用的。 + + \li 如果您希望做到极致的裁剪,可逐一查看这些函数,确定不使用的,
+ 可通过 编译开关 进行手动移除。 + */ + +/** + \brief 清除就绪延时 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iClearDelay()。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _clear_delay_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + __UNUSED(sv); + sc_clear_delay(); +} +#else +#define _clear_delay_ OS_NULL +#endif + +/** + \brief 恢复任务 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iResumeTask(task)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _resume_task_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_tasknode_tsp htask = ((sp_task_tsp)sv)->htask; + #if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + s_ecode_t _ecode = sc_resume_task(htask); + if(_ecode){ + s_psvfifo_ecode = _ecode; + pResumeTask_ErrorCallback(htask); + } + #else + if(htask == OS_NULL) return; + if(htask->status & OS_STATUS_SUSPENDED){ + sa_resume_task(htask); + } + #endif +} +#else +#define _resume_task_ OS_NULL +#endif + +/** + \brief 挂起任务 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iSuspendTask(task)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _suspend_task_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_tasknode_tsp htask = ((sp_task_tsp)sv)->htask; + #if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + s_ecode_t _ecode = sc_suspend_task(htask); + if(_ecode){ + s_psvfifo_ecode = _ecode; + pSuspendTask_ErrorCallback(htask); + } + #else + if(htask == OS_NULL) return; + if(htask->status < OS_STATUS_SUSPENDED){ + sa_suspend_task(htask); + } + #endif +} +#else +#define _suspend_task_ OS_NULL +#endif + +/** + \brief 删除任务 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iDeleteTask(task)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _delete_task_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_tasknode_tsp htask = ((sp_task_tsp)sv)->htask; + #if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + s_ecode_t _ecode = sc_delete_task(htask); + if(_ecode){ + s_psvfifo_ecode = _ecode; + pDeleteTask_ErrorCallback(htask); + } + #else + if(htask == OS_NULL) return; + if(htask->status < OS_STATUS_DELETED){ + sa_delete_task(htask); + } + #endif +} +#else +#define _delete_task_ OS_NULL +#endif + +/** + \brief 清除阻塞(状态) + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iClearBlock(task)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _clear_block_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_tasknode_tsp htask = ((sp_task_tsp)sv)->htask; + #if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + s_ecode_t _ecode = sc_clear_block(htask); + if(_ecode){ + s_psvfifo_ecode = _ecode; + pClearBlock_ErrorCallback(htask); + } + #else + if(htask == OS_NULL) return; + if(htask->status == OS_STATUS_FLOATING || htask->status == OS_STATUS_BLOCKED){ + sa_clear_block(htask); + } + #endif +} +#else +#define _clear_block_ OS_NULL +#endif + +/** + \brief 设置阻塞(时间) + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iSetBlock_tc(task, tc)、iSetBlock_ms(task, ms)、 + iSetBlock_s(task, s)、iSetBlock_m(task, m)、iSetBlock_h(task, h)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _set_block_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_tasknode_tsp htask = ((sp_blocktime_tsp)sv)->htask; + s_delay_t tick = ((sp_blocktime_tsp)sv)->tick; + #if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + s_ecode_t _ecode = sc_set_block(htask, tick); + if(_ecode){ + s_psvfifo_ecode = _ecode; + pSetBlock_ErrorCallback(htask, tick); + } + #else + if(htask == OS_NULL) return; + if(htask->status == OS_STATUS_FLOATING || htask->status == OS_STATUS_BLOCKED){ + sa_set_block(htask, tick); + } + #endif +} +#else +#define _set_block_ OS_NULL +#endif + +/** + \brief 设置任务优先级 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iSetTaskPri(task, npri)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _set_taskpri_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_tasknode_tsp htask = ((sp_taskpri_tsp)sv)->htask; + s_u8_t npri = ((sp_taskpri_tsp)sv)->npri; + #if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + s_ecode_t _ecode = sc_set_taskpri(htask, npri); + if(_ecode){ + s_psvfifo_ecode = _ecode; + pSetTaskPri_ErrorCallback(htask, npri); + } + #else + if(htask == OS_NULL) return; + if(htask->status < OS_STATUS_STOPPED){ + if(htask->pri != npri){ + sa_set_taskpri(htask, npri); + } + } + #endif +} +#else +#define _set_taskpri_ OS_NULL +#endif + +/** + \brief 写二值信号量 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iLockBin(bin)、iGiveBin(bin)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (SYSCFG_BINARY == __ENABLED__) +static void _write_binary_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_binary_tsp hbin = ((sp_binary_tsp)sv)->hbin; + bool value = ((sp_binary_tsp)sv)->value; + sc_write_binary(hbin, value); +} +#else +#define _write_binary_ OS_NULL +#endif + +/** + \brief 给予计数信号量 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iGiveSem(sem)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (SYSCFG_SEMAPHORE == __ENABLED__) +static void _give_semaph_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_semaph_tsp hsem = ((sp_semaph_tsp)sv)->hsem; + sc_give_semaph(hsem); +} +#else +#define _give_semaph_ OS_NULL +#endif + +/** + \brief 发送飞信 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iSendFetion(tbox, tion)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (SYSCFG_FETION == __ENABLED__) +static void _send_fetion_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_tionbox_tsp htbox = ((sp_tionbox_tsp)sv)->htbox; + m_fetion_t tion = ((sp_tionbox_tsp)sv)->tion; + sc_send_fetion(htbox, tion); +} +#else +#define _send_fetion_ OS_NULL +#endif + +/** + \brief 发送邮件 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iSendMail(mbox, mail)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (SYSCFG_MAILBOX == __ENABLED__) +static void _send_mail_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_mailbox_tsp hmbox = ((sp_mailbox_tsp)sv)->hmbox; + void *mail = ((sp_mailbox_tsp)sv)->mail; + sc_send_mail(hmbox, mail); +} +#else +#define _send_mail_ OS_NULL +#endif + +/** + \brief 发送消息 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iSendMsg(que, msg)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (SYSCFG_MSGQUEUE == __ENABLED__) +static void _send_msg_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_msgque_tsp hque = ((sp_msgque_tsp)sv)->hque; + void *msg = ((sp_msgque_tsp)sv)->msg; + #if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + s_ecode_t _ecode = sc_send_msg(hque, msg); + if(_ecode){ + s_psvfifo_ecode = _ecode; + pSendMsg_ErrorCallback(hque, msg); + } + #else + sc_send_msg(hque, msg); + #endif +} +#else +#define _send_msg_ OS_NULL +#endif + +/** + \brief 定时中断 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iTimInt_tc(tmid, tc)、iTimInt_ms(tmid, ms)、iTimInt_s(tmid, s)、 + iTimInt_m(tmid, m)、iTimInt_h(tmid, h)、iTimInt_Cancel(tmid)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (OS_TIMINTTOTAL > 0) +static void _timint_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_u8_t tmid = ((sp_timint_tsp)sv)->tmid; + s_timint_t tick = ((sp_timint_tsp)sv)->tick; + sc_timint(tmid, tick); +} +#else +#define _timint_ OS_NULL +#endif + +/** + \brief 定时查询 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iTimQry_tc(tmid, tc)、iTimQry_ms(tmid, ms)、iTimQry_s(tmid, s)、 + iTimQry_m(tmid, m)、iTimQry_h(tmid, h)、iTimQry_Cancel(tmid)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (OS_TIMQRYTOTAL > 0) +static void _timqry_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + s_u8_t tmid = ((sp_timqry_tsp)sv)->tmid; + s_timqry_t tick = ((sp_timqry_tsp)sv)->tick; + sc_timqry(tmid, tick); +} +#else +#define _timqry_ OS_NULL +#endif + +/** + \brief 写标志组 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iClearFlagGroup(group)、 + iSetFlagBit(group, bit)、iSetFlagBits(group, nbit) ...)、 + iClearFlagBit(group, bit)、iClearFlagBits(group, nbit) ...)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ \ + && (SYSCFG_FLAGGROUP == __ENABLED__) +static void _write_group_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + switch((s_u8_t)(((sp_group_tsp)sv)->size)){ + case 0x01: *(s_u8_t *)((sp_group_tsp)sv)->hgrp |= ((sp_group_tsp)sv)->value; break; + case 0x02: *(s_u16_t *)((sp_group_tsp)sv)->hgrp |= ((sp_group_tsp)sv)->value; break; + case 0x04: *(s_u32_t *)((sp_group_tsp)sv)->hgrp |= ((sp_group_tsp)sv)->value; break; + case 0xFF: *(s_u8_t *)((sp_group_tsp)sv)->hgrp &=~((sp_group_tsp)sv)->value; break; + case 0xFE: *(s_u16_t *)((sp_group_tsp)sv)->hgrp &=~((sp_group_tsp)sv)->value; break; + case 0xFC: *(s_u32_t *)((sp_group_tsp)sv)->hgrp &=~((sp_group_tsp)sv)->value; break; + } +} +#else +#define _write_group_ OS_NULL +#endif + +/** + \brief 全局变量写访问 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iWriteGVar(gv, lv)、iWriteGAry(gp, lp, size)、iWriteGStr(gs, ls)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +#include +static void _write_gvar_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + size_t size = ((sp_gvar_tsp)sv)->size; + void * gp = ((sp_gvar_tsp)sv)->gp; + void * lp = ((sp_gvar_tsp)sv)->lp; + size ? s_memcpy(gp, lp, size) : s_strcpy((char *)gp, (char *)lp); +} +#else +#define _write_gvar_ OS_NULL +#endif + +/** + \brief 挂起服务调用 + \param[in] sv 服务的结构体指针 + \return 无 + \note 关联服务:iPendSVC(fp)。 + */ +#if 1 /* 编译开关 *//* 如果用户不会调用关联服务,可手动移除该函数(1 改为 0)*/ +static void _pendsvc_(void _STATIC_MEM_ *sv) MCUCFG_OSIT_ATTRIBUTE +{ + (*((sp_pendsvc_tsp)sv)->fp)(); +} +#else +#define _pendsvc_ OS_NULL +#endif + +/** + \brief 中断FIFO服务-执行总函数(函数指针数组) + \param[in] [SVID] 服务ID + \param[in] sv 服务的结构体指针 + \return 无 + */ +void (_CODE_MEM_ * const _CONST_MEM_ sPendSV_FIFOHandler[OS_SVID_END])(void _STATIC_MEM_ *sv) = +{ + _clear_delay_, + _resume_task_, + _suspend_task_, + _delete_task_, + _clear_block_, + _set_block_, + _set_taskpri_, + _write_binary_, + _give_semaph_, + _send_fetion_, + _send_mail_, + _send_msg_, + _timint_, + _timqry_, + _write_group_, + _write_gvar_, + _pendsvc_ +}; + +/** @} *//** + \defgroup 中断FIFO服务-错误调用返回 + \note 当需要回调时,下列的回调函数可以在用户文件中实现。 + @{ + */ + +#if (SYSCFG_PENDSVFIFO_ERRORCALLBACK == __ENABLED__) + +/** + \brief iResumeTask(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +#if 1 /* 编译开关 *//* 如果该函数在用户文件中实现且此处的弱定义无效,可手动移除该函数(1 改为 0)*/ \ + && !defined (_resume_task_) +__WEAK void pResumeTask_ErrorCallback(s_tasknode_tsp htask) MCUCFG_OSIT_ATTRIBUTE +{ + /* Prevent unused argument(s) compilation warning */ + __UNUSED(htask); + /* NOTE: This function should not be modified, when the callback is needed, + the pResumeTask_ErrorCallback could be implemented in the user file + */ +} +#endif + +/** + \brief iSuspendTask(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +#if 1 /* 编译开关 *//* 如果该函数在用户文件中实现且此处的弱定义无效,可手动移除该函数(1 改为 0)*/ \ + && !defined (_suspend_task_) +__WEAK void pSuspendTask_ErrorCallback(s_tasknode_tsp htask) MCUCFG_OSIT_ATTRIBUTE +{ + /* Prevent unused argument(s) compilation warning */ + __UNUSED(htask); + /* NOTE: This function should not be modified, when the callback is needed, + the pSuspendTask_ErrorCallback could be implemented in the user file + */ +} +#endif + +/** + \brief iDeleteTask(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +#if 1 /* 编译开关 *//* 如果该函数在用户文件中实现且此处的弱定义无效,可手动移除该函数(1 改为 0)*/ \ + && !defined (_delete_task_) +__WEAK void pDeleteTask_ErrorCallback(s_tasknode_tsp htask) MCUCFG_OSIT_ATTRIBUTE +{ + /* Prevent unused argument(s) compilation warning */ + __UNUSED(htask); + /* NOTE: This function should not be modified, when the callback is needed, + the pDeleteTask_ErrorCallback could be implemented in the user file + */ +} +#endif + +/** + \brief iClearBlock(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +#if 1 /* 编译开关 *//* 如果该函数在用户文件中实现且此处的弱定义无效,可手动移除该函数(1 改为 0)*/ \ + && !defined (_clear_block_) +__WEAK void pClearBlock_ErrorCallback(s_tasknode_tsp htask) MCUCFG_OSIT_ATTRIBUTE +{ + /* Prevent unused argument(s) compilation warning */ + __UNUSED(htask); + /* NOTE: This function should not be modified, when the callback is needed, + the pClearBlock_ErrorCallback could be implemented in the user file + */ +} +#endif + +/** + \brief iSetBlock_x(task, x) error callback + \details iSetBlock_tc(task, tc)、iSetBlock_ms(task, ms)、iSetBlock_s(task, s)、 + iSetBlock_m(task, m)、iSetBlock_h(task, h),都通过该函数实现错误调用返回。 + \param[in] htask 任务句柄 + \param[in] tick 滴答周期(阻塞时间) + \return 无 + */ +#if 1 /* 编译开关 *//* 如果该函数在用户文件中实现且此处的弱定义无效,可手动移除该函数(1 改为 0)*/ \ + && !defined (_set_block_) +__WEAK void pSetBlock_ErrorCallback(s_tasknode_tsp htask, s_delay_t tick) MCUCFG_OSIT_ATTRIBUTE +{ + /* Prevent unused argument(s) compilation warning */ + __UNUSED(htask); + __UNUSED(tick); + /* NOTE: This function should not be modified, when the callback is needed, + the pSetBlock_ErrorCallback could be implemented in the user file + */ +} +#endif + +/** + \brief iSetTaskPri(task, npri) error callback + \param[in] htask 任务句柄 + \param[in] npri 新优先级 + \return 无 + */ +#if 1 /* 编译开关 *//* 如果该函数在用户文件中实现且此处的弱定义无效,可手动移除该函数(1 改为 0)*/ \ + && !defined (_set_taskpri_) +__WEAK void pSetTaskPri_ErrorCallback(s_tasknode_tsp htask, s_u8_t npri) MCUCFG_OSIT_ATTRIBUTE +{ + /* Prevent unused argument(s) compilation warning */ + __UNUSED(htask); + __UNUSED(npri); + /* NOTE: This function should not be modified, when the callback is needed, + the pSetTaskPri_ErrorCallback could be implemented in the user file + */ +} +#endif + +/** + \brief iSendMsg(que, msg) error callback + \param[in] hque 队列句柄 + \param[in] msg 消息指针 + \return 无 + */ +#if 1 /* 编译开关 *//* 如果该函数在用户文件中实现且此处的弱定义无效,可手动移除该函数(1 改为 0)*/ \ + && !defined (_send_msg_) +__WEAK void pSendMsg_ErrorCallback(s_msgque_tsp hque, void *msg) MCUCFG_OSIT_ATTRIBUTE +{ + /* Prevent unused argument(s) compilation warning */ + __UNUSED(hque); + __UNUSED(msg); + /* NOTE: This function should not be modified, when the callback is needed, + the pSendMsg_ErrorCallback could be implemented in the user file + */ +} +#endif + +#endif + +/** @} */ +/** @} */ + +#endif diff --git a/System/sv_int_fifo.h b/System/sv_int_fifo.h new file mode 100644 index 0000000..31eb02f --- /dev/null +++ b/System/sv_int_fifo.h @@ -0,0 +1,181 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file sv_int_fifo.h + * @brief 中断FIFO服务-调用宏 + * @details 仅在用户中断中调用,而后挂起到 PendSV中断 中执行。 + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#ifndef __SV_INT_FIFO_H +#define __SV_INT_FIFO_H + +/** + @addtogroup CosyOS_内核服务 + @{ + *//** + \defgroup 中断FIFO服务 + \brief 在用户中断中调用但不在本地执行,而是把服务的相关内容写入到局部的结构体中, + 再把结构体指针入 PendSV_FIFO,再触发 PendSV,而后在 PendSV中断 中执行服务。 + @{ + *//** + \ingroup 中断FIFO服务 + \defgroup 中断FIFO服务-调用宏 + @{ + */ + +/** 清除就绪延时 */ +#define sIPS_ClearDelay() \ +do{ \ + static sp_svid_ts u_psv = {OS_SVID_CLEARDELAY}; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 恢复任务 */ +#define sIPS_ResumeTask(_htask) \ +do{ \ + static sp_task_ts u_psv = {OS_SVID_RESUMETASK, OS_NULL}; \ + u_psv.htask = _htask; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 挂起任务 */ +#define sIPS_SuspendTask(_htask) \ +do{ \ + static sp_task_ts u_psv = {OS_SVID_SUSPENDTASK, OS_NULL}; \ + u_psv.htask = _htask; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 删除任务 */ +#define sIPS_DeleteTask(_htask) \ +do{ \ + static sp_task_ts u_psv = {OS_SVID_DELETETASK, OS_NULL}; \ + u_psv.htask = _htask; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 清除阻塞(状态)*/ +#define sIPS_ClearBlock(_htask) \ +do{ \ + static sp_task_ts u_psv = {OS_SVID_CLEARBLOCK, OS_NULL}; \ + u_psv.htask = _htask; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 设置阻塞(时间)*/ +#define sIPS_SetBlock(_htask, _tick) \ +do{ \ + static sp_blocktime_ts u_psv = {OS_SVID_SETBLOCK, OS_NULL, _tick}; \ + u_psv.htask = _htask; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 设置任务优先级 */ +#define sIPS_SetTaskPri(_htask, _npri) \ +do{ \ + static sp_taskpri_ts u_psv = {OS_SVID_SETTASKPRI, OS_NULL, _npri}; \ + u_psv.htask = _htask; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 写二值信号量 */ +#define sIPS_WriteBin(_bin, _value) \ +do{ \ + static sp_binary_ts u_psv = {OS_SVID_WRITEBINARY, &_bin, _value}; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 给予计数信号量 */ +#define sIPS_GiveSem(_sem) \ +do{ \ + static sp_semaph_ts u_psv = {OS_SVID_GIVESEMAPH, &_sem}; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 发送飞信 */ +#define sIPS_SendFetion(_tbox, _tion) \ +do{ \ + static sp_tionbox_ts u_psv = {OS_SVID_SENDFETION, &_tbox, 0}; \ + u_psv.tion = _tion; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 发送邮件 */ +#define sIPS_SendMail(_mbox, _mail) \ +do{ \ + static sp_mailbox_ts u_psv = {OS_SVID_SENDMAIL, &_mbox, OS_NULL}; \ + u_psv.mail = _mail; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 发送消息 */ +#define sIPS_SendMsg(_que, _msg) \ +do{ \ + static sp_msgque_ts u_psv = {OS_SVID_SENDMSG, (s_msgque_tsp)&_que, OS_NULL}; \ + u_psv.msg = _msg; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 定时中断 */ +#define sIPS_TimInt(_tmid, _tick) \ +do{ \ + static sp_timint_ts u_psv = {OS_SVID_TIMINT, _tmid, 0}; \ + u_psv.tick = _tick; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 定时查询 */ +#define sIPS_TimQry(_tmid, _tick) \ +do{ \ + static sp_timqry_ts u_psv = {OS_SVID_TIMQRY, _tmid, 0}; \ + u_psv.tick = _tick; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 清除标志组 */ +#define sIPS_ClearFlagGroup(_group) \ +do{ \ + static sp_group_ts u_psv = {OS_SVID_WRITEGROUP, (void *)&_group, -sizeof(_group), ~0}; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 写多标志位 */ +#define sIPS_WriteFlagBits(_group, _sign, _nbit) \ +do{ \ + static sp_group_ts u_psv = {OS_SVID_WRITEGROUP, (void *)&_group, _sign##sizeof(_group), 0}; \ + u_##_group##_ts u_grp; \ + miWriteFlagBits(); \ + sizeof(u_grp) == 1 ? *(s_u8_t *)&u_grp = false : MCUCFG_TERNARYMASK \ + sizeof(u_grp) == 2 ? *(s_u16_t *)&u_grp = false : MCUCFG_TERNARYMASK \ + sizeof(u_grp) == 4 ? *(s_u32_t *)&u_grp = false : false; \ + siWriteFlagBits_##_nbit( + +/** 全局变量写访问 */ +#define sIPS_WriteGVar(_gp, _lp, _size) \ +do{ \ + static sp_gvar_ts u_psv = {OS_SVID_WRITEGVAR, _gp, _lp, _size}; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 挂起服务调用 */ +#define sIPS_PendSVC(_fp) \ +do{ \ + static sp_pendsvc_ts u_psv = {OS_SVID_PENDSVC, _fp}; \ + mPendSV_FIFOLoad(); \ +}while(false) + +/** 设置时间 */ +#define sIPS_SetTime(_t) \ +do{ \ + static const m_rtccount_t _c = 1000000UL / SYSCFG_SYSTICK_CYCLE / 2 + 1; \ + iWriteGAry(&s_rtc, _t, sizeof(s_rtc)); \ + iWriteGVar(s_rtc_counter, _c); \ +}while(false) + +/** @} */ +/** @} */ +/** @} */ + +#endif diff --git a/System/sv_pend.h b/System/sv_pend.h new file mode 100644 index 0000000..6b042e9 --- /dev/null +++ b/System/sv_pend.h @@ -0,0 +1,38 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file sv_pend.h + * @brief PSV服务 + * @details 仅在 PendSV中断 中调用并执行。 + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#ifndef __SV_PEND_H +#define __SV_PEND_H + +/** + @addtogroup CosyOS_内核服务 + @{ + *//** + \defgroup PSV服务 + \brief 仅在 PendSV中断 中调用并执行的服务。 + 包括通过挂起服务调用(iPendSVC)间接调用,在挂起服务钩子(pendsv_hook)中调用。 + 如果通过挂起服务调用(iPendSVC)间接调用,就是 FIFO服务; + 如果通过挂起服务钩子(pendsv_hook) 调用,就是 FIAG服务。 + @{ + */ + +#define sPSV_ClearDelay() sc_clear_delay() /*!< 清除就绪延时 */ +#define sPSV_ResumeTask(htask) sc_resume_task(htask) /*!< 恢复任务 */ +#define sPSV_SuspendTask(htask) sc_suspend_task(htask) /*!< 挂起任务 */ +#define sPSV_DeleteTask(htask) sc_delete_task(htask) /*!< 删除任务 */ +#define sPSV_ClearBlock(htask) sc_clear_block(htask) /*!< 清除阻塞(状态)*/ +#define sPSV_SetBlock(htask, tick) sc_set_block(htask, tick) /*!< 设置阻塞(时间)*/ +#define sPSV_SetTaskPri(htask, npri) sc_set_taskpri(htask, npri) /*!< 设置任务优先级 */ +#define sPSV_GiveBin(bin) sc_write_binary(&bin, true) /*!< 给予二值信号量 */ + +/** @} */ +/** @} */ + +#endif diff --git a/System/ur_api.h b/System/ur_api.h new file mode 100644 index 0000000..8663c06 --- /dev/null +++ b/System/ur_api.h @@ -0,0 +1,1973 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file ur_api.h + * @brief 用户API + * @details 用户API定义,含注释说明,所有内核服务的API说明均在此文件中,并支持doxygen。 + * @author 迟凯峰 + * @version V2.3.1 + * @date 2026.03.01 + ******************************************************************************/ + +#ifndef __UR_API_H +#define __UR_API_H + +#include "os_redef.h" + +/** + \page CosyOS_API_DESCRIBE 概述:API说明 + 用户通过调用API来实现对系统服务的调用,所有API均为宏定义,所有API参数均支持宏定义。 + +
+ + \li API分类 + + \li 创建API
+ 静态创建[前缀:u]:分为 声明对象(uExtern)、创建对象(uCreate)、定义对象(uDef)。
+ 动态创建[前缀:d]:分为 声明对象(dExtern)、创建对象(dCreate)。 + + \li 任务API[前缀:u]
+ 仅在 任务 中调用。 + + \li 滴答API[前缀:t]
+ 仅在 SysTick中断 中调用。
+ 包括直接在 SysTick中断 中调用,在滴答钩子(tick_hook)、定时中断钩子(u_timint_##tmid)、
+ 定时查询钩子(u_timqry_##tmid)、定时查询事件(u_timqryevent_##tmid)中调用。 + + \li PSVAPI[前缀:p]
+ 仅在 PendSV中断 中调用。
+ 包括通过挂起服务调用(iPendSVC)间接调用、在挂起服务钩子(pendsv_hook)中调用。 + + \li 中断API[前缀:i]
+ 仅在 用户中断 中调用。
+ 包括 中断本地服务、中断FIFO服务。 + + \li 公共API[前缀:x]
+ 可在 任意处 调用。 + +
+ + \li API返回 + + \li 无返回
+ (1)服务的执行结果一定是成功的,所以不需要返回。
+ (2)所有中断挂起服务_FIFO均无法直接返回,但其中的部分服务允许支持错误调用返回。 + + \li 返回错误码
+ 服务的执行结果可能会失败,导致失败的原因可能有多个。
+ (1)无错误。
+ (2)由于结果已经成功,导致本次并未执行。
+ (3)失败。 + + \li 返回结果
+ 服务的执行结果可能会失败,但导致失败的原因是唯一的。
+ 执行结果为 bool 类型,true 为成功,false 为失败。 + + \li 返回指针
+ 返回一个指针,(void *) 类型,NULL 为失败。 + + \li 返回值
+ 返回一个数值,特定的数据类型,0 为失败。 + +
+ + \li 名词解释 + + \li 无限阻塞
+ 阻塞时间为无限长。 + + \li 无限等待
+ 超时时间为无限长。 + + \li 无限延时
+ 延时时间为无限长。 + + \li 无限同步
+ 仅同步一次,事件处理线程便可不限次数的周期运行处理事件。
+ 仅二值信号量支持该功能,可通过上锁的方式来终止无限同步。 + +
+ */ + +/** + \defgroup CosyOS_用户API + @{ + */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 构建系统 + \brief 系统构建相关服务。 + @{ + */ + +/** + \brief 启动-CosyOS + \param 无 + \return 错误码 + \note 用户应自主创建main函数,并在其末尾处调用该函数来启动-CosyOS;
+ 在正常情况下,该函数并不会返回,而是直接调度至 Starter 运行;
+ 只有在 Sysidle / Starter 启动失败时,才会返回错误码提示用户。 + */ +s_ecode_t uStartCosyOS(void); + +/** + \brief CosyOS-滴答 + \param 无 + \return 无 + \note 对于Arm用户来说,您应自主创建 SysTick_Handler(),并在其中调用该服务。 + \warning 对于51/251用户来说,系统滴答中断固定采用定时器0中断,并由CosyOS托管,
+ 您应屏蔽掉工程中原有的定时器0中断函数以避免冲突。 + */ +void tCosyTick_Handler(void); + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 任务 + \brief 任务线程的声明、创建、启动,及操作。 + @{ + */ + +/** + \ingroup 任务 + \defgroup 声明任务 + \brief 任务线程的声明 + \note 首先,声明任务不一定是必须的,当仅在一个c文件中启动、操作任务时,时常并不需要声明。 + \note 在声明任务时,通常无论是在h文件中声明还是在c文件中声明,都应采用完整声明方式,
+ 只有在编译器发出警告,与该任务相关的全局变量未引用时,再考虑简化声明方式。
+ 通常这种情况并不会发生,典型的是在使用GCC(GNU)编译器时,可能偶尔会出现这种警告。 + @{ + */ + +/** + \brief 简化声明静态一般任务 + \param[in] task 任务名称 + \return 无 + */ +#define uExtTask(task) sCSV_ExtTask(task)(void) + +/** + \brief 简化声明动态一般任务 + \param[in] task 任务名称 + \return 无 + */ +#define dExtTask(task) dCSV_ExtTask(task)(void) + +/** + \brief 完整声明静态一般任务 + \param[in] task 任务名称 + \return 无 + */ +#define uExternTask(task) sCSV_ExternTask(task)(void) + +/** + \brief 完整声明动态一般任务 + \param[in] task 任务名称 + \return 无 + */ +#define dExternTask(task) dCSV_ExternTask(task)(void) + +/** + \brief 简化声明静态私信任务 + \param[in] task 任务名称 + \param[in] add(...) 附加私信形参 + \return 无 + */ +#define uExtTaskmsg(task) sCSV_ExtTask(task) + +/** + \brief 简化声明动态私信任务 + \param[in] task 任务名称 + \param[in] add(...) 附加私信形参 + \return 无 + */ +#define dExtTaskmsg(task) dCSV_ExtTask(task) + +/** + \brief 完整声明静态私信任务 + \param[in] task 任务名称 + \param[in] add(...) 附加私信形参 + \return 无 + */ +#define uExternTaskmsg(task) sCSV_ExternTask(task) + +/** + \brief 完整声明动态私信任务 + \param[in] task 任务名称 + \param[in] add(...) 附加私信形参 + \return 无 + */ +#define dExternTaskmsg(task) dCSV_ExternTask(task) + +/** @} */ + +/** + \ingroup 任务 + \defgroup 创建任务 + \brief 任务线程的创建 + @{ + */ + +/** + \brief 静态创建一般任务 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define uCreateTask(task, pri, tss, srt, res) \ + sCSV_CreateTask(task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res)) + +/** + \brief 动态创建一般任务 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define dCreateTask(task, pri, tss, srt, res) \ + dCSV_CreateTask(task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res)) + +/** + \brief 静态创建私信任务 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] ntm 私信参数数量(1~8 个) + \param[in] add(...) 附加私信形参
+ 形参类型:任意数据类型
+ 形参名称:必须依次为 tm1、tm2...
+ 示 例:(int tm1, float tm2, char *tm3) + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define uCreateTaskmsg(task, pri, tss, srt, res, ntm) \ + sCSV_CreateTaskmsg(task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res), ntm) + +/** + \brief 动态创建私信任务 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] ntm 私信参数数量(1~8 个) + \param[in] add(...) 附加私信形参
+ 形参类型:任意数据类型
+ 形参名称:必须依次为 tm1、tm2...
+ 示 例:(int tm1, float tm2, char *tm3) + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define dCreateTaskmsg(task, pri, tss, srt, res, ntm) \ + dCSV_CreateTaskmsg(task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res), ntm) + +/** + \brief 静态创建定时中断任务 + \param[in] tmid 定时中断定时器ID + \param[in] arl 自动重装载 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define uCreateTask_TimInt(tmid, arl, task, pri, tss, srt, res) \ + sCSV_CreateTask_TimInt(tmid, arl, task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res)) + +/** + \brief 动态创建定时中断任务 + \param[in] tmid 定时中断定时器ID + \param[in] arl 自动重装载 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define dCreateTask_TimInt(tmid, arl, task, pri, tss, srt, res) \ + dCSV_CreateTask_TimInt(tmid, arl, task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res)) + +/** + \brief 静态创建定时查询任务 + \param[in] tmid 定时查询定时器ID + \param[in] event 定时查询事件 + \param[in] arl 自动重装载 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define uCreateTask_TimQry(tmid, event, arl, task, pri, tss, srt, res) \ + sCSV_CreateTask_TimQry(tmid, event, arl, task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res)) + +/** + \brief 动态创建定时查询任务 + \param[in] tmid 定时查询定时器ID + \param[in] event 定时查询事件 + \param[in] arl 自动重装载 + \param[in] task 任务名称 + \param[in] pri 任务优先级 + \param[in] tss 任务栈大小(单位为字节) + \param[in] srt 安全运行时(单位为滴答周期,0为无限长) + \param[in] res 任务名称文本 + \param[in] add{...} 附加任务代码 + \return 无 + */ +#define dCreateTask_TimQry(tmid, event, arl, task, pri, tss, srt, res) \ + dCSV_CreateTask_TimQry(tmid, event, arl, task, pri, tss, srt, SYSCFG_CREATETASKCUSTOM(task, res)) + +/** @} */ + +/** + \ingroup 任务 + \defgroup 启动任务 + \brief 任务线程的启动。任务只有在启动以后,才能加入到任务队列参与调度并运行。 + \warning 所有定时中断任务和定时查询任务均由操作系统自动启动,用户不要启动。 + \warning 不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + @{ + */ + +/** + \brief 启动任务 + \details 启动任务并置任务的初始状态为设定状态。 + \param[in] task 任务名称 + \param[in] status 任务初始状态
+ 就绪状态:OS_STATUS_READY
+ 阻塞状态:OS_STATUS_BLOCKED,阻塞类型为延时阻塞,延时时间为无限长。
+ 挂起状态:OS_STATUS_SUSPENDED,先前状态为就绪状态。 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_OVERFLOW_TASKSTACK 任务栈溢出 + \retval OS_ECODE_MALLOCFAIL_TASKNODE 任务节点内存分配失败 + \retval OS_ECODE_MALLOCFAIL_TASKSTACK 任务栈内存分配失败 + */ +#if (SYSCFG_TASKMSG == __ENABLED__) +#define uStartTask(task, status) \ + sUSV_StartTask_1(&sCat2Str(u_taskhand_, task), status, sCat2Str(u_task_, task)) +#else +#define uStartTask(task, status) \ + sUSV_StartTask_0(&sCat2Str(u_taskhand_, task), status) +#endif + +/** + \brief 启动任务并就绪 + \details 启动任务并置任务的初始状态为就绪状态。 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_OVERFLOW_TASKSTACK 任务栈溢出 + \retval OS_ECODE_MALLOCFAIL_TASKNODE 任务节点内存分配失败 + \retval OS_ECODE_MALLOCFAIL_TASKSTACK 任务栈内存分配失败 + */ +#define uStartTask_Ready(task) \ + uStartTask(task, OS_STATUS_READY) + +/** + \brief 启动任务并阻塞 + \details 启动任务并置任务的初始状态为阻塞状态(阻塞类型为延时阻塞,延时时间为无限长)。 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_OVERFLOW_TASKSTACK 任务栈溢出 + \retval OS_ECODE_MALLOCFAIL_TASKNODE 任务节点内存分配失败 + \retval OS_ECODE_MALLOCFAIL_TASKSTACK 任务栈内存分配失败 + */ +#define uStartTask_Block(task) \ + uStartTask(task, OS_STATUS_BLOCKED) + +/** + \brief 启动任务并挂起 + \details 启动任务并置任务的初始状态为挂起状态(先前状态为就绪状态)。 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_OVERFLOW_TASKSTACK 任务栈溢出 + \retval OS_ECODE_MALLOCFAIL_TASKNODE 任务节点内存分配失败 + \retval OS_ECODE_MALLOCFAIL_TASKSTACK 任务栈内存分配失败 + */ +#define uStartTask_Suspend(task) \ + uStartTask(task, OS_STATUS_SUSPENDED) + +/** @} */ + +/** + \ingroup 任务 + \defgroup 操作任务 + \brief 对任意任务的操作,如 恢复、挂起、删除、设置优先级 等。 + @{ + */ + +/** + \brief 清除就绪延时 + \details 清除当前任务的就绪延时,前提是当前任务已在就绪延时中。 + \param 无 + \return 无 + \note 同型服务:
+ pClearDelay()。
+ iClearDelay()。 + */ +#define tClearDelay() sTSV_ClearDelay() + +/** + \brief 恢复任务 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTSUSPENDED 任务未挂起 + \retval OS_ECODE_TASKSTOPPED 任务已停止 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tResumeTask(task),同返回。
+ pResumeTask(task),同返回。
+ iResumeTask(task),无返回/错误调用返回。 + */ +#define uResumeTask(task) sUSV_ResumeTask(task) + +/** + \brief 挂起任务 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKSUSPENDED 任务已挂起 + \retval OS_ECODE_TASKSTOPPED 任务已停止 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tSuspendTask(task),同返回。
+ pSuspendTask(task),同返回。
+ iSuspendTask(task),无返回/错误调用返回。 + */ +#define uSuspendTask(task) sUSV_SuspendTask(task) + +/** + \brief 删除任务 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tDeleteTask(task),同返回。
+ pDeleteTask(task),同返回。
+ iDeleteTask(task),无返回/错误调用返回。 + */ +#define uDeleteTask(task) sUSV_DeleteTask(task) + +/** + \brief 设置任务优先级 + \param[in] task 任务名称 + \param[in] npri 新优先级 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKPRIUNCHANGED 任务优先级未改变 + \retval OS_ECODE_TASKSTOPPED 任务已停止 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tSetTaskPri(task, npri),同返回。
+ pSetTaskPri(task, npri),同返回。
+ iSetTaskPri(task, npri),无返回/错误调用返回。 + */ +#define uSetTaskPri(task, npri) sUSV_SetTaskPri(task, npri) + +/** + \brief 清除阻塞(状态) + \details 清除指定任务的阻塞状态并使其就绪。 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTBLOCKED 任务未阻塞 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tClearBlock(task),同返回。
+ pClearBlock(task),同返回。
+ iClearBlock(task),无返回/错误调用返回。 + */ +#define uClearBlock(task) sUSV_ClearBlock(task) + +/** + \ingroup 操作任务 + \defgroup 设置阻塞(时间) + \brief 设置、修改指定任务的阻塞时间,前提是该任务当前已为阻塞状态。 + \note 理想误差:-1tick。 + \warning 按 毫秒、秒钟、分钟、小时 设置,用户需自己保证时间的有效性(可被系统滴答周期整除)。 + \warning 无限阻塞,仅能通过调用 xSetBlock_tc(task, ~0) 来实现。 + @{ + */ + +/** + \brief 设置阻塞-滴答周期 + \param[in] task 任务名称 + \param[in] tc 滴答周期(阻塞时间)
+ +0:清除阻塞
+ ~0:无限阻塞 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTBLOCKED 任务未阻塞 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tSetBlock_tc(task, tc),同返回。
+ pSetBlock_tc(task, tc),同返回。
+ iSetBlock_tc(task, tc),无返回/错误调用返回。 + */ +#define uSetBlock_tc(task, tc) sUSV_SetBlock(task, tc) + +/** + \brief 设置阻塞-毫秒 + \param[in] task 任务名称 + \param[in] ms 毫秒(阻塞时间)
+ 0:清除阻塞 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTBLOCKED 任务未阻塞 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tSetBlock_ms(task, ms),同返回。
+ pSetBlock_ms(task, ms),同返回。
+ iSetBlock_ms(task, ms),无返回/错误调用返回。 + */ +#define uSetBlock_ms(task, ms) uSetBlock_tc(task, (1000UL * (ms)) / SYSCFG_SYSTICK_CYCLE) + +/** + \brief 设置阻塞-秒钟 + \param[in] task 任务名称 + \param[in] s 秒钟(阻塞时间)
+ 0:清除阻塞 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTBLOCKED 任务未阻塞 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tSetBlock_s(task, s),同返回。
+ pSetBlock_s(task, s),同返回。
+ iSetBlock_s(task, s),无返回/错误调用返回。 + */ +#define uSetBlock_s(task, s) uSetBlock_ms(task, 1000UL * (s)) + +/** + \brief 设置阻塞-分钟 + \param[in] task 任务名称 + \param[in] m 分钟(阻塞时间)
+ 0:清除阻塞 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTBLOCKED 任务未阻塞 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tSetBlock_m(task, m),同返回。
+ pSetBlock_m(task, m),同返回。
+ iSetBlock_m(task, m),无返回/错误调用返回。 + */ +#define uSetBlock_m(task, m) uSetBlock_s(task, 60UL * (m)) + +/** + \brief 设置阻塞-小时 + \param[in] task 任务名称 + \param[in] h 小时(阻塞时间)
+ 0:清除阻塞 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTBLOCKED 任务未阻塞 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tSetBlock_h(task, h),同返回。
+ pSetBlock_h(task, h),同返回。
+ iSetBlock_h(task, h),无返回/错误调用返回。 + */ +#define uSetBlock_h(task, h) uSetBlock_m(task, 60UL * (h)) + +/** @} */ +/** @} */ +/** + \ingroup 任务 + \defgroup 操作自身任务 + \brief 仅适用于对自身任务的操作 + @{ + */ + +/** + \brief 禅让任务 + \details 自身任务主动禅让CPU使用权,轮转至下一个相同优先级的任务运行。 + \param 无 + \return 无 + \note 多个相同优先级的任务,通过禅让的方式可实现合作式任务。 + \note 禅让是自身任务主动时间片到期,禅让后任务仍为就绪状态。 + \warning 当开启相同优先级任务的时间片轮转调度时,才支持此服务。 + */ +#define uYieldTasking() su_yield_tasking() + +/** + \brief 设置自身任务优先级 + \param[in] npri 新优先级 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TPLUNCHANGED 优先级未改变 + */ +#define uSetTaskingPri(npri) sUSV_SetTaskPri(s_task_current, npri) + +/** + \brief 挂起自身任务 + \param 无 + \return 错误码(s_ecode_t) + \note 虽然也返回错误码,但在正常情况下结果一定是成功的,不必查看错误码。 + */ +#define uSuspendTasking() sUSV_SuspendTask(s_task_current) + +/** + \brief 删除自身任务 + \param 无 + \return 错误码(s_ecode_t) + \note 虽然也返回错误码,但在正常情况下结果一定是成功的,不必查看错误码。 + */ +#define uDeleteTasking() sUSV_DeleteTask(s_task_current) + +/** + \brief 恢复指定任务并挂起自身任务 + \param[in] task 指定任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTREADY 指定任务未就绪 + \retval OS_ECODE_TASKSTOPPED 指定任务已停止 + \retval OS_ECODE_TASKNOTSTARTED 指定任务未启动/已删除 + \note 当返回错误时,指定任务未能恢复为就绪状态,自身任务不会挂起。 + */ +#define uResumeSuspend(task) sUSV_ResumeSuspend(task) + +/** + \ingroup 操作自身任务 + \defgroup 自身任务延时 + \brief 自身任务延时分为阻塞延时和就绪延时。 + \note 阻塞延时:在延时期间,任务会进入阻塞状态,把CPU使用权转让给其它任务。 + \note 就绪延时:在延时期间,任务会维持就绪状态,原地等待延时时间到达,不转让CPU使用权。 + \note 当在任务临界区中,自动选择为就绪延时,否则选择为阻塞延时。 + \note 理想误差:-1tick。 + \warning 按 毫秒、秒钟、分钟、小时 延时,用户需自己保证时间的有效性(可被系统滴答周期整除)。 + \warning 无限延时,仅能通过调用 uDelay_tc(~0) 来实现。 + \warning 不支持在服务层临界区、全局临界区,或关闭总中断时调用。 + @{ + */ + +/** + \brief 延时-滴答周期 + \param[in] tc 滴答周期(延时时间)
+ ~0:无限延时 + \return 无 + */ +#define uDelay_tc(tc) sUSV_Delay(tc) + +/** + \brief 延时-毫秒 + \param[in] ms 毫秒(延时时间) + \return 无 + */ +#define uDelay_ms(ms) uDelay_tc((1000UL * (ms)) / SYSCFG_SYSTICK_CYCLE) + +/** + \brief 延时-秒钟 + \param[in] s 秒钟(延时时间) + \return 无 + */ +#define uDelay_s(s) uDelay_ms(1000UL * (s)) + +/** + \brief 延时-分钟 + \param[in] m 分钟(延时时间) + \return 无 + */ +#define uDelay_m(m) uDelay_s(60UL * (m)) + +/** + \brief 延时-小时 + \param[in] h 小时(延时时间) + \return 无 + */ +#define uDelay_h(h) uDelay_m(60UL * (h)) +/** @} */ +/** @} */ +/** @} */ +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 定时中断 + \brief 由用户定时操作,当定时器溢出时,系统将自动恢复/调用与其绑定的任务/钩子并可自动重复定时。 + \note 理想误差:-1tick。 + \warning 按 毫秒、秒钟、分钟、小时 定时,用户需自己保证时间的有效性(可被系统滴答周期整除)。 + @{ + */ + +/** + \brief 创建定时中断钩子 + \param[in] tmid 定时器ID + \param[in] arl 自动重装载设置
+ 0:关闭自动重装载
+ 1:开启自动重装载 + \param[in] add{...} 附加钩子代码 + \return 无 + */ +#define uCreateHook_TimInt(tmid, arl) \ + sCSV_CreateHook_TimInt(tmid, arl) + +/** + \brief 定时中断-滴答周期 + \param[in] tmid 定时中断定时器ID + \param[in] tc 滴答周期(定时时间) + \return 无 + \note 同型服务:
+ tTimInt_tc(tmid, tc)。
+ iTimInt_tc(tmid, tc)。 + */ +#define uTimInt_tc(tmid, tc) sUSV_TimInt(tmid, tc) + +/** + \brief 定时中断-毫秒 + \param[in] tmid 定时中断定时器ID + \param[in] ms 毫秒(定时时间) + \return 无 + \note 同型服务:
+ tTimInt_ms(tmid, ms)。
+ iTimInt_ms(tmid, ms)。 + */ +#define uTimInt_ms(tmid, ms) uTimInt_tc(tmid, (1000UL * (ms)) / SYSCFG_SYSTICK_CYCLE) + +/** + \brief 定时中断-秒钟 + \param[in] tmid 定时中断定时器ID + \param[in] s 秒钟(定时时间) + \return 无 + \note 同型服务:
+ tTimInt_s(tmid, s)。
+ iTimInt_s(tmid, s)。 + */ +#define uTimInt_s(tmid, s) uTimInt_ms(tmid, 1000UL * (s)) + +/** + \brief 定时中断-分钟 + \param[in] tmid 定时中断定时器ID + \param[in] m 分钟(定时时间) + \return 无 + \note 同型服务:
+ tTimInt_m(tmid, m)。
+ iTimInt_m(tmid, m)。 + */ +#define uTimInt_m(tmid, m) uTimInt_s(tmid, 60UL * (m)) + +/** + \brief 定时中断-小时 + \param[in] tmid 定时中断定时器ID + \param[in] h 小时(定时时间) + \return 无 + \note 同型服务:
+ tTimInt_h(tmid, h)。
+ iTimInt_h(tmid, h)。 + */ +#define uTimInt_h(tmid, h) uTimInt_m(tmid, 60UL * (h)) + +/** + \brief 终止定时中断 + \param[in] tmid 定时中断定时器ID + \return 无 + \note 同型服务:
+ tTimInt_Cancel(tmid)。
+ iTimInt_Cancel(tmid)。 + */ +#define uTimInt_Cancel(tmid) uTimInt_tc(tmid, 0) + +/** + \brief 定时中断定时器自动重装载 + \param[in] tmid 定时中断定时器ID + \param[in] arl 自动重装载设置
+ 0:关闭自动重装载
+ 1:开启自动重装载 + \return 无 + */ +#define xTimInt_AutoReload(tmid, arl) s_timint_autoreload[tmid] = arl + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 定时查询 + \brief 由用户定时操作,当定时器溢出后,系统在每个滴答周期都会查询用户定义的事件, + 若事件为真,系统将自动恢复/调用与其绑定的任务/钩子并可自动重复定时。 + \note 理想误差:-1tick。 + \warning 按 毫秒、秒钟、分钟、小时 定时,用户需自己保证时间的有效性(可被系统滴答周期整除)。 + @{ + */ + +/** + \brief 创建定时查询钩子 + \param[in] tmid 定时器ID + \param[in] event 定时查询事件 + \param[in] arl 自动重装载设置
+ 0:关闭自动重装载
+ 1:开启自动重装载 + \param[in] add{...} 附加钩子代码 + \return 无 + */ +#define uCreateHook_TimQry(tmid, event, arl) \ + sCSV_CreateHook_TimQry(tmid, event, arl) + +/** + \brief 定时查询-滴答周期 + \param[in] tmid 定时查询定时器ID + \param[in] tc 滴答周期(定时时间) + \return 无 + \note 同型服务:
+ tTimQry_tc(tmid, tc)。
+ iTimQry_tc(tmid, tc)。 + */ +#define uTimQry_tc(tmid, tc) sUSV_TimQry(tmid, tc) + +/** + \brief 定时查询-毫秒 + \param[in] tmid 定时查询定时器ID + \param[in] ms 毫秒(定时时间) + \return 无 + \note 同型服务:
+ tTimQry_ms(tmid, ms)。
+ iTimQry_ms(tmid, ms)。 + */ +#define uTimQry_ms(tmid, ms) uTimQry_tc(tmid, (1000UL * (ms)) / SYSCFG_SYSTICK_CYCLE) + +/** + \brief 定时查询-秒钟 + \param[in] tmid 定时查询定时器ID + \param[in] s 秒钟(定时时间) + \return 无 + \note 同型服务:
+ tTimQry_s(tmid, s)。
+ iTimQry_s(tmid, s)。 + */ +#define uTimQry_s(tmid, s) uTimQry_ms(tmid, 1000UL * (s)) + +/** + \brief 定时查询-分钟 + \param[in] tmid 定时查询定时器ID + \param[in] m 分钟(定时时间) + \return 无 + \note 同型服务:
+ tTimQry_m(tmid, m)。
+ iTimQry_m(tmid, m)。 + */ +#define uTimQry_m(tmid, m) uTimQry_s(tmid, 60UL * (m)) + +/** + \brief 定时查询-小时 + \param[in] tmid 定时查询定时器ID + \param[in] h 小时(定时时间) + \return 无 + \note 同型服务:
+ tTimQry_h(tmid, h)。
+ iTimQry_h(tmid, h)。 + */ +#define uTimQry_h(tmid, h) uTimQry_m(tmid, 60UL * (h)) + +/** + \brief 终止定时查询 + \param[in] tmid 定时查询定时器ID + \return 无 + \note 同型服务:
+ tTimQry_Cancel(tmid)。
+ iTimQry_Cancel(tmid)。 + */ +#define uTimQry_Cancel(tmid) uTimQry_tc(tmid, ~0) + +/** + \brief 定时查询定时器自动重装载 + \param[in] tmid 定时查询定时器ID + \param[in] arl 自动重装载设置
+ 0:关闭自动重装载
+ 1:开启自动重装载 + \return 无 + */ +#define xTimQry_AutoReload(tmid, arl) s_timqry_autoreload[tmid] = arl + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 互斥信号量 + \brief 仅适用于在任务中对任务级公共资源的互斥访问。 + \note 有优先级继承/天花板机制,以抑制优先级反转的发生。 + \note 互斥信号量均支持嵌套使用,最大嵌套深度255,获取与归还必须配对使用。 + \note 如果任务中调用了获取互斥量,应谨慎操作该任务,如操作不当可能会导致获取该互斥量的其它任务死锁。 + @{ + */ + +/** + \brief 声明互斥信号量 + \param[in] mut 互斥信号量名称 + \return 无 + */ +#define uExternMut(mut) sCSV_ExternMut(mut) + +/** + \brief 创建互斥信号量 + \param[in] mut 互斥信号量名称 + \return 无 + \warning 创建互斥信号量时,系统将自动赋初值,用户不可赋初值。 + */ +#define uCreateMut(mut) sCSV_CreateMut(mut) + +/** + \brief 获取互斥信号量 + \param[in] mut 互斥信号量名称 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果(bool) + \retval false 失败 + \retval true 成功 + \warning 不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + */ +#define uTakeMut(mut, tc) sUSV_TakeMut(mut, tc) + +/** + \brief 归还互斥信号量 + \param[in] mut 互斥信号量名称 + \return 无 + */ +#define uBackMut(mut) sUSV_BackMut(mut) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 二值信号量 + \brief 常用于事件同步、互斥访问(中断与任务之间的互斥)。 + @{ + */ + +/** + \brief 声明二值信号量 + \param[in] bin 二值信号量名称 + \return 无 + */ +#define uExternBin(bin) sCSV_ExternBin(bin) + +/** + \brief 创建二值信号量 + \param[in] bin 二值信号量名称 + \param[in] init 二值信号量初始值
+ false(0):已上锁,无法立即成功获取
+ true(1) :已解锁,可以立即成功获取 + \return 无 + \note 当用于互斥访问时,初始值应为true。 + */ +#define uCreateBin(bin, init) sCSV_CreateBin(bin, init) + +/** + \brief 上锁二值信号量 + \details 用于终止线程的无限同步。 + \param[in] bin 二值信号量名称 + \return 无 + \note 同型服务:
+ tLockBin(bin)。
+ pLockBin(bin)。
+ iLockBin(bin)。 + */ +#define uLockBin(bin) bin.binary = false + +/** + \brief 等待二值信号量 + \details 在指定的超时时间内等待二值信号量为真,适用于任务的无限同步,与获取的区别是不上锁。 + \param[in] bin 二值信号量名称 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果(bool) + \retval false 失败 + \retval true 成功 + \warning 不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + */ +#define uWaitBin(bin, tc) sUSV_WaitBin(bin, tc) + +/** + \brief 给予二值信号量 + \details 专用于事件同步。 + \param[in] bin 二值信号量名称 + \return 无 + \note 同型服务:
+ tGiveBin(bin)。
+ pGiveBin(bin)。
+ iGiveBin(bin)。 + */ +#define uGiveBin(bin) sUSV_GiveBin(bin) + +/** + \brief 获取二值信号量 + \details 用于事件同步或互斥访问。 + \param[in] bin 二值信号量名称 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果(bool) + \retval false 失败 + \retval true 成功 + \note 同型服务:
+ tTakeBin(bin)。
+ iTakeBin(bin)。 + \warning 任务中获取,不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + */ +#define uTakeBin(bin, tc) sUSV_TakeBin(bin, tc) + +/** + \brief 归还二值信号量 + \details 专用于互斥访问。 + \param[in] bin 二值信号量名称 + \return 无 + \note 同型服务:
+ tBackBin(bin)。
+ iBackBin(bin)。 + */ +#define uBackBin(bin) uGiveBin(bin) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 计数信号量 + \brief 常用于事件同步、重入访问(资源管理),是唯一能够实现并发事件同步的手段。 + @{ + */ + +/** + \brief 声明计数信号量 + \param[in] sem 计数信号量名称 + \return 无 + */ +#define uExternSem(sem) sCSV_ExternSem(sem) + +/** + \brief 创建计数信号量 + \param[in] sem 计数信号量名称 + \param[in] init 计数信号量初始值 + \param[in] max 计数信号量最大值 + \return 无 + */ +#define uCreateSem(sem, init, max) sCSV_CreateSem(sem, init, max) + +/** + \brief 给予计数信号量 + \param[in] sem 计数信号量名称 + \return 无 + \note 同型服务:
+ tGiveSem(sem)。
+ iGiveSem(sem)。 + */ +#define uGiveSem(sem) sUSV_GiveSem(sem) + +/** + \brief 获取计数信号量 + \param[in] sem 计数信号量名称 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果(bool) + \retval false 失败 + \retval true 成功 + \note 同型服务:
+ tTakeSem(sem)。 + \warning 任务中获取,不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + */ +#define uTakeSem(sem, tc) sUSV_TakeSem(sem, tc) + +/** + \brief 归还计数信号量 + \param[in] sem 计数信号量名称 + \return 无 + \note 同型服务:
+ tBackSem(sem)。 + */ +#define uBackSem(sem) uGiveSem(sem) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 事件标志组 + \brief 适用于对一类事件的事件同步。 + \details 某一类事件,它的发生线程可能会有多个,均同步至同一个事件处理线程中统一处理该类事件。 + \note 名词解释
+ 组名:标志组的名称
+ 位名:标志位的名称
+ 空位:空标志位
+ \note 查询标志位:任务、滴答、中断中,均直接查询。 + @{ + */ + +/** + \brief 声明标志组 + \param[in] group 组名 + \param[in] bits 定义各标志位,分号间隔 + \return 无 + */ +#define uExternFlagGroup(group, bits) sCSV_ExternFlagGroup(group, bits) + +/** + \brief 定义标志位 + \param[in] bit 位名 + \return 无 + */ +#define uDefFlagBit(bit) sDefBitField(bit) + +/** + \brief 定义空位 + \param[in] nvb 空位的数量 + \return 无 + */ +#define uDefVoidBits(nvb) sDefVoidBits(nvb) + +/** + \brief 创建标志组 + \param[in] group 组名 + \param[in] add={...} 附加代码(赋初值) + \return 无 + */ +#define uCreateFlagGroup(group) sCSV_CreateFlagGroup(group) + +/** + \brief 等待标志组 + \param[in] group 组名 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果(bool) + \retval false 失败 + \retval true 成功 + \warning 不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + \warning 事件的各个发生线程中设置标志位后,应调用 uClearBlock(task) 来手动完成事件同步。 + */ +#define uWaitFlagGroup(group, tc) sUSV_WaitFlagGroup(group, tc) + +/** + \brief 查询标志组 + \param[in] group 组名 + \return 结果(bool) + \retval false 失败 + \retval true 成功 + \note 同型服务:
+ tQueryFlagGroup(group)。
+ iQueryFlagGroup(group)。 + */ +#define uQueryFlagGroup(group) sUSV_QueryFlagGroup(group) + +/** + \brief 清除标志组 + \param[in] group 组名 + \return 无 + \note 同型服务:
+ tClearFlagGroup(group)。
+ iClearFlagGroup(group)。 + */ +#define uClearFlagGroup(group) sUSV_ClearFlagGroup(group) + +/** + \brief 设置标志位 + \param[in] group 组名 + \param[in] bit 位名 + \return 无 + \note 同型服务:
+ tSetFlagBit(group, bit)。
+ iSetFlagBit(group, bit)。 + */ +#define uSetFlagBit(group, bit) uSetFlagBits(group, 1) bit) + +/** + \brief 清除标志位 + \param[in] group 组名 + \param[in] bit 位名 + \return 无 + \note 同型服务:
+ tClearFlagBit(group, bit)。
+ iClearFlagBit(group, bit)。 + */ +#define uClearFlagBit(group, bit) uClearFlagBits(group, 1) bit) + +/** + \brief 设置多标志位 + \param[in] group 组名 + \param[in] nbit 标志位的数量 + \param[in] add...) 各位名,逗号间隔 + \return 无 + \note 同型服务:
+ tSetFlagBits(group, nbit)。
+ iSetFlagBits(group, nbit)。 + */ +#define uSetFlagBits(group, nbit) sUSV_WriteFlagBits(group, true, nbit) + +/** + \brief 清除多标志位 + \param[in] group 组名 + \param[in] nbit 标志位的数量 + \param[in] add...) 各位名,逗号间隔 + \return 无 + \note 同型服务:
+ tClearFlagBits(group, nbit)。
+ iClearFlagBits(group, nbit)。 + */ +#define uClearFlagBits(group, nbit) sUSV_WriteFlagBits(group, false, nbit) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 私信 + \brief 随意定义、灵活多变。 + \details 私信是CosyOS独创的一种任务间通信方式,其实质就是任务函数形参。 + \note 私信参数说明:
+ 1、私信参数的数量支持:1~8 个;
+ 2、各个参数的数据类型可为任意类型,只要编译器支持即可;
+ 3、各个参数的名称必须依次为:tm1、tm2...,用户可自行宏定义别名提高易用性。 + @{ + */ + +/** + \brief 接收私信
+
+ 别名
+           + uRecvTM + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果(bool) + \retval false 失败 + \retval true 成功 + \warning 不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + */ +#define uRecvTaskmsg(tc) sUSV_RecvTaskmsg(tc) + +/** + \brief 发送私信
+
+ 别名
+           + uSendTM + \param[in] task 任务名称 + \param[in] add(...) 附加私信实参 + \return 无 + \note 同型服务:
+ tSendTaskmsg(task) / tSendTM。 + \warning 如果在条件分支内调用,分支语句的{}不可省略。 + */ +#define uSendTaskmsg(task) sUSV_SendTaskmsg(task) + +/** + \brief 结束私信任务
+ \details 私信任务的最后一句代码。
+
+ 别名
+           + uEndTM + \param 无 + \return 无 + */ +#define uEndTaskmsg() }while(true) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 飞信 + \brief 原子类型、传输数据。 + \details 仅使用一个变量,同时即是消息,又是新消息标志。
+ 飞信为0时,表示无消息;飞信非0时,表示有消息;
+ 因此: + \warning 用户传输的有效消息必须为真值。 + \note 架构             数据类型
+ 8051            uint8_t
+ 80251          uint16_t
+ Arm32         uint32_t
+ 通用别名     m_fetion_t
+ @{ + */ + +/** + \brief 声明信箱 + \param[in] tbox 信箱名称 + \return 无 + */ +#define uExternTionbox(tbox) sCSV_ExternTionbox(tbox) + +/** + \brief 创建信箱 + \param[in] tbox 信箱名称 + \return 无 + */ +#define uCreateTionbox(tbox) sCSV_CreateTionbox(tbox) + +/** + \brief 接收飞信
+
+ 别名
+           + uRecvFet + \param[in] tbox 信箱名称 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 飞信(m_fetion_t) + \retval false 无飞信 + \note 同型服务:
+ tRecvFetion(tbox) / tRecvFet
+ iRecvFetion(tbox) / iRecvFet。 + \warning 任务中接收,不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + */ +#define uRecvFetion(tbox, tc) sUSV_RecvFetion(tbox, tc) + +/** + \brief 发送飞信
+
+ 别名
+           + uSendFet + \param[in] tbox 信箱名称 + \param[in] tion 飞信 + \return 无 + \note 同型服务:
+ tSendFetion(tbox, tion) / tSendFet
+ iSendFetion(tbox, tion) / iSendFet。 + */ +#define uSendFetion(tbox, tion) sUSV_SendFetion(tbox, tion) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 消息邮箱 + \brief 任意类型、传输指针。 + @{ + */ + +/** + \brief 声明邮箱 + \param[in] mbox 邮箱名称 + \return 无 + */ +#define uExternMailbox(mbox) sCSV_ExternMailbox(mbox) + +/** + \brief 创建邮箱 + \param[in] mbox 邮箱名称 + \return 无 + */ +#define uCreateMailbox(mbox) sCSV_CreateMailbox(mbox) + +/** + \brief 接收邮件 + \param[in] mbox 邮箱名称 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 邮件指针(void *) + \retval NULL 无邮件 + \note 同型服务:
+ tRecvMail(mbox)。
+ iRecvMail(mbox)。 + \warning 任务中接收,不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + */ +#define uRecvMail(mbox, tc) sUSV_RecvMail(mbox, tc) + +/** + \brief 发送邮件 + \param[in] mbox 邮箱名称 + \param[in] mail 邮件指针 + \return 无 + \note 同型服务:
+ tSendMail(mbox, mail)。
+ iSendMail(mbox, mail)。 + */ +#define uSendMail(mbox, mail) sUSV_SendMail(mbox, mail) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 消息队列 + \brief 任意类型、传输指针,是唯一能够实现并发消息同步的手段。 + \details 消息队列包括静态队列和动态队列。
+ 静态队列:收发消息的效率高,队列占用固定的内存;
+ 动态队列:收发消息的效率低,接收消息后,队列内存可被回收。 + \note 每个队列,用户应当自己明确消息的类型和size,此事与OS无关。 + @{ + */ + +/** + \brief 声明静态队列 + \param[in] que 队列名称 + \return 无 + */ +#define uExternQueue_Static(que) sCSV_ExternQueue_Static(que) + +/** + \brief 声明动态队列 + \param[in] que 队列名称 + \return 无 + */ +#define uExternQueue_Dynamic(que) sCSV_ExternQueue_Dynamic(que) + +/** + \brief 创建静态队列 + \param[in] que 队列名称 + \param[in] mode 传输模式
+ 0:FIFO(先入先出)
+ 1:LIFO(后入先出) + \param[in] len 队列长度 + \return 无 + */ +#define uCreateQueue_Static(que, mode, len) sCSV_CreateQueue_Static(que, mode, len) + +/** + \brief 创建动态队列 + \param[in] que 队列名称 + \param[in] mode 传输模式
+ 0:FIFO(先入先出)
+ 1:LIFO(后入先出) + \param[in] len 队列长度 + \return 无 + */ +#define uCreateQueue_Dynamic(que, mode, len) sCSV_CreateQueue_Dynamic(que, mode, len) + +/** + \brief 接收消息 + \param[in] que 队列名称 + \param[in] tc 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 消息指针(void *) + \retval NULL 无消息 + \note 同型服务:
+ tRecvMsg(que)。
+ iRecvMsg(que)。 + \warning 任务中接收,不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + \warning 中断中接收,队列只能是静态队列,消息缓存只能是静态缓存。 + */ +#define uRecvMsg(que, tc) sUSV_RecvMsg(que, tc) + +/** + \brief 发送消息 + \param[in] que 队列名称 + \param[in] msg 消息指针 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval ECODE_OVERFLOW_MSGQUEUE 消息队列溢出 + \retval ECODE_MALLOCFAIL_MSGNODE 消息节点内存分配失败 + \note 同型服务:
+ tSendMsg(que, msg),同返回。
+ iSendMsg(que, msg),无返回/错误调用返回。 + \warning 中断中发送,消息缓存只能是静态缓存。 + */ +#define uSendMsg(que, msg) sUSV_SendMsg(que, msg) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 全局变量访问 + \brief 由CosyOS内核提供服务支持,可实现在任务、滴答、中断中,对非原子型 + 全局变量的线程安全访问,同时不会破坏零中断延迟。 + \note 全局的结构体、数组、字符串等,都可视为非原子型全局变量。 + \note 原子型访问:
+ 滴答中:直接->读访问、写访问、自运算。
+ 任务中:直接->读访问、写访问,内核上锁后->自运算。
+ 中断中:直接->读访问,调用服务->写访问、自运算。 + \note 非原子型访问:
+ 滴答中:直接->读访问、写访问、自运算。
+ 任务中:内核上锁后->读访问、写访问、自运算。
+ 中断中:不可以读访问,调用服务->写访问、自运算。 + \note 不可以读访问:
+ 建议挂起到PendSV中,或同步至某任务中处理事件。
+ 挂起到PendSV中:iPendSVC(fp) 或 pendsv_hook(),均可直接->读访问;
+ 同步至某任务中:内核上锁后->读访问。 + @{ + */ + +/** + \brief 写全局变量 + \param[in] gv 全局变量名称 + \param[in] lv 局部变量名称 + \return 无 + */ +#define iWriteGVar(gv, lv) sIPS_WriteGVar((void *)&gv, (void *)&lv, sizeof(gv)) + +/** + \brief 写全局数组 + \param[in] gp 全局数组指针 + \param[in] lp 局部数组指针 + \param[in] size 拷贝的大小(字节数) + \return 无 + */ +#define iWriteGAry(gp, lp, size) sIPS_WriteGVar(gp, lp, size) + +/** + \brief 写全局字符串 + \param[in] gs 全局字符串指针 + \param[in] ls 局部字符串指针 + \return 无 + */ +#define iWriteGStr(gs, ls) sIPS_WriteGVar(gs, ls, 0) + +/** + \brief 挂起服务调用 + \param[in] fp 函数指针 + \return 无 + \note 适用于全局变量自运算、事件处理等。 + */ +#define iPendSVC(fp) sIPS_PendSVC(fp) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 软件RTC + \brief 适用于没有硬件RTC的物联网终端设备。 + \note 实际应用中,可每间隔一段时间(如一小时)同步一次网络时间,以校正误差。 + @{ + */ + +/** + \brief 获取时间 + \param[in] t 本地时间的指针(s_rtc_ts *) + \return t(void *) + \note 同型服务:
+ tGetTime(t)。 + */ +#define uGetTime(t) sUSV_GetTime(t) + +/** + \brief 设置时间 + \param[in] t 本地时间的指针(s_rtc_ts *) + \return 无 + \note 同型服务:
+ tSetTime(t)。
+ iSetTime(t)。 + */ +#define uSetTime(t) sUSV_SetTime(t) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 动态内存 + @{ + */ + +/** + \ingroup 动态内存 + \defgroup 进程内存 + \brief 以进程为单位初始化内存池,各进程独享自己的内存池。 + @{ + */ + +/** + \brief malloc + \details 在进程内存池或堆中分配一块内存。 + \param[in] size 内存块的大小(字节数) + \return 分配的指针(void _MALLOC_MEM_ *) + \retval NULL 内存分配失败 + */ +#define uMalloc(size) sUSV_Malloc(size) + +/** + \brief calloc + \details 在进程内存池或堆中连续分配多块内存。 + \param[in] nmemb 内存块的数量 + \param[in] size 内存块的大小(字节数) + \return 分配的指针(void _MALLOC_MEM_ *) + \retval NULL 内存分配失败 + */ +#define uCalloc(nmemb, size) sUSV_Calloc(nmemb, size) + +/** + \brief realloc + \details 重新分配内存。 + \param[in] p 预重分配的指针 + \param[in] size 预重分配的大小(字节数) + \return 分配的指针(void _MALLOC_MEM_ *) + \retval NULL 内存分配失败 + */ +#define uRealloc(p, size) sUSV_Realloc(p, size) + +/** + \brief free + \param[in] p 释放的指针 + \return 无 + */ +#define uFree(p) sUSV_Free(p) + +/** @} */ + +/** + \ingroup 动态内存 + \defgroup 线程内存 + \brief 以线程为单位初始化内存池,各线程独享自己的内存池。 + \note 线程内存的分配效率远高于进程内存,因为每一次调用uTalloc都是在自己的线程内存池中直接按序分配内存。 + \note 在某线程中,如果需要多次动态内存分配,可考虑采用线程内存以提高性能。 + \note 线程内存的应用法则:当所有uTalloc的内存都可以释放时,再一次性释放所有内存(线程内存池)。 + @{ + */ + +/** + \brief 创建线程内存池 + \details 实为定义变量(线程内存控制块),C89模式时可考虑在线程的开始处创建。 + \param 无 + \return 无 + */ +#define uCreateMempool() sCSV_CreateMempool() + +/** + \brief 初始化线程内存池 + \details 实质上是通过调用malloc,从进程内存池或堆中分配一块内存来做为线程内存池。 + \param[in] size 线程内存池的大小(字节数) + \return 结果(bool) + \retval false 失败 + \retval true 成功 + */ +#define uInitMempool(size) sUSV_InitMempool(size) + +/** + \brief 线程内存分配 + \details 在线程内存池中分配一块内存。 + \param[in] size 内存块的大小(字节数) + \return 分配的指针(void _MALLOC_MEM_ *) + \retval NULL 内存分配失败 + */ +#define uTalloc(size) sUSV_Talloc(size) + +/** + \brief 释放线程内存池 + \param 无 + \return 无 + */ +#define uFreeMempool() sUSV_FreeMempool() + +/** @} */ +/** @} */ +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 临界区 + \note CosyOS的临界区包括任务临界区、服务层临界区、全局临界区,均支持嵌套使用。
+ 各临界区之间也可随意互相嵌套,但通常推荐在任务临界区中嵌套服务层临界区,
+ 在服务层临界区中嵌套全局临界区,以逐步扩大保护范围。 + @{ + */ + +/** + \ingroup 临界区 + \defgroup 调度锁(任务临界区) + \brief 通过上锁任务调度器的方式,来实现任务级的临界区保护,仅支持在任务中调用。 + \note 仅是上锁任务调度器,不关闭系统中断(SysTick、PendSV),所以即使是长时间的、
+ 对大段的任务级公共资源的独占访问,也不会影响系统节拍和内核服务的执行。 + \note 调度锁支持嵌套使用,最大嵌套深度255,调度上锁与调度解锁必须配对使用。 + \note 调度锁不会破坏零中断延迟,当需要任务级的临界区保护时,可以考虑。 + @{ + */ + +/** + \brief 调度上锁(进入任务临界区) + \param 无 + \return 无 + */ +#define uScheduleLock() su_schedule_locks() + +/** + \brief 调度解锁(退出任务临界区) + \param 无 + \return 无 + */ +#define uScheduleUnlock() su_schedule_unlocks() + +/** @} */ + +/** + \ingroup 临界区 + \defgroup 内核锁(服务层临界区) + \brief OS内核级的临界区保护,会关闭系统中断(SysTick、PendSV),仅支持在任务中调用。 + \note 由SysTick、PendSV、内核锁,共同组成大的服务层临界区,当处理得当时,可实现全局的临界区保护。
+ 实现过程:
+ 滴答中:直接访问即可。
+ 任务中:内核上锁后访问。
+ 中断中:采用中断挂起服务。 + \note 内核锁支持嵌套使用,最大嵌套深度255,内核上锁与内核解锁必须配对使用。 + \note 内核锁不会破坏零中断延迟,当需要全局的临界区保护时,应首先予以考虑。 + \note 内核锁应遵循快进快出的原则,临界段代码的执行时间应远小于系统滴答周期,
+ 否则可能会导致丢失系统节拍、延误其它内核服务的执行,对系统实时性造成不利影响。 + \note 当在任务中访问非原子全局变量时,可采用内核锁实现全局的临界区保护。 + @{ + */ + +/** + \brief 内核上锁(进入服务层临界区) + \param 无 + \return 无 + */ +#define uKernelLock() su_kernel_locks() + +/** + \brief 内核解锁(退出服务层临界区) + \param 无 + \return 无 + */ +#define uKernelUnlock() su_kernel_unlocks() + +/** @} */ + +/** + \ingroup 临界区 + \defgroup 中断锁(全局临界区) + \brief 全局的临界区保护,通常会关闭总中断,支持在任意处调用。 + \note CosyOS内核中从来不会关闭总中断,提供此项服务只是为了便于用户
+ 对全局公共资源和程序过程的保护。 + \note 全局临界区会破坏零中断延迟,应做为最后的选项,慎重使用。 + @{ + */ +#if (MCUCFG_ISA != __ARM__) +/** + \ingroup 全局临界区 + \defgroup 操作-EA + \note 支持嵌套使用,最大嵌套深度255,进入临界区与退出临界区必须配对使用。 + @{ + */ + +/** + \brief 进入全局临界区 + \param 无 + \return 无 + */ +#define xDisableIRQ() mxDisableIRQ() + +/** + \brief 退出全局临界区 + \param 无 + \return 无 + */ +#define xResumeIRQ() mxResumeIRQ() + +/** @} */ +#else +/** + \ingroup 全局临界区 + \defgroup 操作-PRIMASK + \note 支持嵌套使用,进入临界区与退出临界区必须配对使用。 + @{ + */ + +/** + \brief 进入全局临界区 + \param 无 + \return oirq PRIMASK上一次的值(uint32_t类型) + */ +#define xDisableIRQ() mxDisableIRQ() + +/** + \brief 退出全局临界区 + \param[in] oirq PRIMASK上一次的值(uint32_t类型) + \return 无 + */ +#define xResumeIRQ(oirq) mxResumeIRQ(oirq) + +/** @} */ + +/** + \ingroup 全局临界区 + \defgroup 操作-BASEPRI + \note 使用条件:
+ 1、MCU必须有 BASEPRI 寄存器;
+ 2、MCU配置中,系统中断配置必须选择 TIMn_IRQHandler + XXX_IRQHandler。 + \note 使用说明:
+ 1、关于npri,例如中断优先级分组选择 NVIC_PriorityGoup_4,那么中断优先级从高到低为 0~15。
+ 如果需要掩蔽(3~15)的中断,npri应输入3。
+ 2、支持嵌套使用,进入临界区与退出临界区必须配对使用。
+ 3、嵌套使用时,仅能逐步扩大掩蔽范围(npri越来越小),否则新的掩蔽范围不会生效(将维持上一次的掩蔽范围)。 + @{ + */ + +/** + \brief 进入全局临界区 + \param[in] npri 掩蔽范围的最高优先级的优先级号(uint32_t类型) + \return opri BASEPRI的原值(uint32_t类型) + */ +#define xMaskingPRI(npri) mxMaskingPRI(npri) + +/** + \brief 退出全局临界区 + \param[in] opri BASEPRI的原值(uint32_t类型) + \return 无 + */ +#define xResumePRI(opri) mxResumePRI(opri) + +/** @} */ +#endif +/** @} */ +/** @} */ +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 杂项 + @{ + */ + +/** + \ingroup 杂项 + \defgroup 中断FIFO服务-错误调用返回 + \note 当需要回调时,下列的回调函数可以在用户文件中实现。 + \note 对于8051来说,如果系统中断被配置为使用独立的REGBANK(与任务使用不同的REGBANK),
+ 下列的回调函数需要添加using属性、或声明为相对寄存器访问。参见 tick_hook.c 中示例。 + @{ + */ + +/** + \brief iResumeTask(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +void pResumeTask_ErrorCallback(s_tasknode_tsp htask); + +/** + \brief iSuspendTask(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +void pSuspendTask_ErrorCallback(s_tasknode_tsp htask); + +/** + \brief iDeleteTask(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +void pDeleteTask_ErrorCallback(s_tasknode_tsp htask); + +/** + \brief iClearBlock(task) error callback + \param[in] htask 任务句柄 + \return 无 + */ +void pClearBlock_ErrorCallback(s_tasknode_tsp htask); + +/** + \brief iSetBlock_x(task, x) error callback + \details iSetBlock_tc(task, tc)、iSetBlock_ms(task, ms)、iSetBlock_s(task, s)、 + iSetBlock_m(task, m)、iSetBlock_h(task, h),都通过该函数实现错误调用返回。 + \param[in] htask 任务句柄 + \param[in] tick 滴答周期(阻塞时间) + \return 无 + */ +void pSetBlock_ErrorCallback(s_tasknode_tsp htask, s_delay_t tick); + +/** + \brief iSetTaskPri(task, npri) error callback + \param[in] htask 任务句柄 + \param[in] npri 新优先级 + \return 无 + */ +void pSetTaskPri_ErrorCallback(s_tasknode_tsp htask, s_u8_t npri); + +/** + \brief iSendMsg(que, msg) error callback + \param[in] hque 队列句柄 + \param[in] msg 消息指针 + \return 无 + */ +void pSendMsg_ErrorCallback(s_msgque_tsp hque, void *msg); + +/** + \brief error code of error callback + \param 无 + \return 错误码(s_ecode_t) + */ +#define pECode_ErrorCallback() s_psvfifo_ecode + +/** @} */ + +/** + \ingroup 杂项 + \defgroup DEBUG + \brief DEBUG接口,串口发送与接收的实现。 + @{ + */ + +/** + \brief DEBUG发送完成 + \param 无 + \return 无 + */ +#define xDebugSend_Complete() s_debug_sendsign = true + +/** + \brief DEBUG接收解析 + \param[in] p 接收缓存的开始指针 + \param[in] len 接收数据包的长度 + \return 无 + */ +#define xDebugRecv_Handler(p, len) \ +do{ \ + s_debug_recvptr = p; \ + s_debug_recvlen = len; \ +}while(false) + +/** @} */ + +/** + \ingroup 杂项 + \defgroup 时间单位转换 + \brief 把其它单位的时间转换为滴答周期。 + @{ + */ + +/** + \brief 毫秒转换为滴答周期 + \param[in] ms 毫秒 + \return 滴答周期 + */ +#define xTick_ms(ms) ((1000UL * (ms)) / SYSCFG_SYSTICK_CYCLE) + +/** + \brief 秒钟转换为滴答周期 + \param[in] s 秒钟 + \return 滴答周期 + */ +#define xTick_s(s) xTick_ms(1000UL * (s)) + +/** + \brief 分钟转换为滴答周期 + \param[in] m 分钟 + \return 滴答周期 + */ +#define xTick_m(m) xTick_s(60UL * (m)) + +/** + \brief 小时转换为滴答周期 + \param[in] h 小时 + \return 滴答周期 + */ +#define xTick_h(h) xTick_m(60UL * (h)) + +/** @} */ + +/** + \brief 触发PendSV + \details 在用户中断中,当采用FLAG服务时(自行挂起到 PendSV中断 中执行服务),
+ 在设置标志位后需手动触发PendSV,而后在 pendsv_hook() 中执行服务。 + \param 无 + \return 无 + */ +#define iPendSV_Set() mPendSV_Set() + +/** @} */ + + +/** @} */ +#endif