Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СРВ_10_3.doc
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
37 Мб
Скачать
☆

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. 1. Установить признак наличия прерывания

    1. 2. Увеличить счетчик прерывание на 1

    2. 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. 1 Установить признак наличия прерывания 2 Общее число прерываний увеличиь на 1

    2. 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 или пока маркер чтения не будет равен маркеру записи.