Как определить тип микросхемы UART
Как определить тип микросхемы UART
Как же определить, какая из этих микросхем установлена на вашем асинхронном адаптере? Кроме возможности заглянуть в документацию существует еще один способ (для программы этот способ единственный, ведь она не может ознакомиться с документацией). Фактически этот способ основан на различиях в особенностях микросхем UART. Ниже приведены особенности микросхем UART различных типов:
- UART 8250 не имеет регистра расширения.
- UART 16450 не имеет внутренних буферов FIFO.
- UART 16550 имеет внутренние буфера FIFO, но с ошибками. Бит D7 регистра управления прерываниями (IIR) равен единице, а бит D6 - нулю.
- UART 16550A не содержит ошибок при реализации FIFO. Биты D7 и D6 регистра управления прерываниями (IIR) равны единице.
Согласно этим особенностям микросхем UART возможен следующий алгоритм определения их типа:
- Читаем и сохраняем значение регистра расширения. Адрес регистра расширения определяем как базовый адрес плюс семь (base_adr + 7)
- Записываем в регистр расширения какое-либо число, например 0A5h
- Снова считываем значение регистра расширения и сравниваем его с числом, ранее записанным в него (0A5h). Если эти значения не равнозначны, значит регистр расширения отсутствует и, следовательно, тестируемая микросхема - UART 8250
- Затем опять запоминаем в регистре расширения другое число, например 5Ah
- Снова считываем значение регистра расширения и сравниваем его с ранее записанным числом. Если эти значения не одинаковы, значит регистр расширения отсутствует и следовательно, тестируемая микросхема - UART 8250
- Восстанавливаем величину, изначально хранившуюся в регистре расширения
- Считываем и сохраняем регистр управления прерываниями
- Запоминаем единицу в регистре FCR (регистр управления режимом буферизации, подробно описан ниже)
- Считываем значение регистра управления прерываниями. Если бит D7 сохраненного регистра управления прерываниями очищен, запоминаем единицу в регистре FCR
- Если бит D6 регистра управления прерываниями содержит единицу, тестируемая микросхема - UART 16550A
- Если бит D7 регистра управления прерываниями содержит единицу, тестируемая микросхема - UART 16550
- В противном случае тестируемая микросхема - UART 16450.
Теперь приведем программу, реализующую изложенный алгоритм. В данной программе используются созданные нами функции is_UART_8250() и is_UART_FIFO(). Первая позволяет определить по отсутствию регистра расширения микросхему UART 8250, а вторая по особенностям реализации внутреннего буфера данных различает остальные типы микросхем.
// TST_UART.C // Программа определения типа микросхемы UART асинхронного адаптера
#define UART_8250 1 #define UART_16450 2 #define UART_16550 3 #define UART_16550A 4
void main(void) {
// номер асинхронного порта может быть 0 для COM1 // или 1 для COM2
int port = 0;
int test;
printf("\n(c) Frolov G.V. 1992. " "Программа определения типа UART\n\n");
printf("\Введите номер асинхронного порта (COM1 - 0, COM2 - 1):"); scanf( "%d", &port ); if(( port != 0 ) && ( port != 1 )){ printf( "асинхронный порт COM%d не поддерживается\n", port ); exit( -1 ); }
// проверяем, является ли микросхема UART - UART 8250
if( is_UART_8250(port) == UART_8250 ) { printf("Обнаружена микросхема UART 8250\n"); exit(0); }
// проверяем другие типы микросхем UART
if(( test = is_UART_FIFO(port) ) == UART_16550A ) { printf("Обнаружена микросхема UART 16550A\n"); exit(0); }
else if(test == UART_16550) { printf("Обнаружена микросхема UART 16550\n"); exit(0); }
printf("Обнаружена микросхема UART 16450\n"); }
/** *.Name is_UART_8250 *.Title Определяет тип UART. * *.Descr Эта функция определяет тип микросхемы, * используемый данным последовательным асинхронным * адаптером (UART). * *.Proto int is_UART_8250( int port ); * *.Params int port - номер асинхронного адаптера: * 0 - COM1, 1 - COM2 * *.Return Для UART 8250 - возвращает константу UART_8250, * в остальных случаях возвращает 0 * *.Sample tst_uart.c **/ int is_UART_8250( int port ) {
int save_scr, in_scr;
// сохраняем значения регистра расширения save_scr = inp( 0x3ff - 0x100 * port );
// записываем в регистр расширения число 0x5A outp( 0x3ff - 0x100 * port, 0x5A );
// считываем регистр расширения in_scr = inp( 0x3ff - 0x100 * port );
// сохранилось ли записанное число? if( in_scr != 0x5A ) {
// если нет, значит, регистр расширения отсутствует и, // следовательно, тип микросхемы - UART 8250
// восстанавливаем значение регистра расширения outp( 0x3ff - 0x100 * port, save_scr ); return( UART_8250 ); }
// записываем в регистр расширения другое число - 0xA5 outp( 0x3ff - 0x100 * port, 0xA5 );
// считываем регистр расширения in_scr = inp( 0x3ff - 0x100 * port );
// восстанавливаем значение регистра расширения outp( 0x3ff - 0x100 * port, save_scr );
// сохранилось ли записанное число? if( in_scr != 0xA5 )
// если нет, регистр расширения отсутствует и, // следовательно, тип микросхемы - UART 8250 return( UART_8250 );
// в противном случае регистр расширения есть и надо выполнить // дальнейшее тестирование для определения типа UART return( 0 ); }
/** *.Name is_UART_FIFO *.Title Определяет тип UART. * *.Descr Эта функция определяет тип микросхемы, * используемой данным последовательным асинхронным * адаптером (UART). * *.Proto int is_UART_FIFO( int port ); * *.Params int port - номер асинхронного адаптера: * 0 - COM1, 1 - COM2 * *.Return для UART 164550 - возвращает константу UART_16450, * для UART 16550 - возвращает константу UART_16550, * для UART 16550A - возвращает константу UART_16550A * *.Sample tst_uart.c **/ int is_UART_FIFO( int port ) {
int save_iir, in_iir;
// сохраняем значение регистра определения прерывания save_iir = inp( 0x3fa - 0x100 * port );
// разрешаем использование FIFO outp( 0x3fa - 0x100 * port, 0x1 );
// читаем значение регистра определения прерывания in_iir = inp( 0x3fa - 0x100 * port );
// восстанавливаем значение регистра определения прерывания outp( 0x3fa - 0x100 * port, 0x0 );
// если бит D6 содержит единицу, значит, мы имеем UART 16550A if(( in_iir & 0x40 ) == 1 ) return( UART_16550A );
// если бит D7 содержит единицу, значит, мы имеем UART 16550 if(( in_iir & 0x80 ) == 1 ) return( UART_16550 );
// если биты D7 и D6 содержат нули, значит, мы имеем UART 16450 // (буфер FIFO отсутствует) return( UART_16450 ); }