283 lines
8.6 KiB
C
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 */
|
|
|