- •Предисловие
- •Системы реального времени
- •1.1. Особенности систем реального времени
- •2.Аппаратурная среда систем реального времени летательных аппаратов.
- •1.3. Требования к срв ла
- •1.4. Передача данных
- •1.4.1. Синхронная передача данных
- •1.4.2. Асинхронная передача данных
- •1.5. Концепция процесса, потока
- •3.Архитектуры ос рв и ядро ос рв
- •1.6.1. Ядро ос рв
- •1.6.2. Планирование заданий и загрузки процессоров
- •4.Механизмы синхронизации и взаимодействия процессов, потоков
- •1.7.1. Средства синхронизации с помощью таймеров.
- •1.7.2. Синхронизация процессов в Windows 2000, Windows xp с использованием событий
- •1.7.3. Использование семафора для синхронизации работы потоков
- •1.8. Программирование синхронной и асинхронной обработки данных
- •1.8.1. Асинхронная обработка данных
- •1.8.2. Синхронная обработка данных
- •2.1.3. Контрольные вопросы
- •6.Синхронизация потоков с использованием методов «Присоединение», «Барьер», «Мьютекс» и «Блокировки чтения - записи»
- •2.2.1. Порядок выполнения работы
- •2.2.2. Методические указания
- •2.2.3. Задание 1
- •2.2.4. Задание 2
- •2.2.5. Задание 3
- •2.2.6. Синхронизация потоков с использованием мьютексов
- •2.2.7. Задание 4
- •2.2.8. Синхронизация с применением блокировки чтения‑записи.
- •2.2.9. Задание 5
- •2.2.10. Задание 6
- •2.2.11. Контрольные вопросы
- •7.Взаимодействие между процессами с помощью сообщений. Модель «клиент/сервер». Таймеры
- •2.3.1. Порядок выполнения работы
- •2.3.2. Методические указания
- •2.3.3. Задание 7
- •2.3.4. Задание 8
- •2.3.5. Задание 9
- •2.3.6. Задание 10
- •2.4.2. Методические указания
- •2.4.3. Задание 16
- •2.4.4. Задание 17
- •2.4.5. Задание 18
- •2.4.6. Задание 19
- •2.4.7. Задание 20
- •2.4.8. Задание 21
- •2.4.9. Задание 22
- •2.4.15. Контрольные вопросы
- •Библиографический список
- •Оглавление
- •5. Установка ос qnx 48
- •6. Синхронизация потоков с использованием методов «Присоединение», «Барьер», «Мьютекс» и «Блокировки чтения - записи» 59
- •7. Взаимодействие между процессами с помощью сообщений. Модель «клиент/сервер». Таймеры 70
1.8. Программирование синхронной и асинхронной обработки данных
При синхронном обмене данными известно начало и конец информационного пакета. Длина информационного пакета фиксирована. Начало информационного пакета определяется кадровым сигналом FRM.
При асинхронном обмене данными информационные пакеты надо выделять из входного потока информации. Для этого в каждом пакете должен присутствовать заголовок сообщения, с помощью которого можно будет выделить весь пакет данных.
1.8.1. Асинхронная обработка данных
В качестве примера асинхронной обработки приведем разработу драйвера контроллера UARTa.
Контроллер интерфейсов RS-422, RS-485 (контроллер UARTa)
Контроллера интерфейсов RS-422, RS-485 (контроллер UARTа) состоит из: 4 интерфейсов RS-485, 6 интерфейсов RS-422 и разовых команды. Интерфейсы RS-422 настроены на прием и передачу данных. Интерфейсы RS-485 могут в ходе своей работы либо только передавать данные, либо только принимать данные. Настройка интерфейсов RS-485 на режим передачи или приема данных осуществляется с использованием разовых команд.
Для работы каждым из интерфейсов RS-422, RS-485 используются 3 регистра и для приема/передачи данных используется FIFO.
Регистры интерфейсов RS-422, RS-485:
CR (Command register) – командный регистр;
SR (Status Register) – регистр состояния;
MR (Enable Interrupt) – регистр масок прерываний.
Буфер FIFO состоит из 32-х 16 разрядных слов.
Для работы с контроллером UARTa в программном обеспечении вычислителя используется драйвер UARTa 1-го уровня и драйвер UARTa 2-го уроня.
Драйверы UARTа 1 и 2-го уровня реализованы в виде отдельных задач со своими контекстами.
Рисунок 1.8.1 общая схема асинхронной обработки данных контроллера UARTa
Драйвер контроллера UARTa 1-го уровня.
Используется для чтения/записи регистров и буферов FIFO контроллера UARTa. Взаимодействия драйвера и контроллера UARTa осуществляется по SPI. Данные, считанные с FIFO i-го UARTa, записываются в Буфер для чтения данных i-го UARTa.
Данные, предназначенные для записи в FIFO i-го UARTa, считываются с буфера для записи данных и отправляются по шине SPI в контроллер UARTa
Для обмена данными по SPI используется драйвер SPI, который обеспечивает транспортный уровень передачи информации между драйвером UARTa 1-го уровня и контроллером UARTa.
Для простоты изложения
пусть драйвер UARTa 1-го
уровня запускается по таймеру с периодом
.
Структуры данных для работы с драйвером UARTa
#define LENQUART 128 //длина буфера чтения/записи данных i-го UARTa
#define VUART 10 //число UART
Структура данных для обработчика прерывания от таймера драйвера UARTa 1-го уровня
typedef struct __IrqUART{
uint IRQ_UART; //признак наличия прерывания
uint N IRQ_UART; //общее число прерываний
uint FReadyDrvUART; //флаг готовности к работе драйвера UARTa1-го уровня
uint dt; // задержка **
uint ti; //номер i-го такта **
}_IrqUART;
Структура данных для обработки запросов чтения – записи данных с UARTa
#define UART_HANDLER_R 0x80000000 //запрос на чтение данных для i-го UARTa
#define UART_HANDLER_W 0x40000000 //запрос на запись данных для i-го UARTa
typedef struct __UARTInfo{
Uint NUART;//номер UART
Uint attr; //атрибуты
}_UARTInfo;
На рисунке 1.8.2 показано расположение структуры данных _UARTInfo в памяти.
Структура данных для работы с регистрами контроллера UARTa
typedef struct __RegUart{
uint CR[VUART];//командный регистр
uint SR[VUART];//статус регистр
uint MR[VUART];//регистр масок прерываний
}_RegUart;
|
Рис.1.8.2. Расположение в памяти структуры данных для обработки запросов чтения – записи данных с UARTa |
На рис.1.8.3 показано расположение структуры данных _RegUart в памяти.
|
Рис.1.8.3. Расположение в памяти структуры данных для работы с регистрами контроллера UARTa |
Структура данных для буфера чтения/записи данных i-го UARTa.
typedef struct __DataQUART{
uint data;//данные
}_DataQUART;
typedef struct __QUART{
DataQUART DQ;
struct __QUART *pnext; //указатель на следующий элемент буфера чтения/записи данных i-го UARTa.
}_QUART;
#define SZ_QUART (sizeof(_QUART)/sizeof(char)) //размер структуры QUART в байтах
typedef struct __MQUART{
uint NUart; //номер UARTa
QUART *RQWM; //Указатель на маркер записи циклической очереди приема данных
QUART *RQRM; //Указатель на маркер чтения циклической очереди приема данных
QUART *TQWM; //указатель на маркер записи циклической очереди передачи данных
QUART *TQRM; //указатель на маркер чтения циклической очереди передачи данных
uint r;
uiint attr;
}_MQUART;
На рисунке 1.8.4 показано расположение структуры данных_MQUART в памяти.
|
Рисунок 1.8.4. Расположение в памяти структуры данных для буфера чтения/записи данных i-го UARTa |
#define SZ_IRQUART (sizeof(_IrqUART)/sizeof(char))
//размер структуры
//_IrqUART в байтах
#define SZ_UARTINFO (sizeof(_UARTInfo)/sizeof(char))
//размер структуры
//_UARTInfo в байтах
#define SZ_REGUART (sizeof(_RegUart)/sizeof(char))
//размер структуры
//_RegUart в байтах
#define SZ_MQUART (sizeof(_MQUART)/sizeof(char))
//размер структуры
//_MQUART в байтах
#define ADDR_CONT_UARTDRV_L1 (p35mem + 4)//адрес, по которому хранится контект драйвера UARTA
//p35mem резервирование 35 страницы памяти для работы драйвера UARTa 1-го уровня
#define PIRQUART (p35mem+16)
//адрес ячейки памяти, где хранится структура IrqUART
#define PUARTINFO (PIRQUART + SZ_IRQUART) )
//адрес ячейки памяти, где хранится структура _UARTInfo
#define PREGUART (PUARTINFO + SZ_UARTINFO * VUART) )
//адрес ячейки памяти где хранится структура _RegUart
#define PMQUART (PREGUART+SZ_REGUART + 4)// адрес ячейки памяти, где хранится структура _MQUART
#define MEMQUART (PMQUART+SZ_MQUART*VUART+ 4 ) //область памяти для хранения данных буферов чтения/записи UARTов
#define VRS_422 6 // интерфейсов RS-422
#define VRS_485 4 // интерфейса RS-485
Инициализация данных драйвера UARTa 1-го уровня
Начальная инициализация структуры данных для обработчика прерывания _IrqUART
Подключиться к обработчику прерывания от таймера
Начальная инициализация структуры данных для обработки запросов чтения – записи данных с UARTa _UARTInfo
Настроить CR регистры UARTов. Структура _RegUart.
Настроить MR регистры UARTов. Структура _RegUart.
Подключение к драйверу SPORTa на передачу данных в контроллер UART RS-422. Массив идентификаторов ID_DT_RS422[VRS_422]
Подключение к драйверу SPORTa на прием данных с контроллера UART RS-422
Массив идентификаторов ID_DR_RS422[VRS_422].
Подключение к драйверу SPORTa или на передачу, или на прием данных в контроллер UART RS-485. Массив идентификаторов ID_RS485[VRS_485].
Проинициализировать буфера чтения/записи данных для всех UARTов.
Подключение к драйверу SPORTa на запись регистров контроллера UARTа.
Идентификатор ID_RegTUart.
Подключение к драйверу SPORTa на чтение регистров контроллера UARTа.
Идентификатор ID_RegRUart.
Запись регистров CR в контроллер UARTa. Для этого выполнить обмен данных по SPI с идентификатором ID_TRegUart.
Запись регистров MR в контроллер UARTa. Для этого выполнить обмен данных по SPI с идентификатором ID_TRegUart.
Обработчик прерывания от таймера.
Начало
Если наступило время запуска драйвера UARTa 1-го уровня i
то {
1. Установить признак наличия прерывания
2. Увеличить счетчик прерывание на 1
3. Поставить запрос ядру на загрузку контекста драйвера UARTa 1- го уровня
}
Конец
Алгоритм работы драйвера UARTa 1-го уровня
While(1){
Цикл по всем UARTам{
Обработка UART i
Если произошло прерывание от UART (IRQ_UART = 1) и завершена обработка i-го UARTa (UART_HANDLE = 0) или для i-го UART установлен запрос на запись данных, {
Чтение 10 регистров SR с контролера UARTa
RegUart->SR
Если произошло прерывание от таймера
Установить для всех UART в структуре _UARTInfo запрос на обслуживание – бит UART_HANDLE_R.
}
Если для i-го UARTa в структуре_UARTInfo есть запрос на чтение данных, то{
Обработка SR i-го UARTa SR = B_SR[i];
Если число слов приемника > 0, то {
Считать с FIFO i-го UARTa n байт принятых данных. Обмен данными осуществляется по SPI
Если чтение данных завершено {
Проверить обмен по SPI на ошибки
Записать n байт в Буфер для чтения данных с i-го UARTa. Маркер для записи сдвинуть на n-байт.
}
Для i-го UARTa в структуре_UARTInfo сбросить запрос на обслуживание бит UART_HANDLE_R
}
Если для i-го UARTa установлен запрос на запись данных (бит UART_HANDLE_W в структуре _UARTInfo){
Обработка SR i-го UARTa SR = RegUart->SR[i];
Определить сколько байт NB_FREE можно записать в FIFO UART i (Обработка регистра SR i).
Считать из буфера для записи данных i-го UARTa NB_FREE байт или пока Маркер чтения не будет равен Маркеру записи.
Записать полученные байты данных в SPI.
Если запись данных завершена {
Проверить обмен по SPI на ошибки
}
}
Переход к следующему UARTу
}// end Цикл по всем UARTам
}//end while(1)
Заключение
Драйвер UARTa 1-го уровня осуществляет передачу данных между буферами чтение/записи UARTов и FIFO контроллера UARTa.
Для записи данных в FIFO i-го UARTa драйвер выполняет следующий действия:
определяет сколько байт можно записать в FIFO i-го UARTa;
считывает столько же байт с буфера записи данных i-го UARTa или пока Маркер чтения не будет равен Маркеру записи;
записывает считанные байты данных в FIFO i-го UARTa.
Для чтения данных с FIFO i-го UARTa драйвер выполняет следующий действия:
определяет сколько байт поступило в FIFO i-го UARTa;
считывает столько же байт с FIFO i-го UARTa;
записывает считанные байты в Буфер для чтения данных с i-го UARTa или или пока Маркер чтения не будет равен Маркеру записи.
Драйвер контроллера UARTa 2-го уровня
Осуществляет обработку данных буфера чтения данных i-го UARTa и буфера записи данных i-го UARTa.
Для этого он должен:
распознавать информационные пакеты из данных, которые он считывает с буфера чтения данных;
формировать информационные пакеты и передавать их буфер записи данных i-го UARTa для дальнейшей передачи в контроллер UARTa.
При приеме данных с буфера чтения данных i-го UARTa драйвер из принятого массива байт выделяет логическую структуру пакета.
Структура информационного пакета состоит из заголовка сообщения и информационной части, рис.1.8.5.
|
Рис.1.8.5. Структура информационного пакета |
i-й UART может в общем случает осуществлять передачу или прием различного числа информационных пакетов. Для примера, показанного на рис 9.2, i-й UART может принимать и передавать по три информационных пакета.
id1, id2 определяют начало заголовка сообщения из потока входной информации. Данные значения фиксированы для всех сообщений. Например, id1 = 0xa0; id2 = 0x0a. id3 определяет правила интерпретации данных сообщения. Например, id3 = 0xaf, информационная часть содержит данные считанные с АЦП. Len – длина инфомационной части сообщения в байтах.
cid – вспомогательная переменная указывает на область памяти, которая хранит информационную часть сообщения. Через данные областями памяти осуществляется взаимодействие драйвера UARTa 1-го уровня другими с задачами.
Как только, при приеме данных был сформирован информационный пакет, драйвер копирует информационную часть в отдельную область памяти, на которую указывает переменная cid, и далее она уже будет обрабатываться другими задачами.
При записи данных в i-й UART драйвер 2-го уровня считывает информационную часть сообщения с определенной области памяти, на которую указывает переменная cid, формирует информационный пакет, и записывает его в буфер записи данных i-го UARTa.
Драйвер UARTa
2-го запускается с периодом
.
Для правильного взаимодействия драйверов
1-го и 2-го уровней необходимо, чтобы
,
т.е. драйвер UARTa 1-го уровня
должен работать чаще драйвера 2- го
уровня.
Обработчик прерывания от таймера.
Начало
Если наступило время запуска драйвера UARTa 2-го уровня,то{
1 Установить признак наличия прерывания 2 Общее число прерываний увеличиь на 1
3 Поставить запрос ядру на загрузку контекста драйвера UARTa 2-го уровня
}
Конец
Алгоритм работы драйвера UARTa 2-го уровня
while(1){
если установлен признак наличия прерывания, то{
цикл по всем UARTaм iUART = 0 … VUART{
MsgUARTi – массив пакетов, предназначенный для чтения/записи данных с драйвера UARTa 1-го уровня
если есть запрос на чтение данные, то{
Считать данные с буфера приема
данных i-го UARTa пока Маркер чтения
не будет равен Маркеру записи.
}
Если число принятых байт > 0{
// обработка принятого массива BufRcvUARTi
NMsg – номер инф. пакета, куда были скопированы данные, прочитанные с буфера чтения данных i-го UARTa
}
Если принято все сообщение, то скопировать его в область памяти ядра по id = MsgUARTi[NMsg].cid
jMsgUARTi_L2 – j-й пакет для записи в i-й UART.
Цикл по всем сообщениям, предназначенных для записи в i-й UART {
если j-е сообщение полностью передано в драйвер UARTa 1-го уровня{то считать данные с области памяти по MsgUARTi[jMsgUARTi_L2].cid
}
Записать n байт в Буфер записи данных i-го UARTa или пока маркер чтения не будет равен маркеру записи. Маркер для записи сдвинуть на n-байт.
}
Сбросить признак наличие прерывания
Для i-го UARTa для драйвера UARTA 1-го уровня установить бит UART_HANDLER_W (запос на запись данных);
Переход к следующему сообщению jMsgUARTi_L2++;
}// end цикл по всем UARTaм iUART = 0 … VUART
}//end если
}//while
Заключение
Драйвер UARTa 2-го уровня осуществляет пакетную обработку данных. При чтение данных с Буфера чтения данных i-го UARTa драйвер выполняет следующие действия:
Считывает данные с буфера приема данных i-го UARTa пока Маркер чтения не будет равен Маркеру записи.
Обрабатывает принятый массив данных и выделяет структуры пакета данных.
копирует полученных пакет данных в заданную область памяти
При записи данных в Буфер записи данных i-го UARTa драйвер выполняет следующий действия:
считывает информационную часть сообщения с определенной области памяти
формирует пакет на передачу в Буфер записи данных i-го UARTa.
Записать n байт в Буфер передачи данных i-го UARTa или пока маркер чтения не будет равен маркеру записи.
