Подключил смарт карту к UART3 по интерфейсу ISO-7816. Сигнал с TX инвертируется на ключике и идет на разрешающий вход одноканального аналогового коммутатора. Один конец коммутатора подключен к земле, а второй подтянут к питанию (10к) и подключен к I/O смарт карты, сюда же напрямую подключен RX. Таким образом, когда идет передача приемник видит собственную посылку. Когда передача закончена аналоговый коммутатор не оказывает влияния на линию, карта отвечает на RX.
Провожу инициализацию карты - принимаю ATR. Принимаю правильно, все расшифровывается и соответствует даташиту на карту.
Подаю PPS команду (скорость нужно установить), карта ее воспринимает и отвечает эхо-посылкой. Причем в UART-е вижу как запрос, так и ответ.
Кодирую APDU команду в протокол Т=1 (GetVersion) посылаю в карту. И вот тут начинаются чудеса. В буфере UART-а вижу запрос (сама команда) и один байт ответа карты. Смотрю осциллографом, вижу четкий запрос и четкий ответ на 32 байт. Сделал запись, разобрал посылки, все четко. Фронты хорошие, посылки друг на друга не налазят, скорости запроса и ответа совпадают. Более того, подключил на линию RX прослушку и подключился терминалкой с компа. Она принимает и запрос и ответ. Но UART принимать ответ карты отказывается.
Исходники привожу. В них в реальной жизни все гораздо сложнее, но в процессе поиска недостающих байт я из них все лишнее вычистил.
Код
// Ноги UART-а
PINSEL0_bit.P0_0=2; // TxD3
PINSEL0_bit.P0_1=2; // RxD3
Код
// работа с UART
typedef struct
{
unsigned long power_bit;
unsigned long int_no;
void* int_handler;
volatile unsigned long* acr;
volatile unsigned long* fcr;
volatile unsigned char* lcr;
volatile unsigned long* dlm;
volatile unsigned char* dll;
volatile unsigned long* fdr;
volatile unsigned long* ier;
volatile const unsigned char* lsr;
volatile unsigned char* thr;
volatile unsigned long* iir;
volatile unsigned char* rbr;
}NXP_UART_HARDWARE;
// Прерывание UART
void nxp_uart_interrupt(unsigned long uart_index)
{
volatile unsigned char reg;
unsigned long status=(*nxp_uart[uart_index].hardware->iir>>1)&0x07;
switch(status)
{
case 2: //Прием
case 6: //CTI
while(*nxp_uart[uart_index].hardware->lsr&(1<<0))
{
unsigned char data=*nxp_uart[uart_index].hardware->rbr;
#ifdef DEBUG_MODE
// отладка. посчитаем количество принятых байт
nxp_uart[uart_index].receive_count++;
#endif
// сохраняем данные в программное FIFO
if (!fifo_full(&nxp_uart[uart_index].rx_fifo))
fifo_write(&nxp_uart[uart_index].rx_fifo,data);
}
break;
case 1: //Отправка
while((*nxp_uart[uart_index].hardware->lsr&(1<<5)) && !fifo_empty(&nxp_uart[uart_index].tx_fifo))
{
*nxp_uart[uart_index].hardware->thr=fifo_read(&nxp_uart[uart_index].tx_fifo);
#ifdef DEBUG_MODE
// отладка. посчитаем количество отправленных байт
nxp_uart[uart_index].send_count++;
#endif
// данные загружаем из программного FIFO
if (fifo_empty(&nxp_uart[uart_index].tx_fifo))
*nxp_uart[uart_index].hardware->ier&=~(1<<1); //Данных нет, запретим прерывание
}
break;
case 3: //Ошибка
reg=*nxp_uart[uart_index].hardware->lsr;
if (reg&0x9E)
{
#ifdef DEBUG_MODE
nxp_uart[uart_index].last_error_state=reg;
nxp_uart[uart_index].error_count++;
#endif
reg=*nxp_uart[uart_index].hardware->rbr;
}
break;
}
}
// Инициализация UART
void nxp_uart_open(unsigned long uart_index,unsigned char* rx_buffer, unsigned long rx_buffer_size, unsigned char* tx_buffer, unsigned long tx_buffer_size, unsigned long int_priority)
{
nxp_uart[uart_index].hardware=&nxp_uart_hardware[uart_index];
nxp_uart[uart_index].rx_fifo.buffer=rx_buffer;
nxp_uart[uart_index].rx_fifo.read_pointer=0;
nxp_uart[uart_index].rx_fifo.write_pointer=0;
nxp_uart[uart_index].rx_fifo.size=rx_buffer_size;
nxp_uart[uart_index].tx_fifo.buffer=tx_buffer;
nxp_uart[uart_index].tx_fifo.read_pointer=0;
nxp_uart[uart_index].tx_fifo.write_pointer=0;
nxp_uart[uart_index].tx_fifo.size=tx_buffer_size;
#ifdef DEBUG_MODE
nxp_uart[uart_index].receive_count=0;
nxp_uart[uart_index].send_count=0;
nxp_uart[uart_index].error_count=0;
nxp_uart[uart_index].last_error_state=0;
#endif
PCONP|=(1<<nxp_uart[uart_index].hardware->power_bit);
*nxp_uart[uart_index].hardware->acr&=~(1<<0); // autobaud off
*nxp_uart[uart_index].hardware->fcr=0x41; // FIFO Enable, прерывание по приему четвертого байта
//ПРЕРЫВАНИЯ
*nxp_uart[uart_index].hardware->ier|=(1<<0); //Прием разрешим
*nxp_uart[uart_index].hardware->ier&=~(1<<1); //Передачу запретим (начало пакета отправляется из основного цикла)
*nxp_uart[uart_index].hardware->ier|=(1<<2); //Статус разрешим
nxp_irq_install(nxp_uart[uart_index].hardware->int_no,nxp_uart[uart_index].hardware->int_handler,int_priority);
}
Отчего часть байт может быть потеряна. Уже не знаю в какую сторону копать. Считал что библиотеки работы с UART для этого камня давно написаны и отлажены, но как оказалось есть нюансы.