From 893f75546c4e65ca5b72bc7ef9b91003372c4705 Mon Sep 17 00:00:00 2001 From: Jim Mussared Date: Thu, 15 Oct 2020 20:35:11 +1100 Subject: [PATCH] stm32/boards/NUCLEO_WB55/rfcore_firmware.py: Increase GET_STATE timeout. When installing WS firmware, the very first GET_STATE can take several seconds to respond (especially with the larger binaries like BLE_stack_full). Allows stm.rfcore_sys_hci to take an optional timeout, defaulting to SYS_ACK_TIMEOUT_MS (which is 250ms). Signed-off-by: Jim Mussared --- .../boards/NUCLEO_WB55/rfcore_firmware.py | 18 +++++++---- ports/stm32/rfcore.c | 32 +++++++++++-------- ports/stm32/rfcore.h | 2 +- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py b/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py index 3358b246d..b5f1d0072 100644 --- a/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py +++ b/ports/stm32/boards/NUCLEO_WB55/rfcore_firmware.py @@ -180,6 +180,12 @@ _PATH_WS_BLE_HCI = "ws_ble_hci.bin" _ADDR_FUS = 0x080EC000 _ADDR_WS_BLE_HCI = 0x080DC000 +# When installing the FUS/WS it can take a long time to return to the first +# GET_STATE HCI command. +# e.g. Installing stm32wb5x_BLE_Stack_full_fw.bin takes 3600ms to respond. +_INSTALLING_FUS_GET_STATE_TIMEOUT = const(1000) +_INSTALLING_WS_GET_STATE_TIMEOUT = const(6000) + def log(msg, *args, **kwargs): print("[rfcore update]", msg.format(*args, **kwargs)) @@ -272,10 +278,10 @@ def _parse_vendor_response(data): return (op >> 10, op & 0x3FF, data[6], data[7] if len(data) > 7 else 0) -def _run_sys_hci_cmd(ogf, ocf, buf=b""): +def _run_sys_hci_cmd(ogf, ocf, buf=b"", timeout=0): try: ogf_out, ocf_out, status, result = _parse_vendor_response( - stm.rfcore_sys_hci(ogf, ocf, buf) + stm.rfcore_sys_hci(ogf, ocf, buf, timeout) ) except OSError: # Timeout or FUS not active. @@ -285,8 +291,8 @@ def _run_sys_hci_cmd(ogf, ocf, buf=b""): return (status, result) -def fus_get_state(): - return _run_sys_hci_cmd(_OGF_VENDOR, _OCF_FUS_GET_STATE) +def fus_get_state(timeout=0): + return _run_sys_hci_cmd(_OGF_VENDOR, _OCF_FUS_GET_STATE, timeout=timeout) def fus_is_idle(): @@ -468,7 +474,7 @@ def resume(): # followed by a (255,0), followed by (0, 0). elif state == _STATE_INSTALLING_FUS: log("Installing FUS...") - status, result = fus_get_state() + status, result = fus_get_state(_INSTALLING_FUS_GET_STATE_TIMEOUT) log("FUS state: {} {}", status, result) if 0x20 <= status <= 0x2F and result == 0: # FUS_STATE_FUS_UPGRD_ONGOING @@ -520,7 +526,7 @@ def resume(): # As for _STATE_INSTALLING_FUS above. elif state == _STATE_INSTALLING_WS: log("Installing WS...") - status, result = fus_get_state() + status, result = fus_get_state(_INSTALLING_WS_GET_STATE_TIMEOUT) log("FUS state: {} {}", status, result) if 0x10 <= status <= 0x1F and result == 0: # FUS_STATE_FW_UPGRD_ONGOING diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c index 3850a17da..1fc0c9531 100644 --- a/ports/stm32/rfcore.c +++ b/ports/stm32/rfcore.c @@ -68,9 +68,7 @@ #define HCI_EVENT_COMMAND_COMPLETE (0x0E) // #define HCI_EVENT_COMMAND_STATUS (0x0F) // -// There can be quite long delays during firmware update. -#define SYS_ACK_TIMEOUT_MS (1000) - +#define SYS_ACK_TIMEOUT_MS (250) #define BLE_ACK_TIMEOUT_MS (250) // AN5185 @@ -449,12 +447,14 @@ STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opco LL_C1_IPCC_SetFlag_CHx(IPCC, ch); } -STATIC ssize_t tl_sys_wait_ack(const uint8_t *buf) { +STATIC ssize_t tl_sys_wait_ack(const uint8_t *buf, mp_int_t timeout_ms) { uint32_t t0 = mp_hal_ticks_ms(); + timeout_ms = MAX(SYS_ACK_TIMEOUT_MS, timeout_ms); + // C2 will clear this bit to acknowledge the request. while (LL_C1_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_SYS)) { - if (mp_hal_ticks_ms() - t0 > SYS_ACK_TIMEOUT_MS) { + if (mp_hal_ticks_ms() - t0 > timeout_ms) { printf("tl_sys_wait_ack: timeout\n"); return -MP_ETIMEDOUT; } @@ -465,9 +465,9 @@ STATIC ssize_t tl_sys_wait_ack(const uint8_t *buf) { return (ssize_t)tl_parse_hci_msg(buf, NULL); } -STATIC ssize_t tl_sys_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t len) { +STATIC ssize_t tl_sys_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t len, mp_int_t timeout_ms) { tl_hci_cmd(ipcc_membuf_sys_cmd_buf, IPCC_CH_SYS, 0x10, opcode, buf, len); - return tl_sys_wait_ack(ipcc_membuf_sys_cmd_buf); + return tl_sys_wait_ack(ipcc_membuf_sys_cmd_buf, timeout_ms); } STATIC int tl_ble_wait_resp(void) { @@ -559,7 +559,7 @@ void rfcore_ble_init(void) { tl_check_msg_ble(&ipcc_mem_ble_evt_queue, NULL); // Configure and reset the BLE controller - tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params)); + tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params), 0); tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0); } @@ -675,20 +675,24 @@ STATIC mp_obj_t rfcore_fw_version(mp_obj_t fw_id_in) { } MP_DEFINE_CONST_FUN_OBJ_1(rfcore_fw_version_obj, rfcore_fw_version); -STATIC mp_obj_t rfcore_sys_hci(mp_obj_t ogf_in, mp_obj_t ocf_in, mp_obj_t cmd_in) { +STATIC mp_obj_t rfcore_sys_hci(size_t n_args, const mp_obj_t *args) { if (ipcc_mem_dev_info_tab.fus.table_state == MAGIC_IPCC_MEM_INCORRECT) { mp_raise_OSError(MP_EINVAL); } - mp_int_t ogf = mp_obj_get_int(ogf_in); - mp_int_t ocf = mp_obj_get_int(ocf_in); + mp_int_t ogf = mp_obj_get_int(args[0]); + mp_int_t ocf = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo = {0}; - mp_get_buffer_raise(cmd_in, &bufinfo, MP_BUFFER_READ); - ssize_t len = tl_sys_hci_cmd_resp(HCI_OPCODE(ogf, ocf), bufinfo.buf, bufinfo.len); + mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); + mp_int_t timeout_ms = 0; + if (n_args >= 4) { + timeout_ms = mp_obj_get_int(args[3]); + } + ssize_t len = tl_sys_hci_cmd_resp(HCI_OPCODE(ogf, ocf), bufinfo.buf, bufinfo.len, timeout_ms); if (len < 0) { mp_raise_OSError(-len); } return mp_obj_new_bytes(ipcc_membuf_sys_cmd_buf, len); } -MP_DEFINE_CONST_FUN_OBJ_3(rfcore_sys_hci_obj, rfcore_sys_hci); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_sys_hci_obj, 3, 4, rfcore_sys_hci); #endif // defined(STM32WB) diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h index 39f6220a3..6a3c85f67 100644 --- a/ports/stm32/rfcore.h +++ b/ports/stm32/rfcore.h @@ -37,6 +37,6 @@ void rfcore_ble_set_txpower(uint8_t level); MP_DECLARE_CONST_FUN_OBJ_0(rfcore_status_obj); MP_DECLARE_CONST_FUN_OBJ_1(rfcore_fw_version_obj); -MP_DECLARE_CONST_FUN_OBJ_3(rfcore_sys_hci_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(rfcore_sys_hci_obj); #endif // MICROPY_INCLUDED_STM32_RFCORE_H