Переключение контекста в uC / OS (встроенные системы) - PullRequest
2 голосов
/ 05 января 2012

Я хотел бы знать, возможно ли прерывание, заставляющее планировщик переключать контекст для конкретной задачи в ОСРВ. Я работаю с microCOS OS

Вот задача, которая выполняет сканирование ключей и отправляет персонажа в почтовый ящик, мне нужно добавить некоторые дополнительные функции в этот код, такие как 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 ]

2 голосов
/ 05 января 2012

Типичным способом сделать это было бы иметь задачу обработки клавиатуры, которая имеет цикл, в котором она ожидает семафор. Обработчик прерываний клавиатуры отправит семафор, что приведет к тому, что задача обработки будет готова и выполнена.

0 голосов
/ 08 января 2012

Вы должны использовать доступный совместимый с прерываниями механизм (то есть неблокирующий) IPC для сигнализации о задаче. Самый простой способ обслуживания клавиатуры - ISR поместить код клавиши в очередь. Любая задача, требующая ввода пользователя, будет считываться из этой очереди.

В качестве альтернативы вы можете просто увеличить ISR счетным семафором и отложить декодирование клавиатуры на задачу, которая может затем поместить символы в очередь, которая может быть прочитана любой задачей, читающей пользовательский ввод. Это может быть предпочтительным, если время выполнения является длительным или переменным.

В частности, в uC / OS-II ISR, который требует запуска планировщика, должен использовать вызовы OSIntEnter () и OSIntExit (). Именно OSIntExit () заставляет планировщик работать, когда завершается последнее вложенное прерывание. Затем задачи будут запланированы в соответствии с политикой планирования. Невозможно обойти политику, чтобы заставить конкретную задачу работать против политики планирования, и вы не должны этого хотеть! Если определенная задача должна выполняться, сделайте ее наивысшим приоритетом.

Обычно функции пролога / эпилога ISR требуются только для тех ISR, которые выполняют вызовы ОС, поскольку такие, которые не вызывают запуск планировщика.

0 голосов
/ 05 января 2012

Планировщик обычно делает это. Его работа заключается в том, чтобы знать, когда выполнять переключение контекста в зависимости от приоритетов процессов / потоков (с учетом планировщика, поддерживающего поток / процесс)

Редактировать:

Причина, по которой этого не делается

Представьте себе, что злоумышленник создает задачу с низким приоритетом, заставляя ЦП переключать контекст (от задачи с более высоким приоритетом) до выполнения некоторой вредоносной нагрузки

...