diff --git a/System/os_api.h b/System/os_api.h new file mode 100644 index 00000000..a8caf7c2 --- /dev/null +++ b/System/os_api.h @@ -0,0 +1,202 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file os_api.h + * @brief 系统内核专用API + * @author 迟凯峰 + * @version V1.0.1 + * @date 2025.02.26 + ******************************************************************************/ + +#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((s_taskhand_tsp)s_timint_handle[tmid]->hookorhand, OS_STATUS_SUSPENDED) + +/** 启动定时查询任务 */ +#define sStartTask_TimQry(tmid) \ + sUSV_StartTask((s_taskhand_tsp)s_timqry_handle[tmid]->hookorhand, OS_STATUS_SUSPENDED) + +/** 恢复定时中断任务 */ +#define sResumeTask_TimInt(tmid) \ + sTSV_ResumeTask(*((s_taskhand_tsp)s_timint_handle[tmid]->hookorhand)->dualhandle) + +/** 恢复定时查询任务 */ +#define sResumeTask_TimQry(tmid) \ + sTSV_ResumeTask(*((s_taskhand_tsp)s_timqry_handle[tmid]->hookorhand)->dualhandle) + +/** 调用定时中断钩子 */ +#define sCallHook_TimInt(tmid) \ + (*(s_voidvoid_tfp)s_timint_handle[tmid]->hookorhand)() + +/** 调用定时查询钩子 */ +#define sCallHook_TimQry(tmid) \ + (*(s_voidvoid_tfp)s_timqry_handle[tmid]->hookorhand)() + + + +/* + * 更新.全局变量副本 + */ + +#define sUpdateCopy(code) \ +do{ \ + s_sign_updatecopy = true; \ + code; \ + s_sign_updatecopy = false; \ +}while(false) + + + +/* + * 事件标志组 - 写标志位 + */ + +#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) + + + +#endif diff --git a/System/os_redef.h b/System/os_redef.h new file mode 100644 index 00000000..ddaedf91 --- /dev/null +++ b/System/os_redef.h @@ -0,0 +1,725 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file os_redef.h + * @brief 系统重定义 + * @details 基于 os_def.h、os_base.h、syscfg.h、mcucfg_x.h、port_x.h 等文件 + 中的定义而再次定义,包括宏定义和类型定义。 + * @author 迟凯峰 + * @version V1.0.1 + * @date 2025.02.26 + ******************************************************************************/ + +#ifndef __OS_REDEF_H +#define __OS_REDEF_H + +/*------------------------------------------------------------------------------ + * SYSAPI */ + +#define sDefStr(s) sDefStr_0(s) +#define sDefStr_0(s) #s + +#define sCat2Str(s1, s2) sCat2Str_0(s1, s2) +#define sCat2Str_0(s1, s2) s1##s2 + +#define sCat3Str(s1, s2, s3) sCat3Str_0(s1, s2, s3) +#define sCat3Str_0(s1, s2, s3) s1##s2##s3 + +#define sDefBitField(v) sDefBitField_0(v) +#define sDefBitField_0(v) volatile s_u8_t v:1 + +#define sDefVoidBits(n) sDefVoidBits_0(n) +#define sDefVoidBits_0(n) volatile s_u8_t :n + +/*------------------------------------------------------------------------------ + * INCLUDE */ + +#include +#include "..\Config\syscfg.h" +#include sDefStr(sCat2Str(..\Port\port_, SYSCFG_MCUCORE.h)) + +/*------------------------------------------------------------------------------ + * ZERO-INSTALL */ + +#if MCUCFG_OSZEROINSTALL == __ENABLED__ +#define sZeroInstall = 0 +#define sZeroInstall_Group = {0} +#else +#define sZeroInstall +#define sZeroInstall_Group +#endif + +/*------------------------------------------------------------------------------ + * NOPxX */ + +#define OS_NOPx1 MCUCFG_NOP +#define OS_NOPx2 OS_NOPx1; OS_NOPx1 +#define OS_NOPx3 OS_NOPx2; OS_NOPx1 +#define OS_NOPx4 OS_NOPx3; OS_NOPx1 +#define OS_NOPx5 OS_NOPx4; OS_NOPx1 +#define OS_NOPx6 OS_NOPx5; OS_NOPx1 +#define OS_NOPx7 OS_NOPx6; OS_NOPx1 +#define OS_NOPx8 OS_NOPx7; OS_NOPx1 + +/*------------------------------------------------------------------------------ + * TOTAL */ + +#if SYSCFG_SAMEPRISCHEDULE == 0 +#define OS_TASKTOTAL (SYSCFG_TASKPRIORITY - 1) /*!< 在线任务总数 */ +#elif SYSCFG_DEBUGGING == 0 +#define OS_TASKTOTAL (SYSCFG_USERTASKTOTAL + 2) +#else +#define OS_TASKTOTAL (SYSCFG_USERTASKTOTAL + 4) +#endif + +#if SYSCFG_DEBUGGING == 0 +#define OS_TIMINTTOTAL SYSCFG_USERTIMINTTOTAL /*!< 定时中断总数 */ +#define OS_TIMQRYTOTAL SYSCFG_USERTIMQRYTOTAL /*!< 定时查询总数 */ +#else +#define OS_TIMINTTOTAL (SYSCFG_USERTIMINTTOTAL + 1) +#define OS_TIMQRYTOTAL (SYSCFG_USERTIMQRYTOTAL + 2) + +/*------------------------------------------------------------------------------ + * TMID(定时器ID)*/ + +#define OS_TMID_DEBUGGER SYSCFG_USERTIMINTTOTAL /*!< TMID of Debugger */ +#define OS_TMID_DEBUGHOOK SYSCFG_USERTIMQRYTOTAL /*!< TMID of debug_hook */ +/** TMID of Taskmgr */ +#if OS_TIMQRYTOTAL == 2 +#define OS_TMID_TASKMGR 1 +#elif OS_TIMQRYTOTAL == 3 +#define OS_TMID_TASKMGR 2 +#elif OS_TIMQRYTOTAL == 4 +#define OS_TMID_TASKMGR 3 +#elif OS_TIMQRYTOTAL == 5 +#define OS_TMID_TASKMGR 4 +#elif OS_TIMQRYTOTAL == 6 +#define OS_TMID_TASKMGR 5 +#elif OS_TIMQRYTOTAL == 7 +#define OS_TMID_TASKMGR 6 +#elif OS_TIMQRYTOTAL == 8 +#define OS_TMID_TASKMGR 7 +#elif OS_TIMQRYTOTAL == 9 +#define OS_TMID_TASKMGR 8 +#elif OS_TIMQRYTOTAL == 10 +#define OS_TMID_TASKMGR 9 +#elif OS_TIMQRYTOTAL == 11 +#define OS_TMID_TASKMGR 10 +#elif OS_TIMQRYTOTAL == 12 +#define OS_TMID_TASKMGR 11 +#elif OS_TIMQRYTOTAL == 13 +#define OS_TMID_TASKMGR 12 +#elif OS_TIMQRYTOTAL == 14 +#define OS_TMID_TASKMGR 13 +#elif OS_TIMQRYTOTAL == 15 +#define OS_TMID_TASKMGR 14 +#elif OS_TIMQRYTOTAL == 16 +#define OS_TMID_TASKMGR 15 +#elif OS_TIMQRYTOTAL == 17 +#define OS_TMID_TASKMGR 16 +#elif OS_TIMQRYTOTAL == 18 +#define OS_TMID_TASKMGR 17 +#elif OS_TIMQRYTOTAL == 19 +#define OS_TMID_TASKMGR 18 +#elif OS_TIMQRYTOTAL == 20 +#define OS_TMID_TASKMGR 19 +#elif OS_TIMQRYTOTAL == 21 +#define OS_TMID_TASKMGR 20 +#elif OS_TIMQRYTOTAL == 22 +#define OS_TMID_TASKMGR 21 +#elif OS_TIMQRYTOTAL == 23 +#define OS_TMID_TASKMGR 22 +#elif OS_TIMQRYTOTAL == 24 +#define OS_TMID_TASKMGR 23 +#elif OS_TIMQRYTOTAL == 25 +#define OS_TMID_TASKMGR 24 +#elif OS_TIMQRYTOTAL == 26 +#define OS_TMID_TASKMGR 25 +#elif OS_TIMQRYTOTAL == 27 +#define OS_TMID_TASKMGR 26 +#elif OS_TIMQRYTOTAL == 28 +#define OS_TMID_TASKMGR 27 +#elif OS_TIMQRYTOTAL == 29 +#define OS_TMID_TASKMGR 28 +#elif OS_TIMQRYTOTAL == 30 +#define OS_TMID_TASKMGR 29 +#elif OS_TIMQRYTOTAL == 31 +#define OS_TMID_TASKMGR 30 +#elif OS_TIMQRYTOTAL == 32 +#define OS_TMID_TASKMGR 31 +#elif OS_TIMQRYTOTAL == 33 +#define OS_TMID_TASKMGR 32 +#elif OS_TIMQRYTOTAL == 34 +#define OS_TMID_TASKMGR 33 +#elif OS_TIMQRYTOTAL == 35 +#define OS_TMID_TASKMGR 34 +#elif OS_TIMQRYTOTAL == 36 +#define OS_TMID_TASKMGR 35 +#elif OS_TIMQRYTOTAL == 37 +#define OS_TMID_TASKMGR 36 +#elif OS_TIMQRYTOTAL == 38 +#define OS_TMID_TASKMGR 37 +#elif OS_TIMQRYTOTAL == 39 +#define OS_TMID_TASKMGR 38 +#elif OS_TIMQRYTOTAL == 40 +#define OS_TMID_TASKMGR 39 +#elif OS_TIMQRYTOTAL == 41 +#define OS_TMID_TASKMGR 40 +#elif OS_TIMQRYTOTAL == 42 +#define OS_TMID_TASKMGR 41 +#elif OS_TIMQRYTOTAL == 43 +#define OS_TMID_TASKMGR 42 +#elif OS_TIMQRYTOTAL == 44 +#define OS_TMID_TASKMGR 43 +#elif OS_TIMQRYTOTAL == 45 +#define OS_TMID_TASKMGR 44 +#elif OS_TIMQRYTOTAL == 46 +#define OS_TMID_TASKMGR 45 +#elif OS_TIMQRYTOTAL == 47 +#define OS_TMID_TASKMGR 46 +#elif OS_TIMQRYTOTAL == 48 +#define OS_TMID_TASKMGR 47 +#elif OS_TIMQRYTOTAL == 49 +#define OS_TMID_TASKMGR 48 +#elif OS_TIMQRYTOTAL == 50 +#define OS_TMID_TASKMGR 49 +#elif OS_TIMQRYTOTAL == 51 +#define OS_TMID_TASKMGR 50 +#elif OS_TIMQRYTOTAL == 52 +#define OS_TMID_TASKMGR 51 +#elif OS_TIMQRYTOTAL == 53 +#define OS_TMID_TASKMGR 52 +#elif OS_TIMQRYTOTAL == 54 +#define OS_TMID_TASKMGR 53 +#elif OS_TIMQRYTOTAL == 55 +#define OS_TMID_TASKMGR 54 +#elif OS_TIMQRYTOTAL == 56 +#define OS_TMID_TASKMGR 55 +#elif OS_TIMQRYTOTAL == 57 +#define OS_TMID_TASKMGR 56 +#elif OS_TIMQRYTOTAL == 58 +#define OS_TMID_TASKMGR 57 +#elif OS_TIMQRYTOTAL == 59 +#define OS_TMID_TASKMGR 58 +#elif OS_TIMQRYTOTAL == 60 +#define OS_TMID_TASKMGR 59 +#elif OS_TIMQRYTOTAL == 61 +#define OS_TMID_TASKMGR 60 +#elif OS_TIMQRYTOTAL == 62 +#define OS_TMID_TASKMGR 61 +#elif OS_TIMQRYTOTAL == 63 +#define OS_TMID_TASKMGR 62 +#elif OS_TIMQRYTOTAL == 64 +#define OS_TMID_TASKMGR 63 +#elif OS_TIMQRYTOTAL == 65 +#define OS_TMID_TASKMGR 64 +#elif OS_TIMQRYTOTAL == 66 +#define OS_TMID_TASKMGR 65 +#endif +#endif + +/*------------------------------------------------------------------------------ + * Time Sharing(时间片)*/ + +#if SYSCFG_TIMESHARINGMODE == 0 +#define OS_TIMESHARING(htask) SYSCFG_GLOBALTIMESHARING +#define OS_TIMESHARING_MAX SYSCFG_GLOBALTIMESHARING +#define OS_TIMESHARING_MIN SYSCFG_GLOBALTIMESHARING +#elif SYSCFG_TIMESHARINGMODE == 1 +#define OS_TIMESHARING(htask) SYSCFG_ALGORITHMTIMESHARING(htask->pri) +#define OS_TIMESHARING_MAX SYSCFG_ALGORITHMTIMESHARING(0) +#define OS_TIMESHARING_MIN SYSCFG_ALGORITHMTIMESHARING(SYSCFG_TASKPRIORITY - 1) +#elif SYSCFG_TIMESHARINGMODE == 2 +#define OS_TIMESHARING(htask) s_time_sharing[htask->pri] +#define OS_TIMESHARING_MAX SYSCFG_TIMESHARING_MAX +#define OS_TIMESHARING_MIN 1 +#endif +#if OS_TIMESHARING_MIN == 0 || OS_TIMESHARING_MAX > 65535 +#error 时间片定义非法! +#endif + +/*------------------------------------------------------------------------------ + * Taskmgr - LEN */ + +#if MCUCFG_ISA == __ARM__ +#define OS_TASKMGR_LEN_RAM 15 +#else +#define OS_TASKMGR_LEN_RAM 13 +#endif + +#define OS_TASKMGR_LEN_LINE \ +( \ + SYSCFG_TASKNAMELEN_MAX \ + + OS_TASKMGR_LEN_PRI + OS_TASKMGR_LEN_STA \ + + OS_TASKMGR_LEN_CPU + OS_TASKMGR_LEN_RAM \ +) + +/*------------------------------------------------------------------------------ + * DEBUGBUFF - SIZE */ + +#define OS_DEBUGRECVBUFFSIZE (SYSCFG_TASKNAMELEN_MAX + 64) /*!< size of DEBUG 接收缓存 */ +#define OS_CMDLINESENDBUFFSIZE (SYSCFG_TASKNAMELEN_MAX + 64) /*!< size of 命令行 发送缓存 */ +#define OS_TASKMGRSENDBUFFSIZE \ +( \ + (OS_TASKMGR_LEN_LINE + 2) * (OS_TASKTOTAL + 7 + SYSCFG_RTC_SHOW) + 2 * 2 + 1 \ +) /*!< size of Taskmgr 发送缓存 */ + +/*------------------------------------------------------------------------------ + * typedef base */ + +typedef s_u8_t s_ecode_t; /*!< 错误码类型 */ + +#if OS_TIMESHARING_MAX < 256 +typedef s_u8_t s_sharing_t; /*!< 时间片类型 */ +#elif OS_TIMESHARING_MAX < 65536 +typedef s_u16_t s_sharing_t; +#else +#error 时间片溢出! +#endif + +#if OS_TASKTOTAL < 256 +typedef s_u8_t s_tqcount_t; +#else +typedef s_u16_t s_tqcount_t; +#endif + +typedef sCat3Str(s_u, SYSCFG_DELAYBITS, _t) s_delay_t; /*!< 延时定时器类型 */ +typedef sCat3Str(s_u, SYSCFG_TIMINTBITS, _t) s_timint_t; /*!< 定时中断定时器类型 */ +typedef sCat3Str(s_u, SYSCFG_TIMQRYBITS, _t) s_timqry_t; /*!< 定时查询定时器类型 */ +typedef sCat3Str(s_u, SYSCFG_SEMAPHOREBITS, _t) s_semsize_t; /*!< 计数信号量类型 */ + +/*------------------------------------------------------------------------------ + * typedef function and function pointer */ + +typedef bool s_boolvoid_tf(void); /*!< Keil C51 专用 */ +typedef bool (_CODE_MEM_ *s_boolvoid_tfp)(void); +typedef void (_CODE_MEM_ *s_voidvoid_tfp)(void); + +/*------------------------------------------------------------------------------ + * typedef struct */ + +/** + \brief 运行时间 + */ +typedef struct +{ + s_u16_t day; /*!< 天 */ + s_u8_t hour; /*!< 时 */ + s_u8_t minute; /*!< 分 */ + s_u8_t second; /*!< 秒 */ +}s_runtime_ts; + +/** + \brief 软件RTC + */ +typedef struct +{ + s_u8_t yeah; /*!< 年高八位 */ + s_u8_t year; /*!< 年低八位 */ + s_u8_t month; /*!< 月 */ + s_u8_t date; /*!< 日 */ + s_u8_t hour; /*!< 时 [24时制] */ + s_u8_t minute; /*!< 分 */ + s_u8_t second; /*!< 秒 */ + s_u8_t day; /*!< 周 [1:周一,7:周日] */ +}s_rtc_ts; + +/** + \brief 软件RTC-每信号 + \details 典型的应用示例参见 tick_hook。 + */ +typedef struct +{ + sDefBitField(year); /*!< 每年 */ + sDefBitField(month); /*!< 每月 */ + sDefBitField(day); /*!< 每日 */ + sDefBitField(hour); /*!< 每时 */ + sDefBitField(minute); /*!< 每分 */ + sDefBitField(second); /*!< 每秒 */ + sDefBitField(halfsec); /*!< 每半秒 */ + sDefBitField(set); /*!< 设置时间 */ +}s_every_ts; + +/** + \brief 系统警告 + */ +typedef struct +{ + sDefBitField(overflow_msgqueue); /*!<【omq】:消息队列溢出 ....... */ + sDefBitField(timeout_saferuntime); /*!<【srt】:安全运行时超时 ..... */ + sDefBitField(outrange_taskpriority); /*!<【otp】:任务优先级超出范围 . */ + sDefBitField(realloc_taskstack); /*!<【rts】:任务栈重分配发生 ... */ + sDefBitField(overflow_taskstack); /*!<【ots】:未来的任务栈溢出 ... */ + sDefVoidBits(3); +}s_alarm_ts; + +/** + \brief 系统异常 + */ +typedef struct +{ + sDefBitField(mallocfailed_msgnode); /*!<【mmn】:消息节点内存分配失败 */ + sDefBitField(mallocfailed_tasknode); /*!<【mtn】:任务节点内存分配失败 */ + sDefBitField(mallocfailed_taskstack); /*!<【mts】:任务栈内存分配失败 . */ + sDefBitField(reallocfailed_taskstack); /*!<【rts】:任务栈内存重分配失败 */ + sDefBitField(overflow_taskstack); /*!<【ots】:任务栈溢出 ......... */ + sDefBitField(failed_startuptask); /*!<【fst】:启动任务失败 ....... */ + sDefBitField(error_recvmsg_int); /*!<【erm】:中断中接收消息错误 . */ + sDefBitField(overflow_pendsvfifo); /*!<【opd】:PendSV_FIFO溢出 .... */ +}s_fault_ts; + +/** + \brief 任务节点(控制块) + \details CosyOS 的 任务节点 即 任务控制块,包含了任务所需的全部关键信息。 + 任务静态创建时,任务节点为静态;任务动态创建时,任务节点为动态。 + */ +typedef struct s_tasknode_ts +{ + mTaskNode_Head_ /*!< MSP:stacklen,PSP:psp,MSP+PSP:psp */ + s_u8_t opri; /*!< 任务创建时的优先级 */ + m_stacksize_t stacksize; /*!< 任务栈size */ + struct s_tasknode_ts _OBJ_MEM_ * _STATIC_MEM_ *dualhandle; /*!< 任务二重句柄:指向任务句柄的指针 */ + s_voidvoid_tfp entry; /*!< 任务函数入口指针 */ + #if SYSCFG_DEBUGGING == __ENABLED__ + const char _CONST_MEM_ *name; /*!< 任务名称(字符串)*/ + #endif + #if SYSCFG_SAFERUNTIME == __ENABLED__ + s_u16_t saferuntime; /*!< 安全运行时设定值 */ + #endif + s_u8_t _OBJ_MEM_ *bsp; /*!< base stack pointer,任务栈的起始地址 */ + s_u8_t create; /*!< 任务创建 [0:静态创建,1:动态创建未重分配,2:动态创建已重分配] */ + s_u8_t pri; /*!< 任务当前优先级 */ + s_u8_t status; /*!< 任务状态 */ + s_u8_t blocktype; /*!< 阻塞类型 */ + s_delay_t timer; /*!< 软件定时器(延时/超时计数)*/ + #if SYSCFG_MCUCORE == 8051 + void _STATIC_MEM_ *handle; /*!< 内核对象句柄,仅指向静态对象 */ + #endif + #if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__ + s_sharing_t tc_counter; /*!< 滴答周期计数器 */ + #endif + #if SYSCFG_DEBUGGING == __ENABLED__ + s_u32_t usedtime[2]; /*!< CPU 使用时间计数 */ + m_stacksize_t stacklen_max; /*!< 任务栈的实际占用在历史上的最大值 */ + #endif + #if SYSCFG_SAFERUNTIME == __ENABLED__ + s_u32_t srt_counter; /*!< 安全运行时计数器 */ + #endif + struct s_tasknode_ts _OBJ_MEM_ *next_b; /*!< 下一节点 of 阻塞链表 */ + struct s_tasknode_ts _OBJ_MEM_ *next_t; /*!< 下一节点 of 定时器链表 */ + #if SYSCFG_SAMEPRISCHEDULE + struct s_tasknode_ts _OBJ_MEM_ *last; /*!< 上一节点 of 优先级组 */ + struct s_tasknode_ts _OBJ_MEM_ *next; /*!< 下一节点 of 优先级组 */ + #endif + mTaskNode_Tail_ /*!< MCS51/251:mUserReg_C_,减栈:psp_top */ +}s_tasknode_ts; +typedef s_tasknode_ts _OBJ_MEM_ *s_tasknode_tsp; /*!< 任务句柄 */ + +/** + \brief 任务HAND(装载块) + \details 创建任务时,用来装载任务的关键参数。 + 1、当任务为动态创建时,会定义此结构体;在启动任务时,会动态的分配任务节点, + 再把任务HAND中的参数传入任务节点。 + 2、当任务为静态创建时,任务节点就是任务HAND,不会再额外定义此结构体。 + 注:有关结构体成员的相关说明参见任务节点。 + */ +typedef struct +{ + const mTaskNode_Head_ + const s_u8_t opri; + const m_stacksize_t stacksize; + s_tasknode_ts _OBJ_MEM_ * _STATIC_MEM_ * const dualhandle; + s_voidvoid_tfp entry; + #if SYSCFG_DEBUGGING == __ENABLED__ + const char _CONST_MEM_ * const name; + #endif + #if SYSCFG_SAFERUNTIME == __ENABLED__ + const s_u16_t saferuntime; + #endif +}s_taskhand_ts; +typedef s_taskhand_ts _STATIC_MEM_ *s_taskhand_tsp; /*!< 任务装载块句柄 */ + +/** + \brief 定时中断HAND(控制块) + \details 创建定时中断任务或钩子时,会定义此结构体。 + */ +typedef struct +{ + s_timint_t timer; /*!< 定时器 */ + s_timint_t reload; /*!< 重装载值 */ + bool autoreload; /*!< 是否自动重装载定时器?*/ + const bool hookortask; /*!< 该定时中断是钩子还是任务?[0:hook,1:task] */ + void _CODE_MEM_ * const hookorhand; /*!< 钩子函数指针或任务HAND指针 */ +}s_timinthand_ts; +typedef s_timinthand_ts _STATIC_MEM_ *s_timinthand_tsp; /*!< 定时中断句柄 */ + +/** + \brief 定时查询HAND(控制块) + \details 创建定时查询任务或钩子时,会定义此结构体。 + */ +typedef struct +{ + s_timqry_t timer; /*!< 定时器 */ + s_timqry_t reload; /*!< 重装载值 */ + bool autoreload; /*!< 是否自动重装载定时器?*/ + const bool hookortask; /*!< 该定时查询是钩子还是任务?[0:hook,1:task] */ + void _CODE_MEM_ * const hookorhand; /*!< 钩子函数指针或任务HAND指针 */ + s_boolvoid_tfp const event; /*!< 定时查询事件函数指针 */ +}s_timqryhand_ts; +typedef s_timqryhand_ts _STATIC_MEM_ *s_timqryhand_tsp; /*!< 定时查询句柄 */ + +/** + \brief 互斥信号量控制块 + \details 创建互斥信号量时,会定义此结构体。 + */ +typedef struct +{ + volatile s_u8_t mutex; + s_tasknode_tsp htask; + s_tasknode_tsp otask; + s_u8_t opri; +}s_mutex_ts; +typedef s_mutex_ts _STATIC_MEM_ *s_mutex_tsp; /*!< 互斥信号量句柄 */ + +/** + \brief 二值信号量控制块 + \details 创建二值信号量时,会定义此结构体。 + */ +typedef struct +{ + volatile bool binary; + s_tasknode_tsp htask; +}s_binary_ts; +typedef s_binary_ts _STATIC_MEM_ *s_binary_tsp; /*!< 二值信号量句柄 */ + +/** + \brief 计数信号量控制块 + \details 创建计数信号量时,会定义此结构体。 + */ +typedef struct +{ + volatile s_semsize_t counter; + const s_semsize_t maximum; + s_tasknode_tsp htask; +}s_semaph_ts; +typedef s_semaph_ts _STATIC_MEM_ *s_semaph_tsp; /*!< 计数信号量句柄 */ + +/** + \brief 信箱控制块 + \details 创建信箱时,会定义此结构体。 + */ +typedef struct +{ + volatile m_fetion_t tion; + s_tasknode_tsp htask; +}s_tionbox_ts; +typedef s_tionbox_ts _STATIC_MEM_ *s_tionbox_tsp; /*!< 信箱句柄 */ + +/** + \brief 邮箱控制块 + \details 创建邮箱时,会定义此结构体。 + */ +typedef struct +{ + volatile bool flag; + void *mail; + s_tasknode_tsp htask; +}s_mailbox_ts; +typedef s_mailbox_ts _STATIC_MEM_ *s_mailbox_tsp; /*!< 邮箱句柄 */ + +/** + \brief 消息节点 + \details 动态队列之消息节点。 + */ +typedef struct s_msgnode_ts +{ + void *msg; + struct s_msgnode_ts _MALLOC_MEM_ *last; + struct s_msgnode_ts _MALLOC_MEM_ *next; +}s_msgnode_ts; +typedef s_msgnode_ts _MALLOC_MEM_ *s_msgnode_tsp; /*!< 消息句柄 */ + +/** + \brief 动态队列控制块 + \details 创建动态队列时,会定义此结构体。 + */ +typedef struct +{ + size_t counter; + const s_u8_t type; + const s_u8_t mode; + const size_t len; + s_tasknode_tsp htask; + volatile bool mutex; + s_msgnode_tsp head; + s_msgnode_tsp tail; +}sd_queue_ts; +typedef sd_queue_ts _STATIC_MEM_ *sd_queue_tsp; /*!< 动态队列句柄 */ + +/** + \brief 静态队列控制块 + \details 创建静态队列时,会定义此结构体。 + */ +typedef struct +{ + size_t counter; + const s_u8_t type; + const s_u8_t mode; + const size_t len; + s_tasknode_tsp htask; + volatile bool mutex; + void * _STATIC_MEM_ * head; + void * _STATIC_MEM_ * tail; + void * _STATIC_MEM_ * const base; +}ss_queue_ts; +typedef ss_queue_ts _STATIC_MEM_ *ss_queue_tsp; /*!< 静态队列句柄 */ + +/** + \brief 队列控制块 + \details 创建队列时,并不会定义此结构体;访问队列时,通过其队列句柄, + 即可访问动态队列控制块,也可访问静态队列控制块。 + */ +typedef struct +{ + size_t counter; /*!< 队列计数器:记录队列中消息的数量 */ + const s_u8_t type; /*!< 队列类型 [0:静态队列,1:动态队列] */ + const s_u8_t mode; /*!< 传输模式 [0:FIFO,1:LIFO] */ + const size_t len; /*!< 队列长度 */ + s_tasknode_tsp htask; /*!< 任务句柄 */ + volatile bool mutex; /*!< 队列互斥量 */ +}s_queue_ts; +typedef s_queue_ts _STATIC_MEM_ *s_queue_tsp; /*!< 队列句柄 */ + +/** + \brief 线程内存控制块 + \details 创建线程内存池时,会定义此结构体。 + */ +typedef struct +{ + void _MALLOC_MEM_ *head; + void _MALLOC_MEM_ *move; + size_t size; +}s_thrmem_ts; +typedef s_thrmem_ts _STATIC_MEM_ *s_thrmem_tsp; /*!< 线程内存句柄 */ + +/*------------------------------------------------------------------------------ + * 中断挂起服务_FIFO 结构体类型定义 */ + +typedef struct +{ + const s_u8_t svid; +}sp_svid_ts; +typedef sp_svid_ts _STATIC_MEM_ *sp_svid_tsp; + +typedef struct +{ + const s_u8_t svid; + s_tasknode_tsp htask; +}sp_task_ts; +typedef sp_task_ts _STATIC_MEM_ *sp_task_tsp; + +typedef struct +{ + const s_u8_t svid; + s_tasknode_tsp htask; + const s_u8_t npri; +}sp_taskpri_ts; +typedef sp_taskpri_ts _STATIC_MEM_ *sp_taskpri_tsp; + +typedef struct +{ + const s_u8_t svid; + s_tasknode_tsp htask; + const s_delay_t tick; +}sp_blocktime_ts; +typedef sp_blocktime_ts _STATIC_MEM_ *sp_blocktime_tsp; + +typedef struct +{ + const s_u8_t svid; + const s_u8_t tmid; + s_timint_t tick; +}sp_timint_ts; +typedef sp_timint_ts _STATIC_MEM_ *sp_timint_tsp; + +typedef struct +{ + const s_u8_t svid; + const s_u8_t tmid; + s_timqry_t tick; +}sp_timqry_ts; +typedef sp_timqry_ts _STATIC_MEM_ *sp_timqry_tsp; + +typedef struct +{ + const s_u8_t svid; + s_binary_tsp const hbin; + const bool value; +}sp_binary_ts; +typedef sp_binary_ts _STATIC_MEM_ *sp_binary_tsp; + +typedef struct +{ + const s_u8_t svid; + s_semaph_tsp const hsem; +}sp_semaph_ts; +typedef sp_semaph_ts _STATIC_MEM_ *sp_semaph_tsp; + +typedef struct +{ + const s_u8_t svid; + s_tionbox_tsp const htbox; + m_fetion_t tion; +}sp_tionbox_ts; +typedef sp_tionbox_ts _STATIC_MEM_ *sp_tionbox_tsp; + +typedef struct +{ + const s_u8_t svid; + s_mailbox_tsp const hmbox; + void *mail; +}sp_mailbox_ts; +typedef sp_mailbox_ts _STATIC_MEM_ *sp_mailbox_tsp; + +typedef struct +{ + const s_u8_t svid; + s_queue_tsp const hque; + void *msg; +}sp_msg_ts; +typedef sp_msg_ts _STATIC_MEM_ *sp_msg_tsp; + +typedef struct +{ + const s_u8_t svid; + void _STATIC_MEM_ * const hgrp; + const char size; + m_group_t value; +}sp_group_ts; +typedef sp_group_ts _STATIC_MEM_ *sp_group_tsp; + +typedef struct +{ + const s_u8_t svid; + void * const gp; + void * const lp; + const size_t size; +}sp_gvar_ts; +typedef sp_gvar_ts _STATIC_MEM_ *sp_gvar_tsp; + +typedef struct +{ + const s_u8_t svid; + s_voidvoid_tfp const fp; +}sp_pendsvc_ts; +typedef sp_pendsvc_ts _STATIC_MEM_ *sp_pendsvc_tsp; + +typedef struct +{ + const s_u8_t svid; + bool * const sign; +}sp_sign_ts; +typedef sp_sign_ts _STATIC_MEM_ *sp_sign_tsp; + + + +#endif diff --git a/System/os_taskmgr.c b/System/os_taskmgr.c new file mode 100644 index 00000000..116965c2 --- /dev/null +++ b/System/os_taskmgr.c @@ -0,0 +1,575 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file os_taskmgr.c + * @brief 任务管理器(Taskmgr) + * @author 迟凯峰 + * @version V1.0.1 + * @date 2025.02.26 + ******************************************************************************/ + +#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 空格拷贝 + \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 + +uCreateTask_TimQry +( + OS_TMID_TASKMGR, s_sign_taskmgr, true, + Taskmgr, SYSCFG_TASKPRIORITY - 3, MCUCFG_STACKSIZE_TASKMGR, 0, 0 +) +{ + static char _XDATA_MEM_ *p[2]; + s_u8_t i = OS_TASKMGR_LEN_LINE; + mptr = s_taskmgr_sendbuff; + /* Title1 */ + _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; + _spccpy_(OS_TASKMGR_LEN_CPU + OS_TASKMGR_LEN_RAM - 8); + _strcpy_("CosyOS-3"); + _strcpy_("\r\n"); + /* Title2 */ + _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"); + _spccpy_(OS_TASKMGR_LEN_RAM - 4); + _strcpy_("\xC4\xDA\xB4\xE6"); + _strcpy_("\r\n"); + /* - */ + do{ + _chrcpy_('-'); + }while(--i); + _strcpy_("\r\n"); + /* - */ + p[1] = mptr; + while(true){ + static s_timqry_t upspeed = (1000UL * SYSCFG_TASKMGRUPSPEED) / SYSCFG_SYSTICKCYCLE; + static s_tasknode_ts node_temp; + s_tasknode_tsp node_curr; + s_u16_t numerator1 = 10000; + #if SYSCFG_TASKPC_MONITOR == __ENABLED__ + m_pc_t pc = s_pc; + #endif + mptr = p[1]; + i = (s_u8_t)SYSCFG_TASKPRIORITY; + __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; + /* Name */ + _strcpy_(node_temp.name); + if(SYSCFG_TASKNAMELEN_MAX > _strlen_(node_temp.name)){ + _spccpy_((s_u8_t)(SYSCFG_TASKNAMELEN_MAX - _strlen_(node_temp.name))); + } + /* PRI */ + _u8str_ (node_temp.pri); + _spccpy_((s_u8_t)(OS_TASKMGR_LEN_PRI - _strlen_(str))); + _strcpy_(str); + /* STA */ + if(node_temp.status == OS_STATUS_READY){ + _spccpy_(OS_TASKMGR_LEN_STA); + } + else if(node_temp.status == OS_STATUS_BLOCKED){ + _spccpy_(OS_TASKMGR_LEN_STA - 3); + 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_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) + + (node_temp.usedtime[1] * 10000UL) / mSysTick_Cycle + ) / upspeed + ); + _used_ratio_(numerator2); + if(!node_temp.pri){ + numerator1 -= numerator2; + } + /* RAM */ + _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-TOTAL */ + if(true){ + char _XDATA_MEM_ *p0 = mptr; + mptr = p[0]; + _used_ratio_(numerator1); + mptr = p0; + } + /* NULL Line */ + _strcpy_("\r\n"); + /* 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); + _spccpy_( + (s_u8_t)( + OS_TASKMGR_LEN_LINE - 20 - 10 - 1 + - _u16len_((s_u16_t)mPendSV_FIFO_DepthMAX) + - _u16len_((s_u16_t)MCUCFG_PENDSVFIFO_DEPTH) + ) + ); + #else + _strcpy_("null"); + _spccpy_(OS_TASKMGR_LEN_LINE - 20 - 10 - 4); + #endif + _strcpy_("| "); + /* Task-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_("| "); + /* SysTick */ + _strcpy_("\xB5\xCE\xB4\xF0\xCA\xB1\xBC\xE4: "); + #if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__ + mSysIRQ_Disable; + if(s_tick_counter2){ + s_u32_t counter1 = s_tick_counter1; + s_u32_t counter2 = s_tick_counter2; + s_tick_counter1 = 0; + s_tick_counter2 = 0; + mSysIRQ_Enable; + counter2 = (counter1 * 100 * mSysTick_CLKMOD) / (SYSCFG_SYSCLK / 1000000UL) / counter2; + _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"); + /* Alarm */ + _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"); + /* Fault */ + _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; + rtc = s_rtc; + 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 + /* NULL Line */ + _strcpy_("\r\n"); + /* string tail */ + _chrcpy_('\0'); + /* - */ + mSysIRQ_Disable; + upspeed = s_timqry_handle[OS_TMID_TASKMGR]->reload; + s_debug_sendtype |= OS_DEBUG_SEND_TASKMGR; + sv_suspend_task(s_task_current); + su_kernel_unlock0_psv(); + } +} + +#endif diff --git a/System/os_var.c b/System/os_var.c new file mode 100644 index 00000000..e9286a4f --- /dev/null +++ b/System/os_var.c @@ -0,0 +1,128 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file os_var.c + * @brief 系统全局变量定义 + * @author 迟凯峰 + * @version V1.0.3 + * @date 2025.02.26 + ******************************************************************************/ + +#include "os_redef.h" + +/* The Soft-RTC */ +#if SYSCFG_SOFTRTC == __ENABLED__ +const s_u8_t _CONST_MEM_ s_month0day[13] = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /*!< 每月各有几天?*/ + s_u8_t _RTC_MEM_ s_month2day = 28; /*!< 二月有几天?*/ +volatile s_every_ts _SYS_MEM_ s_sign_every/**/sZeroInstall_Group; /*!< 每信号 */ + s_rtc_ts _RTC_MEM_ s_rtc = {SYSCFG_MANUFACTUREDATE}; /*!< RTC正本 */ +#if SYSCFG_GETRTC_INT == __ENABLED__ + s_rtc_ts _RTC_MEM_ s_rtc_copy = {SYSCFG_MANUFACTUREDATE}; /*!< RTC副本 */ +volatile m_bit_t /*_SYS_MEM_*/ s_sign_rtc/**/sZeroInstall; /*!< 更新RTC副本信号 */ +#endif +#endif +/* The Task */ +volatile m_bit_t /*_SYS_MEM_*/ s_sign_schedule/**/sZeroInstall; /*!< 调度信号 */ +volatile m_bit_t /*_SYS_MEM_*/ s_sign_schedule_forbid/**/sZeroInstall;/*!< 禁止调度信号 */ +volatile m_bit_t /*_SYS_MEM_*/ s_sign_ready_delay/**/sZeroInstall; /*!< 就绪延时信号 */ + s_u8_t _SYS_MEM_ s_schedulelock_counter/**/sZeroInstall;/*!< 调度锁嵌套计数器 */ + s_ecode_t _SYS_MEM_ s_startup_code = OS_ECODE_NOERROR; /*!< 启动任务时,用来异地缓存错误码 */ + s_u8_t _SYS_MEM_ s_task_status0 = OS_STATUS_DELETED; /*!< 被启动任务 -> 初始状态 */ + s_taskhand_tsp _SYS_MEM_ s_task_starter/**/sZeroInstall; /*!< 被启动任务 -> 装载块句柄 */ + s_tasknode_tsp _SYS_MEM_ s_task_current/**/sZeroInstall; /*!< 当前任务句柄 */ + s_tasknode_tsp _SYS_MEM_ s_list_timer = OS_VOID; /*!< 定时器链表 */ +#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__ +#if SYSCFG_TIMESHARINGMODE == 2 +const s_sharing_t _CONST_MEM_ s_time_sharing[SYSCFG_TASKPRIORITY] = {SYSCFG_CUSTOMTIMESHARING}; /*!< 自定义时间片 -> 时间片数组 */ +#endif +#endif +#if SYSCFG_KERNELLOCKNESTING == __ENABLED__ + s_u8_t _SYS_MEM_ s_kernellock_counter/**/sZeroInstall; /*!< 内核锁嵌套计数器 */ +#endif +/* The Safe runtime */ +#if SYSCFG_SAFERUNTIME == __ENABLED__ +volatile m_bit_t /*_SYS_MEM_*/ s_sign_timeout/**/sZeroInstall; /*!< 超时信号 */ + s_tasknode_tsp _SYS_MEM_ s_list_timeout = OS_VOID; /*!< 超时链表 */ +#endif +/* The Timing Interrupt */ +#if OS_TIMINTTOTAL + s_timinthand_tsp s_timint_handle[OS_TIMINTTOTAL]; /*!< 定时中断句柄 */ +#endif +/* The Timing Query */ +#if OS_TIMQRYTOTAL + s_timqryhand_tsp s_timqry_handle[OS_TIMQRYTOTAL]; /*!< 定时查询句柄 */ +#endif +/* The Global Variable Accessor */ +volatile m_bit_t /*_SYS_MEM_*/ s_sign_updatecopy/**/sZeroInstall; /*!< 更新副本信号 */ +/* The Debug Interface */ +#if SYSCFG_DEBUGGING == __ENABLED__ +volatile m_bit_t /*_SYS_MEM_*/ s_sign_taskmgr = SYSCFG_TASKMGRAUTOSTART; +volatile m_bit_t /*_SYS_MEM_*/ s_sign_debug_send/**/sZeroInstall; +volatile m_bit_t /*_SYS_MEM_*/ s_sign_debug_recv/**/sZeroInstall; +volatile s_u8_t _SYS_MEM_ s_debug_sendtype/**/sZeroInstall; + char _XDATA_MEM_ s_debug_recvbuff[OS_DEBUGRECVBUFFSIZE];/* + char _XDATA_MEM_ s_cmdline_sendbuff[OS_CMDLINESENDBUFFSIZE];*/ + char _XDATA_MEM_ s_taskmgr_sendbuff[OS_TASKMGRSENDBUFFSIZE]; + char _XDATA_MEM_ * _SYS_MEM_ s_debug_recvptr = s_debug_recvbuff; + char _XDATA_MEM_ * _SYS_MEM_ s_debug_sendptr; + s_alarm_ts _DEBUG_MEM_ s_alarm/**/sZeroInstall_Group; + s_fault_ts _DEBUG_MEM_ s_fault/**/sZeroInstall_Group; +#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__ + s_u32_t _DEBUG_MEM_ s_tick_counter1/**/sZeroInstall; + s_u32_t _DEBUG_MEM_ s_tick_counter2/**/sZeroInstall; +#endif +#if SYSCFG_TASKPC_MONITOR == __ENABLED__ + m_pc_t _SYS_MEM_ s_pc/**/sZeroInstall; +#endif +#if SYSCFG_RUNTIME_COUNT == __ENABLED__ + s_runtime_ts _DEBUG_MEM_ s_runtime/**/sZeroInstall_Group; +#endif +#endif +/* The Task bitmap */ +const s_u8_t _CONST_MEM_ s_task_map_mask[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; +const s_u8_t _CONST_MEM_ s_task_map_pick[SYSCFG_TASKPICKBITMAP * 128] = +{ + #if SYSCFG_TASKPICKBITMAP == 1 + /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F */ +/* 0 */ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, +/* 1 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +/* 2 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +/* 3 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +/* 4 */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* 5 */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* 6 */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* 7 */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + #elif SYSCFG_TASKPICKBITMAP == 2 + /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F */ +/* 0 */~0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, +/* 1 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, +/* 2 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +/* 3 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, +/* 4 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +/* 5 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +/* 6 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +/* 7 */ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, +/* 8 */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* 9 */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* A */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* B */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* C */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* D */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* E */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +/* F */ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 + #endif +}; +#if SYSCFG_TASKPRIORITY > 64 +s_u8_t _SYS_MEM_ s_task_table_index/**/sZeroInstall; /*!< 表索引 */ +s_u8_t _SYS_MEM_ s_task_bytes_index[SYSCFG_TASKPRIORITY / 64]/**/sZeroInstall_Group; /*!< 字节索引 */ +s_u8_t _SYS_MEM_ s_task_ready_table[SYSCFG_TASKPRIORITY / 64][8]/**/sZeroInstall_Group; /*!< 任务就绪表 */ +#elif SYSCFG_TASKPRIORITY > 8 +s_u8_t _SYS_MEM_ s_task_bytes_index/**/sZeroInstall; +s_u8_t _SYS_MEM_ s_task_ready_table[SYSCFG_TASKPRIORITY / 8]/**/sZeroInstall_Group; +#else +s_u8_t _SYS_MEM_ s_task_ready_table/**/sZeroInstall; +#endif +s_tasknode_tsp _QUE_MEM_ s_task_queue[SYSCFG_TASKPRIORITY]/**/sZeroInstall_Group; /*!< 任务队列 */ +s_tqcount_t _QUE_MEM_ s_task_queue_count/**/sZeroInstall; +#if SYSCFG_SAMEPRISCHEDULE +s_u8_t _QUE_MEM_ s_task_ready_count[SYSCFG_TASKPRIORITY]/**/sZeroInstall_Group; +#endif diff --git a/System/sv_task.c b/System/sv_task.c new file mode 100644 index 00000000..9d4447c4 --- /dev/null +++ b/System/sv_task.c @@ -0,0 +1,949 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file sv_task.c + * @brief 任务服务 + * @details 仅在任务中调用并执行。 + * @author 迟凯峰 + * @version V1.0.4 + * @date 2025.02.26 + ******************************************************************************/ + +#include "os_var.h" +#include "os_api.h" +#include "sv_com.h" +#include "sv_task.h" + +/** + @addtogroup CosyOS_内核服务 + @{ + *//** + \defgroup 任务服务 + \brief 仅在任务中调用并执行。 + @{ + */ +#if MCUCFG_ISA != __ARM__ +/** 调度上锁(进入嵌套任务临界区)*/ +void su_schedule_locks(void) +{ + s_sign_schedule_forbid = true; + s_schedulelock_counter++; +} + +/** 内核上锁(进入嵌套服务层临界区)*/ +void su_kernel_locks(void) +{ + mSysIRQ_Disable; + #if SYSCFG_KERNELLOCKNESTING == __ENABLED__ + s_kernellock_counter++; + #endif +} + +/** 内核上锁(进入非嵌套服务层临界区)*/ +void su_kernel_lock0(void) +{ + mSysIRQ_Disable; +} + +static +#else +__STATIC_FORCEINLINE +#endif +/** 内核解锁(退出非嵌套服务层临界区)并返回(void *),邮箱、队列专用 */ +void *su_kernel_unlock0_ret(void *p) +{ + mSysIRQ_Enable; + return p; +} + +/** 调度解锁(退出嵌套任务临界区)*/ +void su_schedule_unlocks(void) +{ + s_schedulelock_counter--; + if(!s_schedulelock_counter){ + #if SYSCFG_KERNELLOCKNESTING == __ENABLED__ + if(s_sign_schedule && !s_kernellock_counter){ + #else + if(s_sign_schedule){ + #endif + s_sign_schedule_forbid = false; + mPendSV_Set; + while(s_sign_schedule); + } + else{ + s_sign_schedule_forbid = false; + } + } +} + +/** 内核解锁(退出嵌套服务层临界区)*/ +void su_kernel_unlocks(void) +{ + #if SYSCFG_KERNELLOCKNESTING == __ENABLED__ + s_kernellock_counter--; + if(s_kernellock_counter) return; + #endif + if(s_sign_schedule && !s_sign_schedule_forbid){ + mPendSV_Set; + mSysIRQ_Enable; + #if MCUCFG_ISA == __ARM__ + OS_NOPx1; + #endif + while(s_sign_schedule); + } + else{ + mSysIRQ_Enable; + } +} + +/** 内核解锁(退出嵌套服务层临界区)并返回(void *) */ +void *su_kernel_unlocks_ret(void *p) +{ + su_kernel_unlocks(); + return p; +} + +/** 内核解锁(退出非嵌套服务层临界区)并触发任务调度 */ +void su_kernel_unlock0_psv(void) +{ + s_sign_schedule = true; + mPendSV_Set; + mSysIRQ_Enable; + #if MCUCFG_ISA == __ARM__ + OS_NOPx1; + #endif + while(s_sign_schedule); +} + + + +/* + * 操作任务 + */ + +/** + \brief 启动任务 + \param[in] hhand 任务HAND句柄 + \param[in] status 任务初始状态 + \return 错误码 + */ +s_ecode_t su_startup_task(s_taskhand_tsp hhand, s_u8_t status) +{ + s_task_status0 = status; + s_task_starter = hhand; + su_kernel_unlock0_psv(); + return s_startup_code; +} + +/** + \brief 恢复任务 + \param[in] htask 任务句柄 + \return 错误码 + */ +s_ecode_t su_resume_task(s_tasknode_tsp htask) +{ + if(htask == OS_NULL){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + if(htask->status & OS_STATUS_SUSPENDED){ + sv_resume_task(htask); + su_kernel_unlocks(); + return OS_ECODE_NOERROR; + } + if(htask->status < OS_STATUS_STOPPED){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSUSPENDED; + } + if(htask->status == OS_STATUS_STOPPED){ + su_kernel_unlocks(); + return OS_ECODE_TASKSTOPPED; + } + if(htask->status == OS_STATUS_DELETED){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_DONOTKNOW; + } +} + +/** + \brief 恢复指定任务并挂起自身任务 + \param[in] htask 任务句柄 + \return 错误码 + */ +s_ecode_t su_resume_suspend(s_tasknode_tsp htask) +{ + if(htask == OS_NULL){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + if(htask->status & OS_STATUS_SUSPENDED){ + sv_resume_task(htask); + } + if(htask->status == OS_STATUS_READY){ + sv_suspend_task(s_task_current); + su_kernel_unlocks(); + return OS_ECODE_NOERROR; + } + if(htask->status < OS_STATUS_STOPPED){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTREADY; + } + if(htask->status == OS_STATUS_STOPPED){ + su_kernel_unlocks(); + return OS_ECODE_TASKSTOPPED; + } + if(htask->status == OS_STATUS_DELETED){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_DONOTKNOW; + } +} + +/** + \brief 挂起任务 + \param[in] htask 任务句柄 + \return 错误码 + */ +s_ecode_t su_suspend_task(s_tasknode_tsp htask) +{ + if(htask == OS_NULL){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + if(htask->status < OS_STATUS_SUSPENDED){ + sv_suspend_task(htask); + su_kernel_unlocks(); + return OS_ECODE_NOERROR; + } + if(htask->status & OS_STATUS_SUSPENDED){ + su_kernel_unlocks(); + return OS_ECODE_TASKSUSPENDED; + } + if(htask->status == OS_STATUS_STOPPED){ + su_kernel_unlocks(); + return OS_ECODE_TASKSTOPPED; + } + if(htask->status == OS_STATUS_DELETED){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_DONOTKNOW; + } +} + +/** + \brief 删除任务 + \param[in] htask 任务句柄 + \return 错误码 + */ +s_ecode_t su_delete_task(s_tasknode_tsp htask) +{ + if(htask == OS_NULL){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + if(htask->status < OS_STATUS_DELETED){ + sv_delete_task(htask); + su_kernel_unlocks(); + return OS_ECODE_NOERROR; + } + if(htask->status == OS_STATUS_DELETED){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_DONOTKNOW; + } +} + +/** + \brief 清除阻塞(状态) + \param[in] htask 任务句柄 + \return 错误码 + */ +s_ecode_t su_clear_block(s_tasknode_tsp htask) +{ + if(htask == OS_NULL){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + if(htask->status == OS_STATUS_BLOCKED){ + sv_clear_block(htask); + su_kernel_unlocks(); + return OS_ECODE_NOERROR; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTBLOCKED; + } +} + +/** + \brief 设置阻塞(时间) + \param[in] htask 任务句柄 + \param[in] tick 滴答周期(阻塞时间)
+ +0:清除阻塞
+ ~0:无限阻塞 + \return 错误码 + */ +s_ecode_t su_set_block(s_tasknode_tsp htask, s_delay_t tick) +{ + if(htask == OS_NULL){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + if(htask->status == OS_STATUS_BLOCKED){ + sv_set_block(htask, tick); + su_kernel_unlocks(); + return OS_ECODE_NOERROR; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTBLOCKED; + } +} + +/** + \brief 设置任务优先级 + \param[in] htask 任务句柄 + \param[in] npri 新优先级 + \return 错误码 + */ +s_ecode_t su_set_taskpri(s_tasknode_tsp htask, s_u8_t npri) +{ + if(htask == OS_NULL){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + if(htask->status < OS_STATUS_STOPPED){ + if(htask->pri != npri){ + sv_set_taskpri(htask, npri); + su_kernel_unlocks(); + return OS_ECODE_NOERROR; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_TASKPRIUNCHANGED; + } + } + if(htask->status == OS_STATUS_STOPPED){ + su_kernel_unlocks(); + return OS_ECODE_TASKSTOPPED; + } + if(htask->status == OS_STATUS_DELETED){ + su_kernel_unlocks(); + return OS_ECODE_TASKNOTSTARTED; + } + else{ + su_kernel_unlocks(); + return OS_ECODE_DONOTKNOW; + } +} + +#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__ +/** + \brief 禅让任务 + \param 无 + \return 无 + */ +void su_yield_tasking(void) +{ + su_kernel_locks(); + s_task_current->tc_counter = ~0; + s_sign_schedule = true; + su_kernel_unlocks(); +} +#endif + +/** + \brief 自身任务延时 + \param[in] tick 滴答周期(延时时间)
+ +0:非法
+ ~0:无限延时 + \return 无 + */ +void su_delay(s_delay_t tick) +{ + s_task_current->timer = tick; + if(!s_sign_schedule_forbid){ /* 阻塞延时 */ + sv_insert_timer_list(); + su_kernel_unlock0_psv(); + } + else{ /* 就绪延时 */ + s_sign_ready_delay = true; + mSysIRQ_Enable; + while(s_sign_ready_delay); + } +} + + + +/* + * 互斥信号量 + */ +#if SYSCFG_MUTEX == __ENABLED__ +/** + \brief 获取互斥信号量 + \param[in] hmut 互斥信号量句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_take_mutex(s_mutex_tsp hmut, s_delay_t tick) +{ + if(!hmut->mutex) goto __RET_TRUE1; + if(s_task_current == hmut->otask) goto __RET_TRUE2; + if(!tick) goto __RET_FALSE; + + sv_insert_block_list(&hmut->htask); + if(s_task_current->pri > hmut->otask->pri){ + #if SYSCFG_SAMEPRISCHEDULE + sv_set_taskpri(hmut->otask, s_task_current->pri); + #else + sv_set_taskpri(hmut->otask, SYSCFG_TASKPRIORITY - 1); + #endif + } + s_task_current->blocktype = OS_BLOCKED_MUTEX; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hmut; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hmut = (s_mutex_tsp)s_task_current->handle; + #endif + if(!hmut->mutex) goto __RET_TRUE1; + +__RET_FALSE: + mSysIRQ_Enable; + return false; + +__RET_TRUE1: + hmut->otask = s_task_current; + hmut->opri = s_task_current->pri; + +__RET_TRUE2: + hmut->mutex++; + mSysIRQ_Enable; + return true; +} + +/** + \brief 归还互斥信号量 + \param[in] hmut 互斥信号量句柄 + \return 无 + */ +void su_back_mutex(s_mutex_tsp hmut) +{ + if(!hmut->mutex); + else if(s_task_current == hmut->otask){ + hmut->mutex--; + if(!hmut->mutex){ + if(s_task_current->pri > hmut->opri){ + sv_set_taskpri(s_task_current, hmut->opri); + } + sv_remove_block_list(&hmut->htask); + } + } + su_kernel_unlocks(); +} +#endif + + + +/* + * 二值信号量 + */ +#if SYSCFG_BINARY == __ENABLED__ +/** + \brief 等待二值信号量 + \param[in] hbin 二值信号量句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_wait_binary(s_binary_tsp hbin, s_delay_t tick) +{ + if(hbin->binary) goto __RET_TRUE; + if(!tick) goto __RET_FALSE; + + sv_insert_block_list(&hbin->htask); + s_task_current->blocktype = OS_BLOCKED_BINARY; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hbin; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hbin = (s_binary_tsp)s_task_current->handle; + #endif + if(hbin->binary) goto __RET_TRUE; + +__RET_FALSE: + mSysIRQ_Enable; + return false; + +__RET_TRUE: + mSysIRQ_Enable; + return true; +} + +/** + \brief 获取二值信号量 + \param[in] hbin 二值信号量句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_take_binary(s_binary_tsp hbin, s_delay_t tick) +{ + if(hbin->binary) goto __RET_TRUE; + if(!tick) goto __RET_FALSE; + + sv_insert_block_list(&hbin->htask); + s_task_current->blocktype = OS_BLOCKED_BINARY; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hbin; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hbin = (s_binary_tsp)s_task_current->handle; + #endif + if(hbin->binary) goto __RET_TRUE; + +__RET_FALSE: + mSysIRQ_Enable; + return false; + +__RET_TRUE: + hbin->binary = false; + mSysIRQ_Enable; + return true; +} +#endif + + + +/* + * 计数信号量 + */ +#if SYSCFG_SEMAPHORE == __ENABLED__ +/** + \brief 获取计数信号量 + \param[in] hsem 计数信号量句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_take_semaphore(s_semaph_tsp hsem, s_delay_t tick) +{ + if(hsem->counter) goto __RET_TRUE; + if(!tick) goto __RET_FALSE; + + sv_insert_block_list(&hsem->htask); + s_task_current->blocktype = OS_BLOCKED_SEMAPHORE; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hsem; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hsem = (s_semaph_tsp)s_task_current->handle; + #endif + if(hsem->counter) goto __RET_TRUE; + +__RET_FALSE: + mSysIRQ_Enable; + return false; + +__RET_TRUE: + (hsem->counter)--; + mSysIRQ_Enable; + return true; +} +#endif + + + +/* + * 飞信 + */ +#if SYSCFG_FETION == __ENABLED__ +/** + \brief 接收飞信 + \param[in] htbox 信箱句柄 + \return 飞信 + */ +static m_fetion_t _recv_fetion_(s_tionbox_tsp htbox) +{ + m_fetion_t tion = htbox->tion; + htbox->tion = false; + mSysIRQ_Enable; + return tion; +} + +/** + \brief 接收飞信 + \param[in] htbox 信箱句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 飞信 + \retval false 失败 + */ +m_fetion_t su_recv_fetion(s_tionbox_tsp htbox, s_delay_t tick) +{ + if(htbox->tion) goto __RET_TION; + if(!tick) goto __RET_FALSE; + + sv_insert_block_list(&htbox->htask); + s_task_current->blocktype = OS_BLOCKED_FETION; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = htbox; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + htbox = (s_tionbox_tsp)s_task_current->handle; + #endif + +__RET_TION: + return _recv_fetion_(htbox); + +__RET_FALSE: + mSysIRQ_Enable; + return false; +} +#endif + + + +/* + * 邮箱 + */ +#if SYSCFG_MAILBOX == __ENABLED__ +/** + \brief 接收邮件 + \param[in] hmbox 邮箱句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 邮件指针 + \retval NULL 失败 + */ +void *su_recv_mail(s_mailbox_tsp hmbox, s_delay_t tick) +{ + if(hmbox->flag) goto __RET_MAIL; + if(!tick) goto __RET_NULL; + + sv_insert_block_list(&hmbox->htask); + s_task_current->blocktype = OS_BLOCKED_MAIL; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hmbox; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hmbox = (s_mailbox_tsp)s_task_current->handle; + #endif + if(hmbox->flag) goto __RET_MAIL; + +__RET_NULL: + mSysIRQ_Enable; + return OS_NULL; + +__RET_MAIL: + hmbox->flag = false; + return su_kernel_unlock0_ret(hmbox->mail); +} +#endif + + + +/* + * 消息队列 + */ +#if SYSCFG_MSGQUEUE == __ENABLED__ +/** + \brief 接收消息 + \param[in] hque 队列句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 消息指针 + \retval NULL 失败 + */ +void *su_recv_msg(s_queue_tsp hque, s_delay_t tick) +{ + void *msg; + hque->mutex = false; + + if(hque->counter) goto __RECV_MSG; + if(!tick) goto __RET_NULL; + + hque->mutex = true; + sv_insert_block_list(&hque->htask); + s_task_current->blocktype = OS_BLOCKED_MSG; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hque; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hque = (s_queue_tsp)s_task_current->handle; + #endif + hque->mutex = false; + if(!hque->counter) goto __RET_NULL; + +__RECV_MSG: + if(hque->type == __DYNAMIC__){ + msg = sv_recv_msg_dynamic((sd_queue_tsp)hque); + } + else{ + msg = sv_recv_msg_static((ss_queue_tsp)hque); + } + hque->mutex = true; + return su_kernel_unlock0_ret(msg); + +__RET_NULL: + hque->mutex = true; + mSysIRQ_Enable; + return OS_NULL; +} + +/** + \brief 发送消息 + \param[in] hque 队列句柄 + \param[in] msg 消息指针 + \return 错误码 + */ +s_ecode_t su_send_msg(s_queue_tsp hque, void *msg) +{ + s_ecode_t _ecode = sv_send_msg(hque, msg); + su_kernel_unlocks(); + return _ecode; +} +#endif + + + +/* + * 事件标志组 + */ +#if SYSCFG_FLAGGROUP == __ENABLED__ +/** + \brief 查询标志组 + \param[in] hgrp 标志组句柄 + \param[in] size sizeof(group) + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_query_group(void _STATIC_MEM_ *hgrp, s_u8_t size) +{ + switch(size){ + case 1: if(*(s_u8_t *)hgrp) goto __RET_TRUE; break; + case 2: if(*(s_u16_t *)hgrp) goto __RET_TRUE; break; + case 4: if(*(s_u32_t *)hgrp) goto __RET_TRUE; break; + } + su_kernel_unlocks(); + return false; + +__RET_TRUE: + su_kernel_unlocks(); + return true; +} + +/** + \brief 等待标志组_1 + \param[in] hgrp 标志组句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_wait_group_1(s_u8_t _STATIC_MEM_ *hgrp, s_delay_t tick) +{ + if(*hgrp) goto __RET_TRUE; + if(!tick) goto __RET_FALSE; + + sv_insert_timer_list(); + s_task_current->blocktype = 1; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hgrp; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hgrp = s_task_current->handle; + #endif + if(*hgrp) goto __RET_TRUE; + +__RET_FALSE: + mSysIRQ_Enable; + return false; + +__RET_TRUE: + mSysIRQ_Enable; + return true; +} + +/** + \brief 等待标志组_2 + \param[in] hgrp 标志组句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_wait_group_2(s_u16_t _STATIC_MEM_ *hgrp, s_delay_t tick) +{ + if(*hgrp) goto __RET_TRUE; + if(!tick) goto __RET_FALSE; + + sv_insert_timer_list(); + s_task_current->blocktype = 2; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hgrp; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hgrp = s_task_current->handle; + #endif + if(*hgrp) goto __RET_TRUE; + +__RET_FALSE: + mSysIRQ_Enable; + return false; + +__RET_TRUE: + mSysIRQ_Enable; + return true; +} + +/** + \brief 等待标志组_4 + \param[in] hgrp 标志组句柄 + \param[in] tick 滴答周期(超时时间)
+ +0:立即返回
+ ~0:无限等待 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_wait_group_4(s_u32_t _STATIC_MEM_ *hgrp, s_delay_t tick) +{ + if(*hgrp) goto __RET_TRUE; + if(!tick) goto __RET_FALSE; + + sv_insert_timer_list(); + s_task_current->blocktype = 4; + s_task_current->timer = tick; + #if SYSCFG_MCUCORE == 8051 + s_task_current->handle = hgrp; + #endif + su_kernel_unlock0_psv(); + #if SYSCFG_MCUCORE == 8051 + hgrp = s_task_current->handle; + #endif + if(*hgrp) goto __RET_TRUE; + +__RET_FALSE: + mSysIRQ_Enable; + return false; + +__RET_TRUE: + mSysIRQ_Enable; + return true; +} +#endif + + + +/* + * 动态内存 + */ +#if SYSCFG_DYNMEMMGE == __ENABLED__ +/** + \brief uxalloc + \param[in] p + \return 指针 + \retval NULL 失败 + */ +void _MALLOC_MEM_ *su_xalloc(void _MALLOC_MEM_ *p) +{ + su_kernel_unlocks(); + return p; +} + +/** + \brief 初始化线程内存池 + \param[in] hmem 线程内存句柄 + \param[in] size 内存池大小 + \return 结果 + \retval false 失败 + \retval true 成功 + */ +bool su_init_mempool(s_thrmem_tsp hmem, size_t size) +{ + hmem->head = hmem->move = (void _MALLOC_MEM_ *)s_malloc(size); + if(hmem->head == OS_NULL){ + su_kernel_unlocks(); + return false; + } + else{ + hmem->size = size; + su_kernel_unlocks(); + return true; + } +} + +/** + \brief 线程内存分配 + \param[in] hmem 线程内存句柄 + \param[in] size 内存块大小 + \return 指针 + \retval NULL 失败 + */ +void _MALLOC_MEM_ *su_talloc(s_thrmem_tsp hmem, size_t size) +{ + if(hmem->head == OS_NULL || (size_t)hmem->move - (size_t)hmem->head + size > hmem->size){ + return OS_NULL; + } + else{ + void _MALLOC_MEM_ *r = hmem->move; + hmem->move = (s_u8_t _MALLOC_MEM_ *)hmem->move + size; + return r; + } +} +#endif + +/** @} */ +/** @} */ diff --git a/System/sv_task.h b/System/sv_task.h new file mode 100644 index 00000000..b2e9e77b --- /dev/null +++ b/System/sv_task.h @@ -0,0 +1,415 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file sv_task.h + * @brief 任务服务 + * @details 仅在任务中调用并执行。 + * @author 迟凯峰 + * @version V1.0.2 + * @date 2025.02.26 + ******************************************************************************/ + +#ifndef __SV_TASK_H +#define __SV_TASK_H + +#include "os_redef.h" + +#if MCUCFG_ISA == __ARM__ +/** 调度上锁(进入嵌套任务临界区)*/ +__STATIC_FORCEINLINE void su_schedule_locks(void) +{ + s_sign_schedule_forbid = true; + s_schedulelock_counter++; +} + +/** 内核上锁(进入嵌套服务层临界区)*/ +__STATIC_FORCEINLINE void su_kernel_locks(void) +{ + mSysIRQ_Disable; + #if SYSCFG_KERNELLOCKNESTING == __ENABLED__ + s_kernellock_counter++; + #endif +} + +/** 内核上锁(进入非嵌套服务层临界区)*/ +__STATIC_FORCEINLINE void su_kernel_lock0(void) +{ + mSysIRQ_Disable; +} +#else +void su_schedule_locks (void); +void su_kernel_locks (void); +void su_kernel_lock0 (void); +#endif + +void su_schedule_unlocks (void); +void su_kernel_unlocks (void); +void *su_kernel_unlocks_ret(void *p); +void su_kernel_unlock0_psv(void); + +s_ecode_t su_startup_task (s_taskhand_tsp hhand, s_u8_t status); +s_ecode_t su_resume_task (s_tasknode_tsp htask); +s_ecode_t su_resume_suspend (s_tasknode_tsp htask); +s_ecode_t su_suspend_task (s_tasknode_tsp htask); +s_ecode_t su_delete_task (s_tasknode_tsp htask); +s_ecode_t su_clear_block (s_tasknode_tsp htask); +s_ecode_t su_set_block (s_tasknode_tsp htask, s_delay_t tick); +s_ecode_t su_set_taskpri (s_tasknode_tsp htask, s_u8_t npri); +void su_yield_tasking (void); +void su_delay (s_delay_t tick); +bool su_take_mutex (s_mutex_tsp hmut, s_delay_t tick); +void su_back_mutex (s_mutex_tsp hmut); +bool su_wait_binary (s_binary_tsp hbin, s_delay_t tick); +bool su_take_binary (s_binary_tsp hbin, s_delay_t tick); +bool su_take_semaphore (s_semaph_tsp hsem, s_delay_t tick); +m_fetion_t su_recv_fetion (s_tionbox_tsp htbox, s_delay_t tick); +void *su_recv_mail (s_mailbox_tsp hmbox, s_delay_t tick); +void *su_recv_msg (s_queue_tsp hque, s_delay_t tick); +s_ecode_t su_send_msg (s_queue_tsp hque, void *msg); +bool su_query_group (void _STATIC_MEM_ *hgrp, s_u8_t size); +bool su_wait_group_1 (s_u8_t _STATIC_MEM_ *hgrp, s_delay_t tick); +bool su_wait_group_2 (s_u16_t _STATIC_MEM_ *hgrp, s_delay_t tick); +bool su_wait_group_4 (s_u32_t _STATIC_MEM_ *hgrp, s_delay_t tick); +bool su_init_mempool (s_thrmem_tsp hmem, size_t size); +void _MALLOC_MEM_ *su_talloc (s_thrmem_tsp hmem, size_t size); +void _MALLOC_MEM_ *su_xalloc (void _MALLOC_MEM_ *p); + + + +/** + @addtogroup 任务服务 + @{ + */ + +/* + * 操作任务 + */ + +/** 启动任务 */ +#define sUSV_StartTask(hhand, status) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_startup_task((s_taskhand_tsp)hhand, !status ? OS_STATUS_READY : OS_STATUS_SUSPENDED) : OS_ECODE_NOERROR \ +) + +/** 挂起任务 */ +#define sUSV_SuspendTask(htask) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_suspend_task(htask) : OS_ECODE_NOERROR \ +) + +/** 恢复任务 */ +#define sUSV_ResumeTask(htask) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_resume_task(htask) : OS_ECODE_NOERROR \ +) + +/** 恢复指定任务并挂起自身任务 */ +#define sUSV_ResumeSuspend(htask) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_resume_suspend(htask) : OS_ECODE_NOERROR \ +) + +/** 删除任务 */ +#define sUSV_DeleteTask(htask) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_delete_task(htask) : OS_ECODE_NOERROR \ +) + +/** 设置任务优先级 */ +#define sUSV_SetTaskPri(htask, npri) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_set_taskpri(htask, npri) : OS_ECODE_NOERROR \ +) + +/** 设置阻塞(时间)*/ +#define sUSV_SetBlock(htask, tick) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_set_block(htask, tick) : OS_ECODE_NOERROR \ +) + +/** 清除阻塞(状态)*/ +#define sUSV_ClearBlock(htask) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_clear_block(htask) : OS_ECODE_NOERROR \ +) + +/** 自身任务延时 */ +#define sUSV_Delay(tick) \ +do{ \ + mSysIRQ_Disable; \ + su_delay(tick); \ +}while(false) + + + +/* + * 定时 + */ + +/** 定时中断 */ +#define sUSV_TimInt(tmid, tick) \ +do{ \ + su_kernel_locks(); \ + sv_timint(tmid, tick); \ + su_kernel_unlocks(); \ +}while(false) + +/** 定时查询 */ +#define sUSV_TimQry(tmid, tick) \ +do{ \ + su_kernel_locks(); \ + sv_timqry(tmid, tick); \ + su_kernel_unlocks(); \ +}while(false) + + + +/* + * 互斥信号量 + */ + +/** 获取互斥信号量 */ +#define sUSV_TakeMut(mut, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_take_mutex(&mut, tick) : false \ +) + +/** 归还互斥信号量 */ +#define sUSV_BackMut(mut) \ +do{ \ + su_kernel_locks(); \ + su_back_mutex(&mut); \ +}while(false) + + + +/* + * 二值信号量 + */ + +/** 等待二值信号量 */ +#define sUSV_WaitBin(bin, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_wait_binary(&bin, tick) : false \ +) + +/** 获取二值信号量 */ +#define sUSV_TakeBin(bin, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_take_binary(&bin, tick) : false \ +) + +/** 给予二值信号量 */ +#define sUSV_GiveBin(bin) \ +do{ \ + su_kernel_locks(); \ + sv_give_binary(&bin); \ + su_kernel_unlocks(); \ +}while(false) + + + +/* + * 计数信号量 + */ + +/** 获取计数信号量 */ +#define sUSV_TakeSem(sem, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_take_semaphore(&sem, tick) : false \ +) + +/** 给予计数信号量 */ +#define sUSV_GiveSem(sem) \ +do{ \ + su_kernel_locks(); \ + sv_give_semaphore(&sem); \ + su_kernel_unlocks(); \ +}while(false) + + + +/* + * 飞信 + */ + +/** 接收飞信 */ +#define sUSV_RecvFetion(tbox, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_recv_fetion(&tbox, tick) : false \ +) + +/** 发送飞信 */ +#define sUSV_SendFetion(tbox, tion) \ +do{ \ + su_kernel_locks(); \ + sv_send_fetion(&tbox, tion); \ + su_kernel_unlocks(); \ +}while(false) + + + +/* + * 邮箱 + */ + +/** 接收邮件 */ +#define sUSV_RecvMail(mbox, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_recv_mail(&mbox, tick) : OS_NULL \ +) + +/** 发送邮件 */ +#define sUSV_SendMail(mbox, mail) \ +do{ \ + su_kernel_locks(); \ + sv_send_mail(&mbox, mail); \ + su_kernel_unlocks(); \ +}while(false) + + + +/* + * 消息队列 + */ + +/** 接收消息 */ +#define sUSV_RecvMsg(que, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? su_recv_msg((s_queue_tsp)&que, tick) : OS_NULL \ +) + +/** 发送消息 */ +#define sUSV_SendMsg(que, msg) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_send_msg((s_queue_tsp)&que, msg) : OS_ECODE_NOERROR \ +) + + + +/* + * 事件标志组 + */ + +/** 查询标志组 */ +#define sUSV_QueryFlagGroup(group) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_query_group((void *)&group, sizeof(group)) : false \ +) + +/** 等待标志组 */ +#define sUSV_WaitFlagGroup(group, tick) \ +( \ + (m_boolvoid_tf(su_kernel_lock0))() || true ? ( \ + sizeof(group) == 1 ? su_wait_group_1((s_u8_t *)&group, tick) \ + : sizeof(group) == 2 ? su_wait_group_2((s_u16_t *)&group, tick) \ + : sizeof(group) == 4 ? su_wait_group_4((s_u32_t *)&group, tick) \ + : false \ + ) : false \ +) + +/** 清除标志组 */ +#define sUSV_ClearFlagGroup(group) \ +do{ \ + su_kernel_locks(); \ + sizeof(group) == 1 ? *(s_u8_t *)&group = false : MCUCFG_TERNARYMASK \ + sizeof(group) == 2 ? *(s_u16_t *)&group = false : MCUCFG_TERNARYMASK \ + sizeof(group) == 4 ? *(s_u32_t *)&group = false : false; \ + su_kernel_unlocks(); \ +}while(false) + +/** 写多标志位 */ +#define sUSV_WriteFlagBits(group, value, nbit) \ + suWriteFlagBits_##nbit(group, value, + + + +/* + * 软件RTC + */ + +/** 获取时间 */ +#define sUSV_GetTime(t) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_kernel_unlocks_ret(s_memcpy(t, &s_rtc, sizeof(s_rtc_ts))) : OS_NULL \ +) + +/** 设置时间 */ +#if SYSCFG_GETRTC_INT == __ENABLED__ +#define sUSV_SetTime(t) \ +do{ \ + su_kernel_locks(); \ + s_memcpy(&s_rtc, t, sizeof(s_rtc_ts)); \ + s_sign_every.set = true; \ + sv_update_rtccopy(); \ + su_kernel_unlocks(); \ +}while(false) +#else +#define sUSV_SetTime(t) \ +do{ \ + su_kernel_locks(); \ + s_memcpy(&s_rtc, t, sizeof(s_rtc_ts)); \ + s_sign_every.set = true; \ + su_kernel_unlocks(); \ +}while(false) +#endif + + + +/* + * 进程内存 + */ + +/** malloc */ +#define sUSV_Malloc(size) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_xalloc((void _MALLOC_MEM_ *)s_malloc(size)) : OS_NULL \ +) + +/** calloc */ +#define sUSV_Calloc(nmemb, size) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_xalloc((void _MALLOC_MEM_ *)s_calloc(nmemb, size)) : OS_NULL \ +) + +/** realloc */ +#define sUSV_Realloc(p, size) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_xalloc((void _MALLOC_MEM_ *)s_realloc(p, size)) : OS_NULL \ +) + +/** free */ +#define sUSV_Free(p) \ +do{ \ + su_kernel_locks(); \ + s_free(p); \ + su_kernel_unlocks(); \ +}while(false) + + + +/* + * 线程内存 + */ + +/** 初始化线程内存池 */ +#define sUSV_InitMempool(size) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_init_mempool(&u_thrmem, size) : false \ +) + +/** 线程内存分配 */ +#define sUSV_Talloc(size) \ +( \ + (m_boolvoid_tf(su_kernel_locks))() || true ? su_xalloc(su_talloc(&u_thrmem, size)) : OS_NULL \ +) + +/** 释放线程内存池 */ +#define sUSV_FreeMempool \ +do{ \ + sUSV_Free(u_thrmem.head); \ + u_thrmem.head = u_thrmem.move = OS_NULL; \ +}while(false) + +/** @} */ + +#endif diff --git a/System/ur_api.h b/System/ur_api.h new file mode 100644 index 00000000..f7031c77 --- /dev/null +++ b/System/ur_api.h @@ -0,0 +1,1746 @@ +/**************************************************************************//** + * @item CosyOS-III Kernel + * @file ur_api.h + * @brief 用户API + * @details 用户API定义,含注释说明,所有内核服务的API说明均在此文件中,并支持 doxygen。 + * @author 迟凯峰 + * @version V1.0.2 + * @date 2025.02.26 + ******************************************************************************/ + +#ifndef __UR_API_H +#define __UR_API_H + +/** + \defgroup CosyOS_用户API + \brief 用户通过调用API来实现对系统服务的调用,所有API均为宏定义, + 所有系统服务也为宏定义,所有API参数均支持宏定义。 + @{ + */ + +/** + \page API说明: + \li API分类 + + \li 创建API
+ 静态创建:前缀为“u”,分为声明对象(uExtern)、创建对象(uCreate)、定义对象(uDef)。
+ 动态创建:前缀为“d”,分为声明对象(dExtern)、创建对象(dCreate)。 + + \li 任务API
+ 前缀为“u”,指仅在任务中调用。 + + \li 滴答API
+ 前缀为“t”,指仅在系统滴答中断中调用,包括在滴答钩子、定时中断钩子、
+ 定时查询钩子、定时查询事件等处调用。 + + \li 中断API
+ 前缀为“i”,指仅在用户中断中调用。 + + \li PSVAPI
+ 前缀为“p”,指仅在 pendsv_hook 中调用。 + + \li 公共API
+ 前缀为“x”,指可在任意处(任务、滴答、中断)调用。 + +
+ + \li API返回 + + \li 无返回
+ (1)服务的执行结果一定是成功的,所以不需要返回。
+ (2)所有中断挂起服务均无返回。 + + \li 返回错误码
+ 服务的执行结果可能会失败,导致失败的原因可能有多个。
+ (1)绿码:无错误。
+ (2)黄码:由于结果已经成功,导致本次并未执行。
+ (3)红码:失败。 + + \li 返回结果
+ 服务的执行结果可能会失败,但导致失败的原因是唯一的。
+ 执行结果为 bool 类型,true 为成功,false 为失败。 + + \li 返回指针
+ 返回一个指针,(void *) 类型,NULL 为失败。 + + \li 返回值
+ 返回一个数值,特定的数据类型,0 为失败。 + +
+ + \li 名词解释 + + \li 无限阻塞
+ 阻塞时间为无限长。 + + \li 无限等待
+ 超时时间为无限长。 + + \li 无限延时
+ 延时时间为无限长。 + + \li 无限同步
+ 仅同步一次,事件处理线程便可不限次数的周期运行。
+ 仅二值信号量支持该功能,可通过上锁的方式来终止无限同步。 + +
+ */ + + + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 任务 + @{ + */ + +/** + \ingroup 任务 + \defgroup 声明任务 + \brief 任务线程的声明 + @{ + */ + +/** + \brief 声明静态创建的任务 + \param[in] task 任务名称 + \return 无 + */ +#define uExternTask(task) \ + sCSV_ExternTask(task) + +/** + \brief 声明动态创建的任务 + \param[in] task 任务名称 + \return 无 + */ +#define dExternTask(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, 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, 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 uCreateTask_TimInt(tmid, arl, task, pri, tss, srt, res) \ + sCSV_CreateTask_TimInt(tmid, arl, task, pri, tss, srt, 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, 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, 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, res) + +/** @} */ + +/** + \ingroup 任务 + \defgroup 启动任务 + \brief 任务线程的启动。任务只有在启动以后,才能加入到任务队列参与调度并运行。 + \warning 所有定时中断任务和定时查询任务均由操作系统自动启动,用户不要启动。 + \warning 不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + @{ + */ + +/** + \brief 启动任务 + \details 启动任务并置任务的初始状态为设定状态。 + \param[in] task 任务名称 + \param[in] status 任务的初始状态
+ 0:就绪状态
+ 1:挂起状态 + \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(task, status) \ + sUSV_StartTask(&u_taskhand_##task, status) + +/** + \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_Suspend(task) \ + uStartTask(task, OS_STATUS_SUSPENDED) + +/** @} */ + +/** + \ingroup 任务 + \defgroup 操作任务 + \brief 对任意任务的操作,如 恢复、挂起、删除、设置优先级 等。 + @{ + */ + +/** + \brief 清除就绪延时 + \details 清除当前任务的就绪延时,前提是当前任务已在就绪延时中。 + \param 无 + \return 无 + \note 同型服务:
+ iClearDelay,无返回。
+ pClearDelay,无返回。 + */ +#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),同返回。
+ iResumeTask(task),无返回。
+ pResumeTask(task),无返回。 + */ +#define uResumeTask(task) \ + sUSV_ResumeTask(u_taskhandle_##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),同返回。
+ iSuspendTask(task),无返回。
+ pSuspendTask(task),无返回。 + */ +#define uSuspendTask(task) \ + sUSV_SuspendTask(u_taskhandle_##task) + +/** + \brief 删除任务 + \param[in] task 任务名称 + \return 错误码(s_ecode_t) + \retval OS_ECODE_NOERROR 无错误 + \retval OS_ECODE_TASKNOTSTARTED 任务未启动/已删除 + \note 同型服务:
+ tDeleteTask(task),同返回。
+ iDeleteTask(task),无返回。
+ pDeleteTask(task),无返回。 + */ +#define uDeleteTask(task) \ + sUSV_DeleteTask(u_taskhandle_##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),同返回。
+ iSetTaskPri(task, npri),无返回。
+ pSetTaskPri(task, npri),无返回。 + */ +#define uSetTaskPri(task, npri) \ + sUSV_SetTaskPri(u_taskhandle_##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),同返回。
+ iClearBlock(task),无返回。
+ pClearBlock(task),无返回。 + */ +#define uClearBlock(task) \ + sUSV_ClearBlock(u_taskhandle_##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),同返回。
+ iSetBlock_tc(task, tc),无返回。
+ pSetBlock_tc(task, tc),无返回。 + */ +#define uSetBlock_tc(task, tc) sUSV_SetBlock(u_taskhandle_##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),同返回。
+ iSetBlock_ms(task, ms),无返回。
+ pSetBlock_ms(task, ms),无返回。 + */ +#define uSetBlock_ms(task, ms) uSetBlock_tc(task, (1000UL * (ms)) / SYSCFG_SYSTICKCYCLE) + +/** + \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),同返回。
+ iSetBlock_s(task, s),无返回。
+ pSetBlock_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),同返回。
+ iSetBlock_m(task, m),无返回。
+ pSetBlock_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),同返回。
+ iSetBlock_h(task, h),无返回。
+ pSetBlock_h(task, h),无返回。 + */ +#define uSetBlock_h(task, h) uSetBlock_m(task, 60UL * (h)) + +/** @} */ +/** @} */ +/** + \ingroup 任务 + \defgroup 操作自身任务 + \brief 仅适用于对自身任务的操作 + @{ + */ + +/** + \brief 禅让任务 + \details 自身任务主动禅让CPU使用权,轮转至下一个相同优先级的任务运行。 + \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 挂起自身任务 + \return 错误码(s_ecode_t) + \note 虽然也返回错误码,但在正常情况下结果一定是成功的,不必查看错误码。 + */ +#define uSuspendTasking sUSV_SuspendTask(s_task_current) + +/** + \brief 删除自身任务 + \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(u_taskhandle_##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_SYSTICKCYCLE) + +/** + \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] hook 钩子函数 + \param[in] add{...} 附加钩子代码 + \return 无 + */ +#define uCreateHook_TimInt(tmid, arl, hook) \ + sCSV_CreateHook_TimInt(tmid, arl, hook) + +/** + \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_SYSTICKCYCLE) + +/** + \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] hook 钩子函数 + \param[in] add{...} 附加钩子代码 + \return 无 + */ +#define uCreateHook_TimQry(tmid, event, arl, hook) \ + sCSV_CreateHook_TimQry(tmid, event, arl, hook) + +/** + \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_SYSTICKCYCLE) + +/** + \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 不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + \warning 当tc为~0时(无限等待),仍建议用户查询返回值,原因是当在多个相同优先级的任务中
+ 获取同一个互斥信号量时(采用时间片轮转调度),其返回结果仍然有失败的可能。 + */ +#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 二值信号量初始值
+ 0:已上锁
+ 1:已解锁 + \return 无 + */ +#define uCreateBin(bin, init) sCSV_CreateBin(bin, init) + +/** + \brief 上锁二值信号量 + \details 用于终止线程的无限同步。 + \param[in] bin 二值信号量名称 + \return 无 + \note 同型服务:
+ tLockBin(bin)。
+ iLockBin(bin)。
+ pLockBin(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)。
+ iGiveBin(bin)。
+ pGiveBin(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 任务中获取,不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + \warning 当用于资源同步时(互斥访问),当tc为~0时(无限等待),仍建议用户查询返回值,原因是
+ 当在多个相同优先级的任务中获取同一个二值信号量时(采用时间片轮转调度),其返回结果仍然有失败的可能。 + */ +#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 任务中获取,不支持在临界区中,包括任务临界区、服务层临界区、全局临界区,或关闭总中断时调用。 + \warning 当用于资源同步时(互斥访问),当tc为~0时(无限等待),仍建议用户查询返回值,原因是
+ 当在多个相同优先级的任务中获取同一个计数信号量时(采用时间片轮转调度),其返回结果仍然有失败的可能。 + */ +#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 仅使用一个变量,同时即是消息,又是新消息标志。
+ 飞信为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 适用于对一类事件的、多对一关系的事件同步。 + \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 由CosyOS内核提供服务支持,可实现在“任务、滴答、中断”中,对非原子全局变量 + 的安全访问,同时不会破坏零中断延迟。 + @{ + */ + +/** + \brief 更新全局变量副本 + \param[in] code 更新副本的代码 + \return 无 + */ +#define xUpdateCopy(code) sUpdateCopy(code) + +/** + \brief 读哪一个全局变量? + \return 结果(bool) + \retval true 读正本 + \retval false 读副本 + */ +#define iWhichGVar_Read s_sign_updatecopy + +/** + \brief 写全局变量 + \param[in] gv 全局变量名称 + \param[in] lv 局部变量名称 + \return 无 + */ +#define iWriteGVar(gv, lv) sPSV_WriteGVar((void *)&gv, (void *)&lv, sizeof(gv)) + +/** + \brief 写全局数组 + \param[in] gp 全局数组指针 + \param[in] lp 局部数组指针 + \param[in] size 拷贝的大小(字节数) + \return 无 + */ +#define iWriteGAry(gp, lp, size) sPSV_WriteGVar(gp, lp, size) + +/** + \brief 写全局字符串 + \param[in] gs 全局字符串指针 + \param[in] ls 局部字符串指针 + \return 无 + */ +#define iWriteGStr(gs, ls) sPSV_WriteGVar(gs, ls, 0) + +/** + \brief 挂起服务调用 + \param[in] fp 函数指针 + \return 无 + */ +#define iPendSVC(fp) sPSV_PendSVC(fp) + +/** + \brief 发送信号 + \param[in] sign 信号名称 + \return 无 + */ +#define iSendSign(sign) sPSV_SendSign(sign) + +/** @} */ + +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 软件RTC + \brief 适用于没有硬件RTC的物联网设备。 + \note 实际应用中,可每间隔一段时间(如一小时)同步一次网络时间,以修正误差。 + @{ + */ + +/** + \brief 获取时间 + \param[in] t 本地时间的指针(s_rtc_ts) + \return 本地时间的指针 + \note 同型服务:
+ tGetTime(t)。
+ iGetTime(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模式时可考虑在线程的开始处创建。 + \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 释放线程内存池 + */ +#define uFreeMempool sUSV_FreeMempool + +/** @} */ +/** @} */ +/**************************************************************************//** + \ingroup CosyOS_用户API + \defgroup 临界区 + \note CosyOS的临界区包括任务临界区、服务层临界区、全局临界区,均支持嵌套使用。
+ 各临界区之间也可随意互相嵌套,但通常推荐在任务临界区中嵌套服务层临界区,
+ 在服务层临界区中嵌套全局临界区,以逐步扩大保护范围。 + @{ + */ + +/** + \ingroup 临界区 + \defgroup 调度锁(任务临界区) + \brief 通过上锁任务调度器的方式,实现任务级的临界区保护,仅支持在任务中调用。 + \note 仅是上锁任务调度器,不关闭系统中断(SysTick、PendSV),所以即使是长时间的、
+ 对大段的任务级公共资源的独占访问,也不会影响系统节拍的精度和内核服务的执行。 + \note 调度锁支持嵌套使用,最大嵌套深度255,调度上锁与调度解锁必须配对使用。 + \note 调度锁不会破坏零中断延迟,当需要任务级的临界区保护时,可以考虑。 + @{ + */ + +/** + \brief 调度上锁(进入任务临界区) + \return 无 + */ +#define uScheduleLock su_schedule_locks() + +/** + \brief 调度解锁(退出任务临界区) + \return 无 + */ +#define uScheduleUnlock su_schedule_unlocks() + +/** @} */ + +/** + \ingroup 临界区 + \defgroup 内核锁(服务层临界区) + \brief OS内核级的临界区保护,会关闭系统中断(SysTick、PendSV),仅支持在任务中调用。 + \note 由 系统滴答、PendSV、内核锁,共同组成大的服务层临界区,当处理得当时,可实现全局的临界区保护。
+ 实现过程:
+ 任务中:对内核上锁后访问。
+ 滴答中:直接访问即可。
+ 中断中:采用中断挂起服务。 + \note 内核锁支持嵌套使用,最大嵌套深度255,内核上锁与内核解锁必须配对使用。 + \note 内核锁不会破坏零中断延迟,当需要全局的临界区保护时,应首先予以考虑。 + \note 内核锁应遵循快进快出的原则,临界段代码的执行时间应远小于系统滴答周期,否则可能会导致
+ 丢失系统节拍、延误中断挂起服务和滴答服务的执行,对系统实时性造成不利影响。 + \note 当在任务中对事件标志组进行 设置位、清除位 等操作时,需采用内核锁。 + \note 当在任务中访问非原子全局变量时(包括读访问、写访问、自运算),
+ 可采用内核锁实现全局的临界区保护(参见 全局变量访问示例)。 + @{ + */ + +/** + \brief 内核上锁(进入服务层临界区) + \return 无 + */ +#define uKernelLock su_kernel_locks() + +/** + \brief 内核解锁(退出服务层临界区) + \return 无 + */ +#define uKernelUnlock su_kernel_unlocks() + +/** @} */ + +/** + \ingroup 临界区 + \defgroup 中断锁(全局临界区) + \brief 全局的临界区保护,通常会关闭总中断,支持在任意处调用。 + \note CosyOS内核中从来不会关闭总中断,提供此项服务只是为了便于用户
+ 对全局公共资源和程序过程的保护。 + \note 全局临界区会破坏零中断延迟,应做为最后的选项,慎重使用。 + @{ + */ +#if MCUCFG_ISA != __ARM__ +/** + \ingroup 全局临界区 + \defgroup 操作-EA + \note 支持嵌套使用,最大嵌套深度255,进入临界区与退出临界区必须配对使用。 + @{ + */ + +/** + \brief 进入全局临界区 + \return 无 + */ +#define xDisableIRQ mxDisableIRQ + +/** + \brief 退出全局临界区 + \return 无 + */ +#define xResumeIRQ mxResumeIRQ + +/** @} */ +#else +/** + \ingroup 全局临界区 + \defgroup 操作-PRIMASK + \note 支持嵌套使用,进入临界区与退出临界区必须配对使用。 + @{ + */ + +/** + \brief 进入全局临界区 + \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 DEBUG + \brief DEBUG接口,串口发送与接收的实现。 + \code +应用示例: + +一、8051/251-UART1 +void UART1_Isr(void) interrupt 4 +{ + if(TI){ + TI = 0; + if(*s_debug_sendptr){ + SBUF = *s_debug_sendptr++; + } + else{ + iDebugSend; + } + } + if(RI){ + RI = 0; + if(s_debug_recvptr - s_debug_recvbuff < OS_DEBUGRECVBUFFSIZE - 1){ + *s_debug_recvptr++ = SBUF; + } + iDebugRecv; + } +} + +二、STM32-USART1 +void USART1_IRQHandler(void) +{ + if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET){ + if(*s_debug_sendptr){ + USART_SendData(USART1, *s_debug_sendptr++); + } + else{ + USART_ITConfig(USART1, USART_IT_TXE, DISABLE); + iDebugSend; + } + } + if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ + if(s_debug_recvptr - s_debug_recvbuff < OS_DEBUGRECVBUFFSIZE - 1){ + *s_debug_recvptr++ = USART_ReceiveData(USART1); + } + iDebugRecv; + } +} + \endcode + @{ + */ +#define iDebugSend s_sign_debug_send = true +#define iDebugRecv s_sign_debug_recv = true + +/** @} */ + +/** + \ingroup 杂项 + \defgroup 时间单位转换 + \brief 把其它单位的时间转换为滴答周期。 + @{ + */ + +/** + \brief 毫秒转换为滴答周期 + \param[in] ms 毫秒 + \return 滴答周期 + */ +#define xTick_ms(ms) ((1000UL * (ms)) / SYSCFG_SYSTICKCYCLE) + +/** + \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)) + +/** @} */ + +/** + \ingroup 杂项 + \defgroup 触发PendSV + \brief 手动触发PendSV,for 中断挂起服务_FLAG。 + \note 在用户中断中,当采用中断挂起服务FLAG队列执行服务时,用户在设置标志位后,
+ 需手动触发PendSV,而后在 pendsv_hook() 中执行服务。 + @{ + */ + +#define iPendSV_Set mPendSV_Set + +/** @} */ +/** @} */ + + +/** @} */ +#endif