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 <jim.mussared@gmail.com>
This commit is contained in:
Jim Mussared 2020-10-15 20:35:11 +11:00 committed by Damien George
parent dfb63b5613
commit 893f75546c
3 changed files with 31 additions and 21 deletions

View File

@ -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

View File

@ -68,9 +68,7 @@
#define HCI_EVENT_COMMAND_COMPLETE (0x0E) // <num packets><opcode 16><status><data...>
#define HCI_EVENT_COMMAND_STATUS (0x0F) // <status><num_packets><opcode 16>
// 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)

View File

@ -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