Переключение контекста в uC/OS (встроенные системы)
Я хотел бы знать, возможно ли иметь прерывание, заставляющее планировщик переключать контекст для конкретной задачи в ОСРВ. Я работаю с ОС microCOS
Вот задача, которая выполняет сканирование ключей и отправляет символ в почтовый ящик, мне нужно добавить еще несколько функций в этот код, таких как debounce и auto repeat, но мне нужно разобрать механизм триггера, чтобы он работал должным образом.
Я не уверен, как использовать опрос или прерывания для достижения этой цели
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
}
3 ответа
Типичный способ сделать это состоит в том, чтобы иметь задачу обработки клавиатуры, которая имеет цикл, в котором она ожидает семафор. Обработчик прерываний клавиатуры разместит семафор, что приведет к готовности и выполнению задачи обработки.
Планировщик обычно делает это. Это его работа, чтобы знать, когда делать переключение контекста, основываясь на приоритетах процессов / потоков (с учетом планировщика, поддерживающего поток / процесс)
Редактировать:
Причина того, почему это не сделано
Представьте себе, что злоумышленник создает задачу с низким приоритетом, заставляя ЦП переключать контекст (с задачи с более высоким приоритетом) на выполнение некоторой вредоносной нагрузки
Вы должны использовать доступный совместимый с прерываниями (то есть неблокирующий) механизм IPC для сигнализации о задаче. Самый простой способ обслуживания клавиатуры - ISR поместить код клавиши в очередь. Любая задача, требующая ввода пользователя, будет считываться из этой очереди.
В качестве альтернативы вы можете просто сделать ISR увеличивающим счетный семафор и отложить декодирование клавиатуры на задачу, которая может затем поместить символы в очередь, которая может быть прочитана любой задачей, читающей пользовательский ввод. Это может быть предпочтительным, если время декодирования является длительным или переменным.
В частности, в uC/OS-II ISR, который требует запуска планировщика, должен использовать вызовы OSIntEnter() и OSIntExit(). Именно OSIntExit() заставляет планировщик работать, когда завершается последнее вложенное прерывание. Затем задачи будут запланированы в соответствии с политикой планирования. Невозможно обойти политику, чтобы заставить конкретную задачу работать против политики планирования, и вы не должны этого хотеть! Если необходимо выполнить определенную задачу, сделайте ее наивысшим приоритетом.
Обычно функции пролога / эпилога ISR требуются только для тех ISR, которые выполняют вызовы ОС, поскольку такие, которые не вызывают запуск планировщика.