Skip to content

Commit 23acde3

Browse files
authored
Merge pull request #407 from iabdalkader/add_zephyr_support
Add Zephyr support.
2 parents 60bc905 + ced8d45 commit 23acde3

File tree

5 files changed

+284
-2
lines changed

5 files changed

+284
-2
lines changed

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ sentence=Enables Bluetooth® Low Energy connectivity on the Arduino MKR WiFi 101
66
paragraph=This library supports creating a Bluetooth® Low Energy peripheral & central mode.
77
category=Communication
88
url=https://www.arduino.cc/en/Reference/ArduinoBLE
9-
architectures=samd,megaavr,mbed,apollo3,mbed_nano,mbed_portenta,mbed_nicla,esp32,mbed_giga,renesas,renesas_portenta,mbed_opta,renesas_uno,silabs
9+
architectures=*
1010
includes=ArduinoBLE.h

src/local/BLELocalDevice.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@
2525

2626
#include "BLELocalDevice.h"
2727

28+
#ifdef __ZEPHYR__
29+
#undef ARDUINO_PORTENTA_H7_M7
30+
#undef ARDUINO_OPTA
31+
#undef ARDUINO_GIGA
32+
#undef ARDUINO_NICLA_VISION
33+
#undef ARDUINO_PORTENTA_C33
34+
#endif
35+
2836
#if defined(PORTENTA_H7_PINS) || defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_OPTA)
2937
#ifndef BT_REG_ON
3038
#define BT_REG_ON PJ_12

src/utility/HCIUartTransport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1818
*/
1919

20-
#if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) && !defined(ARDUINO_SILABS) && !defined(ARDUINO_UNOR4_WIFI) || defined(TARGET_NANO_RP2040_CONNECT) //|| defined(CORE_CM4)
20+
#if !defined(ARDUINO_ARCH_MBED) && !defined(__ZEPHYR__) && !defined(ESP32) && !defined(ARDUINO_SILABS) && !defined(ARDUINO_UNOR4_WIFI) && !defined(__ZEPHYR__) || defined(TARGET_NANO_RP2040_CONNECT) //|| defined(CORE_CM4)
2121

