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



Pdf көрінісі
бет110/129
Дата28.09.2023
өлшемі4.1 Mb.
#478975
1   ...   106   107   108   109   110   111   112   113   ...   129
Kurniz

 учебная программа № 2
Рассмотрим учебную программу № 2, в ко-
торой продемонстрирован обмен инфор-
мацией между сопрограммами и обработ-
чиками прерываний. В программе имеются 
2 обработчика прерывания и 2 сопрограммы, 
которые обмениваются друг с другом сооб-
щениями, помещая их в очередь (в програм-
ме созданы 3 очереди). В демонстрационных 
целях в качестве прерываний используются 
программные прерывания MS-DOS, а слу-
жебная сопрограмма выполняет вызов этих 
прерываний.
В графическом виде обмен информацией 
в учебной программе № 2 показан на рис. 5.
рис. 5. Обмен сообщениями между сопрограммами и обработчиками прерываний в учебной программе № 2


103
КОМПОНЕНТЫ И ТЕХНОЛОГИИ • № 9 '2011
www.kite.ru
компоненты
микроконтроллеры
Текст учебной программы № 2:
#include
#include
#include
#include
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "portasm.h"
#include "croutine.h"
/* Дескрипторы очередей — глобальные переменные */
xQueueHandle xQueue1;
xQueueHandle xQueue2;
xQueueHandle xQueue3;
/* Служебная сопрограмма. Вызывает программные прерывания.
* Приоритет = 1.*/
void vIntCoRoutine( xCoRoutineHandle xHandle, unsigned 
portBASE_TYPE uxIndex ) {
crSTART( xHandle );
for(;;) {
/* Эта инструкция сгенерирует прерывание № 1. */
__asm {int 0x83}
/* Заблокировать сопрограмму на 500 мс */
crDELAY(xHandle, 500);
/* Эта инструкция сгенерирует прерывание № 2. */
__asm {int 0x82}
/* Заблокировать сопрограмму на 500 мс */
crDELAY(xHandle, 500);
}
crEND();
}
/*-----------------------------------------------------------*/
/* Функция, реализующая Сопрограмму № 1 и Сопрограмму № 2,
* то есть будет создано два экземпляра этой сопрограммы. */
void vTransferCoRoutine( xCoRoutineHandle xHandle, unsigned 
portBASE_TYPE uxIndex ) {
static long i;
portBASE_TYPE xResult;
crSTART( xHandle );
for(;;) {
/* Если выполняется Сопрограмма № 1*/
if (uxIndex == 1) {
/* Получить сообщение из Очереди № 1 от Прерывания № 1.
* Если очередь пуста — заблокироваться на время 
portMAX_DELAY квантов */
crQUEUE_RECEIVE(
xHandle,
xQueue1,
(void *)&i,
portMAX_DELAY,
&xResult);
if (xResult == pdTRUE) {
puts("CoRoutine 1 has received a message from Interrupt 1.");
}
/* Передать это же сообщение в Очередь № 2 Сопрограмме № 2 */
crQUEUE_SEND(
xHandle,
xQueue2,
(void *)&i,
portMAX_DELAY ,
&xResult);
if (xResult == pdTRUE) {
puts("CoRoutine 1 has sent a message to CoRoutine 2.");
}
}
/* Если выполняется Сопрограмма № 2 */
else if (uxIndex == 2) {
/* Получить сообщение из Очереди № 2 от Сопрограммы № 1.
* Если очередь пуста — заблокироваться на время 
portMAX_DELAY квантов. */
crQUEUE_RECEIVE(
xHandle,
xQueue2,
(void *)&i,
portMAX_DELAY,
&xResult);
if (xResult == pdTRUE) {
puts("CoRoutine 2 has received a message from CoRoutine 1.");
}
/* Передать это же сообщение в обработчик прерывания 
№ 2 через Очередь № 3. */
crQUEUE_SEND(
xHandle,
xQueue3,
(void *)&i,
portMAX_DELAY ,
&xResult);
if (xResult == pdTRUE) {
puts("CoRoutine 2 has sent a message to Interrupt 1.");
}
}
}
crEND();
}
/*-----------------------------------------------------------*/
/* Обработчик Прерывания 1*/
static void __interrupt __far vSendInterruptHandler( void )
{
static unsigned long ulNumberToSend;
if (crQUEUE_SEND_FROM_ISR( xQueue1,
&ulNumberToSend,
pdFALSE ) == pdPASS) {
puts("Interrupt 1 has sent a message!");
}
}
/*-----------------------------------------------------------*/
/* Обработчик Прерывания 2*/
static void __interrupt __far vReceiveInterruptHandler( void )
{
static portBASE_TYPE pxCoRoutineWoken ;
static unsigned long ulReceivedNumber;
/* Аргумент API-функции crQUEUE_RECEIVE_FROM_ISR(), 
который устанавливается в pdTRUE,
если операция с очередью разблокирует более 
высокоприоритетную сопрограмму.
Перед вызовом crQUEUE_RECEIVE_FROM_ISR() 
следует установить в pdFALSE. */
pxCoRoutineWoken = pdFALSE;
if (crQUEUE_RECEIVE_FROM_ISR(
xQueue3,
&ulReceivedNumber,
&pxCoRoutineWoken ) == pdPASS) {
puts("Interrupt 2 has received a message!\n");
}
/* Проверить, нуждается ли в разблокировке более 
* высокоприоритетная сопрограмма,
* чем та, что была прервана прерыванием. */
if( pxCoRoutineWoken == pdTRUE ) {
/* В текущей версии FreeRTOS нет средств для корректного
* переключения на другую сопрограмму из тела обработчика 
* прерывания! */
}
}
/*-----------------------------------------------------------*/
/* Точка входа. С функции main() начнется выполнение про-
граммы. */
int main(void) {
/* Создать 3 очереди для хранения элементов типа unsigned long.
* Длина каждой очереди — 3 элемента. */
xQueue1 = xQueueCreate(3, sizeof(unsigned long));
xQueue2 = xQueueCreate(3, sizeof(unsigned long));
xQueue3 = xQueueCreate(3, sizeof(unsigned long));
/* Создать служебную сопрограмму.
* Приоритет = 1. */
xCoRoutineCreate(vIntCoRoutine, 1, 0);
/* Создать сопрограммы № 1 и № 2 как экземпляры одной 
сопрограммы.
* Экземпляры различаются целочисленным параметром,
* который передается сопрограмме при ее создании.
* Приоритет обеих сопрограмм = 2. */
xCoRoutineCreate(vTransferCoRoutine, 2, 1);
xCoRoutineCreate(vTransferCoRoutine, 2, 2);
/* Связать прерывания MS-DOS с соответствующими об-
работчиками прерываний. */
_dos_setvect(0x82, vReceiveInterruptHandler);
_dos_setvect(0x83, vSendInterruptHandler);
/* Запуск планировщика. */
vTaskStartScheduler();
/* При нормальном выполнении программа до этого места 
"не дойдет" */
for (;;) ;
}
/*-----------------------------------------------------------*/
/* Функция, реализующая задачу Бездействие,
должна присутствовать в программе и содержать вызов 
vCoRoutineSchedule() */
void vApplicationIdleHook(void) {
/* Так как задача Бездействие не выполняет других действий,
то вызов vCoRoutineSchedule() размещен внутри бесконеч-
ного цикла.*/
for (;;) {
vCoRoutineSchedule();
}
}
По результатам работы учебной програм-
мы (рис. 6) можно проследить, как сообщение 
генерируется сначала в Прерывании № 1, за-
тем передается в Сопрограмму № 1 и далее — 
в Сопрограмму № 2, которая в свою очередь 
отсылает сообщение Прерыванию № 2.


Достарыңызбен бөлісу:
1   ...   106   107   108   109   110   111   112   113   ...   129




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

    Басты бет