Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
555fe90
digitalPins: take into account boards without gpios
facchinm Oct 1, 2024
16cf84d
main.cpp: support loading via llext
facchinm Oct 1, 2024
f95580c
Implement SerialUSB
facchinm Oct 1, 2024
3e52834
Fixes for proper core compatibility
facchinm Oct 1, 2024
390b391
temp_bugfix: make serialEventRun symbol appear if CDC is not defined
facchinm Oct 1, 2024
a1f06b4
Serial: fix long write()
facchinm Oct 14, 2024
54e5bb0
Some Serial object fixes...
KurtE Nov 29, 2024
49cda44
SerialX.flush() - now wait until TC Complete
KurtE Nov 30, 2024
7484a35
core: prerequisites for ArduinoBLE
facchinm Oct 7, 2024
91bbddb
core: add time related macros
facchinm Dec 13, 2024
c4497d5
analogWrite: implement DAC pins
facchinm Jan 23, 2025
34a1681
new: add rewrites for c++17
facchinm Dec 18, 2024
c66a25d
Implement analogReadResolution
KurtE Jan 27, 2025
67e9467
zephyrSerial.h - reduce compiler warnings
KurtE Dec 4, 2024
07f37a3
USB: fix corner case when cdc_acm is in dt and CONFIG_CDC is disabled
facchinm Jan 24, 2025
ad1510f
enable static threads
mjs513 Jan 29, 2025
d83b997
Nano 33 BLE - enable the SPI1 sensors
KurtE Feb 5, 2025
ba941ee
Add call to initVariant in main move ble sense to variant.cpp
KurtE Mar 5, 2025
ca3d01f
TEMP: get rid of serialEvent
facchinm Feb 10, 2025
4f28336
wip: linked build
facchinm Feb 12, 2025
0ccfd9c
usb: start supporting USB_DEVICE_STACK_NEXT
facchinm Feb 19, 2025
29fb2b9
SerialUSB: create SerialUSB object only if CONFIG_USB_CDC_ACM=y
facchinm Mar 6, 2025
cfedec3
cores/arduino: warning squash
pillo79 Apr 10, 2025
eccb689
If sketch is not connected to serial - dump serial output
KurtE May 17, 2025
a6636b4
Fix micros() for nano without breaking giga
KurtE Jan 30, 2025
4cb21f8
serial: add missing include
facchinm Feb 10, 2025
d13d49a
SerialUSB: fix missing overload after #123
facchinm Jun 20, 2025
e9556b5
Arduino.h: fix DIGITAL_PIN_EXISTS macro to avoid comment expansion is…
pillo79 Mar 12, 2025
1cb92ea
linker: forcefully remove exceptions and pack sections
facchinm Dec 18, 2024
1474d8a
loader: impl: add some libc/::std functions
facchinm May 28, 2025
63e52b8
cores/arduino/abi: squash warning
pillo79 Aug 4, 2025
c2c5e5a
ZephyrCommon: allow boards without any ADC channel configured
facchinm Dec 9, 2024
17916e1
make internal arduino_adc array static
facchinm Jan 23, 2025
1139d7e
core: serial: fix availableForWrite()
silabs-bozont Dec 22, 2025
b1291bf
core: restore core-as-zephyr-module functionality
facchinm Jan 24, 2025
206c7e0
misc: Format repo using clang-format.
iabdalkader Aug 28, 2025
768cd06
unoq: implement analogReference
facchinm Aug 26, 2025
d1f2a24
core: add macro to find pins by node
sebromero Sep 17, 2025
6fae725
cores: Remove redundant k_thread_start() calls for static threads.
iabdalkader Oct 1, 2025
c1dcf6c
nano_matter: add initial support for the Arduino Nano Matter
silabs-bozont Sep 1, 2025
168bb07
static_build: fix bss initialization
facchinm Sep 18, 2025
dd24f6f
usb: refactor USBD_NEXT and implement 1200bps touch
facchinm Apr 3, 2025
ce8b0f4
core: implement weak loop hook
facchinm Jul 10, 2025
8f375db
portentac33: add sleep to avoid dfu protocol error
pennam Aug 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,23 @@ config ARDUINO_ENTRY
default y

