Компоненты и технологии • №2 '2011 компоненты


*pxHigherPriorityTaskWoken



Pdf көрінісі
бет63/129
Дата28.09.2023
өлшемі4.1 Mb.
#478975
1   ...   59   60   61   62   63   64   65   66   ...   129
Kurniz

*pxHigherPriorityTaskWoken останется без 
изменений.
Значение *pxHigherPriorityTaskWoken
необходимо отслеживать для того, чтобы 
«вручную» выполнить переключение контекста 
задачи в конце обработчика прерывания, если 
в результате выдачи семафора была разблоки-
рована более высокоприоритетная задача. Если 
этого не сделать, то после выполнения обра-
ботчика прерывания выполнение продолжит 
та задача, выполнение которой были прервано 
этим прерыванием (рис. 3). Ничего «страшно-
го» в этом случае не произойдет: текущая за-
дача будет выполняться до истечения текущего 
кванта времени, после чего планировщик вы-
полнит переключение контекста (которое он 
выполняет каждый системный квант), и управ-
ление получит более высокоприоритетная за-
дача (рис. 3а). Единственное, что пострадает, — 
рис. 3. Результат вызова xSemaphoreGiveFromISR():
а) без принудительного переключения контекста; б) с принудительным переключением контекста
а
б


26
КОМПОНЕНТЫ И ТЕХНОЛОГИИ • № 7 '2011
микроконтроллеры
это время реакции системы на прерывание, ко-
торое может составлять до одного системного 
кванта: величина dT на рис. 3.
Далее в учебной программе № 1 будет 
приведен пример использования значения 
*pxHigherPriorityTaskWoken для принуди-
тельного переключения контекста.
В случае использования API-функции 
xSemaphoreGive() переключение контекста 
происходит автоматически, и нет необходи-
мости в его принудительном переключении.
Рассмотрим учебную программу № 1, в ко-
торой продемонстрировано использование 
двоичного семафора для синхронизации 
прерывания и задачи-обработчика этого пре-
рывания:
#include
#include
#include
#include
#include “FreeRTOS.h”
#include “task.h”
#include “semphr.h”
#include “portasm.h”
/* Двоичный семафор – глобальная переменная */
xSemaphoreHandle xBinarySemaphore;
/*-----------------------------------------------------------*/
/* Периодическая задача */
static void vPeriodicTask(void *pvParameters) {
for (;;) {
* Эта задача используется только с целью генерации 
прерывания каждые 500 мс */
vTaskDelay(500 / portTICK_RATE_MS);
/* Сгенерировать прерывание. 
Вывести сообщение до этого и после. */
puts(“Periodic task - About to generate an interrupt.\r\n”);
__asm {int 0x82} /* Сгенерировать прерывание MS-DOS */
puts(“Periodic task - Interrupt generated.\r\n\r\n\r\n”);
}
}
/*-----------------------------------------------------------*/
/* Обработчик прерывания */
static void __interrupt __far vExampleInterruptHandler( void )
{
static portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
/* Отдать семафор задаче-обработчику */
x S e m a p h o r e G i v e F r o m I S R ( x B i n a r y S e m a p h o r e , 
&xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken == pdTRUE )
{
/* Это разблокирует задачу-обработчик. При этом 
приоритет задачи-обработчика выше приоритета 
выполняющейся в данный момент периодической 
задачи. Поэтому переключаем контекст 
принудительно – так мы добьемся того, что после 
выполнения обработчика прерывания управление 
получит задача-обработчик.*/
/* Макрос, выполняющий переключение контекста.
* На других платформах имя макроса может быть другое! */
portSWITCH_CONTEXT();
}
}
/*-----------------------------------------------------------*/
/* Задача-обработчик */
static void vHandlerTask(void *pvParameters) {
/* Как и большинство задач, реализована как бесконечный цикл */
for (;;) {
/* Реализовано ожидание события с помощью двоичного 
семафора. Семафор после создания становится 
доступен (так, как будто его кто-то отдал). 
Поэтому сразу после запуска планировщика задача 
захватит его. Второй раз сделать это ей не удастся, 
и она будет ожидать, находясь в блокированном 
состоянии, пока семафор не отдаст обработчик 
прерывания. Время ожидания задано равным 
бесконечности, поэтому нет необходимости проверять 
возвращаемое функцией xSemaphoreTake() значение. */
xSemaphoreTake(xBinarySemaphore, portMAX_DELAY);
/* Если программа “дошла” до этого места, значит, 
семафор был успешно захвачен.
Обработка события, связанного с семафором.
В нашем случае – индикация на дисплей. */
puts(“Handler task - Processing event.\r\n”);
}
}
/*-----------------------------------------------------------*/
/* Точка входа. С функции main() начнется выполнение 
программы. */
int main(void) {
/* Перед использованием семафор необходимо создать. */
vSemaphoreCreateBinary(xBinarySemaphore);
/* Связать прерывание MS-DOS с обработчиком прерывания 
vExampleInterruptHandler(). */
_dos_setvect(0x82, vExampleInterruptHandler);
/* Если семафор успешно создан */
if (xBinarySemaphore != NULL) {
/* Создать задачу-обработчик, которая будет 
синхронизирована с прерыванием.
Приоритет задачи-обработчика выше, 
чем у периодической задачи. */
xTaskCreate(vHandlerTask, “Handler”, 1000, NULL, 3, NULL);
/* Создать периодическую задачу, которая будет
генерировать прерывание с некоторым интервалом. 
Ее приоритет – ниже, чем у задачи-обработчика. */
xTaskCreate(vPeriodicTask, “Periodic”, 1000, NULL, 1, NULL);
/* Запуск планировщика. */
vTaskStartScheduler();
}
/* При нормальном выполнении программа до этого места 
“не дойдет” */
for (;;)
;
}
В демонстрационных целях использовано 
не аппаратное, а программное прерывание 
MS-DOS, которое «вручную» вызывается 
из служебной периодической задачи каждые 
500 мс. Заметьте, что сообщение на дисплей 
выводится как до генерации прерывания, так 
и после него, что позволяет проследить по-
следовательность выполнения задач (рис. 4).
Следует обратить внимание на использо-
вание параметра xHigherPriorityTaskWoken 
в API-функции xSemaphoreGiveFromISR()
До вызова функции ему присваивается значе-
ние pdFALSE, а после вызова — проверяется 
на равенство pdTRUE. Таким образом отсле-
живается необходимость принудительного 
переключения контекста. В данной учебной 
программе такая необходимость возникает 
каждый раз, так как в системе постоянно на-
ходится более высокоприоритетная задача-
обработчик, которая ожидает возможности 
захватить семафор.
Для принудительного переключения кон-
текста служит API-макрос portSWITCH_


Достарыңызбен бөлісу:
1   ...   59   60   61   62   63   64   65   66   ...   129




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет