Программирование модемов

         

Как определить тип микросхемы 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 ); }


Содержание раздела