2222
#include "HCIUartTransport.h"
2323

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
/*
2+
This file is part of the ArduinoBLE library.
3+
Copyright (c) 2018-2025 Arduino SA. All rights reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#if defined(__ZEPHYR__)
21+
22+
#include "HCIVirtualTransportZephyr.h"
23+
#include "HCI.h"
24+
25+
#include <zephyr/bluetooth/buf.h>
26+
#include <zephyr/bluetooth/hci.h>
27+
#include <zephyr/bluetooth/hci_raw.h>
28+
#include <zephyr/bluetooth/controller.h>
29+
#include <zephyr/drivers/uart.h>
30+
#include <zephyr/drivers/hwinfo.h>
31+
32+
static K_FIFO_DEFINE(rx_queue);
33+
struct k_fifo* __rx_queue = &rx_queue;
34+
extern "C" int bt_h4_vnd_setup(const struct device *dev);
35+
36+
#if CONFIG_CYW4343W_MURATA_1DX
37+
// External firmware defines.
38+
extern const uint8_t brcm_patchram_buf[];
39+
extern const int brcm_patch_ram_length;
40+
41+
enum {
42+
HCI_VND_OP_FW_DOWNLOAD = 0xFC2E,
43+
HCI_VND_OP_WRITE_RAM = 0xFC4C,
44+
HCI_VND_OP_LAUNCH_RAM = 0xFC4E,
45+
HCI_VND_OP_SET_BAUDRATE = 0xFC18,
46+
};
47+
48+
static int cyw4343_set_baudrate(const struct device *uart, uint32_t baudrate) {
49+
struct __attribute__ ((packed)) {
50+
uint16_t zero;
51+
uint32_t baud;
52+
} param = { 0, baudrate };
53+
54+
struct uart_config uart_cfg;
55+
if (uart_config_get(uart, &uart_cfg)) {
56+
return -1;
57+
}
58+
59+
if (HCI.sendCommand(HCI_VND_OP_SET_BAUDRATE, sizeof(param), (void *) &param)) {
60+
return -1;
61+
}
62+
63+
uart_cfg.baudrate = baudrate;
64+
if (uart_configure(uart, &uart_cfg)) {
65+
return -1;
66+
}
67+
68+
uart_irq_rx_enable(uart);
69+
return 0;
70+
}
71+
72+
static int cyw4343_download_firmware(const struct device *uart) {
73+
#define MURATA_NODE DT_CHILD(DT_CHOSEN(zephyr_bt_hci), murata_1dx)
74+
uint32_t operational_speed = DT_PROP_OR(MURATA_NODE, hci_operation_speed, 115200);
75+
uint32_t fw_download_speed = DT_PROP_OR(MURATA_NODE, fw_download_speed, 115200);
76+
77+
// Reset controller
78+
if (HCI.sendCommand(0x0C03, 0, NULL)) {
79+
return -1;
80+
}
81+
82+
// Switch to fast baudrate
83+
if ((operational_speed != fw_download_speed) &&
84+
cyw4343_set_baudrate(uart, fw_download_speed)) {
85+
return -1;
86+
}
87+
88+
// Start firmware downloader.
89+
if (HCI.sendCommand(HCI_VND_OP_FW_DOWNLOAD, 0, NULL)) {
90+
return -1;
91+
}
92+
93+
// Load the firmware image.
94+
for (size_t offset=0; offset < brcm_patch_ram_length;) {
95+
uint8_t length = brcm_patchram_buf[offset + 2];
96+
uint16_t opcode = (brcm_patchram_buf[offset + 0]) |
97+
(brcm_patchram_buf[offset + 1] << 8);
98+
99+
// Opcode should be write RAM or launch RAM.
100+
if (opcode != HCI_VND_OP_WRITE_RAM && opcode != HCI_VND_OP_LAUNCH_RAM) {
101+
return -1;
102+
}
103+
104+
if (HCI.sendCommand(opcode, length, (void *) &brcm_patchram_buf[offset + 3])) {
105+
return -1;
106+
}
107+
108+
offset += length + 3;
109+
}
110+
111+
// Delay after firmware loading.
112+
delay(250);
113+
114+
// Switch back to the default baudrate.
115+
if ((operational_speed != fw_download_speed) &&
116+
cyw4343_set_baudrate(uart, operational_speed)) {
117+
return -1;
118+
}
119+
120+
return 0;
121+
}
122+
#endif
123+
124+
HCIVirtualTransportZephyrClass::HCIVirtualTransportZephyrClass() {
125+
126+
}
127+
128+
HCIVirtualTransportZephyrClass::~HCIVirtualTransportZephyrClass() {
129+
130+
}
131+
132+
int HCIVirtualTransportZephyrClass::begin() {
133+
bt_enable_raw(__rx_queue);
134+
135+
#if CONFIG_BT_HCI_SETUP
136+
const struct device *uart = DEVICE_DT_GET(DT_PARENT(DT_CHOSEN(zephyr_bt_hci)));
137+
if (!uart) {
138+
return 0;
139+
}
140+
141+
if (bt_h4_vnd_setup(uart)) {
142+
return 0;
143+
}
144+
145+
#if CONFIG_CYW4343W_MURATA_1DX
146+
if (cyw4343_download_firmware(uart)) {
147+
return 0;
148+
}
149+
#endif /* CONFIG_CYW4343W_MURATA_1DX */
150+
#endif /* CONFIG_BT_HCI_SETUP */
151+
152+
#if CONFIG_BT_LL_SW_SPLIT
153+
// Use unique device id for BD addr.
154+
uint8_t bd_addr[6] = { 0xFA, 0xFA, 0xFA, 0xFA, 0xFA, 0xFA };
155+
156+
#if CONFIG_HWINFO
157+
hwinfo_get_device_id(bd_addr, sizeof(bd_addr));
158+
#endif /* CONFIG_HWINFO */
159+
160+
// Set public address for controller.
161+
bt_ctlr_set_public_addr(bd_addr);
162+
#endif /* CONFIG_BT_LL_SW_SPLIT */
163+
164+
rxbuf.clear();
165+
166+
return 1;
167+
}
168+
169+
void HCIVirtualTransportZephyrClass::end() {
170+
171+
}
172+
173+
void HCIVirtualTransportZephyrClass::wait(unsigned long timeout) {
174+
delay(timeout);
175+
}
176+
177+
int HCIVirtualTransportZephyrClass::available() {
178+
static struct net_buf *buf = NULL;
179+
180+
if (rxbuf.available()) {
181+
return rxbuf.available();
182+
}
183+
184+
buf = (struct net_buf *) k_fifo_get(__rx_queue, K_MSEC(10));
185+
if (!buf) {
186+
return 0;
187+
}
188+
189+
for (int i=0; i<buf->len; i++) {
190+
rxbuf.store_char((uint8_t)buf->data[i]);
191+
}
192+
193+
net_buf_pull(buf, buf->len);
194+
if (!buf->len) {
195+
net_buf_unref(buf);
196+
buf = NULL;
197+
}
198+
199+
return rxbuf.available();
200+
}
201+
202+
int HCIVirtualTransportZephyrClass::peek() {
203+
return -1;
204+
}
205+
206+
int HCIVirtualTransportZephyrClass::read() {
207+
if (rxbuf.available()) {
208+
return rxbuf.read_char();
209+
}
210+
211+
return -1;
212+
}
213+
214+
size_t HCIVirtualTransportZephyrClass::write(const uint8_t* data, size_t length) {
215+
enum bt_buf_type type = bt_buf_type_from_h4(data[0], BT_BUF_OUT);
216+
struct net_buf *buf = bt_buf_get_tx(type, K_FOREVER, &data[1], length - 1);
217+
218+
if (buf) {
219+
auto err = bt_send(buf);
220+
if (err) {
221+
net_buf_unref(buf);
222+
}
223+
return length;
224+
}
225+
return 0;
226+
}
227+
228+
HCIVirtualTransportZephyrClass HCIVirtualTransportZephyr;
229+
HCITransportInterface& HCITransport = HCIVirtualTransportZephyr;
230+
#endif
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
This file is part of the ArduinoBLE library.
3+
Copyright (c) 2018-2025 Arduino SA. All rights reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 2.1 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
#include "HCITransport.h"
21+
#include "api/RingBuffer.h"
22+
#include <stdint.h>
23+
#include <stdio.h>
24+
#include <string.h>
25+
26+
class HCIVirtualTransportZephyrClass : public HCITransportInterface {
27+
public:
28+
HCIVirtualTransportZephyrClass();
29+
virtual ~HCIVirtualTransportZephyrClass();
30+
31+
virtual int begin();
32+
virtual void end();
33+
34+
virtual void wait(unsigned long timeout);
35+
36+
virtual int available();
37+
virtual int peek();
38+
virtual int read();
39+
40+
virtual size_t write(const uint8_t* data, size_t length);
41+
42+
private:
43+
RingBufferN<258> rxbuf;
44+
};

0 commit comments

Comments
 (0)