我想知道是否可能让中断强制调度程序在RTOS中将上下文切换到特定任务。我正在使用microCOS OS
这是执行密钥扫描并将字符发布到邮箱的任务,我需要为这段代码添加更多功能,如去抖动和自动重复,但我需要整理一个触发机制,使其正常工作。
我不知道如何使用轮询或中断来完成这个
static void AppTaskKeyscan (void *p_arg)
{
CPU_INT08U debouncing = 1;
CPU_INT16U key;
key_t button={0,0,0};
(void)p_arg;
while (DEF_TRUE)
{
static CPU_INT08U pattern;
key=P10;
OSTimeDlyHMSM(0, 0, 0, 50);
P10=0x0E;
if ((pattern=P10)==0xee)
{button.data='1', button.live=1;}
else if (pattern==0xde)
{button.data='4', button.live=1;}
else if (pattern==0xbe)
{button.data='7', button.live=1;}
else if (pattern==0x7e)
{button.data='*', button.live=1;}
else
{
P10=0x0d;
if ((pattern=P10)==0xed)
{button.data='2', button.live=1;}
else if (pattern==0xdd)
{button.data='5', button.live=1;}
else if (pattern==0xbd)
{button.data='8', button.live=1;}
else if (pattern==0x7d)
{button.data='0', button.live=1;}
else
{
P10=0x0b;
if ((pattern=P10)==0xeb)
{button.data='3', button.live=1;}
else if (pattern==0xdb)
{button.data='6', button.live=1;}
else if (pattern==0xbb)
{button.data='9', button.live=1;}
else if (pattern==0x7b)
{button.data='#', button.live=1;}
else
{
P10=0x07;
if ((pattern=P10)==0xe7)
{button.data='A', button.live=1;}
else if (pattern==0xd7)
{button.data='B', button.live=1;}
else if (pattern==0xb7)
{button.data='C', button.live=1;}
else if (pattern==0x77)
{button.data='D', button.live=1;}
else
button.live=0;
}
}
}
P10=pattern;
if (button.live==0)
OSTimeDlyHMSM(0, 0, 0, 50);
else
{
if (P10==pattern)
OSTimeDlyHMSM(0, 0, 0, 50);
else
button.live=0;
}
P10=0x00;
if (button.live) //if button live, set unread flag to 1 and start count down
{
button.unread=1;
}
if(button.unread&&button.data!='X')
{
key=button.data;
OSMboxPost(KeyMbox, (void *) &key);
button.live=0;
button.unread=0;
}
OSTimeDlyHMSM(0, 0, 0, 200);
} // End of While
}
实现这一点的典型方法是让一个键盘处理任务有一个依赖信号量的循环。键盘中断处理程序将发布信号量,这将导致处理任务准备就绪并执行。
调度程序通常会执行此操作。它的工作是根据进程/线程(给定线程/进程感知调度器)的优先级来知道何时进行上下文切换
编辑:
为什么不这样做的原因
想象一下,一个入侵者生成一个低优先级任务,迫使CPU上下文切换(从更高优先级的任务)到执行一些恶意的有效负载
您必须使用可用的中断兼容(即非阻塞)IPC机制来发出任务信号。维护键盘的最简单方法是ISR将键代码放入队列中。任何需要用户输入的任务都将从此队列中读取。
或者,您可以简单地让ISR增加计数信号量,并将键盘解码推迟到任务,然后将字符放入队列中,任何读取用户输入的任务都可以读取这些字符。如果解码很长或执行时间可变,则这可能是优选的。
特别是在uC/OS-II中,需要运行调度程序的ISR必须使用OSIntEnter()和OSIntExit()调用。OSIntExit()使调度程序在最后一个嵌套中断完成时运行。然后将根据调度策略对任务进行调度。不可能为了强制特定任务按照计划策略运行而绕过该策略,也不应该这样做!如果必须运行特定任务,请将其设置为最高优先级。
通常,ISR序言/尾声函数仅用于进行OS调用的ISR,因为不进行操作系统调用不会导致调度程序需要运行。