From 2fc5d06f2710de45d399d2e07fec29863f28ed00 Mon Sep 17 00:00:00 2001 From: Kamil Rakoczy Date: Wed, 9 Oct 2024 15:31:28 +0200 Subject: [PATCH] pw_bluetooth_sapphire_mcuxpresso: Add support for raw HCI packets NXP SDK doesn't allow to get raw HCI packets without NXP bluetooth stack. This commit registers custom UART callbacks and tasks to handle HCI packets in pigweed itself. Change-Id: Ib622570b42640b911f36251daed22ff0b3d57c6f Signed-off-by: Kamil Rakoczy --- MODULE.bazel.lock | 49 +--- WORKSPACE | 9 - .../host/gap/bredr_connection_manager.cc | 4 +- pw_bluetooth_sapphire_mcuxpresso/BUILD.bazel | 5 + .../controller.cc | 276 ++++++++++++++---- .../controller.h | 61 +++- .../py/pw_build_mcuxpresso/components.py | 4 +- targets/mimxrt595_evk_freertos/boot.cc | 183 ++++++------ third_party/mcuxpresso/BUILD.bazel | 11 +- .../mcuxpresso/config/app_bluetooth_config.h | 32 +- third_party/mcuxpresso/mcuxpresso_sdk.bzl | 10 +- 11 files changed, 407 insertions(+), 237 deletions(-) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index c35760d03..33dcdda59 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -8,11 +8,9 @@ "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", - "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/source.json": "750d5e29326fb59cbe61116a7b803c8a1d0a7090a9c8ed89888d188e3c473fc7", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da", "https://bcr.bazel.build/modules/apple_support/1.13.0/MODULE.bazel": "7c8cdea7e031b7f9f67f0b497adf6d2c6a2675e9304ca93a9af6ed84eef5a524", - "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", - "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", + "https://bcr.bazel.build/modules/apple_support/1.13.0/source.json": "aef5da52fdcfa9173e02c0cb772c85be5b01b9d49f97f9bb0fe3efe738938ba4", "https://bcr.bazel.build/modules/aspect_bazel_lib/1.31.2/MODULE.bazel": "7bee702b4862612f29333590f4b658a5832d433d6f8e4395f090e8f4e85d442f", "https://bcr.bazel.build/modules/aspect_bazel_lib/1.38.0/MODULE.bazel": "6307fec451ba9962c1c969eb516ebfe1e46528f7fa92e1c9ac8646bef4cdaa3f", "https://bcr.bazel.build/modules/aspect_bazel_lib/1.40.3/MODULE.bazel": "668e6bcb4d957fc0e284316dba546b705c8d43c857f87119619ee83c4555b859", @@ -41,8 +39,6 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", - "https://bcr.bazel.build/modules/boringssl/0.20240913.0/MODULE.bazel": "fcaa7503a5213290831a91ed1eb538551cf11ac0bc3a6ad92d0fef92c5bd25fb", - "https://bcr.bazel.build/modules/boringssl/0.20240913.0/source.json": "540753d29c271a302442a3d3c6ccd4faace597e7bcf0f77049fe59535782ce9f", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", "https://bcr.bazel.build/modules/freertos/10.5.1.bcr.2/MODULE.bazel": "dcc13aef86495f5418f4cdd532eefe9a4319c44771ef57b8abda0c3560d8e6ed", @@ -57,9 +53,8 @@ "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4", "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", - "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", - "https://bcr.bazel.build/modules/googletest/1.15.2/source.json": "dbdda654dcb3a0d7a8bc5d0ac5fc7e150b58c2a986025ae5bc634bb2cb61f470", "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", "https://bcr.bazel.build/modules/pico-sdk/2.0.0/MODULE.bazel": "f96b730c6e871c1ca0a879b961a1a2430a4afbcb08a8dae8c8fa3ed2c86d9655", "https://bcr.bazel.build/modules/pico-sdk/2.0.0/source.json": "75dce384ee879127ca9d0f88d2154af4b7e59c7e72f3e2e6995e82c75fcd5961", @@ -81,11 +76,9 @@ "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573", "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", - "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022", "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", - "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", - "https://bcr.bazel.build/modules/re2/2024-07-02/source.json": "547d0111a9d4f362db32196fef805abbf3676e8d6afbe44d395d87816c1130ca", + "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4", "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", "https://bcr.bazel.build/modules/rules_buf/0.1.1/MODULE.bazel": "6189aec18a4f7caff599ad41b851ab7645d4f1e114aa6431acf9b0666eb92162", @@ -151,7 +144,6 @@ "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", - "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", "https://bcr.bazel.build/modules/rules_python/0.36.0/MODULE.bazel": "a4ce1ccea92b9106c7d16ab9ee51c6183107e78ba4a37aa65055227b80cd480c", "https://bcr.bazel.build/modules/rules_python/0.36.0/source.json": "b79cbb7b2ae1751949e2f6ee6692822e4ffd13ca1e959ce99abec4ac7666162a", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", @@ -861,37 +853,6 @@ ] } }, - "@@pybind11_bazel+//:internal_configure.bzl%internal_configure_extension": { - "general": { - "bzlTransitiveDigest": "E2bVqsWslm5GH4rxOm+GWHFpneuy7kuqsKWgAIw5Avo=", - "usagesDigest": "qiX97eIdtifnntL7rISA+4Anot1sjD1YCIoUPSEkeG0=", - "recordedFileInputs": { - "@@pybind11_bazel+//MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34" - }, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "pybind11": { - "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", - "ruleClassName": "http_archive", - "attributes": { - "build_file": "@@pybind11_bazel+//:pybind11-BUILD.bazel", - "strip_prefix": "pybind11-2.12.0", - "urls": [ - "https://github.com/pybind/pybind11/archive/v2.12.0.zip" - ] - } - } - }, - "recordedRepoMappingEntries": [ - [ - "pybind11_bazel+", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, "@@rules_buf+//buf:extensions.bzl%ext": { "general": { "bzlTransitiveDigest": "gmPmM7QT5Jez2VVFcwbbMf/QWSRag+nJ1elFJFFTcn0=", diff --git a/WORKSPACE b/WORKSPACE index eca5e87a2..0b9d88bbc 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -145,15 +145,6 @@ http_archive( url = "https://github.com/Mbed-TLS/mbedtls/releases/download/v2.28.8/mbedtls-2.28.8.tar.bz2", ) -# TODO: https://pwbug.dev/354747966 - Update the BCR version of Emboss. -git_repository( - name = "com_google_emboss", - # LINT.IfChange(emboss) - remote = "https://pigweed.googlesource.com/third_party/github/google/emboss", - tag = "v2024.0809.170004", - # LINT.ThenChange(/pw_package/py/pw_package/packages/emboss.py:emboss) -) - git_repository( name = "mcuxpresso", commit = "6f3fd257cdcf978a4d26e7d6e9eed9240037422b", diff --git a/pw_bluetooth_sapphire/host/gap/bredr_connection_manager.cc b/pw_bluetooth_sapphire/host/gap/bredr_connection_manager.cc index 0bac26539..8885cd883 100644 --- a/pw_bluetooth_sapphire/host/gap/bredr_connection_manager.cc +++ b/pw_bluetooth_sapphire/host/gap/bredr_connection_manager.cc @@ -629,8 +629,8 @@ void BrEdrConnectionManager::AttachInspect(inspect::Node& parent, void BrEdrConnectionManager::WritePageTimeout( pw::chrono::SystemClock::duration page_timeout, hci::ResultFunction<> cb) { - BT_ASSERT(page_timeout >= hci_spec::kMinPageTimeoutDuration); - BT_ASSERT(page_timeout <= hci_spec::kMaxPageTimeoutDuration); + PW_CHECK(page_timeout >= hci_spec::kMinPageTimeoutDuration); + PW_CHECK(page_timeout <= hci_spec::kMaxPageTimeoutDuration); const int64_t raw_page_timeout = page_timeout / hci_spec::kPerPageTimeoutUnit; diff --git a/pw_bluetooth_sapphire_mcuxpresso/BUILD.bazel b/pw_bluetooth_sapphire_mcuxpresso/BUILD.bazel index 606f01c39..e59847036 100644 --- a/pw_bluetooth_sapphire_mcuxpresso/BUILD.bazel +++ b/pw_bluetooth_sapphire_mcuxpresso/BUILD.bazel @@ -16,6 +16,11 @@ cc_library( "public", ], deps = [ + "@pigweed//pw_containers:vector", + "@pigweed//pw_containers:inline_queue", + "@pigweed//pw_thread:thread", + "@pigweed//pw_sync:interrupt_spin_lock", + "@pigweed//pw_sync:thread_notification", "@pigweed//pw_bluetooth:pw_bluetooth", "@pigweed//pw_bluetooth_sapphire/host:stack", "//targets:mcuxpresso_sdk", diff --git a/pw_bluetooth_sapphire_mcuxpresso/controller.cc b/pw_bluetooth_sapphire_mcuxpresso/controller.cc index d83966d2b..db896e2e5 100644 --- a/pw_bluetooth_sapphire_mcuxpresso/controller.cc +++ b/pw_bluetooth_sapphire_mcuxpresso/controller.cc @@ -1,80 +1,251 @@ #include "pw_bluetooth_sapphire_mcuxpresso/controller.h" +#include #include +#include #include -#include "bluetooth/bluetooth.h" -#include "bluetooth/hci.h" +#include "controller/controller.h" #include "pw_bluetooth/controller.h" +#include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h" +#include "pw_bluetooth_sapphire/internal/host/common/packet_view.h" +#include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h" +#include "pw_containers/inline_deque.h" +#include "pw_containers/vector.h" +#include "pw_log/log.h" +#include "pw_preprocessor/util.h" +#include "pw_thread/detached_thread.h" +PW_EXTERN_C_START +#include "controller_hci_uart.h" +PW_EXTERN_C_END +namespace pw::bluetooth { -template -struct CallbackCaster; +static pw::Vector EventPacketFromBytes(std::byte* data) { + bt::hci_spec::EventHeader* eventHeader = + reinterpret_cast(data); + // PW_CHECK_NULL(eventHeader); + return std::move( + pw::Vector(data, + data + sizeof(bt::hci_spec::EventHeader) + + eventHeader->parameter_total_size)); +} -template -struct CallbackCaster { - template - static Ret callback(Args... args) { - return func(args...); +static pw::Vector ACLPacketFromBytes(std::byte* data) { + bt::hci_spec::ACLDataHeader* eventHeader = + reinterpret_cast(data); + // PW_CHECK_NULL(eventHeader); + return std::move( + pw::Vector(data, + data + sizeof(bt::hci_spec::ACLDataHeader) + + eventHeader->data_total_length)); +} + +static void Mimxrt595Controller::hci_uart_transmit_cb(hal_uart_handle_t handle, + hal_uart_status_t status, + void* userData) { + // TODO: make sure if this function doesn't need synchronization with + // 'hci_uart_write_data' + if (handle == nullptr) { + return; + } + Mimxrt595Controller* controller_ptr = + static_cast(userData); + if (controller_ptr == nullptr) { + return; } - static std::function func; -}; -template -std::function CallbackCaster::func; + switch (status) { + case kStatus_HAL_UartTxIdle: + break; + case kStatus_HAL_UartRxIdle: + controller_ptr->hci_uart_rx_bytes_ptr += + controller_ptr->hci_uart_rx.dataSize; + ht_parse_packet(&controller_ptr->ht); -typedef void (*callback_t)(int); + if (controller_ptr->ht.packet_expected_len == 1) { + PacketType packet_type = (PacketType)controller_ptr->hci_uart_rx_buf[0]; + std::byte* packet_data = controller_ptr->hci_uart_rx_buf.data() + 1; + { + std::lock_guard lock(controller_ptr->hci_uart_tx_queue_mutex); + switch (packet_type) { + case kHciEventData: + controller_ptr->hci_uart_tx_queue.push(std::make_pair( + packet_type, EventPacketFromBytes(packet_data))); + break; + case kHciAclData: + controller_ptr->hci_uart_tx_queue.push( + std::make_pair(packet_type, ACLPacketFromBytes(packet_data))); + break; + default: + PW_LOG_CRITICAL("UNIMPLEMENTED: packet_type: %d", packet_type); + break; + } + } + + controller_ptr->hci_uart_rx_bytes_ptr = 0U; + controller_ptr->hci_uart_cond.release(); + } + + controller_ptr->hci_uart_rx.data = + &controller_ptr + ->hci_uart_rx_buf[controller_ptr->hci_uart_rx_bytes_ptr]; + controller_ptr->hci_uart_rx.dataSize = + controller_ptr->ht.packet_expected_len; + + HAL_UartReceiveNonBlocking( + (hal_uart_handle_t)controller_ptr->hci_uart_handle, + (uint8_t*)controller_ptr->hci_uart_rx.data, + controller_ptr->hci_uart_rx.dataSize); + break; + default: + break; + } +} + +void Mimxrt595Controller::hci_uart_write_data(std::byte* buf, uint16_t length) { + HAL_UartSendNonBlocking( + (hal_uart_handle_t)hci_uart_handle, (uint8_t*)buf, length); +} + +void Mimxrt595Controller::hci_uart_send_data(PacketType type, + uint8_t* buf, + uint16_t length) { + hci_uart_tx_buf[0] = (std::byte)type; + std::memcpy(&hci_uart_tx_buf[1], buf, length); + + hci_uart_write_data(hci_uart_tx_buf.data(), length + 1); +} + +pw::Status Mimxrt595Controller::hci_uart_init() { + hal_uart_config_t config; + hal_uart_status_t ret; + hal_uart_status_t status; + + controller_hci_uart_config_t getConfig; + + if (controller_hci_uart_get_configuration(&getConfig) != 0) { + return pw::Status::InvalidArgument(); + } + + config.srcClock_Hz = getConfig.clockSrc; + config.baudRate_Bps = getConfig.runningBaudrate; + config.parityMode = kHAL_UartParityDisabled; + config.stopBitCount = kHAL_UartOneStopBit; + config.enableRx = 1U; + config.enableTx = 1U; + config.instance = getConfig.instance; + config.enableRxRTS = getConfig.enableRxRTS; + config.enableTxCTS = getConfig.enableTxCTS; + + if (HAL_UartInit((hal_uart_handle_t)hci_uart_handle, &config) != + kStatus_HAL_UartSuccess) { + return pw::Status::InvalidArgument(); + } + + if (HAL_UartInstallCallback((hal_uart_handle_t)hci_uart_handle, + hci_uart_transmit_cb, + this) != kStatus_HAL_UartSuccess) { + return pw::Status::Unknown(); + } + + ht_parse_packet_init(&ht); + hci_uart_rx_bytes_ptr = 0U; + ht.packet = (uint8_t*)&hci_uart_rx_buf[0U]; + + hci_uart_rx.data = &hci_uart_rx_buf[hci_uart_rx_bytes_ptr]; + hci_uart_rx.dataSize = ht.packet_expected_len; + + if (HAL_UartReceiveNonBlocking((hal_uart_handle_t)hci_uart_handle, + (uint8_t*)hci_uart_rx.data, + hci_uart_rx.dataSize) != + kStatus_HAL_UartSuccess) { + return pw::Status::Unknown(); + } + + pw::thread::DetachedThread( + pw::thread::freertos::Options() + .set_name("EtherMind UART Task") + .set_priority(BT_TASK_PRIORITY + 2U), + [this]() { + while (true) { + hci_uart_cond.acquire(); + + while (!hci_uart_tx_queue.empty()) { + hci_uart_tx_queue_mutex.lock(); + auto [packet_type, packet_data] = hci_uart_tx_queue.front(); + hci_uart_tx_queue.pop(); + hci_uart_tx_queue_mutex.unlock(); + + switch (packet_type) { + case kHciEventData: + event_function_(pw::span(packet_data.data(), + packet_data.size())); + break; + case kHciAclData: + acl_function_(pw::span(packet_data.data(), + packet_data.size())); + break; + default: + PW_LOG_CRITICAL("UNKNOWN: packet_type: %d", packet_type); + break; + } + } + } + }); + + return pw::Status(); +} -namespace pw::bluetooth { void Mimxrt595Controller::SetEventFunction(DataFunction func) { - (void)func; + event_function_ = std::move(func); } void Mimxrt595Controller::SetReceiveAclFunction(DataFunction func) { - (void)func; + acl_function_ = std::move(func); } void Mimxrt595Controller::SetReceiveScoFunction(DataFunction func) { - (void)func; + (void)func; + PW_LOG_CRITICAL("UNIMPLEMENTED: SetReceiveScoFunction"); } // void Mimxrt595Controller::SetReceiveIsoFunction(DataFunction /*func*/) {} void Mimxrt595Controller::Initialize(Callback complete_callback, Callback error_callback) { - initialize_complete_callback_ = std::move(complete_callback); - initialize_error_callback_ = std::move(error_callback); + error_callback_ = std::move(error_callback); + pw::thread::DetachedThread( + pw::thread::freertos::Options().set_name( + "Mimxrt595Controller Initialize Thread"), + [complete_callback_ = std::move(complete_callback), this]() mutable { + controller_init(); - CallbackCaster::func = - std::bind(&Mimxrt595Controller::bt_ready_cb, this, std::placeholders::_1); - callback_t func = - static_cast(CallbackCaster::callback); + complete_callback_(hci_uart_init()); - bt_enable(func); + PW_LOG_INFO("Bluetooth initialized"); + }); } void Mimxrt595Controller::Close(Callback callback) { - // MIMXRT595 SDK currently doesn't implement a close function - // so we just call the callback with OK + // TODO: Previously used API didn't had a close function + // now, we are using bare HCI API, check again that it still doesn't allow + // to close callback(Status()); } void Mimxrt595Controller::SendCommand(span command) { - uint16_t opcode = (uint16_t)(command[0]) | (uint16_t)(command[1] << 8); - struct net_buf* buf = - bt_hci_cmd_create(opcode, sizeof(std::byte) * command.size() - 2); - std::byte* payload = - (std::byte*)net_buf_add(buf, sizeof(std::byte) * command.size() - 2); - std::copy(command.begin() + 2, command.end(), payload); - - bt_hci_cmd_send(opcode, buf); + auto command_buffer = bt::DynamicByteBuffer(bt::BufferView(command)); + hci_uart_send_data(kHciCommand, command_buffer.data(), command_buffer.size()); } void Mimxrt595Controller::SendAclData(span data) { - (void)data; + auto data_buffer = bt::DynamicByteBuffer(bt::BufferView(data)); + hci_uart_send_data(kHciAclData, data_buffer.data(), data_buffer.size()); } void Mimxrt595Controller::SendScoData(span data) { - (void)data; + PW_LOG_CRITICAL("UNIMPLEMENTED: SendScoData"); + (void)data; } // void Mimxrt595Controller::SendIsoData(span /*data*/) {} @@ -83,34 +254,31 @@ void Mimxrt595Controller::ConfigureSco(ScoCodingFormat coding_format, ScoEncoding encoding, ScoSampleRate sample_rate, Callback callback) { - (void)coding_format; - (void)encoding; - (void)sample_rate; - (void)callback; + PW_LOG_CRITICAL("UNIMPLEMENTED: ConfigureSco"); + (void)coding_format; + (void)encoding; + (void)sample_rate; + (void)callback; } void Mimxrt595Controller::ResetSco(Callback callback) { - (void)callback; + PW_LOG_CRITICAL("UNIMPLEMENTED: ResetSco"); + (void)callback; } void Mimxrt595Controller::GetFeatures(Callback callback) { - constexpr FeaturesBits features = - FeaturesBits::kHciSco | FeaturesBits::kHciIso; + constexpr FeaturesBits features = FeaturesBits::kHciSco | + FeaturesBits::kHciIso | + FeaturesBits::kSetAclPriorityCommand; callback(features); } void Mimxrt595Controller::EncodeVendorCommand( VendorCommandParameters parameters, Callback>)> callback) { - (void)parameters; - (void)callback; + PW_LOG_CRITICAL("UNIMPLEMENTED: EncodeVendorCommand"); + (void)parameters; + (void)callback; } -void Mimxrt595Controller::bt_ready_cb(int err) { - if (err == 0) { - initialize_complete_callback_(Status()); - } else { - initialize_error_callback_(Status::Unknown()); - } -} -}; // namespace pw::bluetooth +} // namespace pw::bluetooth diff --git a/pw_bluetooth_sapphire_mcuxpresso/public/pw_bluetooth_sapphire_mcuxpresso/controller.h b/pw_bluetooth_sapphire_mcuxpresso/public/pw_bluetooth_sapphire_mcuxpresso/controller.h index a62c4fa46..d1e636426 100644 --- a/pw_bluetooth_sapphire_mcuxpresso/public/pw_bluetooth_sapphire_mcuxpresso/controller.h +++ b/pw_bluetooth_sapphire_mcuxpresso/public/pw_bluetooth_sapphire_mcuxpresso/controller.h @@ -1,11 +1,21 @@ #pragma once #include "pw_bluetooth/controller.h" +#include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h" +#include "pw_bluetooth_sapphire/internal/host/transport/acl_data_packet.h" +#include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h" +#include "pw_containers/inline_queue.h" +#include "pw_sync/interrupt_spin_lock.h" +#include "pw_sync/thread_notification.h" + +PW_EXTERN_C_START +#include "fsl_adapter_uart.h" +#include "hci_transport.h" +PW_EXTERN_C_END namespace pw::bluetooth { class Mimxrt595Controller final : public pw::bluetooth::Controller { - // Sets a function that will be called with HCI event packets received from // the controller. This should be called before `Initialize` or else incoming // packets will be dropped. The lifetime of data passed to `func` is only @@ -36,7 +46,7 @@ class Mimxrt595Controller final : public pw::bluetooth::Controller { // initialization. After a fatal error, this object is invalid. `Close` should // be called to ensure a safe clean up. void Initialize(Callback complete_callback, - Callback error_callback) override; + Callback error_callback) override; // Closes the controller interface, resetting all state. `callback` will be // called when closure is complete. After this method is called, this object @@ -67,9 +77,9 @@ class Mimxrt595Controller final : public pw::bluetooth::Controller { // ALREADY_EXISTS - a SCO connection is already configured // INTERNAL - an internal error occurred void ConfigureSco(ScoCodingFormat coding_format, - ScoEncoding encoding, - ScoSampleRate sample_rate, - Callback callback) override; + ScoEncoding encoding, + ScoSampleRate sample_rate, + Callback callback) override; // Releases the resources held by an active SCO connection. This should be // called when a SCO connection is closed. `ConfigureSco` must be called @@ -90,12 +100,41 @@ class Mimxrt595Controller final : public pw::bluetooth::Controller { void EncodeVendorCommand( VendorCommandParameters parameters, Callback>)> callback) override; -private: - void bt_ready_cb(int err); - - Callback initialize_complete_callback_; - Callback initialize_error_callback_; + private: + enum PacketType : uint8_t { + kHciCommand = 0x01, + kHciAclData = 0x02, + kHciScoData = 0x03, + kHciEventData = 0x04, + kHciIsoData = 0x05, + }; + + typedef struct _hci_uart_meta_data_ { + std::byte* data; + size_t dataSize; + } hci_uart_meta_data; + + static void hci_uart_transmit_cb(hal_uart_handle_t handle, + hal_uart_status_t status, + void* userData); + void hci_uart_write_data(std::byte* buf, uint16_t length); + void hci_uart_send_data(PacketType type, unsigned char* buf, uint16_t length); + pw::Status hci_uart_init(); + Callback error_callback_; + DataFunction event_function_; + DataFunction acl_function_; + + hci_uart_meta_data hci_uart_rx; + pw::Vector hci_uart_rx_buf; + pw::Vector hci_uart_tx_buf; + uint16_t hci_uart_rx_bytes_ptr; + pw::sync::ThreadNotification hci_uart_cond; + HT_PARSE ht; + UART_HANDLE_DEFINE(hci_uart_handle); + pw::sync::InterruptSpinLock hci_uart_tx_queue_mutex; + pw::InlineQueue>, 16> + hci_uart_tx_queue; }; -} +} // namespace pw::bluetooth diff --git a/pw_build_mcuxpresso/py/pw_build_mcuxpresso/components.py b/pw_build_mcuxpresso/py/pw_build_mcuxpresso/components.py index a3b7b7421..65df249ba 100644 --- a/pw_build_mcuxpresso/py/pw_build_mcuxpresso/components.py +++ b/pw_build_mcuxpresso/py/pw_build_mcuxpresso/components.py @@ -333,7 +333,9 @@ def _parse_sources( # in this manifest, relative path to ethermind isn't from base path, but from manifest path. # In case of some components, project relative path points to not existing file, but in case of other # files, it is correct. - fixup_component_ids = ["middleware.edgefast_bluetooth.ble.ethermind.lib.cm33.MIMXRT595S", + fixup_component_ids = [ + "middleware.edgefast_bluetooth.ble.ethermind.lib.cm33.MIMXRT595S", + "middleware.edgefast_bluetooth.btble.ethermind.lib.cm33.MIMXRT595S", "middleware.edgefast_bluetooth.config.ethermind.MIMXRT595S"] if base_path is not None and base_path == pathlib.Path("../../wireless/ethermind"): if component_id in fixup_component_ids: diff --git a/targets/mimxrt595_evk_freertos/boot.cc b/targets/mimxrt595_evk_freertos/boot.cc index 7957d22d6..d56677f71 100644 --- a/targets/mimxrt595_evk_freertos/boot.cc +++ b/targets/mimxrt595_evk_freertos/boot.cc @@ -14,20 +14,20 @@ #include "pw_boot/boot.h" +#include "FreeRTOS.h" #include "board.h" #include "clock_config.h" +#include "controller_hci_uart.h" +#include "fsl_clock.h" +#include "fsl_debug_console.h" +#include "fsl_power.h" #include "peripherals.h" #include "pin_mux.h" #include "pw_boot_cortex_m/boot.h" #include "pw_preprocessor/compiler.h" #include "pw_sys_io_mcuxpresso/init.h" -#include "FreeRTOS.h" #include "pw_system/init.h" #include "task.h" -#include "fsl_clock.h" -#include "fsl_debug_console.h" -#include "controller_hci_uart.h" -#include "fsl_power.h" #include "usb_host_config.h" #include "usb_phy.h" #include "usb_host.h" @@ -36,7 +36,7 @@ #include "pw_malloc/malloc.h" #endif // PW_MALLOC_ACTIVE -#define CONTROLLER_ID kUSB_ControllerIp3516Hs0 +#define CONTROLLER_ID kUSB_ControllerIp3516Hs0 void pw_boot_PreStaticMemoryInit() { // Call CMSIS SystemInit code. @@ -63,109 +63,109 @@ void pw_boot_PreStaticConstructorInit() { #define USB_HOST_INTERRUPT_PRIORITY (3U) #endif /*work as debug console with M.2, work as bt usart with non-M.2*/ -#define APP_DEBUG_UART_TYPE kSerialPort_Uart -#define APP_DEBUG_UART_BASEADDR (uint32_t) USART12 +#define APP_DEBUG_UART_TYPE kSerialPort_Uart +#define APP_DEBUG_UART_BASEADDR (uint32_t)USART12 #define APP_DEBUG_UART_INSTANCE 12U #define APP_DEBUG_UART_CLK_FREQ CLOCK_GetFlexcommClkFreq(12) -#define APP_DEBUG_UART_FRG_CLK \ - (const clock_frg_clk_config_t){12U, clock_frg_clk_config_t::kCLOCK_FrgPllDiv, 255U, 0U} /*!< Select FRG0 mux as frg_pll */ +#define APP_DEBUG_UART_FRG_CLK \ + (const clock_frg_clk_config_t){ \ + 12U, clock_frg_clk_config_t::kCLOCK_FrgPllDiv, 255U, 0U} \ + /*!< Select FRG0 mux as frg_pll */ #define APP_DEBUG_UART_CLK_ATTACH kFRG_to_FLEXCOMM12 -#define APP_UART_IRQ_HANDLER FLEXCOMM12_IRQHandler -#define APP_UART_IRQ FLEXCOMM12_IRQn -#define APP_DEBUG_UART_BAUDRATE 115200 - -int controller_hci_uart_get_configuration(controller_hci_uart_config_t *config) -{ - if (NULL == config) - { - return -1; - } - config->clockSrc = BOARD_BT_UART_CLK_FREQ; - config->defaultBaudrate = 115200u; - config->runningBaudrate = BOARD_BT_UART_BAUDRATE; - config->instance = BOARD_BT_UART_INSTANCE; - config->enableRxRTS = 1u; - config->enableTxCTS = 1u; - return 0; +#define APP_UART_IRQ_HANDLER FLEXCOMM12_IRQHandler +#define APP_UART_IRQ FLEXCOMM12_IRQn +#define APP_DEBUG_UART_BAUDRATE 115200 + +int controller_hci_uart_get_configuration( + controller_hci_uart_config_t* config) { + if (config == nullptr) { + return -1; + } + config->clockSrc = BOARD_BT_UART_CLK_FREQ; + config->defaultBaudrate = 115200u; + config->runningBaudrate = BOARD_BT_UART_BAUDRATE; + config->instance = BOARD_BT_UART_INSTANCE; + config->enableRxRTS = 1u; + config->enableTxCTS = 1u; + return 0; } -void USB_HostClockInit(void) -{ - uint8_t usbClockDiv = 1; - uint32_t usbClockFreq; - usb_phy_config_struct_t phyConfig = { - BOARD_USB_PHY_D_CAL, - BOARD_USB_PHY_TXCAL45DP, - BOARD_USB_PHY_TXCAL45DM, - }; - - /* Make sure USDHC ram buffer and usb1 phy has power up */ - POWER_DisablePD(kPDRUNCFG_APD_USBHS_SRAM); - POWER_DisablePD(kPDRUNCFG_PPD_USBHS_SRAM); - POWER_ApplyPD(); - - RESET_PeripheralReset(kUSBHS_PHY_RST_SHIFT_RSTn); - RESET_PeripheralReset(kUSBHS_DEVICE_RST_SHIFT_RSTn); - RESET_PeripheralReset(kUSBHS_HOST_RST_SHIFT_RSTn); - RESET_PeripheralReset(kUSBHS_SRAM_RST_SHIFT_RSTn); - - /* enable usb ip clock */ - CLOCK_EnableUsbHs0HostClock(kOSC_CLK_to_USB_CLK, usbClockDiv); - /* save usb ip clock freq*/ - usbClockFreq = g_xtalFreq / usbClockDiv; - CLOCK_SetClkDiv(kCLOCK_DivPfc1Clk, 4); - /* enable usb ram clock */ - CLOCK_EnableClock(kCLOCK_UsbhsSram); - /* enable USB PHY PLL clock, the phy bus clock (480MHz) source is same with USB IP */ - CLOCK_EnableUsbHs0PhyPllClock(kOSC_CLK_to_USB_CLK, usbClockFreq); - - /* USB PHY initialization */ - USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL_SYS_CLK_HZ, &phyConfig); +void USB_HostClockInit(void) { + uint8_t usbClockDiv = 1; + uint32_t usbClockFreq; + usb_phy_config_struct_t phyConfig = { + BOARD_USB_PHY_D_CAL, + BOARD_USB_PHY_TXCAL45DP, + BOARD_USB_PHY_TXCAL45DM, + }; + + /* Make sure USDHC ram buffer and usb1 phy has power up */ + POWER_DisablePD(kPDRUNCFG_APD_USBHS_SRAM); + POWER_DisablePD(kPDRUNCFG_PPD_USBHS_SRAM); + POWER_ApplyPD(); + + RESET_PeripheralReset(kUSBHS_PHY_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSBHS_DEVICE_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSBHS_HOST_RST_SHIFT_RSTn); + RESET_PeripheralReset(kUSBHS_SRAM_RST_SHIFT_RSTn); + + /* enable usb ip clock */ + CLOCK_EnableUsbHs0HostClock(kOSC_CLK_to_USB_CLK, usbClockDiv); + /* save usb ip clock freq*/ + usbClockFreq = g_xtalFreq / usbClockDiv; + CLOCK_SetClkDiv(kCLOCK_DivPfc1Clk, 4); + /* enable usb ram clock */ + CLOCK_EnableClock(kCLOCK_UsbhsSram); + /* enable USB PHY PLL clock, the phy bus clock (480MHz) source is same with + * USB IP */ + CLOCK_EnableUsbHs0PhyPllClock(kOSC_CLK_to_USB_CLK, usbClockFreq); + + /* USB PHY initialization */ + USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL_SYS_CLK_HZ, &phyConfig); #if ((defined FSL_FEATURE_USBHSH_USB_RAM) && (FSL_FEATURE_USBHSH_USB_RAM > 0U)) - for (int i = 0; i < (FSL_FEATURE_USBHSH_USB_RAM >> 2); i++) - { - ((uint32_t *)FSL_FEATURE_USBHSH_USB_RAM_BASE_ADDRESS)[i] = 0U; - } + for (int i = 0; i < (FSL_FEATURE_USBHSH_USB_RAM >> 2); i++) { + ((uint32_t*)FSL_FEATURE_USBHSH_USB_RAM_BASE_ADDRESS)[i] = 0U; + } #endif - /* enable usb1 device clock */ - CLOCK_EnableClock(kCLOCK_UsbhsDevice); - USBHSH->PORTMODE &= ~USBHSH_PORTMODE_DEV_ENABLE_MASK; - /* Wait until dev_needclk de-asserts */ - while (SYSCTL0->USB0CLKSTAT & SYSCTL0_USB0CLKSTAT_DEV_NEED_CLKST_MASK) - { - __ASM("nop"); - } - /* disable usb1 device clock */ - CLOCK_DisableClock(kCLOCK_UsbhsDevice); + /* enable usb1 device clock */ + CLOCK_EnableClock(kCLOCK_UsbhsDevice); + USBHSH->PORTMODE &= ~USBHSH_PORTMODE_DEV_ENABLE_MASK; + /* Wait until dev_needclk de-asserts */ + while (SYSCTL0->USB0CLKSTAT & SYSCTL0_USB0CLKSTAT_DEV_NEED_CLKST_MASK) { + __ASM("nop"); + } + /* disable usb1 device clock */ + CLOCK_DisableClock(kCLOCK_UsbhsDevice); } -void USB_HostIsrEnable(void) -{ - uint8_t irqNumber; +void USB_HostIsrEnable(void) { + uint8_t irqNumber; - uint8_t usbHOSTEhciIrq[] = USBHSH_IRQS; - irqNumber = usbHOSTEhciIrq[CONTROLLER_ID - kUSB_ControllerIp3516Hs0]; - /* USB_HOST_CONFIG_EHCI */ + uint8_t usbHOSTEhciIrq[] = USBHSH_IRQS; + irqNumber = usbHOSTEhciIrq[CONTROLLER_ID - kUSB_ControllerIp3516Hs0]; + /* USB_HOST_CONFIG_EHCI */ - /* Install isr, set priority, and enable IRQ. */ - NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY); + /* Install isr, set priority, and enable IRQ. */ + NVIC_SetPriority((IRQn_Type)irqNumber, USB_HOST_INTERRUPT_PRIORITY); - EnableIRQ((IRQn_Type)irqNumber); + EnableIRQ((IRQn_Type)irqNumber); } -void APP_InitAppDebugConsole(void) -{ - uint32_t uartClkSrcFreq; +void APP_InitAppDebugConsole(void) { + uint32_t uartClkSrcFreq; - /* attach FRG0 clock to FLEXCOMM12 (debug console) */ - auto debug_uart_cfg = APP_DEBUG_UART_FRG_CLK; - CLOCK_SetFRGClock(&debug_uart_cfg); - CLOCK_AttachClk(APP_DEBUG_UART_CLK_ATTACH); + /* attach FRG0 clock to FLEXCOMM12 (debug console) */ + auto debug_uart_cfg = APP_DEBUG_UART_FRG_CLK; + CLOCK_SetFRGClock(&debug_uart_cfg); + CLOCK_AttachClk(APP_DEBUG_UART_CLK_ATTACH); - uartClkSrcFreq = APP_DEBUG_UART_CLK_FREQ; + uartClkSrcFreq = APP_DEBUG_UART_CLK_FREQ; - DbgConsole_Init(APP_DEBUG_UART_INSTANCE, APP_DEBUG_UART_BAUDRATE, APP_DEBUG_UART_TYPE, uartClkSrcFreq); + DbgConsole_Init(APP_DEBUG_UART_INSTANCE, + APP_DEBUG_UART_BAUDRATE, + APP_DEBUG_UART_TYPE, + uartClkSrcFreq); } void pw_boot_PreMainInit() { @@ -177,6 +177,7 @@ void pw_boot_PreMainInit() { BOARD_InitBootPins(); BOARD_InitBootClocks(); + BOARD_InitI3CPins(); APP_InitAppDebugConsole(); /* attach FRG0 clock to FLEXCOMM0 */ diff --git a/third_party/mcuxpresso/BUILD.bazel b/third_party/mcuxpresso/BUILD.bazel index 3d3529098..55689703b 100644 --- a/third_party/mcuxpresso/BUILD.bazel +++ b/third_party/mcuxpresso/BUILD.bazel @@ -82,11 +82,12 @@ mcuxpresso_sdk( "platform.drivers.common.MIMXRT595S", "platform.drivers.cache_cache64.MIMXRT595S", "platform.drivers.flash_config.evkmimxrt595.MIMXRT595S", + "platform.drivers.i3c.MIMXRT595S", "utility.debug_console.MIMXRT595S", "device.MIMXRT595S_CMSIS.MIMXRT595S", "middleware.wifi.fwdnld_intf_abs.MIMXRT595S", "middleware.edgefast_bluetooth.wifi_nxp.controller.base.MIMXRT595S", - "middleware.edgefast_bluetooth.ble.ethermind.cm33.MIMXRT595S", + "middleware.edgefast_bluetooth.btble.ethermind.cm33.MIMXRT595S", "middleware.usb.device_controller_ip3511hs.MIMXRT595S", "middleware.usb.phy.MIMXRT595S", "middleware.usb.device.controller.driver.MIMXRT595S", @@ -126,6 +127,14 @@ mcuxpresso_sdk( "-Wno-sign-compare", "-Wno-shadow", "-Wno-unused-function", + "-Wno-type-limits", + "-Wno-array-bounds", + "-Wno-stringop-truncation", + "-Wno-format-overflow", + "-Wno-stringop-overflow", + "-Wno-implicit-fallthrough", + "-Wno-nonnull", + "-Wno-cast-qual", "-include", "$(execpath @pigweed//third_party/mcuxpresso:config/app_bluetooth_config.h)" ], deps = [ diff --git a/third_party/mcuxpresso/config/app_bluetooth_config.h b/third_party/mcuxpresso/config/app_bluetooth_config.h index 7e248af53..3da4d712f 100644 --- a/third_party/mcuxpresso/config/app_bluetooth_config.h +++ b/third_party/mcuxpresso/config/app_bluetooth_config.h @@ -49,25 +49,19 @@ #define SD_TIMING_MAX kSD_TimingDDR50Mode #endif /*#define WIFI_IW612_BOARD_MURATA_2EL_M2*/ -/* Select witch beacon application to start */ -#define BEACON_APP 1 -#define IBEACON_APP 0 -#define EDDYSTONE 0 - #define CONFIG_BT_PERIPHERAL 1 -#define CONFIG_BT_PHY_UPDATE 1 -#define CONFIG_BT_AUTO_PHY_UPDATE 1 -#define CONFIG_BT_DATA_LEN_UPDATE 1 -#define CONFIG_BT_AUTO_DATA_LEN_UPDATE 1 -#if (defined EDDYSTONE) && (EDDYSTONE) -#define CONFIG_BT_SETTINGS 1 -#define CONFIG_BT_KEYS_OVERWRITE_OLDEST 1 -#endif -#if defined(IBEACON_APP) && (IBEACON_APP == 1) -#define CONFIG_BT_DEVICE_NAME "ibeacon" -#elif defined(EDDYSTONE) && (EDDYSTONE == 1) -#define CONFIG_BT_DEVICE_NAME "eddystone" -#elif defined(BEACON_APP) && (BEACON_APP == 1) -#define CONFIG_BT_DEVICE_NAME "beacon" +#define CONFIG_BT_CENTRAL 1 +#define CONFIG_BT_BREDR 1 +#define CONFIG_BT_SMP 1 +#define CONFIG_BT_A2DP 1 +#define CONFIG_BT_A2DP_SINK 1 +#define CONFIG_BT_SETTINGS 0 + + +#if (defined(CONFIG_BT_SMP) && (CONFIG_BT_SMP > 0U)) + #define CONFIG_BT_RX_STACK_SIZE 2500 +#else + #define CONFIG_BT_RX_STACK_SIZE 1024 #endif + #include "edgefast_bluetooth_config.h" diff --git a/third_party/mcuxpresso/mcuxpresso_sdk.bzl b/third_party/mcuxpresso/mcuxpresso_sdk.bzl index 4770d6405..10168c904 100644 --- a/third_party/mcuxpresso/mcuxpresso_sdk.bzl +++ b/third_party/mcuxpresso/mcuxpresso_sdk.bzl @@ -213,11 +213,11 @@ mcuxpresso_sdk = rule( ), "_libraries": attr.string_list( default = [ - "libethermind_ble_core.a", - "libethermind_ble_gatt.a", - "libethermind_ble_protocol.a", - "libethermind_ble_util.a", - "libethermind_ble_ga.a", + "libethermind_bt_core.a", + "libethermind_bt_gatt.a", + "libethermind_bt_protocol.a", + "libethermind_bt_util.a", + "libethermind_bt_ga.a", ], ), "_mcuxpresso_sdk_builder": attr.label(