345 lines
9.7 KiB
C
Executable File
345 lines
9.7 KiB
C
Executable File
#include <os/mem.h>
|
|
#include <os/str.h>
|
|
#include <os/os.h>
|
|
#include "cli.h"
|
|
#include "sys_driver.h"
|
|
#include "gpio_driver.h"
|
|
#include "scr_driver.h"
|
|
#include "driver/scr_types.h"
|
|
|
|
typedef struct {
|
|
uint32_t sc_clk_div;
|
|
uint32_t baud_clk_div;
|
|
uint32_t baud_tune;
|
|
uint32_t tx_repeat;
|
|
uint32_t rx_repeat;
|
|
uint32_t c2c_limit;
|
|
uint32_t act_deact_time;
|
|
uint32_t reset_duration;
|
|
uint32_t ATR_start_limit;
|
|
uint32_t intr;
|
|
} scr_config_t;
|
|
|
|
typedef struct {
|
|
uint8_t data[SCR_MAX_LEN];
|
|
uint8_t len;
|
|
} scr_data_t;
|
|
|
|
extern void delay(int num);
|
|
|
|
static gpio_scr_map_group_t g_scr_chan = 0;
|
|
static int hexstr2bin(const char *hex, u8 *buf, size_t len);
|
|
|
|
static int volatile g_scr_ATR_flag = 0;
|
|
static int volatile g_scr_c2c_flag = 0;
|
|
static int volatile g_scr_fast_act_flag = 0;
|
|
|
|
static void scr_fast_active(void)
|
|
{
|
|
scr_config_t scr_config;
|
|
|
|
scr_config.sc_clk_div = bk_scr_get_sc_clk_div(); //0x0D
|
|
scr_config.baud_clk_div = bk_scr_get_baud_clk_div(); //0x0E
|
|
scr_config.baud_tune = bk_scr_get_baud_tune(); //0x19
|
|
scr_config.tx_repeat = bk_scr_get_repeat(BK_SCR_TYPE_TX); //0x0C
|
|
scr_config.rx_repeat = bk_scr_get_repeat(BK_SCR_TYPE_RX); //0x0C
|
|
scr_config.c2c_limit = bk_scr_get_c2c_delay_limit(); //0x13, 0x1A
|
|
scr_config.act_deact_time = bk_scr_get_act_deact_time(); //0x10
|
|
scr_config.reset_duration = bk_scr_get_reset_duration(); //0x11
|
|
scr_config.ATR_start_limit = bk_scr_get_ATR_start_limit(); //0x12
|
|
scr_config.intr = bk_scr_get_intr(BK_SCR_INTR_ALL); //0x07 0x14
|
|
|
|
bk_scr_set_control(BK_SCR_CTRL_RX_EN, 0);
|
|
bk_scr_gpio_config(g_scr_chan, BK_SCR_GPIO_PAUSE);
|
|
|
|
sys_hal_module_power_ctrl(POWER_MODULE_NAME_AHBP, POWER_MODULE_STATE_OFF);
|
|
delay(5000);
|
|
sys_hal_module_power_ctrl(POWER_MODULE_NAME_AHBP, POWER_MODULE_STATE_ON);
|
|
delay(1000);
|
|
|
|
bk_scr_soft_reset();
|
|
|
|
bk_scr_set_sc_clk_div(scr_config.sc_clk_div);
|
|
bk_scr_set_baud_clk_div(scr_config.baud_clk_div);
|
|
bk_scr_set_baud_tune(scr_config.baud_tune);
|
|
bk_scr_set_repeat(scr_config.tx_repeat, BK_SCR_TYPE_TX);
|
|
bk_scr_set_repeat(scr_config.rx_repeat, BK_SCR_TYPE_RX);
|
|
bk_scr_set_c2c_delay_limit(scr_config.c2c_limit);
|
|
bk_scr_set_act_deact_time(scr_config.act_deact_time);
|
|
bk_scr_set_reset_duration(scr_config.reset_duration);
|
|
bk_scr_set_ATR_start_limit(scr_config.ATR_start_limit);
|
|
bk_scr_set_intr(BK_SCR_INTR_ALL, scr_config.intr, NULL, NULL);
|
|
|
|
bk_scr_set_control(BK_SCR_CTRL_TX_EN, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_RX_EN, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_ATR_START_FLUSH_FIFO, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_GLOBAL_INTR_EN, 1);
|
|
|
|
delay(1000);
|
|
|
|
bk_scr_set_control(BK_SCR_CTRL_VCC, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_ACT_FAST, 1);
|
|
|
|
bk_scr_gpio_config(g_scr_chan, BK_SCR_GPIO_STORE);
|
|
bk_scr_set_control(BK_SCR_CTRL_RX_EN, 1);
|
|
|
|
bk_scr_set_control(BK_SCR_CTRL_CLK_STOP, 0);
|
|
}
|
|
|
|
void scr_rx_fifo_full_cb(void *param)
|
|
{
|
|
uint32_t ret;
|
|
scr_data_t *p_data = (scr_data_t *)param;
|
|
ret = bk_scr_read_data(p_data->data + p_data->len, SCR_MAX_LEN - p_data->len);
|
|
p_data->len += ret;
|
|
}
|
|
|
|
void scr_ATR_done_cb(void *param)
|
|
{
|
|
g_scr_ATR_flag = 1;
|
|
}
|
|
|
|
void scr_ATR_fail_cb(void *param)
|
|
{
|
|
g_scr_ATR_flag = -1;
|
|
}
|
|
|
|
void scr_c2c_full_cb(void *param)
|
|
{
|
|
g_scr_c2c_flag = 1;
|
|
}
|
|
|
|
void scr_clk_stop_run_cb(void *param)
|
|
{
|
|
if (g_scr_fast_act_flag == 0) {
|
|
g_scr_fast_act_flag = 1;
|
|
scr_fast_active();
|
|
} else {
|
|
g_scr_fast_act_flag = 0;
|
|
}
|
|
}
|
|
|
|
void cli_scr_cold_reset_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
|
{
|
|
int i;
|
|
uint8_t read_buf[SCR_MAX_LEN];
|
|
uint32_t read_len;
|
|
|
|
/*enable scr with channel 0~2*/
|
|
if (argc < 2) {
|
|
SCR_LOGE("need input scr channel\r\n");
|
|
return;
|
|
}
|
|
g_scr_chan = atoi(argv[1]);
|
|
if (g_scr_chan >= GPIO_SCR_MAP_GROUP_MAX) {
|
|
SCR_LOGE("scr channel: %d is error\r\n", g_scr_chan);
|
|
return;
|
|
}
|
|
bk_scr_init(g_scr_chan);
|
|
|
|
/*scr init config*/
|
|
bk_scr_set_sc_clk_div(3); //clock = 26M/2/3 = 3.25M
|
|
bk_scr_set_baud_clk_div(123); //baud_div = (3+1)*(372/1)-1 = 1487 baud_rate = 26M/(2*(1487+1)) = 8736
|
|
bk_scr_set_baud_tune(0);
|
|
bk_scr_set_repeat(BK_SCR_TYPE_TX, 3);
|
|
bk_scr_set_repeat(BK_SCR_TYPE_RX, 3);
|
|
|
|
/*config control of scr*/
|
|
bk_scr_set_control(BK_SCR_CTRL_TX_EN, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_RX_EN, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_T0T1, 0);
|
|
bk_scr_set_control(BK_SCR_CTRL_ATR_START_FLUSH_FIFO, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_GLOBAL_INTR_EN, 1);
|
|
|
|
/*enable ATR interrupt*/
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_DONE, 1, scr_ATR_done_cb, NULL);
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_FAIL, 1, scr_ATR_fail_cb, NULL);
|
|
|
|
/*cold reset*/
|
|
g_scr_ATR_flag = 0;
|
|
bk_scr_set_control(BK_SCR_CTRL_VCC, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_ACT, 1);
|
|
while (!g_scr_ATR_flag);
|
|
|
|
if (g_scr_ATR_flag == 1) {
|
|
BK_RAW_LOGI(NULL, "ATR done: ");
|
|
read_len = bk_scr_read_data(read_buf, SCR_MAX_LEN);
|
|
for (i = 0; i < read_len; i++) {
|
|
BK_RAW_LOGI(NULL, "%02x ", read_buf[i]);
|
|
}
|
|
BK_RAW_LOGI(NULL, "\r\n");
|
|
} else {
|
|
BK_RAW_LOGI(NULL, "cold reset fail\r\n");
|
|
}
|
|
bk_scr_flush_fifo(BK_SCR_TYPE_RX);
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_FAIL, 0, NULL, NULL);
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_DONE, 0, NULL, NULL);
|
|
}
|
|
|
|
void cli_scr_warm_reset_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
|
{
|
|
int i;
|
|
uint8_t read_buf[SCR_MAX_LEN];
|
|
uint32_t read_len;
|
|
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_DONE, 1, scr_ATR_done_cb, NULL);
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_FAIL, 1, scr_ATR_fail_cb, NULL);
|
|
|
|
g_scr_ATR_flag = 0;
|
|
bk_scr_set_control(BK_SCR_CTRL_WARM_RST, 1);
|
|
while (!g_scr_ATR_flag);
|
|
|
|
if (g_scr_ATR_flag == 1) {
|
|
BK_RAW_LOGI(NULL, "ATR done: ");
|
|
read_len = bk_scr_read_data(read_buf, SCR_MAX_LEN);
|
|
for (i = 0; i < read_len; i++) {
|
|
BK_RAW_LOGI(NULL, "%02x ", read_buf[i]);
|
|
}
|
|
BK_RAW_LOGI(NULL, "\r\n");
|
|
} else {
|
|
BK_RAW_LOGI(NULL, "warm reset fail\r\n");
|
|
}
|
|
bk_scr_flush_fifo(BK_SCR_TYPE_RX);
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_FAIL, 0, NULL, NULL);
|
|
bk_scr_set_intr(BK_SCR_INTR_ATR_DONE, 0, NULL, NULL);
|
|
}
|
|
|
|
void cli_scr_process_t0_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
|
{
|
|
int i;
|
|
uint32_t read_len;
|
|
scr_header_t *header_p;
|
|
scr_data_t scr_send_data, scr_recv_data;
|
|
|
|
if (argc != 2) {
|
|
SCR_LOGE("need apdu\r\n");
|
|
return;
|
|
}
|
|
|
|
if (os_strlen(argv[1]) % 2) {
|
|
SCR_LOGE("apdu: %s error\r\n", argv[1]);
|
|
return;
|
|
}
|
|
|
|
scr_send_data.len = os_strlen(argv[1]) / 2;
|
|
if (hexstr2bin(argv[1], scr_send_data.data, scr_send_data.len)) {
|
|
SCR_LOGE("apdu: %s is not hex string\r\n", argv[1]);
|
|
return;
|
|
}
|
|
|
|
if (scr_send_data.len < sizeof(scr_header_t) && scr_send_data.data[0] != 0xFF) {
|
|
SCR_LOGE("apdu length: %d is error\r\n", scr_send_data.len);
|
|
return;
|
|
}
|
|
|
|
bk_scr_set_intr(BK_SCR_INTR_C2C_FULL, 1, scr_c2c_full_cb, NULL);
|
|
bk_scr_set_intr(BK_SCR_INTR_RX_FIFO_FULL, 1, scr_rx_fifo_full_cb, &scr_recv_data);
|
|
|
|
/*send command header*/
|
|
g_scr_c2c_flag = 0;
|
|
scr_recv_data.len = 0;
|
|
bk_scr_write_data(scr_send_data.data, sizeof(scr_header_t));
|
|
scr_send_data.len -= sizeof(scr_header_t);
|
|
while (!g_scr_c2c_flag);
|
|
|
|
read_len = bk_scr_read_data(scr_recv_data.data + scr_recv_data.len, SCR_MAX_LEN - scr_recv_data.len);
|
|
scr_recv_data.len += read_len;
|
|
BK_RAW_LOGI(NULL, "recv: ");
|
|
for (i = 0; i < scr_recv_data.len; i++) {
|
|
BK_RAW_LOGI(NULL, "%02x ", scr_recv_data.data[i]);
|
|
}
|
|
BK_RAW_LOGI(NULL, "\r\n");
|
|
bk_scr_flush_fifo(BK_SCR_TYPE_RX);
|
|
|
|
/*send command body*/
|
|
if (scr_send_data.len) {
|
|
header_p = (scr_header_t *)scr_send_data.data;
|
|
if (scr_recv_data.len == 1 && scr_recv_data.data[0] == header_p->INS) {
|
|
g_scr_c2c_flag = 0;
|
|
scr_recv_data.len = 0;
|
|
bk_scr_write_data(scr_send_data.data + sizeof(scr_header_t), scr_send_data.len);
|
|
while (!g_scr_c2c_flag);
|
|
|
|
read_len = bk_scr_read_data(scr_recv_data.data + scr_recv_data.len, SCR_MAX_LEN - scr_recv_data.len);
|
|
scr_recv_data.len += read_len;
|
|
BK_RAW_LOGI(NULL, "recv: ");
|
|
for (i = 0; i < scr_recv_data.len; i++) {
|
|
BK_RAW_LOGI(NULL, "%02x ", scr_recv_data.data[i]);
|
|
}
|
|
BK_RAW_LOGI(NULL, "\r\n");
|
|
bk_scr_flush_fifo(BK_SCR_TYPE_RX);
|
|
}
|
|
}
|
|
|
|
bk_scr_set_intr(BK_SCR_INTR_C2C_FULL, 0, NULL, NULL);
|
|
bk_scr_set_intr(BK_SCR_INTR_RX_FIFO_FULL, 0, NULL, NULL);
|
|
}
|
|
|
|
void cli_scr_power_off_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
|
{
|
|
bk_scr_set_control(BK_SCR_CTRL_DEACT, 1);
|
|
bk_scr_set_control(BK_SCR_CTRL_VCC, 1);
|
|
}
|
|
|
|
void cli_scr_fast_active_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
|
{
|
|
bk_scr_set_intr(BK_SCR_INTR_CLK_STOP_RUN, 1, scr_clk_stop_run_cb, NULL);
|
|
bk_scr_set_control(BK_SCR_CTRL_CLK_STOP, 1);
|
|
}
|
|
|
|
#define SCR_CMD_CNT (sizeof(s_scr_commands) / sizeof(struct cli_command))
|
|
|
|
static const struct cli_command s_scr_commands[] = {
|
|
{"scr_cold_reset", "power up", cli_scr_cold_reset_cmd},
|
|
{"scr_warm_reset", "warm reset", cli_scr_warm_reset_cmd},
|
|
{"scr_process_t0", "send t0 hex string", cli_scr_process_t0_cmd},
|
|
{"scr_power_off", "stop", cli_scr_power_off_cmd},
|
|
{"scr_fast_active", "test fast active", cli_scr_fast_active_cmd},
|
|
};
|
|
|
|
int cli_scr_init(void)
|
|
{
|
|
return cli_register_commands(s_scr_commands, SCR_CMD_CNT);
|
|
}
|
|
|
|
static int hex2num(char c)
|
|
{
|
|
if (c >= '0' && c <= '9')
|
|
return c - '0';
|
|
if (c >= 'a' && c <= 'f')
|
|
return c - 'a' + 10;
|
|
if (c >= 'A' && c <= 'F')
|
|
return c - 'A' + 10;
|
|
return -1;
|
|
}
|
|
|
|
|
|
static int hex2byte(const char *hex)
|
|
{
|
|
int a, b;
|
|
a = hex2num(*hex++);
|
|
if (a < 0)
|
|
return -1;
|
|
b = hex2num(*hex++);
|
|
if (b < 0)
|
|
return -1;
|
|
return (a << 4) | b;
|
|
}
|
|
|
|
static int hexstr2bin(const char *hex, u8 *buf, size_t len)
|
|
{
|
|
size_t i;
|
|
int a;
|
|
const char *ipos = hex;
|
|
u8 *opos = buf;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
a = hex2byte(ipos);
|
|
if (a < 0)
|
|
return -1;
|
|
*opos++ = a;
|
|
ipos += 2;
|
|
}
|
|
return 0;
|
|
}
|