维护mtk pmic为mt6623的平台过程中,发现接入其他usb设备时会出现开机十分慢的情况,后来查看log发现是在prelaoder阶段出现了类似于flash_tool握手通信下载的情况,但是由于usb设备没有通信协议,导致最后等待十来秒后通讯失败,跳出通讯等待正常启动,重要Log信息如下:
1.代码跟踪分析
(200217_10:02:42.868)[BLDR] seclib_brom_meta_mode:
(200217_10:02:42.868)hw_set_cc: 450
(200217_10:02:42.868)hw_set_cc: done
(200217_10:02:42.868)step A2 : Standard USB Host!
(200217_10:02:42.868)[PLFM] USB cable in
(200217_10:02:42.868)USB HW reg: index14=0x0
(200217_10:02:42.868)[USBD] USB Full Speed
(200217_10:02:42.868)hw_set_cc: 450
(200217_10:02:42.868)hw_set_cc: done
(200217_10:02:42.868)hw_set_cc: 450
(200217_10:02:42.868)hw_set_cc: done
(200217_10:02:42.868)hw_set_cc: 450
(200217_10:02:42.868)hw_set_cc: done
(200217_10:02:42.868)hw_set_cc: 450
(200217_10:02:42.868)hw_set_cc: done
(200217_10:02:42.868)hw_set_cc: 450
(200217_10:02:42.868)hw_set_cc: done
(200217_10:02:42.868)hw_set_cc: 450
(200217_10:02:42.868)hw_set_cc: done
(200217_10:02:42.869)hw_set_cc: 450
(200217_10:02:42.869)hw_set_cc: done
(200217_10:02:42.869)hw_set_cc: 450
(200217_10:02:42.869)hw_set_cc: done
(200217_10:02:42.869)hw_set_cc: 450
(200217_10:02:42.869)hw_set_cc: done
(200217_10:02:42.869)hw_set_cc: 450
(200217_10:02:42.869)hw_set_cc: done
后来追踪代码(preloader源目录下面)发现:
代码路径:platrom/xxx/src/core/main.c
代码执行:main–>bldr_handshake()
代码路径:platrom/xxx/src/core/handshake_usb.c
代码执行: bldr_handshake()–>usb_handshake()–>usb_cable_in()
bool usb_handshake(struct bldr_command_handler *handler)
{
uint32 enum_tmo = CFG_USB_ENUM_TIMEOUT_EN ? USB_ENUM_TIMEOUT : 0;//获取usb连接超时时间
uint32 handshake_tmo = CFG_USB_HANDSHAKE_TIMEOUT_EN ? USB_SYNC_TIME : 0;
bool result = FALSE;
bool force_download = FALSE;
platform_vusb_on();
//检测是否强制下载
force_download = platform_com_wait_forever_check();
if (TRUE == force_download) {
enum_tmo = 0;
handshake_tmo = 0;
} else if (!usb_cable_in()) {//否则检测是否有usb设备插入
print("%s PMIC not dectect usb cable!\n", MOD);//没有直接返回
return FALSE;
}
//如果有usb设备插入则继续往下走
#if CFG_USB_AUTO_DETECT
platform_usb_auto_detect_flow();
#endif
usbdl_init();
udelay(1000);
usb_disconnect();
//等待usb进行连接通讯
if (usb_connect(enum_tmo) == FALSE) {
//如果在等待时间内没有usb进行通讯连接则直接返回,这里的时间就是参数enum_tmo
print("%s USB enum timeout!\n", MOD);
/* USB enum fail when connecting to a standby PC, remove ASSERT */
/* ASSERT(g_usbphy_ok); */
goto end;
}
udelay(1000);
//如果连接成功,则进行usb通讯
if (FALSE == usb_handshake_handler(handler, handshake_tmo)) {
goto end;
}
result = TRUE;
if (FALSE == usb_port_down(USB_PORT_DOWN_TIME)) {
print("%s USB port down timeout!\n", MOD);
}
end:
usb_service_offline();
#if CFG_USBIF_COMPLIANCE
/* USB compliance test: 100mA charging current when USB is unconfigured. */
platform_set_chrg_cur(70);
#endif
return result;
}
因此根据log来看的,首先进行了usb插入检测,然后再进行usb链接的。
代码路径:preloader/platform/xxx/src/drivers/platform.c
int usb_cable_in(void)
{
#if !CFG_FPGA_PLATFORM && !defined MTK_ALPS_BOX_SUPPORT
int exist = 0;
CHARGER_TYPE ret;
if ((g_boot_reason == BR_USB) || usb_accessory_in()) {//检测usb插入
ret = mt_charger_type_detection();//如果有usb插入,检测类型
if (ret == STANDARD_HOST || ret == CHARGING_HOST) {//根据类型进行相关设置
print("\n%s USB cable in\n", MOD);
mt_usb_phy_poweron();
mt_usb_phy_savecurrent();
/* enable pmic hw charger detection */
#if CFG_BATTERY_DETECT
if (hw_check_battery())
pl_hw_ulc_det();
#endif
exist = 1;
} else if (ret == NONSTANDARD_CHARGER || ret == STANDARD_CHARGER) {
print("\n%s USB cable in - NONSTANDARD CHARGER or STANDARD CHARGER\n", MOD);
#if CFG_USBIF_COMPLIANCE
platform_set_chrg_cur(450);
#endif
#if (CFG_USB_UART_SWITCH)
if (uart_mode) {
print("\n%s Switch back to USB Mode\n", MOD);
set_to_usb_mode();
}
#endif
}
}
return exist;
#else
int exist = 0;
u8 u1_reg =0;
/* enable BG current, this ensure phy can work normal */
USBPHY_CLR8(0x00, 0x20);
USBPHY_SET8(0x00, 0x11);
/* set OTG_VBUSTG = 1.445 v */
USBPHY_SET8(0x06, 0x04);
/* set OTG enable */
USBPHY_SET8(0x1a, 0x10);
/*close vbus by GPIO16 control VBAT.*/
mt_set_gpio_mode(GPIO16, GPIO_MODE_00);
mt_set_gpio_dir(GPIO16, GPIO_DIR_OUT);
mt_set_gpio_pull_enable(GPIO16, GPIO_PULL_ENABLE);
mt_set_gpio_pull_select(GPIO16, GPIO_PULL_UP);
mdelay(100);
/* read vbusvalid bit, when input vbus 5v, phy will modify this bit.*/
u1_reg = usb_readb(0x630);
if((u1_reg &= 0x10) == 0x10)
{
exist = 1;
}
if(exist)
{
print("\n%s USB cable in\n", MOD);
mt_usb_phy_poweron();
mt_usb_phy_savecurrent();
}
return exist;
#endif
}
从上面的代码看出
代码执行: usb_cable_in–>if((g_boot_reason == BR_USB) || usb_accessory_in())–>mt_charger_type_detection
usb_accessory_in–>if(PMIC_CHRDET_EXIST == pmic_IsUsbCableIn())//检测usb插入。
源码路径:preloader/platform/ac8227l/src/drivers/pmic_6323.c
代码执行:mt_charger_type_detection-->hw_charger_type_detection–>hw_charger_type_detection–>
else(1hw_bc11_DCD())–>else(1hw_bc11_stepA2())—>upmu_get_rgs_bc11_cmp_out—>
pmic_read_interface//获取充电类型
usb等待连接:传进来的参数u32 tmo是连接的超时时间
代码路径:platrom/xxx/src/core/handshake_usb.c
static bool usb_connect(u32 tmo)
{
ulong start_time = get_timer(0);
bool result = FALSE;
u32 i = 1;
mt_usb_disconnect_internal();
mt_usb_connect_internal();
#if CFG_USBIF_COMPLIANCE
/* USB compliance test: 100mA charging current when USB is unconfigured. */
platform_set_chrg_cur(70);
#endif
print("%s Enumeration(Start)\n", MOD);
//在这里进行检测usb连接,如果在规定时间tmo内
do {
/* kick wdt to avoid cpu reset during usb driver installation if not present */
platform_wdt_all_kick();
service_interrupts();
//usb连接成功就退出
if (usbdl_configured()) {
#if CFG_USBIF_COMPLIANCE
/* USB compliance test: 500mA charging current when USB is configured but
* we set the charging current to 450mA since 500mA doesn't support in the
* platform.
*/
//usb连接成功则退出循环
platform_set_chrg_cur(450);
#endif
result = TRUE;
break;
}
if (tmo) {
/* enable timeout mechanism */
//检测是否超过超时连接时间,超过便跳出while
if (get_timer(start_time) > tmo)
break;
#if !CFG_FPGA_PLATFORM
/* cable plugged-out and power key detection each 1 second */
//隔1000ms进行一次usb插入检测
if (get_timer(start_time) > i * 1000) {
if (!usb_accessory_in() && !pmic_detect_powerkey())
pl_power_off();
#if !CFG_EVB_PLATFORM
/* check bypass power key from the 2nd second */
if (i > 1 && pmic_detect_powerkey()) {
print("%s Enumeration(Skip): powerkey pressed\n", MOD);
break;
}
i++;
#endif
}
#endif
}
} while(1);
print("%s Enumeration(End): %s %dms \n", MOD, result == TRUE ? "OK" : "TMO",
get_timer(start_time));
return result;
}
从上面的代码看出,usb连接过程中如果连接成功就马上退出,否则就不断等待usb连接,等待超过时间tmo就跳出等待。从上面的代码看出tmo的时间来自USB_ENUM_TIMEOUT,
uint32 enum_tmo = CFG_USB_ENUM_TIMEOUT_EN ? USB_ENUM_TIMEOUT : 0;//获取usb连接超时时间
USB_ENUM_TIMEOUT在代码:platform/ac8227l/src/drivers/inc/platform.h中定义。
#define CFG_USB_ENUM_TIMEOUT (8000) /* 8000ms */
因此这就能解析为何会插入异常usb设备后,usb设备错误的被当做充电设备,然后进行在usb连接的时候一直没有连接成功,等待超时时间超过8秒后直接退出。这就造成了开机延迟了很久。
2.解决方案
直接把超时时间改为2秒
#define CFG_USB_ENUM_TIMEOUT (2000) /* 2000ms */