#include "product_test.h" #include "custom_cfg.h" #include "ui/ui_api.h" #include "tone_player.h" #include "system/timer.h" #include "uart.h" #define LOG_TAG_CONST PRODUCT_TEST #define LOG_TAG "[PRODUCT_TEST]" #define LOG_ERROR_ENABLE #define LOG_DEBUG_ENABLE #define LOG_INFO_ENABLE #define LOG_CLI_ENABLE #include "debug.h" #if PRODUCT_TEST_ENABLE #define PT_TEST 0 #define PT_SIMULATION_TEST 0 #define PT_TASK_NAME "pt" enum { PT_TASK_MSG_RUN, PT_UART_RX_DAT, }; // 消息链表 struct pt_mod_msg { struct list_head entry; struct pt_pkt *pkt; }; // 模块状态 struct pt_mod_stat { u32 init_ok : 1; // 初始化ok。// true or false struct pt_module *opt; }; static struct pt_mod_stat *pt_mod = NULL; static LIST_HEAD(pt_msg_head); static u16 pt_pkt_data_len_max = 512; // 还未实现拼包 struct playload_packet { u16 magic; u16 crc; u16 data_len; u16 seq; u16 op; u8 data[0]; }; #define PT_CRC_EXTRA_LEN sizeof(struct playload_packet) - sizeof(playload_packet->magic) - sizeof(playload_packet->crc) struct playload_packet *playload_packet; static int pt_uart_dev = -1; #if PT_TEST #define PT_TEST_STEP_SYS_START 0 #define PT_TEST_STEP_IDLE 1 #define PT_TEST_STEP_START 2 #define PT_TEST_STEP_CHECK 3 #define PT_TEST_STEP_STOP 4 #define PT_TEST_STEP_STOP_ERR 5 #define PT_TEST_STEP_SYS_STOP 6 #define PT_TEST_PKT_LEN(x) (sizeof(struct playload_packet) + sizeof(struct pt_pkt) + (x)) #define PT_TEST_PKT_CRC_LEN(x) (sizeof(struct pt_pkt) + (x)) struct pt_test_mod { u16 mod; u16 to_100ms; }; static const struct pt_test_mod pt_test_mod_tab[] = { #if PT_GPIO_ENABLE {PT_M_GPIO, 50}, #endif /* #if PT_GPIO_ENABLE */ #if PT_SD_ENABLE {PT_M_SD, 50}, #endif /* #if PT_SD_ENABLE */ #if PT_HR_ENABLE {PT_M_HR, 50}, #endif /* #if PT_HR_ENABLE */ #if PT_GSENSOR_ENABLE {PT_M_GSENSOR, 50}, #endif /* #if PT_GSENSOR_ENABLE */ #if PT_SPEAKER_MIC_ENABLE {PT_M_SPEAKER_MIC, 500}, #endif /* #if PT_SPEAKER_MIC_ENABLE */ #if PT_MOTOR_ENABLE {PT_M_MOTOR, 200}, #endif /* #if PT_MOTOR_ENABLE */ }; static u8 pt_test_idx = 0; static u8 pt_test_step = 0; static u16 pt_test_to = 0; static void uart_isr_hook(int uart_num, enum uart_event event); static void pt_test_deal(void *priv) { uart_isr_hook(pt_uart_dev, UART_EVENT_RX_DATA); } static int pt_test_pkt_enc(u32 order, u8 *inbuf, u32 inbuf_len, u8 *dat, u8 dat_len) { static u16 seq = 0; u32 cmd_size = 0; cmd_size = PT_TEST_PKT_LEN(dat_len); log_debug("enc ord:0x%x, in:0x%x, l:%d, dat:0x%x, l:%d \n", order, inbuf, inbuf_len, dat, dat_len); log_debug("cmd_size :%d \n", cmd_size); if (cmd_size > inbuf_len) { log_error("cmdsize err :%d,%d \n", cmd_size, inbuf_len); return 0; } memset(inbuf, 0, cmd_size); struct playload_packet pld_pkt = {0}; pld_pkt.magic = 0xaa55; pld_pkt.seq = seq++; pld_pkt.data_len = PT_TEST_PKT_CRC_LEN(dat_len); struct pt_pkt pkt = {0}; pkt.order = order; pkt.data_len = dat_len; memcpy(&inbuf[sizeof(struct playload_packet)], &pkt, sizeof(struct pt_pkt)); if (dat_len) { memcpy(&inbuf[PT_TEST_PKT_LEN(0)], dat, dat_len); } memcpy(inbuf, &pld_pkt, sizeof(struct playload_packet)); pld_pkt.crc = CRC16(&inbuf[list_offsetof(struct playload_packet, data_len)], pld_pkt.data_len + PT_CRC_EXTRA_LEN); memcpy(inbuf, &pld_pkt, sizeof(struct playload_packet)); /* log_debug("data_len offset:0x%x \n", &inbuf[list_offsetof(struct playload_packet, data_len)]); */ /* log_debug("data_len :%d,%d \n", pld_pkt.data_len, pld_pkt.data_len + PT_CRC_EXTRA_LEN); */ /* log_debug("crc:0x%x \n", pld_pkt.crc); */ /* put_buf(inbuf, cmd_size); */ return cmd_size; } static void pt_test_dat_write(const u8 *outbuf, u32 len) { int result; u8 *dat = &outbuf[PT_TEST_PKT_LEN(0)]; struct pt_pkt pkt = {0}; memcpy(&pkt, &outbuf[sizeof(struct playload_packet)], sizeof(struct pt_pkt)); u16 mod = PT_ORDER_M_GET(pkt.order); u16 cmd = PT_ORDER_C_GET(pkt.order); log_info("push mod:0x%x, cmd :0x%x \n", mod, cmd); if (mod == PT_M_SYSTEM) { if (cmd == PT_S_C_GET_VER) { if (ARRAY_SIZE(pt_test_mod_tab)) { pt_test_step = PT_TEST_STEP_IDLE; pt_test_idx = 0; } else { pt_test_step = PT_TEST_STEP_SYS_STOP; } sys_s_hi_timerout_add(NULL, pt_test_deal, 100); } else if (cmd == PT_S_C_END) { } else { } } else { memcpy(&result, dat, 4); switch (pt_test_step) { case PT_TEST_STEP_START: if (result) { log_error("PT_TEST_STEP_START err:0x%x \n", result); break; } pt_test_to = pt_test_mod_tab[pt_test_idx].to_100ms; pt_test_step = PT_TEST_STEP_CHECK; sys_s_hi_timerout_add(NULL, pt_test_deal, 100); break; case PT_TEST_STEP_CHECK: if (result == PT_E_OK) { pt_test_step = PT_TEST_STEP_STOP; sys_s_hi_timerout_add(NULL, pt_test_deal, 100); } else if (result == PT_E_MOD_RUN) { if (pt_test_to) { pt_test_to--; sys_s_hi_timerout_add(NULL, pt_test_deal, 100); } else { log_error("pt_test timeout \n"); pt_test_step = PT_TEST_STEP_STOP_ERR; } } else { log_error("PT_TEST_STEP_CHECK err:0x%x \n", result); break; } break; case PT_TEST_STEP_STOP: if (result) { log_error("PT_TEST_STEP_STOP err:0x%x \n", result); break; } if (pt_test_idx >= ARRAY_SIZE(pt_test_mod_tab)) { pt_test_step = PT_TEST_STEP_SYS_STOP; sys_s_hi_timerout_add(NULL, pt_test_deal, 100); break; } pt_test_idx ++; pt_test_step = PT_TEST_STEP_IDLE; sys_s_hi_timerout_add(NULL, pt_test_deal, 100); break; default: break; } } } static u32 pt_test_dat_read(u8 *inbuf, u32 len, u32 timeout) { u32 cmd_size = 0; u32 result = 0; switch (pt_test_step) { case PT_TEST_STEP_SYS_START: cmd_size = pt_test_pkt_enc(PT_ORDER_M_SET(PT_M_SYSTEM) | PT_ORDER_C_SET(PT_S_C_GET_VER), inbuf, len, NULL, 0); break; case PT_TEST_STEP_SYS_STOP: result |= BIT(0); /* result |= BIT(1); */ cmd_size = pt_test_pkt_enc(PT_ORDER_M_SET(PT_M_SYSTEM) | PT_ORDER_C_SET(PT_S_C_END), inbuf, len, &result, 4); break; case PT_TEST_STEP_IDLE: cmd_size = pt_test_pkt_enc(PT_ORDER_M_SET(pt_test_mod_tab[pt_test_idx].mod) | PT_ORDER_C_SET(PT_N_C_START), inbuf, len, NULL, 0); pt_test_step = PT_TEST_STEP_START; break; case PT_TEST_STEP_CHECK: cmd_size = pt_test_pkt_enc(PT_ORDER_M_SET(pt_test_mod_tab[pt_test_idx].mod) | PT_ORDER_C_SET(PT_N_C_GET_RESULT), inbuf, len, NULL, 0); break; case PT_TEST_STEP_STOP: cmd_size = pt_test_pkt_enc(PT_ORDER_M_SET(pt_test_mod_tab[pt_test_idx].mod) | PT_ORDER_C_SET(PT_N_C_STOP), inbuf, len, NULL, 0); break; default: break; } return cmd_size; } static void pt_test_start(void) { sys_s_hi_timerout_add(NULL, pt_test_deal, 2000); } #endif /* #if PT_TEST */ int product_test_pkt_tx(void *dat, int len) { memcpy(playload_packet->data, dat, len); playload_packet->data_len = len; playload_packet->crc = CRC16(&playload_packet->data_len, playload_packet->data_len + PT_CRC_EXTRA_LEN); #if PT_TEST pt_test_dat_write(playload_packet, sizeof(struct playload_packet) + len); #else /* #if PT_TEST */ uart_send_blocking(pt_uart_dev, playload_packet, sizeof(struct playload_packet) + len, 0); #endif /* #if PT_TEST */ log_debug("pt_tx_data:\n"); log_debug_hexdump((u8 *)playload_packet, sizeof(struct playload_packet) + len); return len; } void product_test_pkt_rx(void *dat, int len) { struct pt_mod_msg *msg = zalloc(sizeof(struct pt_mod_msg) + len); ASSERT(msg); msg->pkt = (struct pt_pkt *)((int)msg + sizeof(struct pt_mod_msg)); memcpy(msg->pkt, dat, len); local_irq_disable(); list_add_tail(&msg->entry, &pt_msg_head); local_irq_enable(); os_taskq_post_msg(PT_TASK_NAME, 1, PT_TASK_MSG_RUN); } int product_test_push_data(u32 order, int len, u8 *dat) { ASSERT(len < pt_pkt_data_len_max); // 还未实现拼包 int pkt_len = sizeof(struct pt_pkt) + len; struct pt_pkt *pkt = zalloc(pkt_len); ASSERT(pkt); pkt->order = order; pkt->data_len = len; memcpy(pkt->dat, dat, len); int tlen = product_test_pkt_tx(pkt, pkt_len); if (tlen != pkt_len) { log_error("pt push err:%d,%d \n", tlen, pkt_len); return PT_E_NO_BUFF; } return 0; } struct pt_mod_stat *product_test_find_module(u8 module) { if (!pt_mod) { return NULL; } int i = 0; struct pt_module *mod; list_for_each_pt_module(mod) { if (mod->module == module) { return &pt_mod[i]; } i++; } return NULL; } static void product_test_module_init(void) { int i = 0; struct pt_module *mod; list_for_each_pt_module(mod) { pt_mod[i].opt = mod; pt_mod[i].init_ok = true; if (mod->init) { int ret = mod->init(); if (ret) { // 模块初始化出错 pt_mod[i].init_ok = false; } } i++; } } extern void sys_enter_soft_poweroff(void *priv); static void pt_test_end(void *priv) { //DP、DM设成高阻,关闭串口 if (pt_uart_dev >= 0) { uart_deinit(pt_uart_dev); pt_uart_dev = -1; } gpio_set_mode(IO_PORT_SPILT(IO_PORT_DP), PORT_HIGHZ); gpio_set_mode(IO_PORT_SPILT(IO_PORT_DM), PORT_HIGHZ); /* adc_pmu_detect_en(1); */ /* volatage_trim_init(); */ sys_enter_soft_poweroff(NULL); } static int pt_system_ioctrl(u32 order, int len, void *param) { log_info("%s order:%d", __func__, order); u32 result = 0; switch (PT_ORDER_C_GET(order)) { case PT_S_C_GET_VER: { u8 buf[8]; u16 vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); u16 pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); u16 ver = get_vid_pid_ver_from_cfg_file(GET_VER_FROM_EX_CFG); memcpy(&buf[0], &vid, 2); memcpy(&buf[2], &pid, 2); memcpy(&buf[4], &ver, 2); memcpy(&buf[6], &pt_pkt_data_len_max, 2); log_info("vid:0x%x pid:0x%x ver:0x%x", vid, pid, ver); product_test_push_data(order, sizeof(buf), buf); return 0; } break; case PT_S_C_SET_INFO: /* memcpy((u8*)&pt_pkt_data_len_max, (u8*)param, 2); */ break; case PT_S_C_GET_MODULE: { u8 mod_num = GET_PT_MODULE_NUM(); u8 *buf = zalloc(1 + mod_num + mod_num * 2); ASSERT(buf); buf[0] = mod_num; int i = 0; struct pt_module *mod; list_for_each_pt_module(mod) { buf[1 + i] = mod->module; memcpy((u8 *)&buf[1 + mod_num + i * 2], (u8 *)&mod->attr, 2); i++; } product_test_push_data(order, 1 + mod_num + mod_num * 2, buf); free(buf); return 0; } break; case PT_S_C_HOLD: /* product_test_push_data(order, 0, NULL); */ return 0; break; case PT_S_C_END: { u32 info; u8 pt_result = 0xff; memcpy(&info, param, 4); if (info & BIT(0)) { sys_timeout_add(NULL, pt_test_end, 10); } if (info & BIT(1)) { pt_result = 1; } else { pt_result = 0; } syscfg_write(PT_TEST_RESULT, (u8 *)&pt_result, sizeof(pt_result)); /* return 0; */ break; } break; default: result = PT_E_PARAM; break; } product_test_push_data(order, 4, (u8 *)&result); return result; } static void uart_isr_hook(int uart_num, enum uart_event event) { log_debug("%s %d", __func__, event); u32 rx_flag = 0; if (event & UART_EVENT_TX_DONE) { /* log_debug("uart[%d] tx done", uart_num); */ } if (event & UART_EVENT_RX_DATA) { //log_debug("uart[%d] rx data", uart_num); rx_flag = 1; } if (event & UART_EVENT_RX_TIMEOUT) { //log_debug("uart[%d] rx ot\n", uart_num); rx_flag = 1; } if (event & UART_EVENT_RX_FIFO_OVF) { //log_debug("uart[%d] rx fifo ovf", uart_num); rx_flag = 1; } if (rx_flag) { int ret = os_taskq_post_msg(PT_TASK_NAME, 1, PT_UART_RX_DAT); if (ret) { log_error("%s ret:%d", __func__, ret); } } } static u8 *uart_cbuf = NULL; static u8 product_test_mode = 0; #define BAUD_RATE 1000000 void pt_uart_init() { u32 uart_max_dma_size = pt_pkt_data_len_max + sizeof(playload_packet); u32 index = 0; if (uart_max_dma_size & (uart_max_dma_size - 1)) { for (u32 i = 32; i > 1; i--) { if (uart_max_dma_size & BIT(i)) { index = i; break; } } uart_max_dma_size = 1 << (index + 1); } log_debug("uart_max_dma_size=%d,index=%d\n", uart_max_dma_size, index); uart_cbuf = dma_malloc(uart_max_dma_size); memset(uart_cbuf, 0, uart_max_dma_size); struct uart_config config = { .baud_rate = BAUD_RATE, .tx_pin = PT_IO_TX_PIN, .rx_pin = PT_IO_RX_PIN, /* .parity = UART_PARITY_DISABLE, */ }; struct uart_dma_config dma = { .rx_timeout_thresh = 100, .frame_size = pt_pkt_data_len_max, .event_mask = UART_EVENT_RX_DATA | UART_EVENT_RX_FIFO_OVF | UART_EVENT_RX_TIMEOUT, .irq_callback = uart_isr_hook, .rx_cbuffer = uart_cbuf, .rx_cbuffer_size = uart_max_dma_size, }; pt_uart_dev = uart_init(-1, &config); if (pt_uart_dev >= 0) { uart_dma_init(pt_uart_dev, &dma); uart_dump(); log_info("uart_dev_open() success\n"); } } void uart_rx_data_process() { memset(playload_packet, 0, sizeof(struct playload_packet)); #if PT_TEST u32 rx_len = pt_test_dat_read(playload_packet, sizeof(struct playload_packet) + pt_pkt_data_len_max, 1); #else /* #if PT_TEST */ u32 rx_len = uart_recv_blocking(pt_uart_dev, playload_packet, sizeof(struct playload_packet) + pt_pkt_data_len_max, 10); #endif /* #if PT_TEST */ log_debug("pt_rx_data:\n"); log_debug_hexdump((u8 *)playload_packet, rx_len); if (playload_packet->magic != 0xaa55) { return; } if (playload_packet->op != 0x0) { return; } /* log_debug("pk:0x%x, loffset:0x%x \n", playload_packet, &playload_packet->data_len); */ /* log_debug("data_len :%d,%d \n", playload_packet->data_len, playload_packet->data_len + PT_CRC_EXTRA_LEN); */ /* log_debug("crc:0x%x, 0x%x \n", playload_packet->crc, CRC16(&playload_packet->data_len, playload_packet->data_len + PT_CRC_EXTRA_LEN)); */ if (playload_packet->crc == CRC16(&playload_packet->data_len, playload_packet->data_len + PT_CRC_EXTRA_LEN)) { if (product_test_mode == 0) { /* tone_play_stop(); */ #if PT_GPIO_CHECK_LCD_TP ui_set_shut_down_time(10); ui_auto_shut_down_modify(); #endif /* #if PT_GPIO_CHECK_LCD_TP */ } product_test_mode = 1; product_test_pkt_rx(playload_packet->data, playload_packet->data_len); } } static void product_test_main(void *priv) { int msg[32]; int ret; if (GET_PT_MODULE_NUM()) { pt_mod = zalloc(GET_PT_MODULE_NUM() * sizeof(struct pt_mod_stat)); ASSERT(pt_mod); } product_test_module_init(); while (1) { ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg)); if (ret != OS_TASKQ) { continue; } log_info("%s msg:%d", __func__, msg[1]); if (msg[1] == PT_TASK_MSG_RUN) { struct pt_mod_msg *p, *n; list_for_each_entry_safe(p, n, &pt_msg_head, entry) {//用于安全正序遍历所有入口 struct pt_pkt *pkt; u8 module; u32 result = 0; pkt = p->pkt; ASSERT(pkt->pkt_log == PT_PKT_ONCE); // 还未实现拼包 module = PT_ORDER_M_GET(pkt->order);//获取命令 if (module == PT_M_SYSTEM) { pt_system_ioctrl(pkt->order, pkt->data_len, pkt->dat); } else { do { struct pt_mod_stat *stat = product_test_find_module(module); if (stat == NULL) { result = PT_E_MOD_NULL; } else if (stat->init_ok == false) { result = PT_E_MOD_ERROR; } else { if (stat->opt->ioctrl) { stat->opt->ioctrl(pkt->order, pkt->data_len, pkt->dat); break; // ioctrl回调中push } result = PT_E_PARAM; } product_test_push_data(pkt->order, 4, (u8 *)&result); } while (0); } local_irq_disable(); list_del(&p->entry); free(p); local_irq_enable(); } } else if (msg[1] == PT_UART_RX_DAT) { uart_rx_data_process(); } } } static void pt_check_ot() { log_info("%s %d", __func__, __LINE__); if (!product_test_mode) { if (pt_uart_dev >= 0) { uart_deinit(pt_uart_dev); pt_uart_dev = -1; } dma_free(playload_packet); dma_free(uart_cbuf); gpio_set_mode(IO_PORT_SPILT(IO_PORT_DP), PORT_HIGHZ); gpio_set_mode(IO_PORT_SPILT(IO_PORT_DM), PORT_HIGHZ); task_kill(PT_TASK_NAME); } } int pt_simulation_test() { int pt_gpio_simulation_test(); int pt_gsensor_simulation_test(); int pt_moto_simulation_test(); int pt_spk_simulation_test(); /* pt_gpio_simulation_test(); */ /* pt_gsensor_simulation_test(); */ /* pt_moto_simulation_test(); */ pt_spk_simulation_test(); return 0; } // open int product_test_open(void) { int err = 0; #if PT_SIMULATION_TEST pt_simulation_test(); /* ASSERT(0); */ #else u32 por_reset = is_reset_source(P33_VDDIO_LVD_RST) | is_reset_source(P33_VDDIO_POR_RST); if (!por_reset) { return 0; } pt_uart_init(); playload_packet = (struct playload_packet *)dma_malloc(sizeof(struct playload_packet) + pt_pkt_data_len_max); sys_timeout_add(NULL, pt_check_ot, PT_CHECK_OT); err = task_create(product_test_main, NULL, PT_TASK_NAME); #if PT_TEST pt_test_start(); #endif /* #if PT_TEST */ #endif return err; } int product_test_check_run(void) { if (product_test_mode) { return true; } return false; } static u8 pt_idle_query(void) { return !product_test_mode; } REGISTER_LP_TARGET(pt_lp_target) = { .name = "product_test", .is_idle = pt_idle_query, }; #else /* #if PRODUCT_TEST_ENABLE */ int product_test_push_data(u32 order, int len, u8 *dat) { int ret = *((int *)dat); log_debug("product_test_push_data:0x%x \n", ret); return 0; } #endif /* #if PRODUCT_TEST_ENABLE */