From d5fb52373334635791ec3e98b6022b2935081414 Mon Sep 17 00:00:00 2001 From: Yasmin Bosch Date: Sun, 17 Mar 2024 16:23:10 +0100 Subject: [PATCH 1/5] ports/unix/Makefile: Move up "HAVE_LIBUSB" code to be effective. There is a code that evaluates "HAVE_LIBUSB" and then sets "MICROPY_BLUETOOTH_BTSTACK_USB" and "MICROPY_BLUETOOTH_BTSTACK_H4" accordingly. That code has been moved before "include $(TOP)/extmod/extmod.mk" to be effective. Details: "include $(TOP)/extmod/extmod.mk" will "include $(TOP)/extmod/btstack/btstack.mk" and that in turn sets "MICROPY_BLUETOOTH_BTSTACK_USB ?= 0" "MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1" Signed-off-by: Yasmin Bosch --- ports/unix/Makefile | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index f02e6c6355ab6..67d706e98b7eb 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -33,6 +33,25 @@ QSTR_GLOBAL_DEPENDENCIES += $(VARIANT_DIR)/mpconfigvariant.h # OS name, for simple autoconfig UNAME_S := $(shell uname -s) +# If the variant enables it, enable modbluetooth. +ifeq ($(MICROPY_PY_BLUETOOTH),1) +ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) +HAVE_LIBUSB := $(shell (which pkg-config > /dev/null && pkg-config --exists libusb-1.0) 2>/dev/null && echo '1') + +# Figure out which BTstack transport to use. +ifeq ($(HAVE_LIBUSB),1) +# Default to btstack-over-usb. +MICROPY_BLUETOOTH_BTSTACK_USB ?= 1 +MICROPY_BLUETOOTH_BTSTACK_H4 ?= 0 +else +# Fallback to HCI controller via a H4 UART (e.g. Zephyr on nRF) over a /dev/tty serial port. +MICROPY_BLUETOOTH_BTSTACK_USB ?= 0 +MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 +endif + +endif +endif + # include py core make definitions include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk @@ -144,20 +163,8 @@ ifeq ($(MICROPY_SSL_AXTLS),1) endif endif -# If the variant enables it, enable modbluetooth. ifeq ($(MICROPY_PY_BLUETOOTH),1) ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) -HAVE_LIBUSB := $(shell (which pkg-config > /dev/null && pkg-config --exists libusb-1.0) 2>/dev/null && echo '1') - -# Figure out which BTstack transport to use. -ifeq ($(HAVE_LIBUSB),1) -# Default to btstack-over-usb. -MICROPY_BLUETOOTH_BTSTACK_USB ?= 1 -else -# Fallback to HCI controller via a H4 UART (e.g. Zephyr on nRF) over a /dev/tty serial port. -MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 -endif - SRC_BTSTACK_C += lib/btstack/platform/embedded/btstack_run_loop_embedded.c endif endif From afe286737f19b3a5bbcdfc452abfb5224db8137d Mon Sep 17 00:00:00 2001 From: Yasmin Bosch Date: Sun, 17 Mar 2024 16:24:59 +0100 Subject: [PATCH 2/5] =?UTF-8?q?ports/unix:=20Fix=20"=E2=80=98signal=5Fsco?= =?UTF-8?q?=5Fcan=5Fsend=5Fnow=E2=80=99=20defined=20but=20not=20used".?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a "ports/unix/btstack_config.h" for a workaround: If "MICROPY_BLUETOOTH_BTSTACK_USB" is set and "ENABLE_SCO_OVER_HCI" is not defined there is a compiler error: ../../lib/btstack/platform/libusb/hci_transport_h2_libusb.c:1354:13: error: ‘signal_sco_can_send_now’ defined but not used Because the problem is in an external code a workaround is done by defining MICROPY_BLUETOOTH_BTSTACK_USB in the added "btstack_config.h". The "ports/unix/Makefile" has been changed so that the "btstack_config.h" will be included. Signed-off-by: Yasmin Bosch --- ports/unix/Makefile | 10 ++++++++-- ports/unix/btstack_config.h | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 ports/unix/btstack_config.h diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 67d706e98b7eb..57d1b306c3320 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -49,8 +49,14 @@ MICROPY_BLUETOOTH_BTSTACK_USB ?= 0 MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 endif -endif -endif +# Set the file that will be included by "extmod/btstack/btstack_config.h" +# +# The original file "extmod/btstack/btstack_config_common.h" +# will be included by it. +MICROPY_BLUETOOTH_BTSTACK_CONFIG_FILE ?= '"ports/unix/btstack_config.h"' + +endif # MICROPY_BLUETOOTH_BTSTACK +endif # MICROPY_PY_BLUETOOTH # include py core make definitions include $(TOP)/py/py.mk diff --git a/ports/unix/btstack_config.h b/ports/unix/btstack_config.h new file mode 100644 index 0000000000000..374acc02e95b1 --- /dev/null +++ b/ports/unix/btstack_config.h @@ -0,0 +1,23 @@ +#ifndef MICROPY_INCLUDED_PORTS_UNIX_BTSTACK_CONFIG_H +#define MICROPY_INCLUDED_PORTS_UNIX_BTSTACK_CONFIG_H + + +#include "extmod/btstack/btstack_config_common.h" + +#ifdef MICROPY_BLUETOOTH_BTSTACK_USB +#if MICROPY_BLUETOOTH_BTSTACK_USB + +// Workaround: +// +// If ENABLE_SCO_OVER_HCI is not defined there is a compiler error: +// +// ../../lib/btstack/platform/libusb/hci_transport_h2_libusb.c:1354:13: +// error: ‘signal_sco_can_send_now’ defined but not used +// +// Because the problem is in an external code this workaround is done. +#define ENABLE_SCO_OVER_HCI + +#endif +#endif + +#endif // MICROPY_INCLUDED_PORTS_UNIX_BTSTACK_CONFIG_H From 60a5e47114769f5c20713b48b9b68829e45b80ed Mon Sep 17 00:00:00 2001 From: Yasmin Bosch Date: Sun, 17 Mar 2024 16:30:59 +0100 Subject: [PATCH 3/5] ports/unix: Fix so that "MICROPY_BLUETOOTH_BTSTACK_USB=1" is working. ports/unix/mpbtstackport_usb.c: "lib/btstack/platform/posix/btstack_run_loop_posix.c" is now used instead of "lib/btstack/platform/embedded/btstack_run_loop_embedded.c". Additional code has been added to make it work. Now also a log file "/tmp/hci_dump.pklg" could be activated by setting "MICROPY_BLUETOOTH_BTSTACK_HCI_DUMP=1". The "Makefile" and "mpbtstackport_common.c" has been changed accordingly. Signed-off-by: Yasmin Bosch --- ports/unix/Makefile | 20 +++++ ports/unix/mpbtstackport_common.c | 4 +- ports/unix/mpbtstackport_usb.c | 133 +++++++++++++++++++++++++----- 3 files changed, 135 insertions(+), 22 deletions(-) diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 57d1b306c3320..ec64e730cb84b 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -49,6 +49,12 @@ MICROPY_BLUETOOTH_BTSTACK_USB ?= 0 MICROPY_BLUETOOTH_BTSTACK_H4 ?= 1 endif +# MICROPY_BLUETOOTH_BTSTACK_HCI_DUMP could be set to 1 to activate logging +# to file "/tmp/hci_dump.pklg" for btstack-over-usb. +ifndef MICROPY_BLUETOOTH_BTSTACK_HCI_DUMP +MICROPY_BLUETOOTH_BTSTACK_HCI_DUMP ?= 0 +endif + # Set the file that will be included by "extmod/btstack/btstack_config.h" # # The original file "extmod/btstack/btstack_config_common.h" @@ -171,7 +177,21 @@ endif ifeq ($(MICROPY_PY_BLUETOOTH),1) ifeq ($(MICROPY_BLUETOOTH_BTSTACK),1) + +ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),0) SRC_BTSTACK_C += lib/btstack/platform/embedded/btstack_run_loop_embedded.c +endif + +ifeq ($(MICROPY_BLUETOOTH_BTSTACK_USB),1) +SRC_BTSTACK_C += lib/btstack/platform/posix/btstack_run_loop_posix.c + +ifeq ($(MICROPY_BLUETOOTH_BTSTACK_HCI_DUMP),1) +CFLAGS += -DMICROPY_BLUETOOTH_BTSTACK_HCI_DUMP=1 +SRC_BTSTACK_C += lib/btstack/platform/posix/hci_dump_posix_fs.c +endif + +endif + endif endif diff --git a/ports/unix/mpbtstackport_common.c b/ports/unix/mpbtstackport_common.c index 36412e96f4e0f..6cf9d6562fea5 100644 --- a/ports/unix/mpbtstackport_common.c +++ b/ports/unix/mpbtstackport_common.c @@ -41,7 +41,7 @@ #include "mpbtstackport.h" -// Called by the UART polling thread in mpbthciport.c, or by the USB polling thread in mpbtstackport_usb.c. +// Called by the UART polling thread in mpbthciport.c bool mp_bluetooth_hci_poll(void) { if (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_STARTING || mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_ACTIVE || mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_HALTING) { // Pretend like we're running in IRQ context (i.e. other things can't be running at the same time). @@ -80,9 +80,11 @@ uint32_t hal_time_ms(void) { } void mp_bluetooth_btstack_port_init(void) { + #if !MICROPY_BLUETOOTH_BTSTACK_USB btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); // hci_dump_init(hci_dump_embedded_stdout_get_instance()); + #endif #if MICROPY_BLUETOOTH_BTSTACK_H4 mp_bluetooth_btstack_port_init_h4(); diff --git a/ports/unix/mpbtstackport_usb.c b/ports/unix/mpbtstackport_usb.c index a924fc3ca912a..e46eb5d5690ec 100644 --- a/ports/unix/mpbtstackport_usb.c +++ b/ports/unix/mpbtstackport_usb.c @@ -34,12 +34,12 @@ #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" +#include "py/stackctrl.h" #include "lib/btstack/src/btstack.h" #include "lib/btstack/src/hci_transport_usb.h" -#include "lib/btstack/platform/embedded/btstack_run_loop_embedded.h" -#include "lib/btstack/platform/embedded/hal_cpu.h" -#include "lib/btstack/platform/embedded/hal_time_ms.h" +#include "lib/btstack/platform/posix/btstack_run_loop_posix.h" +#include "lib/btstack/platform/posix/hci_dump_posix_fs.h" #include "extmod/btstack/modbluetooth_btstack.h" @@ -49,9 +49,21 @@ #error Unix btstack requires MICROPY_PY_THREAD #endif -static const useconds_t USB_POLL_INTERVAL_US = 1000; +#define DEBUG_printf(...) // printf("mpbtstackport_usb.c: " __VA_ARGS__) void mp_bluetooth_btstack_port_init_usb(void) { + + #if MICROPY_BLUETOOTH_BTSTACK_HCI_DUMP + // log into file using HCI_DUMP_PACKETLOGGER format + const char *pklg_path = "/tmp/hci_dump.pklg"; + hci_dump_posix_fs_open(pklg_path, HCI_DUMP_PACKETLOGGER); + const hci_dump_t *hci_dump_impl = hci_dump_posix_fs_get_instance(); + hci_dump_init(hci_dump_impl); + printf("Packet Log: %s\n", pklg_path); + #endif + + btstack_run_loop_init(btstack_run_loop_posix_get_instance()); + // MICROPYBTUSB can be a ':'' or '-' separated port list. char *path = getenv("MICROPYBTUSB"); if (path != NULL) { @@ -76,35 +88,114 @@ void mp_bluetooth_btstack_port_init_usb(void) { static pthread_t bstack_thread_id; void mp_bluetooth_btstack_port_deinit(void) { - hci_power_control(HCI_POWER_OFF); + DEBUG_printf("mp_bluetooth_btstack_port_deinit: begin: mp_bluetooth_btstack_state=%d\n", mp_bluetooth_btstack_state); + + // Workaround: + // + // Possibly hci_power_control(HCI_POWER_OFF); + // crashes with memory fault if state is already MP_BLUETOOTH_BTSTACK_STATE_OFF. + if (mp_bluetooth_btstack_state != MP_BLUETOOTH_BTSTACK_STATE_OFF && + mp_bluetooth_btstack_state != MP_BLUETOOTH_BTSTACK_STATE_TIMEOUT) { + + hci_power_control(HCI_POWER_OFF); - // Wait for the poll loop to terminate when the state is set to OFF. + DEBUG_printf("mp_bluetooth_btstack_port_deinit: after HCI_POWER_OFF: mp_bluetooth_btstack_state=%d\n", mp_bluetooth_btstack_state); + } + + // btstack_run_loop_trigger_exit() will call btstack_run_loop_t::trigger_exit() + // i.e. btstack_run_loop_posix_trigger_exit(). + // And that will trigger the exit of btstack_run_loop_execute() + // i.e. btstack_run_loop_posix_execute(). + btstack_run_loop_trigger_exit(); + + // A call of btstack_run_loop_poll_data_sources_from_irq() is needed + // additional to btstack_run_loop_trigger_exit() to exit the posix run loop. + // + // Otherwise the posix run loop will wait forever for ready File Descriptors. + // + // Hint: + // btstack_run_loop_poll_data_sources_from_irq() + // calls btstack_run_loop_posix_poll_data_sources_from_irq() + btstack_run_loop_poll_data_sources_from_irq(); + + // MicroPython threads are created with PTHREAD_CREATE_DETACHED. + // + // Nonetheless the thread is created with PTHREAD_CREATE_JOINABLE and + // pthread_join() is used. + + DEBUG_printf("mp_bluetooth_btstack_port_deinit: pthread_join()\n"); pthread_join(bstack_thread_id, NULL); + + #if MICROPY_BLUETOOTH_BTSTACK_HCI_DUMP + DEBUG_printf("mp_bluetooth_btstack_port_deinit: hci_dump_posix_fs_close()\n"); + hci_dump_posix_fs_close(); + #endif + + DEBUG_printf("mp_bluetooth_btstack_port_deinit: end\n"); } +// +// This function is to be called from a system thread which is not a MicroPython thread. +// It sets up the relevant MicroPython state and obtains the GIL, to synchronize with the +// rest of the runtime. +// +// The function was extracted from invoke_irq_handler() in extmod/modbluetooth.c. +// +// ts: +// Pointer to a mp_state_thread_t that holds the state. +// +// stack_limit: +// Value that will be used for mp_stack_set_limit(). +// +STATIC void init_mp_state_thread(mp_state_thread_t *ts, mp_uint_t stack_limit) { + + mp_thread_set_state(ts); + mp_stack_set_top(ts + 1); // need to include ts in root-pointer scan + mp_stack_set_limit(stack_limit); + ts->gc_lock_depth = 0; + ts->nlr_jump_callback_top = NULL; + ts->mp_pending_exception = MP_OBJ_NULL; + mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context + mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context + MP_THREAD_GIL_ENTER(); +} -// Provided by mpbstackport_common.c. -extern bool mp_bluetooth_hci_poll(void); +// +// This function is to be called after mp_blutooth_init_mp_state_thread() before +// ending the thread. +// It gives back the GIL and resets the MicroPython state. +// +// The function was extracted from invoke_irq_handler() in extmod/modbluetooth.c. +// +STATIC void deinit_mp_state_thread() { + + MP_THREAD_GIL_EXIT(); + mp_thread_set_state(NULL); +} static void *btstack_thread(void *arg) { (void)arg; + + // This code runs on an non-MicroPython thread. + // But some of the code e.g. in "extmod/btstack/modbluetooth_btstack.c" + // make calls that needs the state of a MicroPython thread e. g. "m_del()". + // + // So set up relevant MicroPython state and obtain the GIL, + // to synchronised with the rest of the runtime. + + mp_state_thread_t ts; + init_mp_state_thread(&ts, 40000 * (sizeof(void *) / 4) - 1024); + + log_info("btstack_thread: HCI_POWER_ON"); hci_power_control(HCI_POWER_ON); - // modbluetooth_btstack.c will have set the state to STARTING before - // calling mp_bluetooth_btstack_port_start. - // This loop will terminate when the HCI_POWER_OFF above results - // in modbluetooth_btstack.c setting the state back to OFF. - // Or, if a timeout results in it being set to TIMEOUT. + btstack_run_loop_execute(); - while (true) { - if (!mp_bluetooth_hci_poll()) { - break; - } + log_info("btstack_thread: end"); + + // reset the MicroPython state + deinit_mp_state_thread(); - // The USB transport schedules events to the run loop at 1ms intervals, - // and the implementation currently polls rather than selects. - usleep(USB_POLL_INTERVAL_US); - } return NULL; } From e7d4cd35214e9bd1642bf88f0a01c8621b5bc237 Mon Sep 17 00:00:00 2001 From: Yasmin Bosch Date: Sat, 16 Mar 2024 22:11:34 +0100 Subject: [PATCH 4/5] ports/unix: Change 'STATIC' to 'static'. See 'global: Remove the STATIC macro.': https://github.com/micropython/micropython/pull/13763 Signed-off-by: Yasmin Bosch --- ports/unix/mpbtstackport_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/unix/mpbtstackport_usb.c b/ports/unix/mpbtstackport_usb.c index e46eb5d5690ec..9073f422acda1 100644 --- a/ports/unix/mpbtstackport_usb.c +++ b/ports/unix/mpbtstackport_usb.c @@ -147,7 +147,7 @@ void mp_bluetooth_btstack_port_deinit(void) { // stack_limit: // Value that will be used for mp_stack_set_limit(). // -STATIC void init_mp_state_thread(mp_state_thread_t *ts, mp_uint_t stack_limit) { +static void init_mp_state_thread(mp_state_thread_t *ts, mp_uint_t stack_limit) { mp_thread_set_state(ts); mp_stack_set_top(ts + 1); // need to include ts in root-pointer scan @@ -167,7 +167,7 @@ STATIC void init_mp_state_thread(mp_state_thread_t *ts, mp_uint_t stack_limit) { // // The function was extracted from invoke_irq_handler() in extmod/modbluetooth.c. // -STATIC void deinit_mp_state_thread() { +static void deinit_mp_state_thread() { MP_THREAD_GIL_EXIT(); mp_thread_set_state(NULL); From 44acdbf1877fbfb7d9304573f84a6b04174e71d1 Mon Sep 17 00:00:00 2001 From: Yasmin Bosch Date: Sat, 16 Mar 2024 23:12:07 +0100 Subject: [PATCH 5/5] ports/unix: Use 'mp_thread_init_state()' instead of own function. The function 'mp_thread_init_state()' has been added to 'py/runtime.h' with commit #bc424dd in micropython/micropython: 'py/modthread: Move thread state initialisation to shared function.' So use that function instead of defining own function in 'ports/unix/mpbtstackport_usb.c'. Signed-off-by: Yasmin Bosch --- ports/unix/mpbtstackport_usb.c | 47 ++++------------------------------ 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/ports/unix/mpbtstackport_usb.c b/ports/unix/mpbtstackport_usb.c index 9073f422acda1..0388d68911e26 100644 --- a/ports/unix/mpbtstackport_usb.c +++ b/ports/unix/mpbtstackport_usb.c @@ -134,45 +134,6 @@ void mp_bluetooth_btstack_port_deinit(void) { DEBUG_printf("mp_bluetooth_btstack_port_deinit: end\n"); } -// -// This function is to be called from a system thread which is not a MicroPython thread. -// It sets up the relevant MicroPython state and obtains the GIL, to synchronize with the -// rest of the runtime. -// -// The function was extracted from invoke_irq_handler() in extmod/modbluetooth.c. -// -// ts: -// Pointer to a mp_state_thread_t that holds the state. -// -// stack_limit: -// Value that will be used for mp_stack_set_limit(). -// -static void init_mp_state_thread(mp_state_thread_t *ts, mp_uint_t stack_limit) { - - mp_thread_set_state(ts); - mp_stack_set_top(ts + 1); // need to include ts in root-pointer scan - mp_stack_set_limit(stack_limit); - ts->gc_lock_depth = 0; - ts->nlr_jump_callback_top = NULL; - ts->mp_pending_exception = MP_OBJ_NULL; - mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context - mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context - MP_THREAD_GIL_ENTER(); -} - -// -// This function is to be called after mp_blutooth_init_mp_state_thread() before -// ending the thread. -// It gives back the GIL and resets the MicroPython state. -// -// The function was extracted from invoke_irq_handler() in extmod/modbluetooth.c. -// -static void deinit_mp_state_thread() { - - MP_THREAD_GIL_EXIT(); - mp_thread_set_state(NULL); -} - static void *btstack_thread(void *arg) { (void)arg; @@ -184,7 +145,8 @@ static void *btstack_thread(void *arg) { // to synchronised with the rest of the runtime. mp_state_thread_t ts; - init_mp_state_thread(&ts, 40000 * (sizeof(void *) / 4) - 1024); + mp_thread_init_state(&ts, 40000 * (sizeof(void *) / 4) - 1024, NULL, NULL); + MP_THREAD_GIL_ENTER(); log_info("btstack_thread: HCI_POWER_ON"); hci_power_control(HCI_POWER_ON); @@ -193,8 +155,9 @@ static void *btstack_thread(void *arg) { log_info("btstack_thread: end"); - // reset the MicroPython state - deinit_mp_state_thread(); + // Give back the GIL and reset the MicroPython state. + MP_THREAD_GIL_EXIT(); + mp_thread_set_state(NULL); return NULL; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy