Files
ch32v20x-examples/EVT/EXAM/USART/USART_SmartCard/User/main.c
T
2024-05-09 16:45:21 +08:00

405 lines
12 KiB
C

/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0.0
* Date : 2024/02/20
* Description : Main program body.
*********************************************************************************
* Copyright (c) 2024 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*
*@Note
This example shows that the USART peripheral is configured in smart card mode
and reads ATR data, and then attempts to read the data in T=0 mode.
pins:
SMARTCARD_CK -- PA4
SMARTCARD_IO -- PA2
SMARTCARD_RST -- PA5
SMARTCARD_VCC -- 3.3V
*
*/
#include "debug.h"
#include "string.h"
/* Paramenters */
#define ATR_MAX_SIZE ((uint8_t)33) /* Maximum size of ATR byte array */
#define ATR_MAX_HISTORICAL ((uint8_t)15) /* Maximum number of historical bytes */
#define ATR_MAX_PROTOCOLS ((uint8_t)7) /* Maximun number of protocols */
#define ATR_MAX_IB ((uint8_t)4) /* Maximum number of interface bytes per protocol */
#define ATR_INTERFACE_BYTE_TA ((uint8_t)0) /* Interface byte TAi */
#define ATR_INTERFACE_BYTE_TB ((uint8_t)1) /* Interface byte TBi */
#define ATR_INTERFACE_BYTE_TC ((uint8_t)2) /* Interface byte TCi */
#define ATR_INTERFACE_BYTE_TD ((uint8_t)3) /* Interface byte TDi */
#define STATE_PARSE_TS 1
#define STATE_PARSE_T0 2
#define STATE_PARSE_TA 3
#define STATE_PARSE_TB 4
#define STATE_PARSE_TC 5
#define STATE_PARSE_TD 6
#define STATE_PARSE_HIST_BYTES 7
#define STATE_PARSE_TCK 8
#define STATE_PARSE_END 255
#define LC_MAX (20)
#define RST_PIN GPIO_Pin_5
typedef struct {
uint32_t length;
uint8_t TS; /* Initial character */
uint8_t T0; /* Format character */
struct {
uint8_t value; /* The value of the Interface byte */
uint8_t present; /* The presence of the Interface byte */
} ib[ATR_MAX_PROTOCOLS][ATR_MAX_IB], TCK; /* Interface bytes, TCK */
uint8_t pn; /* Protocol number: the value of i of the Interface bytes */
uint8_t Ti[ATR_MAX_HISTORICAL]; /* Historical bytes table */
uint8_t Tin; /* Historical bytes number */
int8_t protocol;
} ATR_TypeDef;
int ATR_Parse(ATR_TypeDef *atr, uint8_t *atr_buf, int32_t len) {
uint8_t data;
uint8_t TCK = 0;
uint8_t K = 0;
uint8_t Yi = 0;
int32_t k, state, index, length, protocol;
uint8_t *ptr;
length = len;
ptr = atr_buf;
state = STATE_PARSE_TS;
index = 0;
k = 0;
protocol = 0;
while (ptr < (atr_buf + length)) {
data = *ptr++;
if (state != STATE_PARSE_TS) {
TCK ^= data;
}
switch (state) {
case STATE_PARSE_TS:
atr->TS = data;
printf("Ts=%x \n", data);
if (data == 0x3b) {
state = STATE_PARSE_T0;
} else if (data == 0x03) {
printf("not support\n");
return 1;
} else {
printf("error Ts\n");
return 1;
}
break;
case STATE_PARSE_T0:
atr->T0 = data;
atr->Tin = data & 0x0f;
printf("T0=%x\n", data);
printf("Historical bytes number=%d\n", data & 0x0f);
K = data & 0x0F;
Yi = data;
if (data & 0x10) {
state = STATE_PARSE_TA;
} else if (data & 0x20) {
state = STATE_PARSE_TB;
} else {
if (data & 0x40) {
state = STATE_PARSE_TC;
} else if (data & 0x80) {
state = STATE_PARSE_TD;
} else {
state = STATE_PARSE_HIST_BYTES;
}
}
break;
case STATE_PARSE_TA:
printf("TA%d=%x \n", index, data);
atr->ib[index][ATR_INTERFACE_BYTE_TA].present = 1;
atr->ib[index][ATR_INTERFACE_BYTE_TA].value = data;
if (Yi & 0x20) {
state = STATE_PARSE_TB;
} else if (Yi & 0x40) {
state = STATE_PARSE_TC;
} else if (Yi & 0x80) {
state = STATE_PARSE_TD;
} else {
state = STATE_PARSE_HIST_BYTES;
}
break;
case STATE_PARSE_TB:
printf("TB%d=%x \n", index, data);
atr->ib[index][ATR_INTERFACE_BYTE_TB].present = 1;
atr->ib[index][ATR_INTERFACE_BYTE_TB].value = data;
if (Yi & 0x40) {
state = STATE_PARSE_TC;
} else if (Yi & 0x80) {
state = STATE_PARSE_TD;
} else {
state = STATE_PARSE_HIST_BYTES;
}
break;
case STATE_PARSE_TC:
printf("TC%d=%x \n", index, data);
atr->ib[index][ATR_INTERFACE_BYTE_TC].present = 1;
atr->ib[index][ATR_INTERFACE_BYTE_TC].value = data;
if (Yi & 0x80) {
state = STATE_PARSE_TD;
} else {
state = STATE_PARSE_HIST_BYTES;
}
break;
case STATE_PARSE_TD:
Yi = data;
printf("TD%d=%x \n", index, data);
atr->ib[index][ATR_INTERFACE_BYTE_TD].present = 1;
atr->ib[index][ATR_INTERFACE_BYTE_TD].value = data;
if (index == 0) {
protocol = Yi & 0x0F;
}
index++;
atr->pn = index;
if (Yi & 0xF0) {
if (Yi & 0x10) {
/* TAx character present */
state = STATE_PARSE_TA;
} else if (Yi & 0x20) {
/* TBx character present */
state = STATE_PARSE_TB;
} else if (Yi & 0x40) {
/* TCx character present */
state = STATE_PARSE_TC;
} else if (Yi & 0x80) {
/* TDx character present */
state = STATE_PARSE_TD;
} else {
state = STATE_PARSE_HIST_BYTES;
}
} else {
state = STATE_PARSE_HIST_BYTES;
}
break;
case STATE_PARSE_HIST_BYTES:
if (K) {
if (k < K) {
atr->Ti[k] = data;
printf("T[%d]=%x\n", k, data);
k++;
if (k == K) {
if (protocol > 0) {
state = STATE_PARSE_TCK;
}
}
}
break;
}
case STATE_PARSE_TCK:
atr->TCK.present = 1;
atr->TCK.value = data;
printf("get TCK %x\n", data);
if (TCK) {
// TCK != 0
printf("TCK error\n");
return 1;
}
// printf("cal TCK result %x\n", TCK);
break;
}
if (state == STATE_PARSE_HIST_BYTES && K == 0 && protocol == 0)
break;
}
atr->protocol = protocol;
return 0;
}
void USART2_ReCFG(void) {
GPIO_InitTypeDef GPIO_InitStructure = {0};
USART_InitTypeDef USART_InitStructure = {0};
USART_ClockInitTypeDef USART_ClockInitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* USART2 Ck-->A.4 TX-->A.2 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_ClockInitStructure.USART_Clock = USART_Clock_Enable;
USART_ClockInit(USART2, &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
/// Enable NACK transmission
USART_SmartCardNACKCmd(USART2, ENABLE);
/// Enable Smartcard mode
USART_SmartCardCmd(USART2, ENABLE);
USART_SetPrescaler(USART2, 5);
USART_SetGuardTime(USART2, 15);
}
void RST_Init() {
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = RST_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_ResetBits(GPIOA, RST_PIN);
}
void SC_ClearUart() {
int32_t i = 0;
while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == SET) {
i++;
if (i > 1) {
break;
}
USART_ReceiveData(USART2);
}
}
void SC_TransmitData(uint8_t *data, uint16_t size) {
uint8_t dat = 0;
for (uint8_t index = 0; index < size; index++) {
dat = data[index];
USART_SendData(USART2, dat);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {
}
}
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET) {
}
}
void SC_ReceiveData(uint8_t *data, uint16_t *size) {
uint32_t i = 0, t = 0;
SC_ClearUart();
while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET) {
t++;
Delay_Ms(1);
if (t > 10) {
break;
}
}
t = 0;
while (1) {
if (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == SET) {
data[i] = USART_ReceiveData(USART2);
i++;
t = 0;
} else if (t < 10) {
Delay_Ms(1);
t++;
} else {
break;
}
}
*size = i;
}
/*********************************************************************
* @fn main
*
* @brief Main program.
*
* @return none
*/
int main(void) {
ATR_TypeDef atr = {0}; /* Answer To Reset structure */
uint8_t pps[] = {0xff, 0x00, 0xff};
uint8_t testcmd[] = {0x00, 0x84, 0x00, 0x00, 0x08};
uint8_t recvbuf[ATR_MAX_SIZE] = {0};
uint16_t recvpos = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
SystemCoreClockUpdate();
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n", SystemCoreClock);
printf("ChipID:%08x\r\n", DBGMCU_GetCHIPID());
printf("USART SmartCard TEST\r\n");
RST_Init();
USART2_ReCFG(); /* USART2 INIT */
GPIO_ResetBits(GPIOA, RST_PIN);
Delay_Ms(1);
GPIO_SetBits(GPIOA, RST_PIN);
// try to get ATR
SC_ReceiveData(recvbuf, &(recvpos));
if (recvpos == 0) {
printf("cannot get atr\n");
printf("end\n");
while (1) {
}
}
if (ATR_Parse(&atr, recvbuf, recvpos) != 0) {
printf("end\n");
while (1) {
}
}
printf("mode T=%d \n", atr.protocol);
if (atr.protocol != 0) {
recvpos = 0;
// send pps
SC_TransmitData(pps, 3);
SC_ReceiveData(recvbuf, &(recvpos));
if (memcmp(pps, recvbuf, recvpos) != 0) {
printf("cannot switch to T=0 mode\n");
printf("end\n");
while (1) {
}
} else {
printf("switch to T=0 mode\n");
}
}
SC_TransmitData(testcmd, 5);
SC_ReceiveData(recvbuf, &(recvpos));
for (int i = 0; i < recvpos; i++) {
printf("[%d]=%x \n", i, recvbuf[i]);
}
printf("SW1 = %x \n", recvbuf[recvpos - 2]);
printf("SW2 = %x \n", recvbuf[recvpos - 1]);
if (recvbuf[recvpos - 2] == 0x90 && recvbuf[recvpos - 1] == 0x00 && recvpos == 11) {
printf("success\n");
}
printf("end\n");
while (1) {
}
}