/**************************************************************************//** * @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 /** @} */ /** @} */