Files
2025-12-03 11:12:34 +08:00

283 lines
8.6 KiB
C

#include "product_test.h"
#include "pt_gpio.h"
#include "gpio.h"
#include "asm/gpio_hw.h"
#include "ui/ui_api.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 PT_GPIO_ENABLE
#define GPIO_CHECK_DELAY_US 10
// 记录PCBA中没有外接设备的GPIO。
// 相邻的写在一起,和其他的块之间以IO_PORT_MAX间隔
// 此处以7070为例,PCBA不接屏,不做屏幕测试
// 使用其他芯片时请按实际io和硬件外设配置,删掉没有邦的io口
static const u8 idle_gpio_list[] = {
IO_PORTA_00, IO_PORTA_01, IO_PORT_MAX,//NMOS_IN
IO_PORTA_03, IO_PORT_MAX, //NULL
IO_PORTA_13, IO_PORT_MAX, //NULL
IO_PORTB_00, IO_PORT_MAX, //IO_KEY0
IO_PORTB_04, IO_PORTB_05, IO_PORT_MAX, //sd_nand
IO_PORTC_04, IO_PORTC_05, IO_PORTC_06, IO_PORTC_07, IO_PORTC_08, IO_PORTC_09, IO_PORTC_10, IO_PORTC_11, IO_PORT_MAX, //espi
#if PT_GPIO_CHECK_LCD_TP
IO_PORTA_07, IO_PORTA_08, IO_PORTA_09, IO_PORTA_10, IO_PORTA_11, IO_PORTA_12, IO_PORT_MAX, // LCD CS/D0/D1/D2/D3/CLK
IO_PORTC_00, IO_PORT_MAX, // LCD TE
IO_PORTC_03, IO_PORT_MAX, // LCD RST
IO_PORTA_05, IO_PORTA_06, IO_PORT_MAX, // TP SDA/SCL
IO_PORTB_08, IO_PORT_MAX, //TP INI
IO_PORTA_02, IO_PORT_MAX, //TP RST
#endif /* #if PT_GPIO_CHECK_LCD_TP */
};
static const u32 gpio_regs[] = {
(u32) JL_PORTA,
(u32) JL_PORTB,
(u32) JL_PORTC,
(u32) JL_PORTP,
};
struct pt_gpio {
unsigned int out;
unsigned int dir;
unsigned int pu0;
unsigned int pu1;
unsigned int pd0;
unsigned int pd1;
};
struct pt_gpio pt_gpio1;
struct pt_gpio pt_gpio2;
struct port_reg *pt_gpio_status;
void gpio_status_config(u32 gpio, u32 mode)
{
pt_gpio_status = (struct port_reg *)gpio_regs[gpio / IO_GROUP_NUM];
u32 pt_pin = gpio % 16;
switch (mode & 0xf) {
case 0://保存gpio1的状态
pt_gpio1.out = pt_gpio_status->out & BIT(pt_pin);
pt_gpio1.dir = pt_gpio_status->dir & BIT(pt_pin);
pt_gpio1.pu0 = pt_gpio_status->pu0 & BIT(pt_pin);
pt_gpio1.pu1 = pt_gpio_status->pu1 & BIT(pt_pin);
pt_gpio1.pd0 = pt_gpio_status->pd0 & BIT(pt_pin);
pt_gpio1.pd1 = pt_gpio_status->pd1 & BIT(pt_pin);
break;
case 1://恢复gpio1的状态
pt_gpio_status->out |= pt_gpio1.out;
pt_gpio_status->dir |= pt_gpio1.dir;
pt_gpio_status->pu0 |= pt_gpio1.pu0;
pt_gpio_status->pu1 |= pt_gpio1.pu1;
pt_gpio_status->pd0 |= pt_gpio1.pd0;
pt_gpio_status->pd1 |= pt_gpio1.pd1;
break;
case 2://保存gpio2的状态
pt_gpio2.out = pt_gpio_status->out & BIT(pt_pin);
pt_gpio2.dir = pt_gpio_status->dir & BIT(pt_pin);
pt_gpio2.pu0 = pt_gpio_status->pu0 & BIT(pt_pin);
pt_gpio2.pu1 = pt_gpio_status->pu1 & BIT(pt_pin);
pt_gpio2.pd0 = pt_gpio_status->pd0 & BIT(pt_pin);
pt_gpio2.pd1 = pt_gpio_status->pd1 & BIT(pt_pin);
break;
case 3://恢复gpio2的状态
pt_gpio_status->out |= pt_gpio2.out;
pt_gpio_status->dir |= pt_gpio2.dir;
pt_gpio_status->pu0 |= pt_gpio2.pu0;
pt_gpio_status->pu1 |= pt_gpio2.pu1;
pt_gpio_status->pd0 |= pt_gpio2.pd0;
pt_gpio_status->pd1 |= pt_gpio2.pd1;
break;
}
}
static u8 pt_gpio_busy = 0; // 忙碌标记
static u8 pt_gpio_res = PT_E_SYS_UNREADY; // 测试结果
static int idle_gpio_test(void)
{
int ret = true;
for (int i = 0; i < sizeof(idle_gpio_list) - 1; i++) {
if (idle_gpio_list[i] == IO_PORT_MAX) {
continue;
}
local_irq_disable();
// 保存idle_gpio_list[i]状态
u32 mode = 0;
gpio_status_config(idle_gpio_list[i], mode);
if (idle_gpio_list[i + 1] != IO_PORT_MAX) {
// 保存idle_gpio_list[i+1]状态
mode = 2;
gpio_status_config(idle_gpio_list[i + 1], mode);
// idle_gpio_list[i+1]输出高电平
// idle_gpio_list[i]下拉输入
// delay
// 检测idle_gpio_list[i],高电平标记出错并退出
gpio_set_mode(IO_PORT_SPILT(idle_gpio_list[i + 1]), PORT_OUTPUT_HIGH);
gpio_set_mode(IO_PORT_SPILT(idle_gpio_list[i ]), PORT_INPUT_PULLDOWN_10K);
udelay(100);
if (gpio_read(idle_gpio_list[i])) {
local_irq_enable();
log_error("%s,%d, i:%d, io:%d \n", __func__, __LINE__, i, idle_gpio_list[i]);
return false;
}
// idle_gpio_list[i+1]输出低电平
// idle_gpio_list[i]上拉输入
// delay
// 检测idle_gpio_list[i],低电平标记出错并退出
gpio_set_mode(IO_PORT_SPILT(idle_gpio_list[i + 1]), PORT_OUTPUT_LOW);
gpio_set_mode(IO_PORT_SPILT(idle_gpio_list[i ]), PORT_INPUT_PULLUP_10K);
udelay(100);
if (gpio_read(idle_gpio_list[i]) == 0) {
local_irq_enable();
log_error("%s,%d, i:%d, io:%d \n", __func__, __LINE__, i, idle_gpio_list[i]);
return false;
}
// 恢复idle_gpio_list[i+1]状态
mode = 3;
gpio_status_config(idle_gpio_list[i + 1], mode);
} else {
// idle_gpio_list[i]下拉输入
// delay
// 检测idle_gpio_list[i],高电平标记出错并退出
gpio_set_mode(IO_PORT_SPILT(idle_gpio_list[i ]), PORT_INPUT_PULLDOWN_10K);
udelay(100);
if (gpio_read(idle_gpio_list[i])) {
local_irq_enable();
log_error("%s,%d, i:%d, io:%d \n", __func__, __LINE__, i, idle_gpio_list[i]);
return false;
}
// idle_gpio_list[i]上拉输入
// delay
// 检测idle_gpio_list[i],低电平标记出错并退出
gpio_set_mode(IO_PORT_SPILT(idle_gpio_list[i ]), PORT_INPUT_PULLUP_10K);
udelay(100);
if (gpio_read(idle_gpio_list[i]) == 0) {
local_irq_enable();
log_error("%s,%d, i:%d, io:%d \n", __func__, __LINE__, i, idle_gpio_list[i]);
return false;
}
}
// 恢复idle_gpio_list[i]状态
mode = 1;
gpio_status_config(idle_gpio_list[i], mode);
local_irq_enable();
}
return true;
}
static int pt_gpio_test(int priv)
{
u32 result = PT_E_OK;
if (idle_gpio_test() == false) {
result = PT_E_MOD_ERROR;
}
pt_gpio_busy = 0;
pt_gpio_res = result;
/* product_test_push_data(PT_ORDER_M_SET(PT_M_GPIO) | PT_ORDER_C_SET(PT_N_C_PUSH_RESULT), 4, &result); */
/* product_test_push_data(PT_ORDER_M_SET(PT_M_SYSTEM) | PT_ORDER_C_SET(PT_S_C_HOLD), 4, &result); */
return 0;
}
int pt_gpio_start(void)
{
if (pt_gpio_busy) {
return PT_E_MOD_RUN;
}
#if PT_GPIO_CHECK_LCD_TP
ui_set_shut_down_time(10);
ui_auto_shut_down_modify();
u8 cnt = 100;
while (!lcd_sleep_status()) {
os_time_dly(1);
if (cnt == 0) {
break;
}
cnt --;
}
log_debug("lcd_sleep_status:%d \n", lcd_sleep_status());
#endif /* #if PT_GPIO_CHECK_LCD_TP */
pt_gpio_res = PT_E_MOD_RUN;
int msg[3] = {0};
msg[0] = (int)pt_gpio_test;
msg[1] = 1;
msg[2] = (int)0;
do {
int os_err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
if (os_err == OS_ERR_NONE) {
break;
}
if (os_err != OS_Q_FULL) {
pt_gpio_res = PT_E_SYS_ERROR;
return PT_E_SYS_ERROR;
}
os_time_dly(1);
} while (1);
/* pt_gpio_busy = 1; */
return 0;
}
int pt_gpio_stop(void)
{
if (pt_gpio_busy) {
return PT_E_MOD_CANT_STOP;
}
if (pt_gpio_res == PT_E_MOD_RUN) {
pt_gpio_res = PT_E_MOD_STOP_NO_END;
}
return 0;
}
int pt_gpio_ioctrl(u32 order, int len, void *param)
{
u32 result = 0;
switch (PT_ORDER_C_GET(order)) {
case PT_N_C_START:
result = pt_gpio_start();
break;
case PT_N_C_STOP:
result = pt_gpio_stop();
break;
case PT_N_C_GET_RESULT:
result = pt_gpio_res;
break;
default:
result = PT_E_PARAM;
break;
}
product_test_push_data(order, 4, (u8 *)&result);
return result;
}
REGISTER_PT_MODULE(gpio) = {
.module = PT_M_GPIO,
.attr = PT_ATTR_SELF,
.init = NULL,
.ioctrl = pt_gpio_ioctrl,
};
int pt_gpio_simulation_test()
{
log_debug("%s %d", __func__, __LINE__);
int ret = pt_gpio_test(0);
ASSERT(!pt_gpio_res, "%s result:%d", __func__, pt_gpio_res);
return ret;
}
#endif /* #if PT_GPIO_ENABLE */