Files
cosyos/System/os_handler.c
零中断延迟的RTOS f83b72b7f0 update CosyOS-II 内核文件.
Signed-off-by: 零中断延迟的RTOS <cosyos@139.com>
2023-11-25 15:57:45 +00:00

780 lines
21 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**************************************************************************//**
* @item CosyOS-II Kernel
* @file os_handler.c
* @brief SysTick_Handler and PendSV_Replacer
* @author 迟凯峰
* @version V1.2.0
* @date 2023.11.25
******************************************************************************/
#include "os_link.h"
#if SYSCFG_DEBUGGING == __ENABLED__
static s_u32_t usedtime[2];
#endif
void SysTick_Handler(void) MCUCFG_SYSTICK_ATTRIBUTE
{
s_tid_t _SYS_REG_ i;
/* 系统滴答时间统计开始 */
#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
static m_tick_t tick_temp;
if(s_taskmgr_binary){
tick_temp = mSysTick_Counter;
}
#endif
/* 软件RTC */
#if SYSCFG_SOFTRTC == __ENABLED__
if(true){
static
#if SYSCFG_SYSTICKCYCLE > 1000000UL / 65536
s_u16_t
#else
s_u32_t
#endif
_SYS_MEM_ counter = 0;
if(counter < 1000000UL / SYSCFG_SYSTICKCYCLE - 1) counter++;
else{
counter = 0;
s_sign_every.second = true;
if(s_rtc[0][5] < 59) s_rtc[0][5]++;
else{
s_rtc[0][5] = 0;
s_sign_every.minute = true;
if(s_rtc[0][4] < 59) s_rtc[0][4]++;
else{
s_rtc[0][4] = 0;
s_sign_every.hour = true;
if(s_rtc[0][3] < 23) s_rtc[0][3]++;
else{
s_rtc[0][3] = 0;
s_sign_every.day = true;
if(s_rtc[0][6] < 7) s_rtc[0][6]++;
else s_rtc[0][6] = 1;
if(s_rtc[0][2] < (s_rtc[0][1] == 2 ? s_month2day : s_month0day[s_rtc[0][1]])) s_rtc[0][2]++;
else{
s_rtc[0][2] = 1;
s_sign_every.month = true;
if(s_rtc[0][1] < 12) s_rtc[0][1]++;
else{
s_rtc[0][1] = 1;
s_sign_every.year = true;
if(s_rtc[0][0] < 99) s_rtc[0][0]++;
else s_rtc[0][0] = 0;
}
}
}
}
}
}
tUpdateCopy_GVar(s_memcpy(s_rtc[1], s_rtc[0], sizeof(s_rtc[0])));
}
#endif
/* 滴答钩子 */
#if SYSCFG_TICKHOOK == __ENABLED__
tick_hook();
#endif
/* 定时中断 */
#if OS_TIMINTTOTAL
i = OS_TIMINTTOTAL;
while(i--){
if(s_timint_loader[i] && s_timint_loader[i] < ~0){
s_timint_loader[i]--;
if(!s_timint_loader[i]){
if(s_timint_hookortask[i]){
sResumeTask_TimInt(i);
}
else{
(*s_timint_handle[i]->hook)();
}
if(s_timint_autoreload[i]){
s_timint_loader[i] = s_timint_reload[i];
}
}
}
}
#endif
/* 定时查询 */
#if OS_TIMQRYTOTAL
i = OS_TIMQRYTOTAL;
while(i--){
if(s_timqry_loader[i] && s_timqry_loader[i] < ~0){
s_timqry_loader[i]--;
}
if(!s_timqry_loader[i]){
if((*s_timqry_handle[i]->event)()){
if(s_timqry_hookortask[i]){
sResumeTask_TimQry(i);
}
else{
(*s_timqry_handle[i]->hook)();
}
if(s_timqry_autoreload[i]){
s_timqry_loader[i] = s_timqry_reload[i];
}
else{
s_timqry_loader[i] = ~0;
}
}
}
}
#endif
/* 延时定时器 */
i = OS_TASKTOTAL;
do{
if(s_delay_loader[i] && s_delay_loader[i] < ~0){
s_delay_loader[i]--;
}
}while(--i);
/* 时间片滴答计数 */
s_tick_counter++;
/* 安全运行时 */
#if SYSCFG_SAFERUNTIME == __ENABLED__
if(s_task_current != NULL && s_task_current->pri && s_task_current->saferuntime){
s_task_current->counter++;
if(s_task_current->counter > 1UL * s_task_current->saferuntime * OS_TIMESHARING){
s_task_current->status = OS_STATUS_OVERTIME;
s_sign_timeout[s_task_current->tid] = true;
#if SYSCFG_DEBUGGING == __ENABLED__
s_alarm.timedout_saferuntime = true;
#endif
}
}
#endif
/* 任务管理器相关 */
#if SYSCFG_DEBUGGING == __ENABLED__
if(s_taskmgr_binary){
usedtime[0]++; /* CPU使用时间计数 */
#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
mSysTick_Counting; /* 系统滴答时间统计 */
#endif
}
#endif
/* 触发任务调度(定时调度)*/
if(!s_sign_return){
s_sign_scheduling = true;
mPendSV_Set;
}
}
/* 任务节点 */
#define node_head task_node[0] /* 头节点 */
#define node_midd task_node[1] /* 中间节点 */
#define node_tail task_node[2] /* 尾节点 */
#define node_curr node_buff[0] /* 当前节点 */
#define node_news node_buff[1] /* 新节点 */
#define node_temp node_buff[2] /* 缓存节点 */
#define node_last node_curr->last /* 上一节点 */
#define node_next node_curr->next /* 下一节点 */
/* 初始化任务队列CosyOS的任务队列为双向循环链表*/
#define init_taskqueue \
node_head = node_midd = node_tail = \
node_news->last = node_news->next = node_news
#define init_node_head node_curr = node_head /* 初始化 头节点 */
#define init_node_midd node_curr = node_midd /* 初始化中间节点 */
#define move_forward node_curr = node_last /* 当前节点前移 */
#define move_backward node_curr = node_next /* 当前节点后移 */
/* 移除节点(从任务队列中移除当前节点)*/
#define node_remove \
do{ \
node_last->next = node_next; \
node_next->last = node_last; \
if(node_curr == node_head){ \
node_head = node_next; \
} \
task_queue_len--; \
}while(false)
/* 插入方向 */
#define forward 0x01 /* 向前 */
#define voidward 0x00 /* 空 */
#define backward 0xFF /* 向后 */
/* 前插(新节点插入当前节点之前)*/
#define insert_forward \
do{ \
node_news->next = node_curr; \
node_news->last = node_last; \
node_last->next = node_news; \
node_last = node_news; \
if(node_curr == node_head){ \
node_head = node_news; \
} \
switch(insert_direction){ \
case forward: \
insert_direction = voidward; \
node_midd = node_midd->last; \
break; \
case voidward: \
insert_direction = forward; \
break; \
case backward: \
insert_direction = voidward; \
break; \
} \
}while(false)
/* 后插(新节点插入当前节点之后)*/
#define insert_backward \
do{ \
node_news->last = node_curr; \
node_news->next = node_next; \
node_next->last = node_news; \
node_next = node_news; \
if(node_curr == node_tail){ \
node_tail = node_news; \
} \
switch(insert_direction){ \
case forward: \
insert_direction = voidward; \
break; \
case voidward: \
insert_direction = backward; \
break; \
case backward: \
insert_direction = voidward; \
node_midd = node_midd->next; \
break; \
} \
}while(false)
/* 抢占式调度 or 时间片轮转调度 */
#define preemptive_or_rotate \
do{ \
if(!rotate_f){ \
node_news = node_curr; \
if(s_task_current == NULL || node_news->pri != s_task_current->pri){ \
goto __TASK_SCHEDULING; \
} \
rotate_f = true; \
} \
}while(false)
/* 入栈监控 */
#if MCUCFG_TASKSTACK_REALLOC == __DISABLED__
#if SYSCFG_DEBUGGING == __ENABLED__
#define sPUSH_Monitor \
do{ \
if(s_task_current->stacksize < stacklen){ \
s_task_current->status = OS_STATUS_STOPPED_TSOF; \
s_fault.overflow_taskstack = true; \
} \
else{ \
push_f = true; \
} \
}while(false)
#else
#define sPUSH_Monitor push_f = true
#endif
#else
#if SYSCFG_DEBUGGING == __ENABLED__
#define sPUSH_Monitor_01 s_task_current->realloc = true; \
s_alarm.realloc_taskstack = true
#define sPUSH_Monitor_02 s_fault.reallocfailed_taskstack = true
#else
#define sPUSH_Monitor_01 do{}while(false)
#define sPUSH_Monitor_02 do{}while(false)
#endif
#define sPUSH_Monitor \
do{ \
if(s_task_current->stacksize < stacklen){ \
s_task_current->stacksize = stacklen + MCUCFG_TASKSTACKREALLOC_INC; \
s_free(s_task_current->bsp); \
s_task_current->bsp = NULL; \
s_task_current->bsp = (s_u8_t *)s_malloc(s_task_current->stacksize); \
if(s_task_current->bsp != NULL){ \
push_f = true; \
sPUSH_Monitor_01; \
} \
else{ \
s_task_current->status = OS_STATUS_STOPPED_TSRF; \
sPUSH_Monitor_02; \
} \
} \
else{ \
push_f = true; \
} \
}while(false)
#endif
#if SYSCFG_MCUCORE == 80251
#pragma functions(static)
#endif
void PendSV_Replacer(void) MCUCFG_PENDSV_ATTRIBUTE
{
/* 中断挂起服务 */
{
mPendSV_Entry;
}
/* 中断服务钩子 */
{
#if SYSCFG_PENDSVHOOK == __ENABLED__
pendsv_hook();
#endif
}
/* 更新全局变量副本 */
{
#if SYSCFG_SOFTRTC == __ENABLED__ || SYSCFG_GVARHOOK == __ENABLED__
s_sign_updatecopy = true;
#if SYSCFG_SOFTRTC == __ENABLED__
if(s_rtc_binary){
s_rtc_binary = false;
s_memcpy(s_rtc[1], s_rtc[0], sizeof(s_rtc[0]));
}
#endif
#if SYSCFG_GVARHOOK == __ENABLED__
gvar_hook();
#endif
s_sign_updatecopy = false;
#endif
}
/* 任务调度 */
if(s_sign_scheduling)
{
static s_u8_t _SYS_MEM_ task_queue_len = 0;
static s_u8_t _SYS_MEM_ insert_direction = 0;
static s_tasknode_tsp _SYS_MEM_ task_node[3] = {NULL, NULL, NULL};
s_tasknode_tsp _SYS_REG_ node_buff[3];
#if SYSCFG_DEBUGGING == __ENABLED__
m_tick_t _SYS_REG_ counter;
#endif
m_bit_t push_f = false;
m_bit_t rotate_f = false;
/* 调度初始化 */
mScheduler_INIT;
/* 启动任务 */
if(s_task_starter != NULL){
if(task_queue_len < OS_TASKQUEUELEN_MAX){
/* 静态创建 */
#if SYSCFG_TASKCREATEMODE == __STATIC__
node_news = s_task_starter;
if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
#if SYSCFG_DEBUGGING == __ENABLED__
s_fault.failed_startuptask = true;
s_fault.overflow_taskstack = true;
#endif
s_startup_code = OS_ECODE_OVERFLOW_TASKSTACK;
goto __STARTUP_END;
}
else{
mTaskStack_INIT;
if(node_news->oldpri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){
node_news->pri = node_news->oldpri;
}
else{
node_news->pri = SYSCFG_TASKPRIORITY - 2;
#if SYSCFG_DEBUGGING == __ENABLED__
s_alarm.outrange_taskpriority = true;
#endif
}
node_news->blocktype = 0;
node_news->ptr = NULL;
#if SYSCFG_DEBUGGING == __ENABLED__
node_news->usedtime[0] = 0;
node_news->usedtime[1] = 0;
node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
#endif
node_news->counter = 0;
s_delay_loader[node_news->tid] = 0;
}
/* 平衡创建 */
#elif SYSCFG_TASKCREATEMODE == __BALANCE__
node_news = s_task_starter;
if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
node_news->stacksize = MCUCFG_BASICSTACKSIZE;
#if SYSCFG_DEBUGGING == __ENABLED__
node_news->realloc = true;
#endif
}
#if SYSCFG_DEBUGGING == __ENABLED__
else{
node_news->realloc = false;
}
#endif
node_news->bsp = NULL;
node_news->bsp = (s_u8_t *)s_malloc(node_news->stacksize);
if(node_news->bsp != NULL){
mTaskStack_INIT;
if(node_news->oldpri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){
node_news->pri = node_news->oldpri;
}
else{
node_news->pri = SYSCFG_TASKPRIORITY - 2;
#if SYSCFG_DEBUGGING == __ENABLED__
s_alarm.outrange_taskpriority = true;
#endif
}
node_news->blocktype = 0;
node_news->ptr = NULL;
#if SYSCFG_DEBUGGING == __ENABLED__
node_news->usedtime[0] = 0;
node_news->usedtime[1] = 0;
node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
#endif
node_news->counter = 0;
s_delay_loader[node_news->tid] = 0;
}
else{
#if SYSCFG_DEBUGGING == __ENABLED__
s_fault.failed_startuptask = true;
s_fault.mallocfailed_taskstack = true;
#endif
s_startup_code = OS_ECODE_MALLOCFAIL_TASKSTACK;
goto __STARTUP_END;
}
/* 动态创建 */
#elif SYSCFG_TASKCREATEMODE == __DYNAMIC__
node_news = NULL;
node_news = (s_tasknode_tsp)s_malloc(sizeof(s_tasknode_ts));
if(node_news != NULL){
node_news->stacksize = s_task_starter->stacksize;
if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
node_news->stacksize = MCUCFG_BASICSTACKSIZE;
#if SYSCFG_DEBUGGING == __ENABLED__
node_news->realloc = true;
#endif
}
#if SYSCFG_DEBUGGING == __ENABLED__
else{
node_news->realloc = false;
}
#endif
node_news->bsp = NULL;
node_news->bsp = (s_u8_t *)s_malloc(node_news->stacksize);
if(node_news->bsp != NULL){
mTaskStack_INIT;
node_news->tid = s_task_starter->tid;
if(s_task_starter->oldpri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){
node_news->pri = s_task_starter->oldpri;
}
else{
node_news->pri = SYSCFG_TASKPRIORITY - 2;
#if SYSCFG_DEBUGGING == __ENABLED__
s_alarm.outrange_taskpriority = true;
#endif
}
node_news->status = s_task_status0;
node_news->blocktype = 0;
node_news->ptr = NULL;
#if SYSCFG_DEBUGGING == __ENABLED__
node_news->name = s_task_starter->name;
node_news->usedtime[0] = 0;
node_news->usedtime[1] = 0;
node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
#endif
node_news->saferuntime = s_task_starter->saferuntime;
node_news->counter = 0;
node_news->hand = s_task_starter;
s_task_starter->node = node_news;
s_delay_loader[node_news->tid] = 0;
}
else{
s_free(node_news);
#if SYSCFG_DEBUGGING == __ENABLED__
s_fault.failed_startuptask = true;
s_fault.mallocfailed_taskstack = true;
#endif
s_startup_code = OS_ECODE_MALLOCFAIL_TASKSTACK;
goto __STARTUP_END;
}
}
else{
#if SYSCFG_DEBUGGING == __ENABLED__
s_fault.failed_startuptask = true;
s_fault.mallocfailed_tasknode = true;
#endif
s_startup_code = OS_ECODE_MALLOCFAIL_TASKNODE;
goto __STARTUP_END;
}
#endif
/* 新任务加入任务队列 */
if(!task_queue_len){
init_taskqueue;
}
else{
init_node_midd;
if(node_curr != node_tail && node_news->pri <= node_curr->pri){
do{
move_backward;
}while(node_curr != node_tail && node_news->pri <= node_curr->pri);
}
else if(node_curr != node_head && node_news->pri > node_curr->pri){
do{
move_forward;
}while(node_curr != node_head && node_news->pri > node_curr->pri);
}
if(node_news->pri > node_curr->pri){
insert_forward;
}
else if(node_curr == node_tail && node_curr->pri == 0){
insert_forward;
}
else{
insert_backward;
}
}
task_queue_len++;
s_startup_code = OS_ECODE_NOERROR;
}
else{
#if SYSCFG_DEBUGGING == __ENABLED__
s_fault.failed_startuptask = true;
s_alarm.overflow_taskqueue = true;
#endif
s_startup_code = OS_ECODE_OVERFLOW_TASKQUEUE;
}
__STARTUP_END:
s_task_starter = NULL;
if(s_sign_return) return;
s_task_current->blocktype = s_startup_code;
}
/**
* \brief 任务优先级调整
* \detail 如果任务优先级发生改变,执行服务时已从任务队列中移除并加入到临时链表。
* 在此,从临时链表中依次取出各任务,并根据任务优先级重新加入到任务队列。
*/
if(s_taskpri_tail != NULL){
node_temp = s_taskpri_tail;
do{
node_news = node_temp;
node_temp = node_temp->last;
init_node_midd;
if(node_curr != node_tail && node_news->pri <= node_curr->pri){
do{
move_backward;
}while(node_curr != node_tail && node_news->pri <= node_curr->pri);
}
else if(node_curr != node_head && node_news->pri > node_curr->pri){
do{
move_forward;
}while(node_curr != node_head && node_news->pri > node_curr->pri);
}
if(node_news->pri > node_curr->pri){
insert_forward;
}
else if(node_curr == node_tail && node_curr->pri == 0){
insert_forward;
}
else{
insert_backward;
}
}while(node_temp != NULL);
s_taskpri_tail = NULL;
}
/**
* \brief 查找就绪
* \detail 更新任务状态并同步查找可以运行的、优先级最高的任务。
*/
init_node_head;
while(true){
switch(node_curr->status){
case OS_STATUS_BLOCKED:
if(!s_delay_loader[node_curr->tid]){
node_curr->status = OS_STATUS_READY;
preemptive_or_rotate;
}
else if(node_curr->blocktype != OS_BLOCKED_DELAY){
switch(node_curr->blocktype & 0x0F){
case 1:
if(*(s_u8_t *)node_curr->ptr){
node_curr->status = OS_STATUS_FLOATING;
preemptive_or_rotate;
}
break;
case 2:
if(*(s_u16_t *)node_curr->ptr){
node_curr->status = OS_STATUS_FLOATING;
preemptive_or_rotate;
}
break;
case 4:
if(*(s_u32_t *)node_curr->ptr){
node_curr->status = OS_STATUS_FLOATING;
preemptive_or_rotate;
}
break;
case 0x0F:
if(!*(s_u8_t *)node_curr->ptr){
node_curr->status = OS_STATUS_FLOATING;
preemptive_or_rotate;
}
break;
}
}
break;
case OS_STATUS_FLOATING:
if(!s_delay_loader[node_curr->tid]){
node_curr->status = OS_STATUS_READY;
preemptive_or_rotate;
}
else{
switch(node_curr->blocktype & 0x0F){
case 1:
if(*(s_u8_t *)node_curr->ptr){
preemptive_or_rotate;
}
else{
node_curr->status = OS_STATUS_BLOCKED;
}
break;
case 2:
if(*(s_u16_t *)node_curr->ptr){
preemptive_or_rotate;
}
else{
node_curr->status = OS_STATUS_BLOCKED;
}
break;
case 4:
if(*(s_u32_t *)node_curr->ptr){
preemptive_or_rotate;
}
else{
node_curr->status = OS_STATUS_BLOCKED;
}
break;
case 0x0F:
if(!*(s_u8_t *)node_curr->ptr){
preemptive_or_rotate;
}
else{
node_curr->status = OS_STATUS_BLOCKED;
}
break;
}
}
break;
case OS_STATUS_READY:
preemptive_or_rotate;
break;
case OS_STATUS_DELETED:
if(node_curr != s_task_current){
node_remove;
#if SYSCFG_TASKCREATEMODE != __STATIC__
s_free(node_curr->bsp);
#endif
#if SYSCFG_TASKCREATEMODE == __DYNAMIC__
((s_taskhand_tsp)node_curr->hand)->node = NULL;
s_free(node_curr);
#endif
}
break;
#if SYSCFG_SAFERUNTIME == __ENABLED__
case OS_STATUS_OVERTIME:
if(!s_sign_timeout[node_curr->tid]) {
node_curr->status = OS_STATUS_READY;
preemptive_or_rotate;
}
break;
#endif
}
move_backward;
/* 当前任务优先级组查询完毕 -> 当前任务预处理 */
if(rotate_f && node_curr->pri != s_task_current->pri){
goto __TASKING_PREPROCESS;
}
}
/* 准备任务调度(首次任务调度 -> 新任务预处理)*/
__TASK_SCHEDULING:
if(s_task_current == NULL){
goto __NEWTASK_PREPROCESS;
}
/* 当前任务预处理 */
__TASKING_PREPROCESS:{
mTaskStack_LEN;
/* 每调度监控(假定入栈)*/
#if SYSCFG_DEBUGGING == __ENABLED__
if(s_task_current->stacklen_max < stacklen){
s_task_current->stacklen_max = stacklen;
if(s_task_current->stacksize < stacklen){
s_alarm.overflow_taskstack_future = true;
}
}
#endif
}
/* 开始任务调度 */
if(true){
/* 1、新任务与当前任务优先级不同 -> 当前任务后处理 */
if(node_news->pri != s_task_current->pri){
goto __TASKING_POSTPROCESS;
}
/* 2、当前任务可以运行 && 时间片未到期 -> 返回 */
if(s_tick_counter < OS_TIMESHARING && s_task_current->status <= OS_STATUS_FLOATING){
s_task_current->status = OS_STATUS_READY;
return;
}
/* 3、当前任务不可运行 || 时间片已到期 -> 时间片轮转调度 */
node_curr = s_task_current;
move_backward;
while(node_last != node_tail && node_last->pri == node_curr->pri){
if(node_curr->status > OS_STATUS_FLOATING){
move_backward;
}
else{
node_news = node_curr;
goto __TASKING_POSTPROCESS;
}
}
/* 4、新任务仍为当前任务说明时间片已到期 -> 返回 */
if(node_news == s_task_current){
s_task_current->status = OS_STATUS_READY;
s_tick_counter = 0;
return;
}
}
/* 当前任务后处理 */
__TASKING_POSTPROCESS:{
if(s_task_current->status < OS_STATUS_STOPPED){
sPUSH_Monitor;
}
else if(s_task_current->status == OS_STATUS_DELETED){
node_curr = s_task_current;
node_remove;
#if SYSCFG_TASKCREATEMODE != __STATIC__
s_free(node_curr->bsp);
#endif
#if SYSCFG_TASKCREATEMODE == __DYNAMIC__
((s_taskhand_tsp)node_curr->hand)->node = NULL;
s_free(node_curr);
#endif
}
}
/* 新任务预处理 */
__NEWTASK_PREPROCESS:{
node_news->status = OS_STATUS_READY;
s_tick_counter = 0;
#if SYSCFG_DEBUGGING == __ENABLED__
if(s_taskmgr_binary) counter = mSysTick_Counter;
#endif
}
/* 当前任务入栈 */
if(push_f){
#if SYSCFG_SAFERUNTIME == __ENABLED__
if(s_task_current->pri > node_news->pri){
s_task_current->counter = 0;
}
#endif
#if SYSCFG_DEBUGGING == __ENABLED__
if(s_taskmgr_binary) mUsedTime_END;
#endif
mTaskStack_PUSH;
}
/* 新任务出栈 */
if(true){
#if SYSCFG_DEBUGGING == __ENABLED__
if(s_taskmgr_binary) mUsedTime_INIT;
#endif
mTaskStack_POP;
}
}
}