endif

if USB_DEVICE_STACK_NEXT

config USB_DEVICE_PRODUCT
string "USB Device Product"
default "Arduino Generic board"

config USB_DEVICE_MANUFACTURER
string "USB Device Manufacturer"
default "Arduino"

config USB_DEVICE_VID
hex "USB Device Vendor ID"
default 0x2341

config USB_DEVICE_PID
hex "USB Device Product ID"
default 0x0001

endif
92 changes: 70 additions & 22 deletions cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,43 +12,52 @@
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/pwm.h>
#include <zephyr/drivers/adc.h>
#include <zephyr/drivers/dac.h>
#include <zephyr/drivers/i2c.h>
#include <math.h>

#if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 0
/* Note: DT_REG_ADDR needs an expanded argument or it will not work properly */
#define DIGITAL_PIN_MATCHES(dev_pha, pin, dev, num) \
(((dev == DT_REG_ADDR(dev_pha)) && (num == pin)) ? 1 : 0)
#define DIGITAL_PIN_EXISTS(n, p, i, dev, num) \
(((dev == DT_REG_ADDR(DT_PHANDLE_BY_IDX(n, p, i))) && \
(num == DT_PHA_BY_IDX(n, p, i, pin))) \
? 1 \
: 0)
DIGITAL_PIN_MATCHES(DT_PHANDLE_BY_IDX(n, p, i), DT_PHA_BY_IDX(n, p, i, pin), dev, num)

/* Check all pins are defined only once */
#define DIGITAL_PIN_CHECK_UNIQUE(i, _) \
((DT_FOREACH_PROP_ELEM_SEP_VARGS( \
DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, (+), \
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), digital_pin_gpios, i)), \
((DT_FOREACH_PROP_ELEM_SEP_VARGS( \
DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, (+), \
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), digital_pin_gpios, i)), \
DT_PHA_BY_IDX(DT_PATH(zephyr_user), digital_pin_gpios, i, pin))) == 1)

#if !LISTIFY(DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios), DIGITAL_PIN_CHECK_UNIQUE, (&&))
#error "digital_pin_gpios has duplicate definition"
#endif

#undef DIGITAL_PIN_CHECK_UNIQUE
#endif

// Helper macro to get Arduino pin number from device tree alias
#define DIGITAL_PIN_GPIOS_FIND_NODE(node) \
DIGITAL_PIN_GPIOS_FIND_PIN(DT_REG_ADDR(DT_PHANDLE_BY_IDX(node, gpios, 0)), \
DT_PHA_BY_IDX(node, gpios, 0, pin))

/* Return the index of it if matched, oterwise return 0 */
#define LED_BUILTIN_INDEX_BY_REG_AND_PINNUM(n, p, i, dev, num) \
(DIGITAL_PIN_EXISTS(n, p, i, dev, num) ? i : 0)

/* Only matched pin returns non-zero value, so the sum is matched pin's index */
#define DIGITAL_PIN_GPIOS_FIND_PIN(dev, pin) \
DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_PATH(zephyr_user), digital_pin_gpios, \
LED_BUILTIN_INDEX_BY_REG_AND_PINNUM, (+), dev, pin)
#define DIGITAL_PIN_GPIOS_FIND_PIN(dev, pin) \
DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_PATH(zephyr_user), digital_pin_gpios, \
LED_BUILTIN_INDEX_BY_REG_AND_PINNUM, (+), dev, pin)

#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), builtin_led_gpios) && \
(DT_PROP_LEN(DT_PATH(zephyr_user), builtin_led_gpios) > 0)

