Переключение контекста в 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, которые выполняют вызовы ОС, поскольку такие, которые не вызывают запуск планировщика.

Другие вопросы по тегам