ARM-LINUX开发板通过SDIO 接口和AIC8800M40低功耗WIFI/BT芯片连接,然后整个WIFI协议栈都是跑在AIC8800M40芯片上面,所以就不需要LINUX的WIFI驱动和CFG80211协议栈,当然AIC8800M40的固件就需要能够OTA升级了,看了下SDK提供的文档,OTA升级可以通过HOST_OTA和HTTP_OTA,这里我记录一下HOST OTA方式的调试经验:
FLASH分区
首先看一下整个FLASH的分区,bootloader有20KB,当前工作区(包含image_info和cur_image),备份分区(可以删除),OTA升级分区(image_header + upg_image)
从上图可以看到升级分区的烧写地址是0x08156000,当前工作区代码运行的地址为0x08006000。升级分区LZMA压缩代码段地址为0x08157000;
1:制作包含bootloader的基础固件:
/**********************LZMA OTA BUILD********************/
./build_fhostif_wifi_case.sh -j8
cd ../target_test/
./build_lzma_bootloader.sh -j8
cd ../../../docs/Tool/OTA-Tool/bootloader_lzma
cp ../../../../build/basic-aic8800m40/bootloader.bin source/bootloader.bin
cp ../../../../build/host-wifi-aic8800m40/host_wb_aic8800m40.bin source/host_wb.bin
python ota_bin_generator.py
2:制作升级的OTA固件:
cp ../../../../build/host-wifi-aic8800m40/host_wb_aic8800m40.bin source/host_wb_upg.bin
python image_pack_ota.py 0x8157000 v0.1.3 //注意这里的0x8157000是LZMA升级固件的地址,v0.1.3是版本号
下面列举一下在调试过程中碰到的问题:
问题1:
通过在linux host上发送升级命令:custom_msg vnet0 13 /app/host_wb_upg_lzma.bin,然后通过串口查看wifi芯片的打印,发现wifi芯片直接栈溢出死机了:
解决方案:加大Hostif task线程栈的深度,从原来的384字节翻一倍到768字节:
index e3711b6..cc4497c 100644
--- a/aic8800-sdk/applications/fhostifwifi/src/fhostif_example.c
+++ b/aic8800-sdk/applications/fhostifwifi/src/fhostif_example.c
@@ -834,7 +834,7 @@ int fhost_application_init(void)
}
if (rtos_task_create(hostif_task, "Hostif task", APP_HOSTIF_TASK,
- 384, NULL, TASK_PRIORITY_HOSTIF, NULL)) {
+ 768, NULL, TASK_PRIORITY_HOSTIF, NULL)) {
return 3;
}
if (rtos_task_create(hostif_rxdata_task, "Hostif rxdata", APP_HOSTIF_RX_TASK,
问题2:
在Linux主机上第一次发送custom_msg vnet0 13 /app/host_wb_upg_lzma.bin命令升级不成功,需要发送第二次才能成功,查看了一下linux主机dmesg log:
[ 163.003209] rwnx_do_ioctl cmd 35314
[ 163.003216] IOCTL PRIVATE+2
[ 163.003219] AICWFDBG(LOGTRACE) >>> mcu_cust_msg()
[ 163.003223] mcu_cust_msg: Devipc custom msg "13 /app/host_wb_upg_lzma.bin" on vnet0
[ 163.003230] APP_CMD_HOST_OTA
[ 163.003234] load_file: /app/host_wb_upg_lzma.bin
[ 163.003248] bin-file size: 521727 Byte
[ 163.003256] aicwf_sdio_bus_txmsg 1056
[ 165.057479] error: aicwf mcu-ota confirm timeout
[ 166.171683] MCU-OTA: flash erase OK.
这里发现错误打印:aicwf mcu-ota confirm timeout,通过查看代码发现是主机等待wifi芯片擦除flash 2秒超时了,估计擦除时间比较长,需要3秒多,干脆把超时时间调整为8秒,改动如下:
index f270e77..97b62c7 100644
--- a/aic8800-sdk/wifi/LinuxDriver/aic8800_netdrv/aicwf_custom_utils.h
+++ b/aic8800-sdk/wifi/LinuxDriver/aic8800_netdrv/aicwf_custom_utils.h
@@ -13,7 +13,7 @@
#include "rwnx_main.h"
-#define MCU_OTA_TIMEOUT 2000
+#define MCU_OTA_TIMEOUT 8000
#define IMAGE_INFO_SIZE 0x1000
enum OTA_STEP
改动之后,OTA成功升级,Log打印如下:
/app # dmesg -c
[ 515.323602] rwnx_do_ioctl cmd 35314
[ 515.323608] IOCTL PRIVATE+2
[ 515.323611] AICWFDBG(LOGTRACE) >>> mcu_cust_msg()
[ 515.323615] mcu_cust_msg: Devipc custom msg "13 /app/host_wb_upg_lzma.bin" on vnet0
[ 515.323622] APP_CMD_HOST_OTA
[ 515.323626] load_file: /app/host_wb_upg_lzma.bin
[ 515.323639] bin-file size: 521727 Byte
[ 515.323647] aicwf_sdio_bus_txmsg 1056
[ 518.523923] MCU-OTA: flash erase OK.
[ 518.523958] aicwf_sdio_bus_txmsg 1056
[ 518.526858] aicwf_sdio_bus_txmsg 1056
[ 518.529762] aicwf_sdio_bus_txmsg 1056
[ 520.033543] MCU-OTA: finish LZMA-OTA...
问题三
升级成功后,重启linux系统,发现SDIO WIFI识别不成功,查看一下WIFI芯片的串口打印:
发现wifi芯片重启后,bootloader首先会检测升级分区的版本号,如果有新的版本,则会把升级分区的image搬运到当前的image工作区,这个过程比较耗时;虽然我们linux kernel的SDIO设备检测扫描会延迟3秒,但bootloader搬运的时间加上WIFI系统启动时间远远大于3秒,就会造成SDIO扫描检测不成功。
解决方案:WIFI固件升级后,直接让WIFI芯片重启,而不是等到主控芯片的WIFI ENABLE GPIO来拉低电平重启,修改代码如下:
--- a/aic8800-sdk/wifi/hostif/fhostif_cmd.c
+++ b/aic8800-sdk/wifi/hostif/fhostif_cmd.c
@@ -51,7 +51,7 @@
#define HOSTIF_KEEP_ALIVE 0
#define HOST_CNTRL_DHCP 0
-#define HOST_OTA_REBOOT 0
+#define HOST_OTA_REBOOT 1
#if HOSTIF_KEEP_ALIVE
struct custom_msg_keep_alive
@@ -1135,17 +1135,17 @@ static int custom_msg_start_ap_handler(uint16_t const host_type,
set_hostif_wlan_status(HOSTIF_ST_IDLE);
dbg("HOSTIF_ST: IDLE\n");
-
+#if 1
// If sta is CONN or ap is START, close it first.
if (WLAN_CONNECTED == wlan_get_connect_status()) {
msg.id = WIFI_STA_DISCONNECT;
wifi_msg_write(&msg);
}
+#endif
if (wlan_get_softap_status()) {
msg.id = WIFI_AP_STOP;
wifi_msg_write(&msg);
}
-
uint8_t *pssid = rtos_malloc(SSID_LEN);
if (pssid == NULL) {
dbg("alloc buff fail.\n");
@@ -1470,6 +1470,7 @@ static int custom_msg_host_ota_handler(uint16_t const host_type,
} else {
flash_cache_invalid_range((void *)UPGRADE_START_ADDR, 0x1000 + a4k);
cfm->status = OTA_STEP_FLASH_ERASE_OK;
+ dbg("OTA-Step0: flash erase addr=0x%x, len=0x%x\n", UPGRADE_START_ADDR ,0x1000 + a4k);
}
} else if(OTA_STEP_FR_PKG_WRITE == req->ota_step) {
@@ -1478,6 +1479,7 @@ static int custom_msg_host_ota_handler(uint16_t const host_type,
dbg("OTA_Step1: write pkg at 0x%x fail. Please restart OTA.\r\n", req->ota_msg.ota_pkg_info.flash_addr);
cfm->status = OTA_STEP_FR_PKG_WRITE_ERR;
} else {
+ dbg("OTA_Step1: write pkg at 0x%x ,size 0x%x \r\n", req->ota_msg.ota_pkg_info.flash_addr, req->ota_msg.ota_pkg_info.flash_size);
cfm->status = OTA_STEP_FR_PKG_WRITE_OK;
}
@@ -1493,6 +1495,7 @@ static int custom_msg_host_ota_handler(uint16_t const host_type,
flash_cache_invalid_range((void *)UPGRADE_IMAGE_ADDR,
(req->ota_msg.ota_pkg_info.flash_addr - UPGRADE_IMAGE_ADDR) + req->ota_msg.ota_pkg_info.flash_size);
cfm->status = OTA_STEP_LT_PKG_WRITE_OK;
+ dbg("OTA_Step2: recv last pkg and write OK, UPGRADE_IMAGE_ADDR = 0x%x.\r\n", UPGRADE_IMAGE_ADDR);
}
}
@@ -1516,7 +1519,7 @@ static int custom_msg_host_ota_handler(uint16_t const host_type,
// Use OTA-Tool to build OTA.bin, its version is "v0.1.0".
// Updated version is necessary and newer (than "v0.1.0") when build newer bin!
- char *version = "v0.1.1"; // strlen(version) <= VER_BYTE_CNT
+ char *version = "v0.1.2"; // strlen(version) <= VER_BYTE_CNT
struct image_info *curr_info = (void *)CURRENT_INFO_ADDR;
dbg("OTA_Step3: new-version is %s, curr-version is %s\n", version, curr_info->version);
if (strcmp((const char *)curr_info->version, version) >= 0) {
@@ -1561,8 +1564,17 @@ static int custom_msg_host_ota_handler(uint16_t const host_type,
dbg("OTA_Step3: erease upg_image header fail.\n");
}
} else {
- dbg("OTA_Step3: LZMA OTA finish...\n");
+ dbg("OTA_Step3: LZMA OTA finish....\n");
cfm->status = OTA_STEP_LZMA_CRC_CHECK_OK;
+ e2a_msg_send(host_type, cfm);
+ #if HOST_OTA_REBOOT
+ int ret = rtos_timer_start(reboot_timer, 1000, false);
+ if (ret)
+ dbg("start reboot_timer failed: %d\n", ret);
+ #endif
+ return KE_MSG_CONSUMED;
+
+
}
}
}
@@ -1574,12 +1586,6 @@ static int custom_msg_host_ota_handler(uint16_t const host_type,
e2a_msg_send(host_type, cfm);
#endif /* PLF_OTA */
- #if HOST_OTA_REBOOT
- int ret = rtos_timer_start(reboot_timer, 1000, false);
- if (ret)
- dbg("start reboot_timer failed: %d\n", ret);
- #endif
-
return KE_MSG_CONSUMED;
}