#if !(DT_FOREACH_PROP_ELEM_SEP_VARGS( \
DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, (+), \
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0)), \
DT_PHA_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0, pin)) > 0)
#if !(DT_FOREACH_PROP_ELEM_SEP_VARGS( \
DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, (+), \
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0)), \
DT_PHA_BY_IDX(DT_PATH(zephyr_user), builtin_led_gpios, 0, pin)) > 0)
#warning "pin not found in digital_pin_gpios"
#else
#define ZARD_LED_BUILTIN \
Expand All @@ -60,9 +69,10 @@
/* If digital-pin-gpios is not defined, tries to use the led0 alias */
#elif DT_NODE_EXISTS(DT_ALIAS(led0))

#if !(DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, \
(+), DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_ALIAS(led0), gpios, 0)), \
DT_PHA_BY_IDX(DT_ALIAS(led0), gpios, 0, pin)) > 0)
#if !(DT_FOREACH_PROP_ELEM_SEP_VARGS(DT_PATH(zephyr_user), digital_pin_gpios, DIGITAL_PIN_EXISTS, \
(+), \
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_ALIAS(led0), gpios, 0)), \
DT_PHA_BY_IDX(DT_ALIAS(led0), gpios, 0, pin)) > 0)
#warning "pin not found in digital_pin_gpios"
#else
#define ZARD_LED_BUILTIN \
Expand All @@ -79,17 +89,38 @@
* enum digitalPins { D0, D1, ... LED... NUM_OF_DIGITAL_PINS };
*/
enum digitalPins {
#if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 0
DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, DN_ENUMS, (, )),
#endif
NUM_OF_DIGITAL_PINS
};

#ifdef CONFIG_ADC

#define AN_ENUMS(n, p, i) A ## i = DIGITAL_PIN_GPIOS_FIND_PIN( \
DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), p, i)), \
DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)),
enum analogPins { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user),
adc_pin_gpios, AN_ENUMS) };
#define AN_ENUMS(n, p, i) \
A##i = DIGITAL_PIN_GPIOS_FIND_PIN(DT_REG_ADDR(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), p, i)), \
DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)),

enum analogPins {
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), adc_pin_gpios, AN_ENUMS)
};

// We provide analogReadResolution APIs
void analogReadResolution(int bits);

#endif

#ifdef CONFIG_DAC

#undef DAC0
#undef DAC1
#undef DAC2
#undef DAC3
#define DAC_ENUMS(n, p, i) DAC##i = i,

enum dacPins {
DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), dac_channels, DAC_ENUMS) NUM_OF_DACS
};

#endif

Expand All @@ -98,12 +129,29 @@ void noInterrupts(void);

int digitalPinToInterrupt(pin_size_t pin);

#define digitalPinToPort(x) (x)
#define digitalPinToBitMask(x) (x)
#define portOutputRegister(x) (x)
#define portInputRegister(x) (x)

void analogReadResolution(int bits);
void analogWriteResolution(int bits);

#include <variant.h>

#if !defined(LED_BUILTIN) && defined(ZARD_LED_BUILTIN)
#define LED_BUILTIN ZARD_LED_BUILTIN
#endif // LED_BUILTIN

#ifdef __cplusplus
#include <SerialUSB.h>
#include <zephyrSerial.h>
#include <strings.h>
#include <api/itoa.h>
#include <time_macros.h>
#include <overloads.h>

// Allow namespace-less operations if Arduino.h is included
using namespace arduino;

#endif // __cplusplus
3 changes: 3 additions & 0 deletions cores/arduino/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ if(NOT DEFINED ARDUINO_BUILD_PATH)

zephyr_sources(zephyrSerial.cpp)
zephyr_sources(zephyrCommon.cpp)
zephyr_sources(USB.cpp)
zephyr_sources(itoa.cpp)

if(CONFIG_USE_ARDUINO_API_RUST_IMPLEMENTATION)
zephyr_sources(zephyrPrint.cpp)
Expand All @@ -21,6 +23,7 @@ endif()

if(DEFINED CONFIG_ARDUINO_ENTRY)
zephyr_sources(main.cpp)
zephyr_sources(threads.cpp)
endif()

endif()
Expand Down
59 changes: 59 additions & 0 deletions cores/arduino/SerialUSB.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2024 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#include <zephyrSerial.h>

