summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/modstm.c7
-rw-r--r--ports/stm32/rfcore.c103
-rw-r--r--ports/stm32/rfcore.h4
3 files changed, 96 insertions, 18 deletions
diff --git a/ports/stm32/modstm.c b/ports/stm32/modstm.c
index 418b8bde2..3f4f33979 100644
--- a/ports/stm32/modstm.c
+++ b/ports/stm32/modstm.c
@@ -30,6 +30,7 @@
#include "py/obj.h"
#include "py/objint.h"
#include "extmod/machine_mem.h"
+#include "rfcore.h"
#include "portmodules.h"
#if MICROPY_PY_STM
@@ -44,6 +45,12 @@ STATIC const mp_rom_map_elem_t stm_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
#include "genhdr/modstm_const.h"
+
+ #if defined(STM32WB)
+ { MP_ROM_QSTR(MP_QSTR_rfcore_status), MP_ROM_PTR(&rfcore_status_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rfcore_fw_version), MP_ROM_PTR(&rfcore_fw_version_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rfcore_sys_hci), MP_ROM_PTR(&rfcore_sys_hci_obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(stm_module_globals, stm_module_globals_table);
diff --git a/ports/stm32/rfcore.c b/ports/stm32/rfcore.c
index dc23bbe0b..436042cc2 100644
--- a/ports/stm32/rfcore.c
+++ b/ports/stm32/rfcore.c
@@ -30,6 +30,7 @@
#include "py/mperrno.h"
#include "py/mphal.h"
+#include "py/runtime.h"
#include "rtc.h"
#include "rfcore.h"
@@ -66,9 +67,16 @@
#define HCI_EVENT_COMMAND_COMPLETE (0x0E) // <num packets><opcode 16><status><data...>
-#define SYS_ACK_TIMEOUT_MS (250)
+// There can be quite long delays during firmware update.
+#define SYS_ACK_TIMEOUT_MS (1000)
+
#define BLE_ACK_TIMEOUT_MS (250)
+// AN5185
+#define MAGIC_FUS_ACTIVE 0xA94656B9
+// AN5289
+#define MAGIC_IPCC_MEM_INCORRECT 0x3DE96F61
+
typedef struct _tl_list_node_t {
volatile struct _tl_list_node_t *next;
volatile struct _tl_list_node_t *prev;
@@ -267,10 +275,10 @@ void ipcc_init(uint32_t irq_pri) {
/******************************************************************************/
// Transport layer HCI interface
-STATIC void tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
+STATIC size_t tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
const char *info;
- size_t len = 0;
bool applied_set_event_event_mask2_fix = false;
+ size_t len;
switch (buf[0]) {
case HCI_KIND_BT_ACL: {
info = "HCI_ACL";
@@ -334,6 +342,7 @@ STATIC void tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
}
default:
info = "HCI_UNKNOWN";
+ len = 0;
break;
}
@@ -354,6 +363,8 @@ STATIC void tl_parse_hci_msg(const uint8_t *buf, parse_hci_info_t *parse) {
#else
(void)info;
#endif
+
+ return len;
}
STATIC void tl_process_msg(volatile tl_list_node_t *head, unsigned int ch, parse_hci_info_t *parse) {
@@ -397,7 +408,7 @@ STATIC void tl_check_msg_ble(volatile tl_list_node_t *head, parse_hci_info_t *pa
}
}
-STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opcode, size_t len, const uint8_t *buf) {
+STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opcode, const uint8_t *buf, size_t len) {
tl_list_node_t *n = (tl_list_node_t *)cmd;
n->next = n;
n->prev = n;
@@ -407,11 +418,19 @@ STATIC void tl_hci_cmd(uint8_t *cmd, unsigned int ch, uint8_t hdr, uint16_t opco
cmd[11] = len;
memcpy(&cmd[12], buf, len);
+ #if HCI_TRACE
+ printf("[% 8d] >HCI(", mp_hal_ticks_ms());
+ for (int i = 0; i < len + 4; ++i) {
+ printf(":%02x", cmd[i + 8]);
+ }
+ printf(")\n");
+ #endif
+
// Indicate that this channel is ready.
LL_C1_IPCC_SetFlag_CHx(IPCC, ch);
}
-STATIC int tl_sys_wait_ack(const uint8_t *buf) {
+STATIC ssize_t tl_sys_wait_ack(const uint8_t *buf) {
uint32_t t0 = mp_hal_ticks_ms();
// C2 will clear this bit to acknowledge the request.
@@ -422,14 +441,14 @@ STATIC int tl_sys_wait_ack(const uint8_t *buf) {
}
}
- // C1-to-C2 bit cleared, so process (but ignore) the response.
- tl_parse_hci_msg(buf, NULL);
- return 0;
+ // C1-to-C2 bit cleared, so process the response (just get the length, do
+ // not parse any further).
+ return (ssize_t)tl_parse_hci_msg(buf, NULL);
}
-STATIC void tl_sys_hci_cmd_resp(uint16_t opcode, size_t len, const uint8_t *buf) {
- tl_hci_cmd(ipcc_membuf_sys_cmd_buf, IPCC_CH_SYS, 0x10, opcode, len, buf);
- tl_sys_wait_ack(ipcc_membuf_sys_cmd_buf);
+STATIC ssize_t tl_sys_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t len) {
+ 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);
}
STATIC int tl_ble_wait_resp(void) {
@@ -447,10 +466,9 @@ STATIC int tl_ble_wait_resp(void) {
}
// Synchronously send a BLE command.
-STATIC void tl_ble_hci_cmd_resp(uint16_t opcode, size_t len, const uint8_t *buf) {
- tl_hci_cmd(ipcc_membuf_ble_cmd_buf, IPCC_CH_BLE, HCI_KIND_BT_CMD, opcode, len, buf);
+STATIC void tl_ble_hci_cmd_resp(uint16_t opcode, const uint8_t *buf, size_t len) {
+ tl_hci_cmd(ipcc_membuf_ble_cmd_buf, IPCC_CH_BLE, HCI_KIND_BT_CMD, opcode, buf, len);
tl_ble_wait_resp();
-
}
/******************************************************************************/
@@ -522,8 +540,8 @@ 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), sizeof(ble_init_params), (const uint8_t *)&ble_init_params);
- tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), 0, NULL);
+ tl_sys_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_BLE_INIT), (const uint8_t *)&ble_init_params, sizeof(ble_init_params));
+ tl_ble_hci_cmd_resp(HCI_OPCODE(0x03, 0x0003), NULL, 0);
}
void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) {
@@ -573,14 +591,14 @@ void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env)
SWAP_UINT8(buf[2], buf[7]);
SWAP_UINT8(buf[3], buf[6]);
SWAP_UINT8(buf[4], buf[5]);
- tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_WRITE_CONFIG), 8, buf); // set BDADDR
+ tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_WRITE_CONFIG), buf, 8); // set BDADDR
}
}
// "level" is 0x00-0x1f, ranging from -40 dBm to +6 dBm (not linear).
void rfcore_ble_set_txpower(uint8_t level) {
uint8_t buf[2] = { 0x00, level };
- tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_SET_TX_POWER), 2, buf);
+ tl_ble_hci_cmd_resp(HCI_OPCODE(OGF_VENDOR, OCF_SET_TX_POWER), buf, 2);
}
// IPCC IRQ Handlers
@@ -605,4 +623,53 @@ void IPCC_C1_RX_IRQHandler(void) {
IRQ_EXIT(IPCC_C1_RX_IRQn);
}
+/******************************************************************************/
+// MicroPython bindings
+
+STATIC mp_obj_t rfcore_status(void) {
+ return mp_obj_new_int_from_uint(ipcc_mem_dev_info_tab.fus.table_state);
+}
+MP_DEFINE_CONST_FUN_OBJ_0(rfcore_status_obj, rfcore_status);
+
+STATIC mp_obj_t get_version_tuple(uint32_t data) {
+ mp_obj_t items[] = {
+ MP_OBJ_NEW_SMALL_INT(data >> 24), MP_OBJ_NEW_SMALL_INT(data >> 16 & 0xFF), MP_OBJ_NEW_SMALL_INT(data >> 8 & 0xFF), MP_OBJ_NEW_SMALL_INT(data >> 4 & 0xF), MP_OBJ_NEW_SMALL_INT(data & 0xF)
+ };
+ return mp_obj_new_tuple(5, items);
+}
+
+STATIC mp_obj_t rfcore_fw_version(mp_obj_t fw_id_in) {
+ if (ipcc_mem_dev_info_tab.fus.table_state == MAGIC_IPCC_MEM_INCORRECT) {
+ mp_raise_OSError(MP_EINVAL);
+ }
+ mp_int_t fw_id = mp_obj_get_int(fw_id_in);
+ bool fus_active = ipcc_mem_dev_info_tab.fus.table_state == MAGIC_FUS_ACTIVE;
+ uint32_t v;
+ if (fw_id == 0) {
+ // FUS
+ v = fus_active ? ipcc_mem_dev_info_tab.fus.fus_version : ipcc_mem_dev_info_tab.ws.fus_version;
+ } else {
+ // WS
+ v = fus_active ? ipcc_mem_dev_info_tab.fus.ws_version : ipcc_mem_dev_info_tab.ws.fw_version;
+ }
+ return get_version_tuple(v);
+}
+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) {
+ 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_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);
+ 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);
+
#endif // defined(STM32WB)
diff --git a/ports/stm32/rfcore.h b/ports/stm32/rfcore.h
index fbe111e1e..39f6220a3 100644
--- a/ports/stm32/rfcore.h
+++ b/ports/stm32/rfcore.h
@@ -35,4 +35,8 @@ void rfcore_ble_hci_cmd(size_t len, const uint8_t *src);
void rfcore_ble_check_msg(int (*cb)(void *, const uint8_t *, size_t), void *env);
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);
+
#endif // MICROPY_INCLUDED_STM32_RFCORE_H