#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
#include <zephyr/usb/usbd.h>
extern "C" struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb);
#endif

namespace arduino {

class SerialUSB_ : public ZephyrSerial {

public:
SerialUSB_(const struct device *dev) : ZephyrSerial(dev) {
}

void begin(unsigned long baudrate, uint16_t config);

void begin(unsigned long baudrate) {
begin(baudrate, SERIAL_8N1);
}

operator bool() override;
size_t write(const uint8_t *buffer, size_t size) override;

size_t write(const uint8_t data) override {
return write(&data, 1);
}

void flush() override;

protected:
uint32_t dtr = 0;
uint32_t baudrate;
static void baudChangeHandler(const struct device *dev, uint32_t rate);

private:
bool started = false;

#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
struct usbd_context *_usbd;
int enable_usb_device_next();
static void usbd_next_cb(struct usbd_context *const ctx, const struct usbd_msg *msg);
static int usb_disable();
#endif
};
} // namespace arduino

#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && \
(CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS))
extern arduino::SerialUSB_ Serial;
#endif
110 changes: 110 additions & 0 deletions cores/arduino/USB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2024 Arduino SA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/devicetree.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/uart/cdc_acm.h>
#include <zephyr/usb/usb_device.h>
#include <SerialUSB.h>

#if ((DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm)) && \
(CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS))
const struct device *const usb_dev =
DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), cdc_acm, 0));

void __attribute__((weak)) _on_1200_bps() {
NVIC_SystemReset();
}

void arduino::SerialUSB_::baudChangeHandler(const struct device *dev, uint32_t rate) {
(void)dev; // unused
if (rate == 1200) {
usb_disable();
_on_1200_bps();
}
}

#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
int arduino::SerialUSB_::usb_disable() {
// To avoid Cannot perform port reset: 1200-bps touch: setting DTR to OFF: protocol error
k_sleep(K_MSEC(100));
return usbd_disable(Serial._usbd);
}

void arduino::SerialUSB_::usbd_next_cb(struct usbd_context *const ctx, const struct usbd_msg *msg) {
if (usbd_can_detect_vbus(ctx)) {
if (msg->type == USBD_MSG_VBUS_READY) {
usbd_enable(ctx);
}

if (msg->type == USBD_MSG_VBUS_REMOVED) {
usbd_disable(ctx);
}
}

if (msg->type == USBD_MSG_CDC_ACM_LINE_CODING) {
uint32_t baudrate;
uart_line_ctrl_get(Serial.uart, UART_LINE_CTRL_BAUD_RATE, &baudrate);
Serial.baudChangeHandler(nullptr, baudrate);
}
}

int arduino::SerialUSB_::enable_usb_device_next(void) {
int err;

_usbd = usbd_init_device(arduino::SerialUSB_::usbd_next_cb);
if (_usbd == NULL) {
return -ENODEV;
}

if (!usbd_can_detect_vbus(_usbd)) {
err = usbd_enable(_usbd);
if (err) {
return err;
}
}
return 0;
}
#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */

void arduino::SerialUSB_::begin(unsigned long baudrate, uint16_t config) {
if (!started) {
#ifndef CONFIG_USB_DEVICE_STACK_NEXT
usb_enable(NULL);
#ifndef CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT
#warning "Can't read CDC baud change, please enable CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT"
#else
cdc_acm_dte_rate_callback_set(usb_dev, SerialUSB_::baudChangeHandler);
#endif
#else
enable_usb_device_next();
#endif
ZephyrSerial::begin(baudrate, config);
started = true;
}
}

arduino::SerialUSB_::operator bool() {
uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &dtr);
return dtr;
}

size_t arduino::SerialUSB_::write(const uint8_t *buffer, size_t size) {
if (!Serial) {
return 0;
}
return arduino::ZephyrSerial::write(buffer, size);
}

void arduino::SerialUSB_::flush() {
if (!Serial) {
return;
}
arduino::ZephyrSerial::flush();
}

arduino::SerialUSB_ Serial(usb_dev);
#endif
Loading
Loading