From 555fe907ea2bc27df0a41fc63476634cd353dd9e Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 1 Oct 2024 11:01:50 +0200 Subject: [PATCH 01/44] digitalPins: take into account boards without gpios Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 4 ++++ cores/arduino/zephyrCommon.cpp | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 9657a7125..9d4fca138 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -14,6 +14,7 @@ #include #include +#if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 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))) \ @@ -32,6 +33,7 @@ #endif #undef DIGITAL_PIN_CHECK_UNIQUE +#endif /* Return the index of it if matched, oterwise return 0 */ #define LED_BUILTIN_INDEX_BY_REG_AND_PINNUM(n, p, i, dev, num) \ @@ -79,7 +81,9 @@ * 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 }; diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 92d99ff02..f98b459d9 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -12,6 +12,8 @@ static const struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP( namespace { +#if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 0 + /* * Calculate GPIO ports/pins number statically from devicetree configuration */ @@ -68,6 +70,13 @@ const int port_num = const int max_ngpios = max_in_list( 0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, GPIO_NGPIOS, (, ))); +#else + +const int port_num = 1; +const int max_ngpios = 0; + +#endif + /* * GPIO callback implementation */ From 16cf84ddbd548959eaade4acba9b30feacef1a7e Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 1 Oct 2024 11:02:32 +0200 Subject: [PATCH 02/44] main.cpp: support loading via llext Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 97afd420d..7530464a6 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -5,6 +5,9 @@ */ #include "Arduino.h" +#ifdef CONFIG_LLEXT +#include +#endif int main(void) { setup(); @@ -16,3 +19,7 @@ int main(void) { return 0; } + +#ifdef CONFIG_LLEXT +LL_EXTENSION_SYMBOL(main); +#endif \ No newline at end of file From f95580c2cd5b0198f41590cf1dbd43d8f3e873f2 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 1 Oct 2024 11:06:25 +0200 Subject: [PATCH 03/44] Implement SerialUSB Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 1 + cores/arduino/SerialUSB.h | 36 +++++++++++++++ cores/arduino/USB.cpp | 80 ++++++++++++++++++++++++++++++++++ cores/arduino/main.cpp | 3 ++ cores/arduino/zephyrSerial.cpp | 4 ++ cores/arduino/zephyrSerial.h | 16 +++++-- 6 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 cores/arduino/SerialUSB.h create mode 100644 cores/arduino/USB.cpp diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 9d4fca138..22b7bb105 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -109,5 +109,6 @@ int digitalPinToInterrupt(pin_size_t pin); #endif // LED_BUILTIN #ifdef __cplusplus +#include #include #endif // __cplusplus diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h new file mode 100644 index 000000000..0e67dc715 --- /dev/null +++ b/cores/arduino/SerialUSB.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +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; + +protected: + uint32_t dtr = 0; + uint32_t baudrate; + void _baudChangeHandler(); + static void _baudChangeDispatch(struct k_timer *timer); + +private: + struct k_timer baud_timer; + bool started = false; +}; +} // namespace arduino + +#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +extern arduino::SerialUSB_ Serial; +#endif \ No newline at end of file diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp new file mode 100644 index 000000000..3847d96d2 --- /dev/null +++ b/cores/arduino/USB.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// Make PluggableUSB link happy +#include "api/PluggableUSB.h" + +static uint8_t _epBuffer[1]; +void* epBuffer(unsigned int n) { + return &_epBuffer[n]; +}; + +arduino::PluggableUSB_::PluggableUSB_() {} + +#include +#include +#include +#include +#include + +#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +const struct device *const usb_dev = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), cdc_acm, 0)); + +void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) { + if (cb_status == USB_DC_CONFIGURED) { + + } +} + +void __attribute__((weak)) _on_1200_bps() { + NVIC_SystemReset(); +} + +void arduino::SerialUSB_::_baudChangeHandler() +{ + uart_line_ctrl_get(uart, UART_LINE_CTRL_BAUD_RATE, &baudrate); + if (baudrate == 1200) { + usb_disable(); + _on_1200_bps(); + } +} + +static void _baudChangeHandler(const struct device *dev, uint32_t rate) +{ + if (rate == 1200) { + usb_disable(); + _on_1200_bps(); + } +} + +void arduino::SerialUSB_::_baudChangeDispatch(struct k_timer *timer) { + arduino::SerialUSB_* dev = (arduino::SerialUSB_*)k_timer_user_data_get(timer); + dev->_baudChangeHandler(); +} + + +void arduino::SerialUSB_::begin(unsigned long baudrate, uint16_t config) { + if (!started) { + usb_enable(NULL); + #ifndef CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT + k_timer_init(&baud_timer, SerialUSB_::_baudChangeDispatch, NULL); + k_timer_user_data_set(&baud_timer, this); + k_timer_start(&baud_timer, K_MSEC(100), K_MSEC(100)); + #else + cdc_acm_dte_rate_callback_set(usb_dev, ::_baudChangeHandler); + #endif + ZephyrSerial::begin(baudrate, config); + started = true; + } +} + +arduino::SerialUSB_::operator bool() { + uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &dtr); + return dtr; +} + +arduino::SerialUSB_ Serial(usb_dev); +#endif \ No newline at end of file diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 7530464a6..641ed1b58 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -10,6 +10,9 @@ #endif int main(void) { +#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) + Serial.begin(115200); +#endif setup(); for (;;) { diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index b3047ac1c..2a8f476ea 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -9,6 +9,7 @@ #include #include +#include namespace { @@ -164,7 +165,10 @@ size_t arduino::ZephyrSerial::write(const uint8_t *buffer, size_t size) } #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) +#if !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +// If CDC USB, use that object as Serial (and SerialUSB) arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), serials, 0))); +#endif #if (DT_PROP_LEN(DT_PATH(zephyr_user), serials) > 1) #define ARDUINO_SERIAL_DEFINED_0 1 diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index b62e54f64..d280d2519 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -7,8 +7,6 @@ #pragma once #include - -#include #include namespace arduino { @@ -38,7 +36,7 @@ class ZephyrSerial : public HardwareSerial template class ZephyrSerialBuffer { - friend arduino::ZephyrSerial; + friend arduino::ZephyrSerial; struct ring_buf ringbuf; uint8_t buffer[SZ]; struct k_sem sem; @@ -53,10 +51,15 @@ class ZephyrSerial : public HardwareSerial ZephyrSerial(const struct device *dev) : uart(dev) { } void begin(unsigned long baudrate, uint16_t config); void begin(unsigned long baudrate) { begin(baudrate, SERIAL_8N1); } - void flush() { } + void flush() { + while (ring_buf_size_get(&tx.ringbuf) > 0) { + k_yield(); + } + } void end() { } size_t write(const uint8_t *buffer, size_t size); size_t write(const uint8_t data) { return write(&data, 1); } + using Print::write; // pull in write(str) and write(buf, size) from Print int available(); int peek(); int read(); @@ -66,6 +69,8 @@ class ZephyrSerial : public HardwareSerial return true; } + friend class SerialUSB_; + protected: void IrqHandler(); static void IrqDispatch(const struct device *dev, void *data); @@ -79,7 +84,10 @@ class ZephyrSerial : public HardwareSerial } // namespace arduino #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) +#if !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +// If CDC USB, use that object as Serial (and SerialUSB) extern arduino::ZephyrSerial Serial; +#endif #if (DT_PROP_LEN(DT_PATH(zephyr_user), serials) > 1) #define SERIAL_DEFINED_0 1 #define EXTERN_SERIAL_N(i) extern arduino::ZephyrSerial Serial##i; From 3e528343f2db27fefc725b3fe27177f8170a5e92 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 1 Oct 2024 11:07:30 +0200 Subject: [PATCH 04/44] Fixes for proper core compatibility Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 5 ++ cores/arduino/abi.cpp | 24 +++++++++ cores/arduino/itoa.cpp | 116 ++++++++++++++++++++++++++++++++++++++++ cores/arduino/new | 54 +++++++++++++++++++ cores/arduino/new.cpp | 105 ++++++++++++++++++++++++++++++++++++ cores/arduino/new.h | 3 ++ 6 files changed, 307 insertions(+) create mode 100644 cores/arduino/abi.cpp create mode 100644 cores/arduino/itoa.cpp create mode 100644 cores/arduino/new create mode 100644 cores/arduino/new.cpp create mode 100644 cores/arduino/new.h diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 22b7bb105..99f6830d3 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -13,6 +13,7 @@ #include #include #include +#include #if DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios) > 0 #define DIGITAL_PIN_EXISTS(n, p, i, dev, num) \ @@ -111,4 +112,8 @@ int digitalPinToInterrupt(pin_size_t pin); #ifdef __cplusplus #include #include + +// Allow namespace-less operations if Arduino.h is included +using namespace arduino; + #endif // __cplusplus diff --git a/cores/arduino/abi.cpp b/cores/arduino/abi.cpp new file mode 100644 index 000000000..606882d83 --- /dev/null +++ b/cores/arduino/abi.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); +extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); + +namespace std { + [[gnu::weak, noreturn]] void terminate() { + abort(); + } +} + +void __cxa_pure_virtual(void) { + std::terminate(); +} + +void __cxa_deleted_virtual(void) { + std::terminate(); +} diff --git a/cores/arduino/itoa.cpp b/cores/arduino/itoa.cpp new file mode 100644 index 000000000..929ec4d0a --- /dev/null +++ b/cores/arduino/itoa.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern char* itoa( int value, char *string, int radix ) +{ + return ltoa( value, string, radix ) ; +} + +extern char* ltoa( long value, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if ( string == NULL ) + { + return 0 ; + } + + if (radix > 36 || radix <= 1) + { + return 0 ; + } + + sign = (radix == 10 && value < 0); + if (sign) + { + v = -value; + } + else + { + v = (unsigned long)value; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + + if (sign) + *sp++ = '-'; + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + + return string; +} + +extern char* utoa( unsigned int value, char *string, int radix ) +{ + return ultoa( value, string, radix ) ; +} + +extern char* ultoa( unsigned long value, char *string, int radix ) +{ + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if ( string == NULL ) + { + return 0; + } + + if (radix > 36 || radix <= 1) + { + return 0; + } + + while (v || tp == tmp) + { + i = v % radix; + v = v / radix; + if (i < 10) + *tp++ = i+'0'; + else + *tp++ = i + 'a' - 10; + } + + sp = string; + + + while (tp > tmp) + *sp++ = *--tp; + *sp = 0; + + return string; +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/cores/arduino/new b/cores/arduino/new new file mode 100644 index 000000000..060507477 --- /dev/null +++ b/cores/arduino/new @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NEW_H +#define NEW_H + +#include + +namespace std { + struct nothrow_t {}; + extern const nothrow_t nothrow; + + // These are not actually implemented, to prevent overhead and + // complexity. They are still declared to allow implementing + // them in user code if needed. + typedef void (*new_handler)(); + new_handler set_new_handler(new_handler new_p) noexcept; + new_handler get_new_handler() noexcept; + + // This is normally declared in various headers that we do not have + // available, so just define it here. We could also use ::size_t + // below, but then anyone including can no longer assume + // std::size_t is available. + using size_t = ::size_t; +} // namespace std + +[[gnu::weak]] void * operator new(std::size_t size); +[[gnu::weak]] void * operator new[](std::size_t size); + +[[gnu::weak]] void * operator new(std::size_t size, const std::nothrow_t tag) noexcept; +[[gnu::weak]] void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept; + +void * operator new(std::size_t size, void *place) noexcept; +void * operator new[](std::size_t size, void *place) noexcept; + +[[gnu::weak]] void operator delete(void * ptr) noexcept; +[[gnu::weak]] void operator delete[](void * ptr) noexcept; + +#if __cplusplus >= 201402L +[[gnu::weak]] void operator delete(void* ptr, std::size_t size) noexcept; +[[gnu::weak]] void operator delete[](void * ptr, std::size_t size) noexcept; +#endif // __cplusplus >= 201402L + +[[gnu::weak]] void operator delete(void* ptr, const std::nothrow_t& tag) noexcept; +[[gnu::weak]] void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept; + +void operator delete(void* ptr, void* place) noexcept; +void operator delete[](void* ptr, void* place) noexcept; + +#endif + diff --git a/cores/arduino/new.cpp b/cores/arduino/new.cpp new file mode 100644 index 000000000..0dd8406bb --- /dev/null +++ b/cores/arduino/new.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "new.h" + +// The C++ spec dictates that allocation failure should cause the +// (non-nothrow version of the) operator new to throw an exception. +// Since we expect to have exceptions disabled, it would be more +// appropriate (and probably standards-compliant) to terminate instead. +// Historically failure causes null to be returned, but this define +// allows switching to more robust terminating behaviour (that might +// become the default at some point in the future). Note that any code +// that wants null to be returned can (and should) use the nothrow +// versions of the new statement anyway and is unaffected by this. +// #define NEW_TERMINATES_ON_FAILURE + +namespace std { + // Defined in abi.cpp + void terminate(); + + const nothrow_t nothrow; +} + +static void * new_helper(std::size_t size) { + // Even zero-sized allocations should return a unique pointer, but + // malloc does not guarantee this + if (size == 0) + size = 1; + return malloc(size); +} + +void * operator new(std::size_t size) { + void *res = new_helper(size); +#if defined(NEW_TERMINATES_ON_FAILURE) + if (!res) + std::terminate(); +#endif + return res; +} +void * operator new[](std::size_t size) { + return operator new(size); +} + +void * operator new(std::size_t size, const std::nothrow_t tag) noexcept { +#if defined(NEW_TERMINATES_ON_FAILURE) + // Cannot call throwing operator new as standard suggests, so call + // new_helper directly then + return new_helper(size); +#else + return operator new(size); +#endif +} +void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept { +#if defined(NEW_TERMINATES_ON_FAILURE) + // Cannot call throwing operator new[] as standard suggests, so call + // malloc directly then + return new_helper(size); +#else + return operator new[](size); +#endif +} + +void * operator new(std::size_t size, void *place) noexcept { + // Nothing to do + (void)size; // unused + return place; +} +void * operator new[](std::size_t size, void *place) noexcept { + return operator new(size, place); +} + +void operator delete(void * ptr) noexcept { + free(ptr); +} +void operator delete[](void * ptr) noexcept { + operator delete(ptr); +} + +#if __cplusplus >= 201402L +void operator delete(void* ptr, std::size_t size) noexcept { + operator delete(ptr); +} +void operator delete[](void * ptr, std::size_t size) noexcept { + operator delete[](ptr); +} +#endif // __cplusplus >= 201402L + +void operator delete(void* ptr, const std::nothrow_t& tag) noexcept { + operator delete(ptr); +} +void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept { + operator delete[](ptr); +} + +void operator delete(void* ptr, void* place) noexcept { + (void)ptr; (void)place; // unused + // Nothing to do +} +void operator delete[](void* ptr, void* place) noexcept { + (void)ptr; (void)place; // unused + // Nothing to do +} diff --git a/cores/arduino/new.h b/cores/arduino/new.h new file mode 100644 index 000000000..d52985368 --- /dev/null +++ b/cores/arduino/new.h @@ -0,0 +1,3 @@ +// This file originally used a non-standard name for this Arduino core +// only, so still expose the old new.h name for compatibility. +#include "new" From 390b3911fae78cd6687997ed09694f81b7e95d82 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 1 Oct 2024 17:50:25 +0200 Subject: [PATCH 05/44] temp_bugfix: make serialEventRun symbol appear if CDC is not defined Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 641ed1b58..88874624a 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -10,7 +10,7 @@ #endif int main(void) { -#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) || DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) Serial.begin(115200); #endif setup(); From a1f06b479cf48f62ddf922c02b03a5348f163160 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 14 Oct 2024 18:21:53 +0200 Subject: [PATCH 06/44] Serial: fix long write() Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrSerial.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index 2a8f476ea..f51893a8a 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -79,10 +79,6 @@ void arduino::ZephyrSerial::IrqHandler() return; } - if (ring_buf_size_get(&tx.ringbuf) == 0) { - uart_irq_tx_disable(uart); - } - k_sem_take(&rx.sem, K_NO_WAIT); while (uart_irq_rx_ready(uart) && ((length = uart_fifo_read(uart, buf, sizeof(buf))) > 0)) { length = min(sizeof(buf), static_cast(length)); @@ -95,6 +91,11 @@ void arduino::ZephyrSerial::IrqHandler() k_sem_give(&rx.sem); k_sem_take(&tx.sem, K_NO_WAIT); + + if (ring_buf_size_get(&tx.ringbuf) == 0) { + uart_irq_tx_disable(uart); + } + while (uart_irq_tx_ready(uart) && ((length = ring_buf_size_get(&tx.ringbuf)) > 0)) { length = min(sizeof(buf), static_cast(length)); ring_buf_peek(&tx.ringbuf, &buf[0], length); @@ -149,19 +150,28 @@ int arduino::ZephyrSerial::read() size_t arduino::ZephyrSerial::write(const uint8_t *buffer, size_t size) { - int ret; - - k_sem_take(&tx.sem, K_FOREVER); - ret = ring_buf_put(&tx.ringbuf, buffer, size); - k_sem_give(&tx.sem); + int idx = 0; - if (ret < 0) { - return 0; + while (1) { + k_sem_take(&tx.sem, K_FOREVER); + auto ret = ring_buf_put(&tx.ringbuf, &buffer[idx], size-idx); + k_sem_give(&tx.sem); + if (ret < 0) { + return 0; + } + idx += ret; + if (ret == 0) { + uart_irq_tx_enable(uart); + yield(); + } + if (idx == size) { + break; + } } uart_irq_tx_enable(uart); - return ret; + return size; } #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) From 54e5bb00f27275ff3173ff100c65833ead782f0c Mon Sep 17 00:00:00 2001 From: Kurt Eckhardt Date: Fri, 29 Nov 2024 15:10:04 -0800 Subject: [PATCH 07/44] Some Serial object fixes... added availableForWrite - overwrite Print virtual - get it from ring buffer fix peek and Read, that if 0 bytes read from ring buffer return -1 begin method appeared to have initial garbage in it. so have it call ring_buf_reset on the rx ring buffer Co-authored-by: Kurt Eckhardt Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrSerial.cpp | 23 +++++++++++++++++++---- cores/arduino/zephyrSerial.h | 1 + 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index f51893a8a..023f5c7ff 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -66,6 +66,10 @@ void arduino::ZephyrSerial::begin(unsigned long baud, uint16_t conf) uart_configure(uart, &config); uart_irq_callback_user_data_set(uart, arduino::ZephyrSerial::IrqDispatch, this); + k_sem_take(&rx.sem, K_FOREVER); + ring_buf_reset(&rx.ringbuf); + k_sem_give(&rx.sem); + uart_irq_rx_enable(uart); } @@ -126,15 +130,26 @@ int arduino::ZephyrSerial::available() return ret; } +int arduino::ZephyrSerial::availableForWrite() +{ + int ret; + + k_sem_take(&rx.sem, K_FOREVER); + ret = ring_buf_space_get(&rx.ringbuf); + k_sem_give(&rx.sem); + + return ret; +} + int arduino::ZephyrSerial::peek() { uint8_t data; k_sem_take(&rx.sem, K_FOREVER); - ring_buf_peek(&rx.ringbuf, &data, 1); + uint32_t cb_ret = ring_buf_peek(&rx.ringbuf, &data, 1); k_sem_give(&rx.sem); - return data; + return cb_ret? data : -1; } int arduino::ZephyrSerial::read() @@ -142,10 +157,10 @@ int arduino::ZephyrSerial::read() uint8_t data; k_sem_take(&rx.sem, K_FOREVER); - ring_buf_get(&rx.ringbuf, &data, 1); + uint32_t cb_ret = ring_buf_get(&rx.ringbuf, &data, 1); k_sem_give(&rx.sem); - return data; + return cb_ret? data : -1; } size_t arduino::ZephyrSerial::write(const uint8_t *buffer, size_t size) diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index d280d2519..ff3e82066 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -61,6 +61,7 @@ class ZephyrSerial : public HardwareSerial size_t write(const uint8_t data) { return write(&data, 1); } using Print::write; // pull in write(str) and write(buf, size) from Print int available(); + int availableForWrite(); int peek(); int read(); From 49cda443405509bfe93ade7ed2b6c3d1f86ad4e2 Mon Sep 17 00:00:00 2001 From: Kurt Eckhardt Date: Sat, 30 Nov 2024 10:37:52 -0800 Subject: [PATCH 08/44] SerialX.flush() - now wait until TC Complete SerialX.flush() - now waits until the TX completes... Looks at the TC flag of the uart to know when it has completed the transfer. Moved the flush() function to .cpp file as it now uses the device header file which is only included in the .cpp file Co-authored-by: Kurt Eckhardt Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrSerial.cpp | 10 ++++++++++ cores/arduino/zephyrSerial.h | 6 +----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index 023f5c7ff..b6f50e10e 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -189,6 +189,16 @@ size_t arduino::ZephyrSerial::write(const uint8_t *buffer, size_t size) return size; } +void arduino::ZephyrSerial::flush() { + while (ring_buf_size_get(&tx.ringbuf) > 0) { + k_yield(); + } + while (uart_irq_tx_complete(uart) == 0){ + k_yield(); + } +} + + #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) #if !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) // If CDC USB, use that object as Serial (and SerialUSB) diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index ff3e82066..2febd3695 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -51,11 +51,7 @@ class ZephyrSerial : public HardwareSerial ZephyrSerial(const struct device *dev) : uart(dev) { } void begin(unsigned long baudrate, uint16_t config); void begin(unsigned long baudrate) { begin(baudrate, SERIAL_8N1); } - void flush() { - while (ring_buf_size_get(&tx.ringbuf) > 0) { - k_yield(); - } - } + void flush(); void end() { } size_t write(const uint8_t *buffer, size_t size); size_t write(const uint8_t data) { return write(&data, 1); } From 7484a353bd82252264e9b1f7817f8425c2153013 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 7 Oct 2024 12:25:41 +0200 Subject: [PATCH 09/44] core: prerequisites for ArduinoBLE Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 99f6830d3..de7346175 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -112,6 +112,8 @@ int digitalPinToInterrupt(pin_size_t pin); #ifdef __cplusplus #include #include +#include +#include // Allow namespace-less operations if Arduino.h is included using namespace arduino; From 91bbddbfec9582e3a6790ecfd53e54df5485be22 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 13 Dec 2024 12:43:45 +0100 Subject: [PATCH 10/44] core: add time related macros Fixes compilation error found at https://www.cnx-software.com/2024/12/10/arduino-core-for-zephyr-beta-released/ Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 1 + cores/arduino/time_macros.h | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 cores/arduino/time_macros.h diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index de7346175..d53666d8a 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -114,6 +114,7 @@ int digitalPinToInterrupt(pin_size_t pin); #include #include #include +#include // Allow namespace-less operations if Arduino.h is included using namespace arduino; diff --git a/cores/arduino/time_macros.h b/cores/arduino/time_macros.h new file mode 100644 index 000000000..6c9290f6c --- /dev/null +++ b/cores/arduino/time_macros.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#define clockCyclesPerMicrosecond() (1000000 / k_cyc_to_ns_near64(1000)) +#define clockCyclesToMicroseconds(a) (a / clockCyclesPerMicrosecond()) +#define microsecondsToClockCycles(a) (a * clockCyclesPerMicrosecond()) From c4497d56b6028f45cb76a93793715f94014d433a Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 23 Jan 2025 17:28:41 +0100 Subject: [PATCH 11/44] analogWrite: implement DAC pins Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 21 +++++++++++++++ cores/arduino/overloads.h | 9 +++++++ cores/arduino/zephyrCommon.cpp | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 cores/arduino/overloads.h diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index d53666d8a..8a1a2ed1e 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -98,11 +99,30 @@ enum analogPins { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), #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 + void interrupts(void); 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 #if !defined(LED_BUILTIN) && defined(ZARD_LED_BUILTIN) @@ -115,6 +135,7 @@ int digitalPinToInterrupt(pin_size_t pin); #include #include #include +#include // Allow namespace-less operations if Arduino.h is included using namespace arduino; diff --git a/cores/arduino/overloads.h b/cores/arduino/overloads.h new file mode 100644 index 000000000..5670b2701 --- /dev/null +++ b/cores/arduino/overloads.h @@ -0,0 +1,9 @@ +#ifdef CONFIG_DAC + +void analogWrite(enum dacPins pinNumber, int value); + +#endif + +// In c++ mode, we also provide analogReadResolution and analogWriteResolution getters +int analogReadResolution(); +int analogWriteResolution(); \ No newline at end of file diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index f98b459d9..dbc4627d6 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -184,6 +184,28 @@ size_t analog_pin_index(pin_size_t pinNumber) { #endif //CONFIG_ADC +#ifdef CONFIG_DAC + +#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), dac)) + +#define DAC_NODE DT_PHANDLE(DT_PATH(zephyr_user), dac) +#define DAC_RESOLUTION DT_PROP(DT_PATH(zephyr_user), dac_resolution) +static const struct device *const dac_dev = DEVICE_DT_GET(DAC_NODE); + +#define DAC_CHANNEL_DEFINE(n, p, i) \ + { \ + .channel_id = DT_PROP_BY_IDX(n, p, i), \ + .resolution = DAC_RESOLUTION, \ + .buffered = true, \ + }, + +static const struct dac_channel_cfg dac_ch_cfg[] = + { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), dac_channels, DAC_CHANNEL_DEFINE) }; + +#endif + +#endif //CONFIG_DAC + static unsigned int irq_key; static bool interrupts_disabled = false; } // namespace @@ -307,6 +329,16 @@ unsigned long millis(void) { return k_uptime_get_32(); } +#if defined(CONFIG_DAC) || defined(CONFIG_PWM) +static int _analog_write_resolution = 8; +void analogWriteResolution(int bits) { + _analog_write_resolution = bits; +} +int analogWriteResolution() { + return _analog_write_resolution; +} +#endif + #ifdef CONFIG_PWM void analogWrite(pin_size_t pinNumber, int value) @@ -321,6 +353,8 @@ void analogWrite(pin_size_t pinNumber, int value) return; } + value = map(value, 0, 1 << _analog_write_resolution, 0, arduino_pwm[idx].period); + if (((uint32_t)value) > arduino_pwm[idx].period) { value = arduino_pwm[idx].period; } else if (value < 0) { @@ -336,6 +370,21 @@ void analogWrite(pin_size_t pinNumber, int value) #endif +#ifdef CONFIG_DAC +void analogWrite(enum dacPins dacName, int value) +{ + if (dacName >= NUM_OF_DACS) { + return; + } + + dac_channel_setup(dac_dev, &dac_ch_cfg[dacName]); + + const int max_dac_value = 1U << dac_ch_cfg[dacName].resolution; + dac_write_value(dac_dev, dac_ch_cfg[dacName].channel_id, map(value, 0, 1 << _analog_write_resolution, 0, max_dac_value)); +} +#endif + + #ifdef CONFIG_ADC void analogReference(uint8_t mode) From 34a168142426328921a1d6265498e55aa3745179 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 18 Dec 2024 10:46:38 +0100 Subject: [PATCH 12/44] new: add rewrites for c++17 Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/new | 32 ++++++++++++++++++++++---------- cores/arduino/new.cpp | 32 +++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/cores/arduino/new b/cores/arduino/new index 060507477..b97bc949f 100644 --- a/cores/arduino/new +++ b/cores/arduino/new @@ -8,6 +8,7 @@ #define NEW_H #include +//#pragma long_calls namespace std { struct nothrow_t {}; @@ -27,25 +28,36 @@ namespace std { using size_t = ::size_t; } // namespace std -[[gnu::weak]] void * operator new(std::size_t size); -[[gnu::weak]] void * operator new[](std::size_t size); +void * operator new(std::size_t size); +void * operator new[](std::size_t size); -[[gnu::weak]] void * operator new(std::size_t size, const std::nothrow_t tag) noexcept; -[[gnu::weak]] void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept; +#if __cplusplus >= 201703L +void * operator new(std::size_t count, std::align_val_t al); +void * operator new[](std::size_t count, std::align_val_t al); + +void* operator new(std::size_t count, std::align_val_t al, + const std::nothrow_t& tag) noexcept; +void* operator new[](std::size_t count, std::align_val_t al, + const std::nothrow_t& tag) noexcept; +#endif + +void * operator new(std::size_t size, const std::nothrow_t tag) noexcept; +void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept; void * operator new(std::size_t size, void *place) noexcept; void * operator new[](std::size_t size, void *place) noexcept; -[[gnu::weak]] void operator delete(void * ptr) noexcept; -[[gnu::weak]] void operator delete[](void * ptr) noexcept; + +void operator delete(void * ptr) noexcept; +void operator delete[](void * ptr) noexcept; #if __cplusplus >= 201402L -[[gnu::weak]] void operator delete(void* ptr, std::size_t size) noexcept; -[[gnu::weak]] void operator delete[](void * ptr, std::size_t size) noexcept; +void operator delete(void* ptr, std::size_t size) noexcept; +void operator delete[](void * ptr, std::size_t size) noexcept; #endif // __cplusplus >= 201402L -[[gnu::weak]] void operator delete(void* ptr, const std::nothrow_t& tag) noexcept; -[[gnu::weak]] void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept; +void operator delete(void* ptr, const std::nothrow_t& tag) noexcept; +void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept; void operator delete(void* ptr, void* place) noexcept; void operator delete[](void* ptr, void* place) noexcept; diff --git a/cores/arduino/new.cpp b/cores/arduino/new.cpp index 0dd8406bb..ad85eecc4 100644 --- a/cores/arduino/new.cpp +++ b/cores/arduino/new.cpp @@ -44,6 +44,36 @@ void * operator new[](std::size_t size) { return operator new(size); } +#if __cplusplus >= 201703L +void* operator new(std::size_t count, std::align_val_t al) { + return operator new(count); +} + +void* operator new[](std::size_t count, std::align_val_t al) { + return operator new(count); +} + +void * operator new(std::size_t size, std::align_val_t al, const std::nothrow_t tag) noexcept { +#if defined(NEW_TERMINATES_ON_FAILURE) + // Cannot call throwing operator new as standard suggests, so call + // new_helper directly then + return new_helper(size); +#else + return operator new(size); +#endif +} + +void * operator new[](std::size_t size, std::align_val_t al, const std::nothrow_t& tag) noexcept { +#if defined(NEW_TERMINATES_ON_FAILURE) + // Cannot call throwing operator new[] as standard suggests, so call + // malloc directly then + return new_helper(size); +#else + return operator new[](size); +#endif +} +#endif + void * operator new(std::size_t size, const std::nothrow_t tag) noexcept { #if defined(NEW_TERMINATES_ON_FAILURE) // Cannot call throwing operator new as standard suggests, so call @@ -102,4 +132,4 @@ void operator delete(void* ptr, void* place) noexcept { void operator delete[](void* ptr, void* place) noexcept { (void)ptr; (void)place; // unused // Nothing to do -} +} \ No newline at end of file From c66a25d0af3b7bd7385149fe81b5300359c34205 Mon Sep 17 00:00:00 2001 From: Kurt Eckhardt Date: Mon, 27 Jan 2025 09:26:19 +0100 Subject: [PATCH 13/44] Implement analogReadResolution Co-authored-by: Kurt Eckhardt Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 3 +++ cores/arduino/zephyrCommon.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 8a1a2ed1e..64a7aa4a9 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -97,6 +97,9 @@ enum digitalPins { 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 diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index dbc4627d6..5e82a8d6a 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -399,10 +399,24 @@ void analogReference(uint8_t mode) } } +// Note: We can not update the arduino_adc structure as it is read only... +static int read_resolution = 10; + +void analogReadResolution(int bits) +{ + read_resolution = bits; +} + +int analogReadResolution() +{ + return read_resolution; +} + + int analogRead(pin_size_t pinNumber) { int err; - int16_t buf; + uint16_t buf; struct adc_sequence seq = { .buffer = &buf, .buffer_size = sizeof(buf) }; size_t idx = analog_pin_index(pinNumber); @@ -432,7 +446,13 @@ int analogRead(pin_size_t pinNumber) return err; } - return buf; + /* + * If necessary map the return value to the + * number of bits the user has asked for + */ + if (read_resolution == seq.resolution) return buf; + if (read_resolution < seq.resolution) return buf >> (seq.resolution - read_resolution); + return buf << (read_resolution - seq.resolution) ; } #endif From 67e9467b0224fd93342ad0a12e32121c83e1ff84 Mon Sep 17 00:00:00 2001 From: kurte Date: Wed, 4 Dec 2024 09:19:47 -0800 Subject: [PATCH 14/44] zephyrSerial.h - reduce compiler warnings Co-authored-by: kurte Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrSerial.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index 2febd3695..7e7a160ab 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -14,8 +14,8 @@ namespace arduino { class ZephyrSerialStub : public HardwareSerial { public: - void begin(unsigned long baudRate) { } - void begin(unsigned long baudrate, uint16_t config) { } + void begin(__attribute__((unused)) unsigned long baudRate) { } + void begin(__attribute__((unused)) unsigned long baudrate, __attribute__((unused)) uint16_t config) { } void end() { } int available() { return 0; } int peek() { return 0; } From 07f37a33bdf4a1525e8348ed962500acf26acd2e Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 24 Jan 2025 15:13:35 +0100 Subject: [PATCH 15/44] USB: fix corner case when cdc_acm is in dt and CONFIG_CDC is disabled Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/SerialUSB.h | 2 +- cores/arduino/USB.cpp | 12 +----------- cores/arduino/main.cpp | 6 ++++-- cores/arduino/zephyrSerial.cpp | 9 +++++++-- cores/arduino/zephyrSerial.h | 2 +- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h index 0e67dc715..f26de64a7 100644 --- a/cores/arduino/SerialUSB.h +++ b/cores/arduino/SerialUSB.h @@ -31,6 +31,6 @@ class SerialUSB_ : public ZephyrSerial { }; } // namespace arduino -#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) extern arduino::SerialUSB_ Serial; #endif \ No newline at end of file diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 3847d96d2..735f23505 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -4,23 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -// Make PluggableUSB link happy -#include "api/PluggableUSB.h" - -static uint8_t _epBuffer[1]; -void* epBuffer(unsigned int n) { - return &_epBuffer[n]; -}; - -arduino::PluggableUSB_::PluggableUSB_() {} - #include #include #include #include #include -#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) const struct device *const usb_dev = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), cdc_acm, 0)); void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) { diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 88874624a..b6754e170 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -10,14 +10,16 @@ #endif int main(void) { -#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) || DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) +#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) Serial.begin(115200); #endif setup(); for (;;) { loop(); + #if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) || DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) if (arduino::serialEventRun) arduino::serialEventRun(); + #endif } return 0; @@ -25,4 +27,4 @@ int main(void) { #ifdef CONFIG_LLEXT LL_EXTENSION_SYMBOL(main); -#endif \ No newline at end of file +#endif diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index b6f50e10e..3bde2de44 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -198,11 +198,16 @@ void arduino::ZephyrSerial::flush() { } } +#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm)) +#define FIRST_UART_INDEX 1 +#else +#define FIRST_UART_INDEX 0 +#endif #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) -#if !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) // If CDC USB, use that object as Serial (and SerialUSB) -arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), serials, 0))); +arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), serials, FIRST_UART_INDEX))); #endif #if (DT_PROP_LEN(DT_PATH(zephyr_user), serials) > 1) #define ARDUINO_SERIAL_DEFINED_0 1 diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index 7e7a160ab..047262e80 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -81,7 +81,7 @@ class ZephyrSerial : public HardwareSerial } // namespace arduino #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) -#if !DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) +#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) // If CDC USB, use that object as Serial (and SerialUSB) extern arduino::ZephyrSerial Serial; #endif From ad1510f90dfb389ca9809ba857a4a2c59f789f11 Mon Sep 17 00:00:00 2001 From: Mike S Date: Wed, 29 Jan 2025 10:13:53 +0100 Subject: [PATCH 16/44] enable static threads Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Mike S Signed-off-by: TOKITA Hiroshi --- cores/arduino/CMakeLists.txt | 1 + cores/arduino/main.cpp | 9 +++++++++ cores/arduino/threads.cpp | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 cores/arduino/threads.cpp diff --git a/cores/arduino/CMakeLists.txt b/cores/arduino/CMakeLists.txt index 36e337b90..90b775589 100644 --- a/cores/arduino/CMakeLists.txt +++ b/cores/arduino/CMakeLists.txt @@ -21,6 +21,7 @@ endif() if(DEFINED CONFIG_ARDUINO_ENTRY) zephyr_sources(main.cpp) +zephyr_sources(threads.cpp) endif() endif() diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index b6754e170..ef8a34df8 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -9,10 +9,19 @@ #include #endif +#ifdef CONFIG_MULTITHREADING +void start_static_threads(); +#endif + int main(void) { #if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) Serial.begin(115200); #endif + +#ifdef CONFIG_MULTITHREADING + start_static_threads(); +#endif + setup(); for (;;) { diff --git a/cores/arduino/threads.cpp b/cores/arduino/threads.cpp new file mode 100644 index 000000000..99a4a141c --- /dev/null +++ b/cores/arduino/threads.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "Arduino.h" + +#ifdef CONFIG_MULTITHREADING +void start_static_threads() { + #define _FOREACH_STATIC_THREAD(thread_data) \ + STRUCT_SECTION_FOREACH(_static_thread_data, thread_data) + + _FOREACH_STATIC_THREAD(thread_data) { + k_thread_create(thread_data->init_thread, thread_data->init_stack, thread_data->init_stack_size, thread_data->init_entry, + thread_data->init_p1, thread_data->init_p2, thread_data->init_p3, thread_data->init_prio, + thread_data->init_options, thread_data->init_delay); + k_thread_name_set(thread_data->init_thread, thread_data->init_name); + thread_data->init_thread->init_data = thread_data; + } + + /* + * Take a sched lock to prevent them from running + * until they are all started. + */ + k_sched_lock(); + _FOREACH_STATIC_THREAD(thread_data) { + k_thread_start(thread_data->init_thread); + } + k_sched_unlock(); +} +#endif \ No newline at end of file From d83b997448e5a61521dc47e6f058fa4e05c4cddf Mon Sep 17 00:00:00 2001 From: kurte Date: Wed, 5 Feb 2025 11:19:02 -0800 Subject: [PATCH 17/44] Nano 33 BLE - enable the SPI1 sensors Resolves: #51 There is an IO pin on the NANO that that when turned on, enables most of the sensors on the BLE sense which are on SPI1. The MBED version, enables this pin as part of the main(). Which I am trying to emulate. There is code already in, that if you use at least one of the zephyr device drivers, will eanble this pin. However that does not help when you are using external libraries or the like. So I added details about this pin in our overlay file, in the zephyr,user section. I then added code to main.cpp, that is only included if your are building using an NRFX board. Currently the nano and one of the nicla boards. Could also specically only do this on the NANO, but probably does not matter as, the code tries to find that property and only if it is found, does it turn on the pin. Note: The MBED version turn on this pin with high drive. Which I emulated using the information, mentioned in the zephyr discussion. https://github.com/zephyrproject-rtos/zephyr/discussions/78710 In one of my sketches I verified that the pin pads configuration looks the same as mbed setup. With these changes I am able to access most of the sensors. Most of the testing has been done by @mjs513, with some by myself as well. Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: kurte Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index ef8a34df8..c4d38833f 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -13,6 +13,10 @@ void start_static_threads(); #endif +#ifdef CONFIG_GPIO_NRFX +#include +#endif + int main(void) { #if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) Serial.begin(115200); @@ -22,6 +26,20 @@ int main(void) { start_static_threads(); #endif +#ifdef CONFIG_GPIO_NRFX + static const struct gpio_dt_spec enable_sensors = + GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), pin_enable_gpios); + if (gpio_is_ready_dt(&enable_sensors)) { + gpio_flags_t flags = enable_sensors.dt_flags | GPIO_OUTPUT_HIGH | GPIO_ACTIVE_HIGH | NRF_GPIO_DRIVE_H0H1; + Serial.println((uint32_t)flags, HEX); + + gpio_pin_configure(enable_sensors.port, enable_sensors.pin, flags); + gpio_pin_set(enable_sensors.port, enable_sensors.pin, HIGH); + //Serial.println("### Sensor pin enabled ###"); + + delay(500); + } +#endif setup(); for (;;) { From ba941ee5e2dbf23763945b8766717b114e3971e1 Mon Sep 17 00:00:00 2001 From: Kurt Eckhardt Date: Wed, 5 Mar 2025 11:28:36 -0800 Subject: [PATCH 18/44] Add call to initVariant in main move ble sense to variant.cpp Added call to main.cpp to initVariant. Added a weak version in main.cpp. Then moved the code for initializing the enable sensor pin out of main.cpp into the initVariant that I added to variant.cpp for the specific board Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Kurt Eckhardt Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index c4d38833f..d27b11f13 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -13,33 +13,24 @@ void start_static_threads(); #endif -#ifdef CONFIG_GPIO_NRFX -#include -#endif + +// This function will be overwriten by most variants. +void __attribute__((weak))initVariant(void) { + +} + int main(void) { #if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) Serial.begin(115200); #endif + initVariant(); + #ifdef CONFIG_MULTITHREADING start_static_threads(); #endif -#ifdef CONFIG_GPIO_NRFX - static const struct gpio_dt_spec enable_sensors = - GPIO_DT_SPEC_GET(DT_PATH(zephyr_user), pin_enable_gpios); - if (gpio_is_ready_dt(&enable_sensors)) { - gpio_flags_t flags = enable_sensors.dt_flags | GPIO_OUTPUT_HIGH | GPIO_ACTIVE_HIGH | NRF_GPIO_DRIVE_H0H1; - Serial.println((uint32_t)flags, HEX); - - gpio_pin_configure(enable_sensors.port, enable_sensors.pin, flags); - gpio_pin_set(enable_sensors.port, enable_sensors.pin, HIGH); - //Serial.println("### Sensor pin enabled ###"); - - delay(500); - } -#endif setup(); for (;;) { From ca3d01f1e7c278f6adf72cc762947bafd328d383 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 10 Feb 2025 17:25:01 +0100 Subject: [PATCH 19/44] TEMP: get rid of serialEvent Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index d27b11f13..69ea2850c 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -35,7 +35,7 @@ int main(void) { for (;;) { loop(); - #if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) || DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) + #if 0 //(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) || DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) if (arduino::serialEventRun) arduino::serialEventRun(); #endif } From 4f283364d9d8a6a0fd0ab9b862cb7435fa27e301 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 12 Feb 2025 13:13:34 +0100 Subject: [PATCH 20/44] wip: linked build Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++ cores/arduino/new.cpp | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 69ea2850c..67dbb91ec 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -5,6 +5,8 @@ */ #include "Arduino.h" +#include "zephyr/kernel.h" +#include #ifdef CONFIG_LLEXT #include #endif @@ -46,3 +48,47 @@ int main(void) { #ifdef CONFIG_LLEXT LL_EXTENSION_SYMBOL(main); #endif + +/* These magic symbols are provided by the linker. */ +extern void (*__preinit_array_start []) (void) __attribute__((weak)); +extern void (*__preinit_array_end []) (void) __attribute__((weak)); +extern void (*__init_array_start []) (void) __attribute__((weak)); +extern void (*__init_array_end []) (void) __attribute__((weak)); + +static void __libc_init_array (void) +{ + size_t count; + size_t i; + + count = __preinit_array_end - __preinit_array_start; + for (i = 0; i < count; i++) + __preinit_array_start[i] (); + + count = __init_array_end - __init_array_start; + for (i = 0; i < count; i++) + __init_array_start[i] (); +} + +extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struct k_heap* stack, size_t stack_size) { + // copy .data in the right place + // .bss should already be in the right place + // call constructors + extern uintptr_t _sidata; + extern uintptr_t _sdata; + extern uintptr_t _edata; + extern uintptr_t _sbss; + extern uintptr_t _ebss; + extern uintptr_t __heap_start; + extern uintptr_t __heap_end; + //__asm volatile ("cpsie i"); + + const size_t alignment = 4096; + printk("Heap end: %p\n", &__heap_end); + printk("Heap start: %p\n", &__heap_start); + // __heap_start = (__heap_start + (alignment - 1)) & ~(alignment - 1); + + memcpy(&_sdata, &_sidata, &_edata - &_sdata); + memset(&_sbss, 0, &_ebss - &_sbss); + __libc_init_array(); + main(); +} diff --git a/cores/arduino/new.cpp b/cores/arduino/new.cpp index ad85eecc4..7cf51eeba 100644 --- a/cores/arduino/new.cpp +++ b/cores/arduino/new.cpp @@ -132,4 +132,4 @@ void operator delete(void* ptr, void* place) noexcept { void operator delete[](void* ptr, void* place) noexcept { (void)ptr; (void)place; // unused // Nothing to do -} \ No newline at end of file +} From 0ccfd9cb52bd951b2196842da077f84a13dbf005 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 19 Feb 2025 17:23:30 +0100 Subject: [PATCH 21/44] usb: start supporting USB_DEVICE_STACK_NEXT Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- Kconfig | 20 +++ cores/arduino/SerialUSB.h | 2 +- cores/arduino/USB.cpp | 58 +++++++- cores/arduino/main.cpp | 10 +- cores/arduino/usb_device_descriptor.c | 185 ++++++++++++++++++++++++++ cores/arduino/zephyrSerial.cpp | 2 +- cores/arduino/zephyrSerial.h | 2 +- 7 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 cores/arduino/usb_device_descriptor.c diff --git a/Kconfig b/Kconfig index 20f88b8d2..256f97a9c 100644 --- a/Kconfig +++ b/Kconfig @@ -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 diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h index f26de64a7..94d5cc830 100644 --- a/cores/arduino/SerialUSB.h +++ b/cores/arduino/SerialUSB.h @@ -31,6 +31,6 @@ class SerialUSB_ : public ZephyrSerial { }; } // namespace arduino -#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) +#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 \ No newline at end of file diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 735f23505..0caef974c 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -10,7 +10,7 @@ #include #include -#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) +#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm)) const struct device *const usb_dev = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), cdc_acm, 0)); void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) { @@ -40,6 +40,58 @@ static void _baudChangeHandler(const struct device *dev, uint32_t rate) } } +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + +extern "C" { + #include + struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb); +} + +struct usbd_context *_usbd; + +int usb_disable() { + return usbd_disable(_usbd); +} + +static void 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(ctx->dev, UART_LINE_CTRL_BAUD_RATE, &baudrate); + _baudChangeHandler(nullptr, baudrate); + } +} + +static int enable_usb_device_next(void) +{ + int err; + + //_usbd = usbd_init_device(usbd_next_cb); + _usbd = usbd_init_device(nullptr); + 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_::_baudChangeDispatch(struct k_timer *timer) { arduino::SerialUSB_* dev = (arduino::SerialUSB_*)k_timer_user_data_get(timer); dev->_baudChangeHandler(); @@ -48,6 +100,7 @@ void arduino::SerialUSB_::_baudChangeDispatch(struct k_timer *timer) { 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 k_timer_init(&baud_timer, SerialUSB_::_baudChangeDispatch, NULL); @@ -56,6 +109,9 @@ void arduino::SerialUSB_::begin(unsigned long baudrate, uint16_t config) { #else cdc_acm_dte_rate_callback_set(usb_dev, ::_baudChangeHandler); #endif + #else + enable_usb_device_next(); + #endif ZephyrSerial::begin(baudrate, config); started = true; } diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 67dbb91ec..7152201f5 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -80,14 +80,18 @@ extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struc extern uintptr_t _ebss; extern uintptr_t __heap_start; extern uintptr_t __heap_end; + extern uintptr_t kheap_llext_heap; + extern uintptr_t kheap_llext_heap_size; + //__asm volatile ("cpsie i"); const size_t alignment = 4096; - printk("Heap end: %p\n", &__heap_end); - printk("Heap start: %p\n", &__heap_start); + printk("System Heap end: %p\n", &__heap_end); + printk("System Heap start: %p\n", &__heap_start); + printk("Sketch Heap start: %p, size %p\n", &kheap_llext_heap, &kheap_llext_heap_size); // __heap_start = (__heap_start + (alignment - 1)) & ~(alignment - 1); - memcpy(&_sdata, &_sidata, &_edata - &_sdata); + memcpy(&_sdata, &_sidata, (&_edata - &_sdata) * sizeof(uint32_t)); memset(&_sbss, 0, &_ebss - &_sbss); __libc_init_array(); main(); diff --git a/cores/arduino/usb_device_descriptor.c b/cores/arduino/usb_device_descriptor.c new file mode 100644 index 000000000..1c0eb887d --- /dev/null +++ b/cores/arduino/usb_device_descriptor.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2025 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include + +#ifdef CONFIG_USB_DEVICE_STACK_NEXT + +/* By default, do not register the USB DFU class DFU mode instance. */ +static const char *const blocklist[] = { + "dfu_dfu", + NULL, +}; + +/* doc device instantiation start */ +USBD_DEVICE_DEFINE(usbd, + DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), + CONFIG_USB_DEVICE_VID, CONFIG_USB_DEVICE_PID); +/* doc device instantiation end */ + +/* doc string instantiation start */ +USBD_DESC_LANG_DEFINE(sample_lang); +USBD_DESC_MANUFACTURER_DEFINE(sample_mfr, CONFIG_USB_DEVICE_MANUFACTURER); +USBD_DESC_PRODUCT_DEFINE(sample_product, CONFIG_USB_DEVICE_PRODUCT); +USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn); +/* doc string instantiation end */ + +USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "FS Configuration"); +USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "HS Configuration"); + +/* doc configuration instantiation start */ +static const uint8_t attributes = 0; + +/* Full speed configuration */ +USBD_CONFIGURATION_DEFINE(sample_fs_config, + attributes, + 250, &fs_cfg_desc); + +/* High speed configuration */ +USBD_CONFIGURATION_DEFINE(sample_hs_config, + attributes, + 250, &hs_cfg_desc); +/* doc configuration instantiation end */ + +/* + * This does not yet provide valuable information, but rather serves as an + * example, and will be improved in the future. + */ +static const struct usb_bos_capability_lpm bos_cap_lpm = { + .bLength = sizeof(struct usb_bos_capability_lpm), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION, + .bmAttributes = 0UL, +}; + +USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm); + +static void sample_fix_code_triple(struct usbd_context *uds_ctx, + const enum usbd_speed speed) +{ + /* Always use class code information from Interface Descriptors */ + if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) || + IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) || + IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) || + IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) { + /* + * Class with multiple interfaces have an Interface + * Association Descriptor available, use an appropriate triple + * to indicate it. + */ + usbd_device_set_code_triple(uds_ctx, speed, + USB_BCC_MISCELLANEOUS, 0x02, 0x01); + } else { + usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0); + } +} + +struct usbd_context *usbd_setup_device(usbd_msg_cb_t msg_cb) +{ + int err; + + /* doc add string descriptor start */ + err = usbd_add_descriptor(&usbd, &sample_lang); + if (err) { + return NULL; + } + + err = usbd_add_descriptor(&usbd, &sample_mfr); + if (err) { + return NULL; + } + + err = usbd_add_descriptor(&usbd, &sample_product); + if (err) { + return NULL; + } + + err = usbd_add_descriptor(&usbd, &sample_sn); + if (err) { + return NULL; + } + /* doc add string descriptor end */ + + if (usbd_caps_speed(&usbd) == USBD_SPEED_HS) { + err = usbd_add_configuration(&usbd, USBD_SPEED_HS, + &sample_hs_config); + if (err) { + return NULL; + } + + err = usbd_register_all_classes(&usbd, USBD_SPEED_HS, 1, + blocklist); + if (err) { + return NULL; + } + + sample_fix_code_triple(&usbd, USBD_SPEED_HS); + } + + /* doc configuration register start */ + err = usbd_add_configuration(&usbd, USBD_SPEED_FS, + &sample_fs_config); + if (err) { + return NULL; + } + /* doc configuration register end */ + + /* doc functions register start */ + err = usbd_register_all_classes(&usbd, USBD_SPEED_FS, 1, blocklist); + if (err) { + return NULL; + } + /* doc functions register end */ + + sample_fix_code_triple(&usbd, USBD_SPEED_FS); + + if (msg_cb != NULL) { + /* doc device init-and-msg start */ + err = usbd_msg_register_cb(&usbd, msg_cb); + if (err) { + return NULL; + } + /* doc device init-and-msg end */ + } + + if (0) { + (void)usbd_device_set_bcd_usb(&usbd, USBD_SPEED_FS, 0x0201); + (void)usbd_device_set_bcd_usb(&usbd, USBD_SPEED_HS, 0x0201); + + err = usbd_add_descriptor(&usbd, &sample_usbext); + if (err) { + return NULL; + } + } + + return &usbd; +} + +struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb) +{ + int err; + + if (usbd_setup_device(msg_cb) == NULL) { + return NULL; + } + + /* doc device init start */ + err = usbd_init(&usbd); + if (err) { + return NULL; + } + /* doc device init end */ + + return &usbd; +} + +#endif \ No newline at end of file diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index 3bde2de44..9277e8bc1 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -205,7 +205,7 @@ void arduino::ZephyrSerial::flush() { #endif #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) -#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) +#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) // If CDC USB, use that object as Serial (and SerialUSB) arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), serials, FIRST_UART_INDEX))); #endif diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index 047262e80..86acdc3a0 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -81,7 +81,7 @@ class ZephyrSerial : public HardwareSerial } // namespace arduino #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) -#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) +#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) // If CDC USB, use that object as Serial (and SerialUSB) extern arduino::ZephyrSerial Serial; #endif From 29fb2b9a9010ecbf18b3459d46a1385d97d91f6e Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 6 Mar 2025 10:29:54 +0100 Subject: [PATCH 22/44] SerialUSB: create SerialUSB object only if CONFIG_USB_CDC_ACM=y Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/USB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 0caef974c..6873c798b 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -10,7 +10,7 @@ #include #include -#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm)) +#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 usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) { From cfedec3f810b561a2375cf828c22aa54449c6bee Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Thu, 10 Apr 2025 18:20:18 +0200 Subject: [PATCH 23/44] cores/arduino: warning squash Silence a number of trivial compiler warnings in the Arduino core: - unused arguments - "constexpr const" - signed/unsigned mismatches Signed-off-by: Luca Burelli Signed-off-by: TOKITA Hiroshi --- cores/arduino/USB.cpp | 4 +++- cores/arduino/abi.cpp | 8 ++++++-- cores/arduino/main.cpp | 4 ++-- cores/arduino/new.cpp | 10 ++++++++++ cores/arduino/zephyrCommon.cpp | 13 +++++++------ cores/arduino/zephyrSerial.cpp | 3 ++- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 6873c798b..6f45e1f2b 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -14,6 +14,7 @@ const struct device *const usb_dev = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), cdc_acm, 0)); void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) { + (void)param; // unused if (cb_status == USB_DC_CONFIGURED) { } @@ -34,6 +35,7 @@ void arduino::SerialUSB_::_baudChangeHandler() static void _baudChangeHandler(const struct device *dev, uint32_t rate) { + (void)dev; // unused if (rate == 1200) { usb_disable(); _on_1200_bps(); @@ -123,4 +125,4 @@ arduino::SerialUSB_::operator bool() { } arduino::SerialUSB_ Serial(usb_dev); -#endif \ No newline at end of file +#endif diff --git a/cores/arduino/abi.cpp b/cores/arduino/abi.cpp index 606882d83..4aaf0b8c6 100644 --- a/cores/arduino/abi.cpp +++ b/cores/arduino/abi.cpp @@ -6,8 +6,12 @@ #include -extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); -extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); +extern "C" void __cxa_pure_virtual(void) {} +extern "C" void __cxa_deleted_virtual(void) {} +extern "C" int __cxa_atexit(void (*func) (void *), void * arg, void * dso_handle) { + (void)func; (void)arg; (void)dso_handle; // unused + return 0; +} namespace std { [[gnu::weak, noreturn]] void terminate() { diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 7152201f5..9359e745e 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -70,6 +70,8 @@ static void __libc_init_array (void) } extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struct k_heap* stack, size_t stack_size) { + (void)stack; (void)stack_size; // unused + // copy .data in the right place // .bss should already be in the right place // call constructors @@ -85,11 +87,9 @@ extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struc //__asm volatile ("cpsie i"); - const size_t alignment = 4096; printk("System Heap end: %p\n", &__heap_end); printk("System Heap start: %p\n", &__heap_start); printk("Sketch Heap start: %p, size %p\n", &kheap_llext_heap, &kheap_llext_heap_size); - // __heap_start = (__heap_start + (alignment - 1)) & ~(alignment - 1); memcpy(&_sdata, &_sidata, (&_edata - &_sdata) * sizeof(uint32_t)); memset(&_sbss, 0, &_ebss - &_sbss); diff --git a/cores/arduino/new.cpp b/cores/arduino/new.cpp index 7cf51eeba..ed203f860 100644 --- a/cores/arduino/new.cpp +++ b/cores/arduino/new.cpp @@ -46,14 +46,17 @@ void * operator new[](std::size_t size) { #if __cplusplus >= 201703L void* operator new(std::size_t count, std::align_val_t al) { + (void)al; // unused return operator new(count); } void* operator new[](std::size_t count, std::align_val_t al) { + (void)al; // unused return operator new(count); } void * operator new(std::size_t size, std::align_val_t al, const std::nothrow_t tag) noexcept { + (void)al; (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) // Cannot call throwing operator new as standard suggests, so call // new_helper directly then @@ -64,6 +67,7 @@ void * operator new(std::size_t size, std::align_val_t al, const std::nothrow_t } void * operator new[](std::size_t size, std::align_val_t al, const std::nothrow_t& tag) noexcept { + (void)al; (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) // Cannot call throwing operator new[] as standard suggests, so call // malloc directly then @@ -75,6 +79,7 @@ void * operator new[](std::size_t size, std::align_val_t al, const std::nothrow_ #endif void * operator new(std::size_t size, const std::nothrow_t tag) noexcept { + (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) // Cannot call throwing operator new as standard suggests, so call // new_helper directly then @@ -84,6 +89,7 @@ void * operator new(std::size_t size, const std::nothrow_t tag) noexcept { #endif } void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept { + (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) // Cannot call throwing operator new[] as standard suggests, so call // malloc directly then @@ -111,17 +117,21 @@ void operator delete[](void * ptr) noexcept { #if __cplusplus >= 201402L void operator delete(void* ptr, std::size_t size) noexcept { + (void)size; // unused operator delete(ptr); } void operator delete[](void * ptr, std::size_t size) noexcept { + (void)size; // unused operator delete[](ptr); } #endif // __cplusplus >= 201402L void operator delete(void* ptr, const std::nothrow_t& tag) noexcept { + (void)tag; // unused operator delete(ptr); } void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept { + (void)tag; // unused operator delete[](ptr); } diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 5e82a8d6a..693025554 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -18,37 +18,37 @@ namespace { * Calculate GPIO ports/pins number statically from devicetree configuration */ -template constexpr const N sum_of_list(const N sum, const Head &head) +template constexpr N sum_of_list(const N sum, const Head &head) { return sum + head; } template -constexpr const N sum_of_list(const N sum, const Head &head, const Tail &...tail) +constexpr N sum_of_list(const N sum, const Head &head, const Tail &...tail) { return sum_of_list(sum + head, tail...); } -template constexpr const N max_in_list(const N max, const Head &head) +template constexpr N max_in_list(const N max, const Head &head) { return (max >= head) ? max : head; } template -constexpr const N max_in_list(const N max, const Head &head, const Tail &...tail) +constexpr N max_in_list(const N max, const Head &head, const Tail &...tail) { return max_in_list((max >= head) ? max : head, tail...); } template -constexpr const size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, +constexpr size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, const Query &query, const Head &head) { return ((found == ((size_t)-1)) && (query == head) && (idx == at)) ? 1 : 0; } template -constexpr const size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, +constexpr size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, const Query &query, const Head &head, const Tail &...tail) { @@ -119,6 +119,7 @@ void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uint32_t pins) { + (void)port; // unused struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb; for (uint32_t i = 0; i < max_ngpios; i++) { diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index 9277e8bc1..84578c2f2 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -116,6 +116,7 @@ void arduino::ZephyrSerial::IrqHandler() void arduino::ZephyrSerial::IrqDispatch(const struct device *dev, void *data) { + (void)dev; // unused reinterpret_cast(data)->IrqHandler(); } @@ -165,7 +166,7 @@ int arduino::ZephyrSerial::read() size_t arduino::ZephyrSerial::write(const uint8_t *buffer, size_t size) { - int idx = 0; + size_t idx = 0; while (1) { k_sem_take(&tx.sem, K_FOREVER); From eccb6896c95629a0539df4d30ca1731778f9c77e Mon Sep 17 00:00:00 2001 From: kurte Date: Sat, 17 May 2025 13:33:57 -0700 Subject: [PATCH 24/44] If sketch is not connected to serial - dump serial output Current code would hang after a few Serial.print like statements happened when we are not connected to the Serial monitor. So I put overrides in for the Serial.write(buf, cnt) and Serial.flush() That would first check to see if Serial returns true (DTR)... This appears to match the behavior of the MBED Portenta H8 code. Co-authored-by: kurte Signed-off-by: TOKITA Hiroshi --- cores/arduino/SerialUSB.h | 2 ++ cores/arduino/USB.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h index 94d5cc830..442d28d0a 100644 --- a/cores/arduino/SerialUSB.h +++ b/cores/arduino/SerialUSB.h @@ -18,6 +18,8 @@ class SerialUSB_ : public ZephyrSerial { void begin(unsigned long baudrate) { begin(baudrate, SERIAL_8N1); } operator bool() override; + size_t write(const uint8_t *buffer, size_t size) override; + void flush() override; protected: uint32_t dtr = 0; diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 6f45e1f2b..60f5fc7ae 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -124,5 +124,16 @@ arduino::SerialUSB_::operator bool() { 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 From a6636b489389cb256ec240eda1b4dbc4701de497 Mon Sep 17 00:00:00 2001 From: Kurt Eckhardt Date: Thu, 30 Jan 2025 14:19:03 -0800 Subject: [PATCH 25/44] Fix micros() for nano without breaking giga The rollover fix for the giga used the 64 bit timer instead of 32 bits. The nano does not have a 64 bit timer, so you need to use the 32 bit instead. So I know check to see if the processor supports 64 bits if so use it else fall back to 32 bit. Co-authored-by: Kurt Eckhardt Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrCommon.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 693025554..1b68a10e7 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -323,7 +323,11 @@ void delayMicroseconds(unsigned int us) { } unsigned long micros(void) { +#ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER + return k_cyc_to_us_floor32(k_cycle_get_64()); +#else return k_cyc_to_us_floor32(k_cycle_get_32()); +#endif } unsigned long millis(void) { From 4cb21f889270700ef16a98d78705804247d9046d Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 10 Feb 2025 17:24:02 +0100 Subject: [PATCH 26/44] serial: add missing include Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrSerial.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index 86acdc3a0..ecc18a81b 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include namespace arduino { From d13d49ac5c931d3a4f951b113f9c7df3cf8b6e3f Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 20 Jun 2025 08:03:59 +0800 Subject: [PATCH 27/44] SerialUSB: fix missing overload after #123 This would have been spotted if we extend the CI to compile all the exaples (TestClient in particular). Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/SerialUSB.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h index 442d28d0a..be1377f8b 100644 --- a/cores/arduino/SerialUSB.h +++ b/cores/arduino/SerialUSB.h @@ -19,6 +19,7 @@ class SerialUSB_ : public ZephyrSerial { 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: From e9556b5105bf4a493ff6748f409b1d4f84c634e1 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Wed, 12 Mar 2025 15:02:50 +0100 Subject: [PATCH 28/44] Arduino.h: fix DIGITAL_PIN_EXISTS macro to avoid comment expansion issues The DIGITAL_PIN_EXISTS macro (used e.g. by LED_BUILTIN) was not working properly because the inline comments in devicetree_generated.h were confusing the preprocessor: one internal macro tried to create an unsigned constant by pasting a '*/' comment end marker with the 'U' character. Splitting that macro into two parts, so that the DT_REG_ADDR macro is invoked with an expanded argument, fixes the issue. Signed-off-by: Luca Burelli Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 64a7aa4a9..6233e2df4 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -17,11 +17,11 @@ #include #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, _) \ From 1cb92ead1be36718ad4904e1c73791e3a1aa3643 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 18 Dec 2024 10:48:36 +0100 Subject: [PATCH 29/44] linker: forcefully remove exceptions and pack sections There's no way to convince the compiler to consider the provided flags when linking modern c++ code (std::). Get rid of the useless symbols in the linker and add the (then) missing implementations in abi.cpp Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/abi.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cores/arduino/abi.cpp b/cores/arduino/abi.cpp index 4aaf0b8c6..5c030cd36 100644 --- a/cores/arduino/abi.cpp +++ b/cores/arduino/abi.cpp @@ -14,15 +14,14 @@ extern "C" int __cxa_atexit(void (*func) (void *), void * arg, void * dso_handle } namespace std { - [[gnu::weak, noreturn]] void terminate() { - abort(); - } -} + void __throw_length_error(const char* __s __attribute__((unused))) {} +}; -void __cxa_pure_virtual(void) { - std::terminate(); -} - -void __cxa_deleted_virtual(void) { - std::terminate(); +extern "C" int strcmp(const char* s1, const char* s2) { + while(*s1 && (*s1 == *s2)) + { + s1++; + s2++; + } + return *(const unsigned char*)s1 - *(const unsigned char*)s2; } From 1474d8a567cf6939a53bbffb03b73c60c75954d9 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 28 May 2025 15:51:14 +0200 Subject: [PATCH 30/44] loader: impl: add some libc/::std functions Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/abi.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cores/arduino/abi.cpp b/cores/arduino/abi.cpp index 5c030cd36..e6700a7e5 100644 --- a/cores/arduino/abi.cpp +++ b/cores/arduino/abi.cpp @@ -12,9 +12,15 @@ extern "C" int __cxa_atexit(void (*func) (void *), void * arg, void * dso_handle (void)func; (void)arg; (void)dso_handle; // unused return 0; } +extern "C" int atexit(void (*func)(void)) { + (void)func; + return 0; +} namespace std { void __throw_length_error(const char* __s __attribute__((unused))) {} + void __throw_bad_alloc() {} + void __throw_bad_function_call() {} }; extern "C" int strcmp(const char* s1, const char* s2) { From 63e52b889e1cd1040f1b00d561622fa5dd3d5238 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Mon, 4 Aug 2025 14:27:01 +0200 Subject: [PATCH 31/44] cores/arduino/abi: squash warning Use a global 'extern "C" { }' block to avoid warnings about variables being initialized and declared extern. Signed-off-by: Luca Burelli Signed-off-by: TOKITA Hiroshi --- cores/arduino/abi.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/cores/arduino/abi.cpp b/cores/arduino/abi.cpp index e6700a7e5..9e8fabd6d 100644 --- a/cores/arduino/abi.cpp +++ b/cores/arduino/abi.cpp @@ -6,24 +6,29 @@ #include -extern "C" void __cxa_pure_virtual(void) {} -extern "C" void __cxa_deleted_virtual(void) {} -extern "C" int __cxa_atexit(void (*func) (void *), void * arg, void * dso_handle) { +namespace std { + void __throw_length_error(const char* __s __attribute__((unused))) {} + void __throw_bad_alloc() {} + void __throw_bad_function_call() {} +}; + +extern "C" { + +void* __dso_handle = (void*) &__dso_handle; + +void __cxa_pure_virtual(void) {} +void __cxa_deleted_virtual(void) {} +int __cxa_atexit(void (*func) (void *), void * arg, void * dso_handle) { (void)func; (void)arg; (void)dso_handle; // unused return 0; } -extern "C" int atexit(void (*func)(void)) { + +int atexit(void (*func)(void)) { (void)func; return 0; } -namespace std { - void __throw_length_error(const char* __s __attribute__((unused))) {} - void __throw_bad_alloc() {} - void __throw_bad_function_call() {} -}; - -extern "C" int strcmp(const char* s1, const char* s2) { +int strcmp(const char* s1, const char* s2) { while(*s1 && (*s1 == *s2)) { s1++; @@ -31,3 +36,5 @@ extern "C" int strcmp(const char* s1, const char* s2) { } return *(const unsigned char*)s1 - *(const unsigned char*)s2; } + +} /* extern "C" */ From c2c5e5a3baae1c8a1b49693d5cc8851f67200900 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Mon, 9 Dec 2024 16:07:17 +0100 Subject: [PATCH 32/44] ZephyrCommon: allow boards without any ADC channel configured Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 1b68a10e7..8a36d3f92 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -171,7 +171,7 @@ const struct adc_dt_spec arduino_adc[] = const pin_size_t arduino_analog_pins[] = { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), adc_pin_gpios, ADC_PINS) }; -struct adc_channel_cfg channel_cfg[ARRAY_SIZE(arduino_analog_pins)] = +struct adc_channel_cfg channel_cfg[] = { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_CH_CFG) }; size_t analog_pin_index(pin_size_t pinNumber) { From 17916e1cbd01f13c872d164d01148d04149e5128 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 23 Jan 2025 17:29:33 +0100 Subject: [PATCH 33/44] make internal arduino_adc array static Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 8a36d3f92..80cfbacfa 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -164,7 +164,7 @@ size_t pwm_pin_index(pin_size_t pinNumber) { DT_PHA_BY_IDX(DT_PATH(zephyr_user), p, i, pin)), #define ADC_CH_CFG(n,p,i) arduino_adc[i].channel_cfg, -const struct adc_dt_spec arduino_adc[] = +static const struct adc_dt_spec arduino_adc[] = { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), io_channels, ADC_DT_SPEC) }; /* io-channel-pins node provides a mapping digital pin numbers to adc channels */ From 1139d7e8ef761ce3c37d6f1ba0437bee7c276a2a Mon Sep 17 00:00:00 2001 From: Tamas Jozsi Date: Mon, 22 Dec 2025 11:40:29 +0100 Subject: [PATCH 34/44] core: serial: fix availableForWrite() availableForWrite() was taking the free space of the Rx buffer instead of the Tx buffer. Co-authored-by: Tamas Jozsi Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrSerial.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index 84578c2f2..b463615e6 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -135,9 +135,9 @@ int arduino::ZephyrSerial::availableForWrite() { int ret; - k_sem_take(&rx.sem, K_FOREVER); - ret = ring_buf_space_get(&rx.ringbuf); - k_sem_give(&rx.sem); + k_sem_take(&tx.sem, K_FOREVER); + ret = ring_buf_space_get(&tx.ringbuf); + k_sem_give(&tx.sem); return ret; } From b1291bfaf5c6bf1bacab28fc45a1135700513690 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 24 Jan 2025 15:22:22 +0100 Subject: [PATCH 35/44] core: restore core-as-zephyr-module functionality Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cores/arduino/CMakeLists.txt b/cores/arduino/CMakeLists.txt index 90b775589..d625dd827 100644 --- a/cores/arduino/CMakeLists.txt +++ b/cores/arduino/CMakeLists.txt @@ -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) From 206c7e040b170a5551f3f877b14ed2f305cf07c0 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Thu, 28 Aug 2025 15:41:30 +0200 Subject: [PATCH 36/44] misc: Format repo using clang-format. Note by committer: Only under the `cores/arduino` was picked. Signed-off-by: iabdalkader --- cores/arduino/Arduino.h | 52 +- cores/arduino/SerialUSB.h | 22 +- cores/arduino/USB.cpp | 113 +++-- cores/arduino/abi.cpp | 48 +- cores/arduino/apiCommon.cpp | 16 +- cores/arduino/itoa.cpp | 171 ++++--- cores/arduino/main.cpp | 115 ++--- cores/arduino/new.cpp | 163 ++++--- cores/arduino/overloads.h | 2 +- cores/arduino/threads.cpp | 39 +- cores/arduino/usb_device_descriptor.c | 43 +- cores/arduino/zephyrCommon.cpp | 673 +++++++++++++------------- cores/arduino/zephyrPrint.cpp | 33 +- cores/arduino/zephyrPrint.h | 91 ++-- cores/arduino/zephyrSerial.cpp | 73 ++- cores/arduino/zephyrSerial.h | 88 ++-- 16 files changed, 864 insertions(+), 878 deletions(-) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 6233e2df4..34f436b17 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -25,9 +25,9 @@ /* 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, (&&)) @@ -42,17 +42,17 @@ (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 \ @@ -64,9 +64,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 \ @@ -91,11 +92,13 @@ enum digitalPins { #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); @@ -108,8 +111,11 @@ void analogReadResolution(int bits); #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 }; +#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 @@ -118,10 +124,10 @@ void noInterrupts(void); int digitalPinToInterrupt(pin_size_t pin); -#define digitalPinToPort(x) (x) +#define digitalPinToPort(x) (x) #define digitalPinToBitMask(x) (x) -#define portOutputRegister(x) (x) -#define portInputRegister(x) (x) +#define portOutputRegister(x) (x) +#define portInputRegister(x) (x) void analogReadResolution(int bits); void analogWriteResolution(int bits); diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h index be1377f8b..f6459d3c4 100644 --- a/cores/arduino/SerialUSB.h +++ b/cores/arduino/SerialUSB.h @@ -13,13 +13,22 @@ namespace arduino { class SerialUSB_ : public ZephyrSerial { public: - SerialUSB_(const struct device *dev) : ZephyrSerial(dev) { } + SerialUSB_(const struct device *dev) : ZephyrSerial(dev) { + } + void begin(unsigned long baudrate, uint16_t config); - void begin(unsigned long baudrate) { begin(baudrate, SERIAL_8N1); } + + 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); } + + size_t write(const uint8_t data) override { + return write(&data, 1); + } + void flush() override; protected: @@ -32,8 +41,9 @@ class SerialUSB_ : public ZephyrSerial { struct k_timer baud_timer; bool started = false; }; -} // namespace arduino +} // namespace arduino -#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) +#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 \ No newline at end of file +#endif diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 60f5fc7ae..6e0179ea1 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -10,53 +10,51 @@ #include #include -#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)); +#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 usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) { - (void)param; // unused - if (cb_status == USB_DC_CONFIGURED) { - - } + (void)param; // unused + if (cb_status == USB_DC_CONFIGURED) { + } } void __attribute__((weak)) _on_1200_bps() { - NVIC_SystemReset(); + NVIC_SystemReset(); } -void arduino::SerialUSB_::_baudChangeHandler() -{ - uart_line_ctrl_get(uart, UART_LINE_CTRL_BAUD_RATE, &baudrate); - if (baudrate == 1200) { - usb_disable(); - _on_1200_bps(); - } +void arduino::SerialUSB_::_baudChangeHandler() { + uart_line_ctrl_get(uart, UART_LINE_CTRL_BAUD_RATE, &baudrate); + if (baudrate == 1200) { + usb_disable(); + _on_1200_bps(); + } } -static void _baudChangeHandler(const struct device *dev, uint32_t rate) -{ - (void)dev; // unused - if (rate == 1200) { - usb_disable(); - _on_1200_bps(); - } +static void _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) extern "C" { - #include - struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb); +#include +struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb); } struct usbd_context *_usbd; int usb_disable() { - return usbd_disable(_usbd); + return usbd_disable(_usbd); } -static void usbd_next_cb(struct usbd_context *const ctx, const struct usbd_msg *msg) -{ +static void 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); @@ -68,14 +66,13 @@ static void usbd_next_cb(struct usbd_context *const ctx, const struct usbd_msg * } if (msg->type == USBD_MSG_CDC_ACM_LINE_CODING) { - uint32_t baudrate; + uint32_t baudrate; uart_line_ctrl_get(ctx->dev, UART_LINE_CTRL_BAUD_RATE, &baudrate); - _baudChangeHandler(nullptr, baudrate); + _baudChangeHandler(nullptr, baudrate); } } -static int enable_usb_device_next(void) -{ +static int enable_usb_device_next(void) { int err; //_usbd = usbd_init_device(usbd_next_cb); @@ -95,44 +92,46 @@ static int enable_usb_device_next(void) #endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */ void arduino::SerialUSB_::_baudChangeDispatch(struct k_timer *timer) { - arduino::SerialUSB_* dev = (arduino::SerialUSB_*)k_timer_user_data_get(timer); - dev->_baudChangeHandler(); + arduino::SerialUSB_ *dev = (arduino::SerialUSB_ *)k_timer_user_data_get(timer); + dev->_baudChangeHandler(); } - 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 - k_timer_init(&baud_timer, SerialUSB_::_baudChangeDispatch, NULL); - k_timer_user_data_set(&baud_timer, this); - k_timer_start(&baud_timer, K_MSEC(100), K_MSEC(100)); - #else - cdc_acm_dte_rate_callback_set(usb_dev, ::_baudChangeHandler); - #endif - #else - enable_usb_device_next(); - #endif - ZephyrSerial::begin(baudrate, config); - started = true; - } + if (!started) { +#ifndef CONFIG_USB_DEVICE_STACK_NEXT + usb_enable(NULL); +#ifndef CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT + k_timer_init(&baud_timer, SerialUSB_::_baudChangeDispatch, NULL); + k_timer_user_data_set(&baud_timer, this); + k_timer_start(&baud_timer, K_MSEC(100), K_MSEC(100)); +#else + cdc_acm_dte_rate_callback_set(usb_dev, ::_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; + 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); +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(); + if (!Serial) { + return; + } + arduino::ZephyrSerial::flush(); } arduino::SerialUSB_ Serial(usb_dev); diff --git a/cores/arduino/abi.cpp b/cores/arduino/abi.cpp index 9e8fabd6d..872c8d083 100644 --- a/cores/arduino/abi.cpp +++ b/cores/arduino/abi.cpp @@ -7,34 +7,44 @@ #include namespace std { - void __throw_length_error(const char* __s __attribute__((unused))) {} - void __throw_bad_alloc() {} - void __throw_bad_function_call() {} -}; +void __throw_length_error(const char *__s __attribute__((unused))) { +} + +void __throw_bad_alloc() { +} + +void __throw_bad_function_call() { +} +}; // namespace std extern "C" { -void* __dso_handle = (void*) &__dso_handle; +void *__dso_handle = (void *)&__dso_handle; + +void __cxa_pure_virtual(void) { +} + +void __cxa_deleted_virtual(void) { +} -void __cxa_pure_virtual(void) {} -void __cxa_deleted_virtual(void) {} -int __cxa_atexit(void (*func) (void *), void * arg, void * dso_handle) { - (void)func; (void)arg; (void)dso_handle; // unused - return 0; +int __cxa_atexit(void (*func)(void *), void *arg, void *dso_handle) { + (void)func; + (void)arg; + (void)dso_handle; // unused + return 0; } int atexit(void (*func)(void)) { - (void)func; - return 0; + (void)func; + return 0; } -int strcmp(const char* s1, const char* s2) { - while(*s1 && (*s1 == *s2)) - { - s1++; - s2++; - } - return *(const unsigned char*)s1 - *(const unsigned char*)s2; +int strcmp(const char *s1, const char *s2) { + while (*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char *)s1 - *(const unsigned char *)s2; } } /* extern "C" */ diff --git a/cores/arduino/apiCommon.cpp b/cores/arduino/apiCommon.cpp index cfb6d919f..36e808d8e 100644 --- a/cores/arduino/apiCommon.cpp +++ b/cores/arduino/apiCommon.cpp @@ -8,19 +8,19 @@ #include "zephyrInternal.h" extern "C" { - int32_t map_i32(int32_t x, int32_t in_min, int32_t in_max, int32_t out_min, int32_t out_max); - uint16_t makeWord_w(uint16_t w); - uint16_t makeWord_hl(byte h, byte l); +int32_t map_i32(int32_t x, int32_t in_min, int32_t in_max, int32_t out_min, int32_t out_max); +uint16_t makeWord_w(uint16_t w); +uint16_t makeWord_hl(byte h, byte l); } -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return map_i32(x, in_min, in_max, out_min, out_max); +long map(long x, long in_min, long in_max, long out_min, long out_max) { + return map_i32(x, in_min, in_max, out_min, out_max); } uint16_t makeWord(uint16_t w) { - return makeWord_w(w); + return makeWord_w(w); } + uint16_t makeWord(byte h, byte l) { - return makeWord_hl(h, l); + return makeWord_hl(h, l); } diff --git a/cores/arduino/itoa.cpp b/cores/arduino/itoa.cpp index 929ec4d0a..193cd6ab9 100644 --- a/cores/arduino/itoa.cpp +++ b/cores/arduino/itoa.cpp @@ -13,102 +13,93 @@ extern "C" { #include -extern char* itoa( int value, char *string, int radix ) -{ - return ltoa( value, string, radix ) ; +extern char *itoa(int value, char *string, int radix) { + return ltoa(value, string, radix); } -extern char* ltoa( long value, char *string, int radix ) -{ - char tmp[33]; - char *tp = tmp; - long i; - unsigned long v; - int sign; - char *sp; - - if ( string == NULL ) - { - return 0 ; - } - - if (radix > 36 || radix <= 1) - { - return 0 ; - } - - sign = (radix == 10 && value < 0); - if (sign) - { - v = -value; - } - else - { - v = (unsigned long)value; - } - - while (v || tp == tmp) - { - i = v % radix; - v = v / radix; - if (i < 10) - *tp++ = i+'0'; - else - *tp++ = i + 'a' - 10; - } - - sp = string; - - if (sign) - *sp++ = '-'; - while (tp > tmp) - *sp++ = *--tp; - *sp = 0; - - return string; +extern char *ltoa(long value, char *string, int radix) { + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v; + int sign; + char *sp; + + if (string == NULL) { + return 0; + } + + if (radix > 36 || radix <= 1) { + return 0; + } + + sign = (radix == 10 && value < 0); + if (sign) { + v = -value; + } else { + v = (unsigned long)value; + } + + while (v || tp == tmp) { + i = v % radix; + v = v / radix; + if (i < 10) { + *tp++ = i + '0'; + } else { + *tp++ = i + 'a' - 10; + } + } + + sp = string; + + if (sign) { + *sp++ = '-'; + } + while (tp > tmp) { + *sp++ = *--tp; + } + *sp = 0; + + return string; } -extern char* utoa( unsigned int value, char *string, int radix ) -{ - return ultoa( value, string, radix ) ; +extern char *utoa(unsigned int value, char *string, int radix) { + return ultoa(value, string, radix); } -extern char* ultoa( unsigned long value, char *string, int radix ) -{ - char tmp[33]; - char *tp = tmp; - long i; - unsigned long v = value; - char *sp; - - if ( string == NULL ) - { - return 0; - } - - if (radix > 36 || radix <= 1) - { - return 0; - } - - while (v || tp == tmp) - { - i = v % radix; - v = v / radix; - if (i < 10) - *tp++ = i+'0'; - else - *tp++ = i + 'a' - 10; - } - - sp = string; - - - while (tp > tmp) - *sp++ = *--tp; - *sp = 0; - - return string; +extern char *ultoa(unsigned long value, char *string, int radix) { + char tmp[33]; + char *tp = tmp; + long i; + unsigned long v = value; + char *sp; + + if (string == NULL) { + return 0; + } + + if (radix > 36 || radix <= 1) { + return 0; + } + + while (v || tp == tmp) { + i = v % radix; + v = v / radix; + if (i < 10) { + *tp++ = i + '0'; + } else { + *tp++ = i + 'a' - 10; + } + } + + sp = string; + + while (tp > tmp) { + *sp++ = *--tp; + } + *sp = 0; + + return string; } #ifdef __cplusplus diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 9359e745e..bd37be8f6 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -15,34 +15,32 @@ void start_static_threads(); #endif - // This function will be overwriten by most variants. -void __attribute__((weak))initVariant(void) { - +void __attribute__((weak)) initVariant(void) { } - int main(void) { #if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) - Serial.begin(115200); + Serial.begin(115200); #endif - initVariant(); + initVariant(); #ifdef CONFIG_MULTITHREADING - start_static_threads(); + start_static_threads(); #endif - setup(); + setup(); - for (;;) { - loop(); - #if 0 //(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) || DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) + for (;;) { + loop(); +#if 0 //(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) || + // DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) if (arduino::serialEventRun) arduino::serialEventRun(); - #endif - } +#endif + } - return 0; + return 0; } #ifdef CONFIG_LLEXT @@ -50,49 +48,52 @@ LL_EXTENSION_SYMBOL(main); #endif /* These magic symbols are provided by the linker. */ -extern void (*__preinit_array_start []) (void) __attribute__((weak)); -extern void (*__preinit_array_end []) (void) __attribute__((weak)); -extern void (*__init_array_start []) (void) __attribute__((weak)); -extern void (*__init_array_end []) (void) __attribute__((weak)); - -static void __libc_init_array (void) -{ - size_t count; - size_t i; - - count = __preinit_array_end - __preinit_array_start; - for (i = 0; i < count; i++) - __preinit_array_start[i] (); - - count = __init_array_end - __init_array_start; - for (i = 0; i < count; i++) - __init_array_start[i] (); +extern void (*__preinit_array_start[])(void) __attribute__((weak)); +extern void (*__preinit_array_end[])(void) __attribute__((weak)); +extern void (*__init_array_start[])(void) __attribute__((weak)); +extern void (*__init_array_end[])(void) __attribute__((weak)); + +static void __libc_init_array(void) { + size_t count; + size_t i; + + count = __preinit_array_end - __preinit_array_start; + for (i = 0; i < count; i++) { + __preinit_array_start[i](); + } + + count = __init_array_end - __init_array_start; + for (i = 0; i < count; i++) { + __init_array_start[i](); + } } -extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struct k_heap* stack, size_t stack_size) { - (void)stack; (void)stack_size; // unused - - // copy .data in the right place - // .bss should already be in the right place - // call constructors - extern uintptr_t _sidata; - extern uintptr_t _sdata; - extern uintptr_t _edata; - extern uintptr_t _sbss; - extern uintptr_t _ebss; - extern uintptr_t __heap_start; - extern uintptr_t __heap_end; - extern uintptr_t kheap_llext_heap; - extern uintptr_t kheap_llext_heap_size; - - //__asm volatile ("cpsie i"); - - printk("System Heap end: %p\n", &__heap_end); - printk("System Heap start: %p\n", &__heap_start); - printk("Sketch Heap start: %p, size %p\n", &kheap_llext_heap, &kheap_llext_heap_size); - - memcpy(&_sdata, &_sidata, (&_edata - &_sdata) * sizeof(uint32_t)); - memset(&_sbss, 0, &_ebss - &_sbss); - __libc_init_array(); - main(); +extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struct k_heap *stack, + size_t stack_size) { + (void)stack; + (void)stack_size; // unused + + // copy .data in the right place + // .bss should already be in the right place + // call constructors + extern uintptr_t _sidata; + extern uintptr_t _sdata; + extern uintptr_t _edata; + extern uintptr_t _sbss; + extern uintptr_t _ebss; + extern uintptr_t __heap_start; + extern uintptr_t __heap_end; + extern uintptr_t kheap_llext_heap; + extern uintptr_t kheap_llext_heap_size; + + //__asm volatile ("cpsie i"); + + printk("System Heap end: %p\n", &__heap_end); + printk("System Heap start: %p\n", &__heap_start); + printk("Sketch Heap start: %p, size %p\n", &kheap_llext_heap, &kheap_llext_heap_size); + + memcpy(&_sdata, &_sidata, (&_edata - &_sdata) * sizeof(uint32_t)); + memset(&_sbss, 0, &_ebss - &_sbss); + __libc_init_array(); + main(); } diff --git a/cores/arduino/new.cpp b/cores/arduino/new.cpp index ed203f860..7b2a63a90 100644 --- a/cores/arduino/new.cpp +++ b/cores/arduino/new.cpp @@ -18,128 +18,141 @@ // #define NEW_TERMINATES_ON_FAILURE namespace std { - // Defined in abi.cpp - void terminate(); +// Defined in abi.cpp +void terminate(); - const nothrow_t nothrow; -} +const nothrow_t nothrow; +} // namespace std -static void * new_helper(std::size_t size) { - // Even zero-sized allocations should return a unique pointer, but - // malloc does not guarantee this - if (size == 0) - size = 1; - return malloc(size); +static void *new_helper(std::size_t size) { + // Even zero-sized allocations should return a unique pointer, but + // malloc does not guarantee this + if (size == 0) { + size = 1; + } + return malloc(size); } -void * operator new(std::size_t size) { - void *res = new_helper(size); +void *operator new(std::size_t size) { + void *res = new_helper(size); #if defined(NEW_TERMINATES_ON_FAILURE) - if (!res) - std::terminate(); + if (!res) { + std::terminate(); + } #endif - return res; + return res; } -void * operator new[](std::size_t size) { - return operator new(size); + +void *operator new[](std::size_t size) { + return operator new(size); } #if __cplusplus >= 201703L -void* operator new(std::size_t count, std::align_val_t al) { - (void)al; // unused - return operator new(count); +void *operator new(std::size_t count, std::align_val_t al) { + (void)al; // unused + return operator new(count); } -void* operator new[](std::size_t count, std::align_val_t al) { - (void)al; // unused - return operator new(count); +void *operator new[](std::size_t count, std::align_val_t al) { + (void)al; // unused + return operator new(count); } -void * operator new(std::size_t size, std::align_val_t al, const std::nothrow_t tag) noexcept { - (void)al; (void)tag; // unused +void *operator new(std::size_t size, std::align_val_t al, const std::nothrow_t tag) noexcept { + (void)al; + (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) - // Cannot call throwing operator new as standard suggests, so call - // new_helper directly then - return new_helper(size); + // Cannot call throwing operator new as standard suggests, so call + // new_helper directly then + return new_helper(size); #else - return operator new(size); + return operator new(size); #endif } -void * operator new[](std::size_t size, std::align_val_t al, const std::nothrow_t& tag) noexcept { - (void)al; (void)tag; // unused +void *operator new[](std::size_t size, std::align_val_t al, const std::nothrow_t &tag) noexcept { + (void)al; + (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) - // Cannot call throwing operator new[] as standard suggests, so call - // malloc directly then - return new_helper(size); + // Cannot call throwing operator new[] as standard suggests, so call + // malloc directly then + return new_helper(size); #else - return operator new[](size); + return operator new[](size); #endif } #endif -void * operator new(std::size_t size, const std::nothrow_t tag) noexcept { - (void)tag; // unused +void *operator new(std::size_t size, const std::nothrow_t tag) noexcept { + (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) - // Cannot call throwing operator new as standard suggests, so call - // new_helper directly then - return new_helper(size); + // Cannot call throwing operator new as standard suggests, so call + // new_helper directly then + return new_helper(size); #else - return operator new(size); + return operator new(size); #endif } -void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept { - (void)tag; // unused + +void *operator new[](std::size_t size, const std::nothrow_t &tag) noexcept { + (void)tag; // unused #if defined(NEW_TERMINATES_ON_FAILURE) - // Cannot call throwing operator new[] as standard suggests, so call - // malloc directly then - return new_helper(size); + // Cannot call throwing operator new[] as standard suggests, so call + // malloc directly then + return new_helper(size); #else - return operator new[](size); + return operator new[](size); #endif } -void * operator new(std::size_t size, void *place) noexcept { - // Nothing to do - (void)size; // unused - return place; +void *operator new(std::size_t size, void *place) noexcept { + // Nothing to do + (void)size; // unused + return place; } -void * operator new[](std::size_t size, void *place) noexcept { - return operator new(size, place); + +void *operator new[](std::size_t size, void *place) noexcept { + return operator new(size, place); } -void operator delete(void * ptr) noexcept { - free(ptr); +void operator delete(void *ptr) noexcept { + free(ptr); } -void operator delete[](void * ptr) noexcept { - operator delete(ptr); + +void operator delete[](void *ptr) noexcept { + operator delete(ptr); } #if __cplusplus >= 201402L -void operator delete(void* ptr, std::size_t size) noexcept { - (void)size; // unused - operator delete(ptr); +void operator delete(void *ptr, std::size_t size) noexcept { + (void)size; // unused + operator delete(ptr); } -void operator delete[](void * ptr, std::size_t size) noexcept { - (void)size; // unused - operator delete[](ptr); + +void operator delete[](void *ptr, std::size_t size) noexcept { + (void)size; // unused + operator delete[](ptr); } #endif // __cplusplus >= 201402L -void operator delete(void* ptr, const std::nothrow_t& tag) noexcept { - (void)tag; // unused - operator delete(ptr); +void operator delete(void *ptr, const std::nothrow_t &tag) noexcept { + (void)tag; // unused + operator delete(ptr); } -void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept { - (void)tag; // unused - operator delete[](ptr); + +void operator delete[](void *ptr, const std::nothrow_t &tag) noexcept { + (void)tag; // unused + operator delete[](ptr); } -void operator delete(void* ptr, void* place) noexcept { - (void)ptr; (void)place; // unused - // Nothing to do +void operator delete(void *ptr, void *place) noexcept { + (void)ptr; + (void)place; // unused + // Nothing to do } -void operator delete[](void* ptr, void* place) noexcept { - (void)ptr; (void)place; // unused - // Nothing to do + +void operator delete[](void *ptr, void *place) noexcept { + (void)ptr; + (void)place; // unused + // Nothing to do } diff --git a/cores/arduino/overloads.h b/cores/arduino/overloads.h index 5670b2701..a96653d7f 100644 --- a/cores/arduino/overloads.h +++ b/cores/arduino/overloads.h @@ -6,4 +6,4 @@ void analogWrite(enum dacPins pinNumber, int value); // In c++ mode, we also provide analogReadResolution and analogWriteResolution getters int analogReadResolution(); -int analogWriteResolution(); \ No newline at end of file +int analogWriteResolution(); diff --git a/cores/arduino/threads.cpp b/cores/arduino/threads.cpp index 99a4a141c..f34a7f6d9 100644 --- a/cores/arduino/threads.cpp +++ b/cores/arduino/threads.cpp @@ -8,25 +8,26 @@ #ifdef CONFIG_MULTITHREADING void start_static_threads() { - #define _FOREACH_STATIC_THREAD(thread_data) \ - STRUCT_SECTION_FOREACH(_static_thread_data, thread_data) +#define _FOREACH_STATIC_THREAD(thread_data) \ + STRUCT_SECTION_FOREACH (_static_thread_data, thread_data) - _FOREACH_STATIC_THREAD(thread_data) { - k_thread_create(thread_data->init_thread, thread_data->init_stack, thread_data->init_stack_size, thread_data->init_entry, - thread_data->init_p1, thread_data->init_p2, thread_data->init_p3, thread_data->init_prio, - thread_data->init_options, thread_data->init_delay); - k_thread_name_set(thread_data->init_thread, thread_data->init_name); - thread_data->init_thread->init_data = thread_data; - } + _FOREACH_STATIC_THREAD(thread_data) { + k_thread_create(thread_data->init_thread, thread_data->init_stack, + thread_data->init_stack_size, thread_data->init_entry, thread_data->init_p1, + thread_data->init_p2, thread_data->init_p3, thread_data->init_prio, + thread_data->init_options, thread_data->init_delay); + k_thread_name_set(thread_data->init_thread, thread_data->init_name); + thread_data->init_thread->init_data = thread_data; + } - /* - * Take a sched lock to prevent them from running - * until they are all started. - */ - k_sched_lock(); - _FOREACH_STATIC_THREAD(thread_data) { - k_thread_start(thread_data->init_thread); - } - k_sched_unlock(); + /* + * Take a sched lock to prevent them from running + * until they are all started. + */ + k_sched_lock(); + _FOREACH_STATIC_THREAD(thread_data) { + k_thread_start(thread_data->init_thread); + } + k_sched_unlock(); } -#endif \ No newline at end of file +#endif diff --git a/cores/arduino/usb_device_descriptor.c b/cores/arduino/usb_device_descriptor.c index 1c0eb887d..396379370 100644 --- a/cores/arduino/usb_device_descriptor.c +++ b/cores/arduino/usb_device_descriptor.c @@ -21,9 +21,8 @@ static const char *const blocklist[] = { }; /* doc device instantiation start */ -USBD_DEVICE_DEFINE(usbd, - DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), - CONFIG_USB_DEVICE_VID, CONFIG_USB_DEVICE_PID); +USBD_DEVICE_DEFINE(usbd, DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), CONFIG_USB_DEVICE_VID, + CONFIG_USB_DEVICE_PID); /* doc device instantiation end */ /* doc string instantiation start */ @@ -40,14 +39,10 @@ USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "HS Configuration"); static const uint8_t attributes = 0; /* Full speed configuration */ -USBD_CONFIGURATION_DEFINE(sample_fs_config, - attributes, - 250, &fs_cfg_desc); +USBD_CONFIGURATION_DEFINE(sample_fs_config, attributes, 250, &fs_cfg_desc); /* High speed configuration */ -USBD_CONFIGURATION_DEFINE(sample_hs_config, - attributes, - 250, &hs_cfg_desc); +USBD_CONFIGURATION_DEFINE(sample_hs_config, attributes, 250, &hs_cfg_desc); /* doc configuration instantiation end */ /* @@ -63,28 +58,22 @@ static const struct usb_bos_capability_lpm bos_cap_lpm = { USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm); -static void sample_fix_code_triple(struct usbd_context *uds_ctx, - const enum usbd_speed speed) -{ +static void sample_fix_code_triple(struct usbd_context *uds_ctx, const enum usbd_speed speed) { /* Always use class code information from Interface Descriptors */ - if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) || - IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) || - IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) || - IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) { + if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) || IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) || + IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) || IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) { /* * Class with multiple interfaces have an Interface * Association Descriptor available, use an appropriate triple * to indicate it. */ - usbd_device_set_code_triple(uds_ctx, speed, - USB_BCC_MISCELLANEOUS, 0x02, 0x01); + usbd_device_set_code_triple(uds_ctx, speed, USB_BCC_MISCELLANEOUS, 0x02, 0x01); } else { usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0); } } -struct usbd_context *usbd_setup_device(usbd_msg_cb_t msg_cb) -{ +struct usbd_context *usbd_setup_device(usbd_msg_cb_t msg_cb) { int err; /* doc add string descriptor start */ @@ -110,14 +99,12 @@ struct usbd_context *usbd_setup_device(usbd_msg_cb_t msg_cb) /* doc add string descriptor end */ if (usbd_caps_speed(&usbd) == USBD_SPEED_HS) { - err = usbd_add_configuration(&usbd, USBD_SPEED_HS, - &sample_hs_config); + err = usbd_add_configuration(&usbd, USBD_SPEED_HS, &sample_hs_config); if (err) { return NULL; } - err = usbd_register_all_classes(&usbd, USBD_SPEED_HS, 1, - blocklist); + err = usbd_register_all_classes(&usbd, USBD_SPEED_HS, 1, blocklist); if (err) { return NULL; } @@ -126,8 +113,7 @@ struct usbd_context *usbd_setup_device(usbd_msg_cb_t msg_cb) } /* doc configuration register start */ - err = usbd_add_configuration(&usbd, USBD_SPEED_FS, - &sample_fs_config); + err = usbd_add_configuration(&usbd, USBD_SPEED_FS, &sample_fs_config); if (err) { return NULL; } @@ -164,8 +150,7 @@ struct usbd_context *usbd_setup_device(usbd_msg_cb_t msg_cb) return &usbd; } -struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb) -{ +struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb) { int err; if (usbd_setup_device(msg_cb) == NULL) { @@ -182,4 +167,4 @@ struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb) return &usbd; } -#endif \ No newline at end of file +#endif diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 80cfbacfa..15798fc62 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -7,7 +7,8 @@ #include #include "zephyrInternal.h" -static const struct gpio_dt_spec arduino_pins[] = {DT_FOREACH_PROP_ELEM_SEP( +static const struct gpio_dt_spec arduino_pins[] = { + DT_FOREACH_PROP_ELEM_SEP( DT_PATH(zephyr_user), digital_pin_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, ))}; namespace { @@ -18,57 +19,49 @@ namespace { * Calculate GPIO ports/pins number statically from devicetree configuration */ -template constexpr N sum_of_list(const N sum, const Head &head) -{ - return sum + head; +template constexpr N sum_of_list(const N sum, const Head &head) { + return sum + head; } template -constexpr N sum_of_list(const N sum, const Head &head, const Tail &...tail) -{ - return sum_of_list(sum + head, tail...); +constexpr N sum_of_list(const N sum, const Head &head, const Tail &...tail) { + return sum_of_list(sum + head, tail...); } -template constexpr N max_in_list(const N max, const Head &head) -{ - return (max >= head) ? max : head; +template constexpr N max_in_list(const N max, const Head &head) { + return (max >= head) ? max : head; } template -constexpr N max_in_list(const N max, const Head &head, const Tail &...tail) -{ - return max_in_list((max >= head) ? max : head, tail...); +constexpr N max_in_list(const N max, const Head &head, const Tail &...tail) { + return max_in_list((max >= head) ? max : head, tail...); } template constexpr size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, - const Query &query, const Head &head) -{ - return ((found == ((size_t)-1)) && (query == head) && (idx == at)) ? 1 : 0; + const Query &query, const Head &head) { + return ((found == ((size_t)-1)) && (query == head) && (idx == at)) ? 1 : 0; } template constexpr size_t is_first_appearance(const size_t &idx, const size_t &at, const size_t &found, - const Query &query, const Head &head, - const Tail &...tail) -{ - return ((found == ((size_t)-1)) && (query == head) && (idx == at)) - ? 1 - : is_first_appearance(idx + 1, at, (query == head ? idx : found), query, - tail...); + const Query &query, const Head &head, const Tail &...tail) { + return ((found == ((size_t)-1)) && (query == head) && (idx == at)) ? + 1 : + is_first_appearance(idx + 1, at, (query == head ? idx : found), query, tail...); } #define GET_DEVICE_VARGS(n, p, i, _) DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(n, p, i)) #define FIRST_APPEARANCE(n, p, i) \ - is_first_appearance(0, i, ((size_t)-1), DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(n, p, i)), \ - DT_FOREACH_PROP_ELEM_SEP_VARGS(n, p, GET_DEVICE_VARGS, (, ), 0)) -const int port_num = - sum_of_list(0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, + is_first_appearance(0, i, ((size_t)-1), DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(n, p, i)), \ + DT_FOREACH_PROP_ELEM_SEP_VARGS(n, p, GET_DEVICE_VARGS, (, ), 0)) +const int port_num = sum_of_list( + 0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, FIRST_APPEARANCE, (, ))); #define GPIO_NGPIOS(n, p, i) DT_PROP(DT_GPIO_CTLR_BY_IDX(n, p, i), ngpios) const int max_ngpios = max_in_list( - 0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, GPIO_NGPIOS, (, ))); + 0, DT_FOREACH_PROP_ELEM_SEP(DT_PATH(zephyr_user), digital_pin_gpios, GPIO_NGPIOS, (, ))); #else @@ -82,137 +75,132 @@ const int max_ngpios = 0; */ struct arduino_callback { - voidFuncPtr handler; - bool enabled; + voidFuncPtr handler; + bool enabled; }; struct gpio_port_callback { - struct gpio_callback callback; - struct arduino_callback handlers[max_ngpios]; - gpio_port_pins_t pins; - const struct device *dev; + struct gpio_callback callback; + struct arduino_callback handlers[max_ngpios]; + gpio_port_pins_t pins; + const struct device *dev; } port_callback[port_num] = {0}; -struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) -{ - for (size_t i = 0; i < ARRAY_SIZE(port_callback); i++) { - if (port_callback[i].dev == dev) { - return &port_callback[i]; - } - if (port_callback[i].dev == nullptr) { - port_callback[i].dev = dev; - return &port_callback[i]; - } - } +struct gpio_port_callback *find_gpio_port_callback(const struct device *dev) { + for (size_t i = 0; i < ARRAY_SIZE(port_callback); i++) { + if (port_callback[i].dev == dev) { + return &port_callback[i]; + } + if (port_callback[i].dev == nullptr) { + port_callback[i].dev = dev; + return &port_callback[i]; + } + } - return nullptr; + return nullptr; } -void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) -{ - struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); +void setInterruptHandler(pin_size_t pinNumber, voidFuncPtr func) { + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); - if (pcb) { - pcb->handlers[arduino_pins[pinNumber].pin].handler = func; - } + if (pcb) { + pcb->handlers[arduino_pins[pinNumber].pin].handler = func; + } } -void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uint32_t pins) -{ - (void)port; // unused - struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb; +void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uint32_t pins) { + (void)port; // unused + struct gpio_port_callback *pcb = (struct gpio_port_callback *)cb; - for (uint32_t i = 0; i < max_ngpios; i++) { - if (pins & BIT(i) && pcb->handlers[i].enabled) { - pcb->handlers[i].handler(); - } - } + for (uint32_t i = 0; i < max_ngpios; i++) { + if (pins & BIT(i) && pcb->handlers[i].enabled) { + pcb->handlers[i].handler(); + } + } } #ifdef CONFIG_PWM -#define PWM_DT_SPEC(n,p,i) PWM_DT_SPEC_GET_BY_IDX(n, i), -#define PWM_PINS(n, p, 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)), +#define PWM_DT_SPEC(n, p, i) PWM_DT_SPEC_GET_BY_IDX(n, i), +#define PWM_PINS(n, p, 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)), -const struct pwm_dt_spec arduino_pwm[] = - { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC) }; +const struct pwm_dt_spec arduino_pwm[] = { + DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwms, PWM_DT_SPEC)}; /* pwm-pins node provides a mapping digital pin numbers to pwm channels */ -const pin_size_t arduino_pwm_pins[] = - { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwm_pin_gpios, PWM_PINS) }; +const pin_size_t arduino_pwm_pins[] = { + DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), pwm_pin_gpios, PWM_PINS)}; size_t pwm_pin_index(pin_size_t pinNumber) { - for(size_t i=0; ipin]; - - if (pt->count == 0) { - k_timer_stop(timer); - gpio_pin_set_dt(spec, 0); - } else { - gpio_pin_toggle_dt(spec); - if (!pt->infinity) { - pt->count--; - } - } -} - -void tone(pin_size_t pinNumber, unsigned int frequency, - unsigned long duration) { - const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; - struct k_timer *timer; - k_timeout_t timeout; - - if (pinNumber >= MAX_TONE_PINS) { - return; - } - - timer = &arduino_pin_timers[pinNumber].timer; - - pinMode(pinNumber, OUTPUT); - k_timer_stop(&arduino_pin_timers[pinNumber].timer); - - if (frequency == 0) { - gpio_pin_set_dt(spec, 0); - return; - } - - timeout = K_NSEC(NSEC_PER_SEC / (TOGGLES_PER_CYCLE * frequency)); - if (timeout.ticks == 0) { - timeout.ticks = 1; - } - - arduino_pin_timers[pinNumber].infinity = (duration == 0); - arduino_pin_timers[pinNumber].count = (uint64_t)duration * frequency * + struct pin_timer *pt = CONTAINER_OF(timer, struct pin_timer, timer); + const struct gpio_dt_spec *spec = &arduino_pins[pt->pin]; + + if (pt->count == 0) { + k_timer_stop(timer); + gpio_pin_set_dt(spec, 0); + } else { + gpio_pin_toggle_dt(spec); + if (!pt->infinity) { + pt->count--; + } + } +} + +void tone(pin_size_t pinNumber, unsigned int frequency, unsigned long duration) { + const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; + struct k_timer *timer; + k_timeout_t timeout; + + if (pinNumber >= MAX_TONE_PINS) { + return; + } + + timer = &arduino_pin_timers[pinNumber].timer; + + pinMode(pinNumber, OUTPUT); + k_timer_stop(&arduino_pin_timers[pinNumber].timer); + + if (frequency == 0) { + gpio_pin_set_dt(spec, 0); + return; + } + + timeout = K_NSEC(NSEC_PER_SEC / (TOGGLES_PER_CYCLE * frequency)); + if (timeout.ticks == 0) { + timeout.ticks = 1; + } + + arduino_pin_timers[pinNumber].infinity = (duration == 0); + arduino_pin_timers[pinNumber].count = (uint64_t)duration * frequency * (MSEC_PER_SEC / TOGGLES_PER_CYCLE); - arduino_pin_timers[pinNumber].pin = pinNumber; - k_timer_init(timer, tone_expiry_cb, NULL); + arduino_pin_timers[pinNumber].pin = pinNumber; + k_timer_init(timer, tone_expiry_cb, NULL); - gpio_pin_set_dt(spec, 0); - k_timer_start(timer, timeout, timeout); + gpio_pin_set_dt(spec, 0); + k_timer_start(timer, timeout, timeout); } void noTone(pin_size_t pinNumber) { - const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; + const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; - k_timer_stop(&arduino_pin_timers[pinNumber].timer); - gpio_pin_set_dt(spec, 0); + k_timer_stop(&arduino_pin_timers[pinNumber].timer); + gpio_pin_set_dt(spec, 0); } void delay(unsigned long ms) { - k_sleep(K_MSEC(ms)); + k_sleep(K_MSEC(ms)); } void delayMicroseconds(unsigned int us) { - k_busy_wait(us); + k_busy_wait(us); } unsigned long micros(void) { #ifdef CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER - return k_cyc_to_us_floor32(k_cycle_get_64()); + return k_cyc_to_us_floor32(k_cycle_get_64()); #else - return k_cyc_to_us_floor32(k_cycle_get_32()); + return k_cyc_to_us_floor32(k_cycle_get_32()); #endif } unsigned long millis(void) { - return k_uptime_get_32(); + return k_uptime_get_32(); } #if defined(CONFIG_DAC) || defined(CONFIG_PWM) static int _analog_write_resolution = 8; + void analogWriteResolution(int bits) { - _analog_write_resolution = bits; + _analog_write_resolution = bits; } + int analogWriteResolution() { - return _analog_write_resolution; + return _analog_write_resolution; } #endif #ifdef CONFIG_PWM -void analogWrite(pin_size_t pinNumber, int value) -{ - size_t idx = pwm_pin_index(pinNumber); +void analogWrite(pin_size_t pinNumber, int value) { + size_t idx = pwm_pin_index(pinNumber); - if (idx >= ARRAY_SIZE(arduino_pwm)) { - return; - } + if (idx >= ARRAY_SIZE(arduino_pwm)) { + return; + } - if (!pwm_is_ready_dt(&arduino_pwm[idx])) { - return; - } + if (!pwm_is_ready_dt(&arduino_pwm[idx])) { + return; + } - value = map(value, 0, 1 << _analog_write_resolution, 0, arduino_pwm[idx].period); + value = map(value, 0, 1 << _analog_write_resolution, 0, arduino_pwm[idx].period); - if (((uint32_t)value) > arduino_pwm[idx].period) { - value = arduino_pwm[idx].period; - } else if (value < 0) { - value = 0; - } + if (((uint32_t)value) > arduino_pwm[idx].period) { + value = arduino_pwm[idx].period; + } else if (value < 0) { + value = 0; + } - /* - * A duty ratio determines by the period value defined in dts - * and the value arguments. So usually the period value sets as 255. - */ - (void)pwm_set_pulse_dt(&arduino_pwm[idx], value); + /* + * A duty ratio determines by the period value defined in dts + * and the value arguments. So usually the period value sets as 255. + */ + (void)pwm_set_pulse_dt(&arduino_pwm[idx], value); } #endif #ifdef CONFIG_DAC -void analogWrite(enum dacPins dacName, int value) -{ - if (dacName >= NUM_OF_DACS) { - return; - } +void analogWrite(enum dacPins dacName, int value) { + if (dacName >= NUM_OF_DACS) { + return; + } - dac_channel_setup(dac_dev, &dac_ch_cfg[dacName]); + dac_channel_setup(dac_dev, &dac_ch_cfg[dacName]); - const int max_dac_value = 1U << dac_ch_cfg[dacName].resolution; - dac_write_value(dac_dev, dac_ch_cfg[dacName].channel_id, map(value, 0, 1 << _analog_write_resolution, 0, max_dac_value)); + const int max_dac_value = 1U << dac_ch_cfg[dacName].resolution; + dac_write_value(dac_dev, dac_ch_cfg[dacName].channel_id, + map(value, 0, 1 << _analog_write_resolution, 0, max_dac_value)); } #endif - #ifdef CONFIG_ADC -void analogReference(uint8_t mode) -{ - /* - * The Arduino API not clearly defined what means of - * the mode argument of analogReference(). - * Treat the value as equivalent to zephyr's adc_reference. - */ - for (size_t i=0; i(mode); - } +void analogReference(uint8_t mode) { + /* + * The Arduino API not clearly defined what means of + * the mode argument of analogReference(). + * Treat the value as equivalent to zephyr's adc_reference. + */ + for (size_t i = 0; i < ARRAY_SIZE(channel_cfg); i++) { + channel_cfg[i].reference = static_cast(mode); + } } // Note: We can not update the arduino_adc structure as it is read only... static int read_resolution = 10; -void analogReadResolution(int bits) -{ - read_resolution = bits; +void analogReadResolution(int bits) { + read_resolution = bits; } -int analogReadResolution() -{ - return read_resolution; +int analogReadResolution() { + return read_resolution; } +int analogRead(pin_size_t pinNumber) { + int err; + uint16_t buf; + struct adc_sequence seq = {.buffer = &buf, .buffer_size = sizeof(buf)}; + size_t idx = analog_pin_index(pinNumber); -int analogRead(pin_size_t pinNumber) -{ - int err; - uint16_t buf; - struct adc_sequence seq = { .buffer = &buf, .buffer_size = sizeof(buf) }; - size_t idx = analog_pin_index(pinNumber); + if (idx >= ARRAY_SIZE(arduino_adc)) { + return -EINVAL; + } - if (idx >= ARRAY_SIZE(arduino_adc) ) { - return -EINVAL; - } + /* + * ADC that is on MCU supported by Zephyr exists + * only 16bit resolution, currently. + */ + if (arduino_adc[idx].resolution > 16) { + return -ENOTSUP; + } - /* - * ADC that is on MCU supported by Zephyr exists - * only 16bit resolution, currently. - */ - if (arduino_adc[idx].resolution > 16) { - return -ENOTSUP; - } + err = adc_channel_setup(arduino_adc[idx].dev, &arduino_adc[idx].channel_cfg); + if (err < 0) { + return err; + } - err = adc_channel_setup(arduino_adc[idx].dev, &arduino_adc[idx].channel_cfg); - if (err < 0) { - return err; - } + seq.channels = BIT(arduino_adc[idx].channel_id); + seq.resolution = arduino_adc[idx].resolution; + seq.oversampling = arduino_adc[idx].oversampling; - seq.channels = BIT(arduino_adc[idx].channel_id); - seq.resolution = arduino_adc[idx].resolution; - seq.oversampling = arduino_adc[idx].oversampling; + err = adc_read(arduino_adc[idx].dev, &seq); + if (err < 0) { + return err; + } - err = adc_read(arduino_adc[idx].dev, &seq); - if (err < 0) { - return err; - } - - /* - * If necessary map the return value to the - * number of bits the user has asked for - */ - if (read_resolution == seq.resolution) return buf; - if (read_resolution < seq.resolution) return buf >> (seq.resolution - read_resolution); - return buf << (read_resolution - seq.resolution) ; + /* + * If necessary map the return value to the + * number of bits the user has asked for + */ + if (read_resolution == seq.resolution) { + return buf; + } + if (read_resolution < seq.resolution) { + return buf >> (seq.resolution - read_resolution); + } + return buf << (read_resolution - seq.resolution); } #endif -void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) -{ - struct gpio_port_callback *pcb; - gpio_flags_t intmode = 0; +void attachInterrupt(pin_size_t pinNumber, voidFuncPtr callback, PinStatus pinStatus) { + struct gpio_port_callback *pcb; + gpio_flags_t intmode = 0; - if (!callback) { - return; - } + if (!callback) { + return; + } - if (pinStatus == LOW) { - intmode |= GPIO_INT_LEVEL_LOW; - } else if (pinStatus == HIGH) { - intmode |= GPIO_INT_LEVEL_HIGH; - } else if (pinStatus == CHANGE) { - intmode |= GPIO_INT_EDGE_BOTH; - } else if (pinStatus == FALLING) { - intmode |= GPIO_INT_EDGE_FALLING; - } else if (pinStatus == RISING) { - intmode |= GPIO_INT_EDGE_RISING; - } else { - return; - } + if (pinStatus == LOW) { + intmode |= GPIO_INT_LEVEL_LOW; + } else if (pinStatus == HIGH) { + intmode |= GPIO_INT_LEVEL_HIGH; + } else if (pinStatus == CHANGE) { + intmode |= GPIO_INT_EDGE_BOTH; + } else if (pinStatus == FALLING) { + intmode |= GPIO_INT_EDGE_FALLING; + } else if (pinStatus == RISING) { + intmode |= GPIO_INT_EDGE_RISING; + } else { + return; + } - pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); - __ASSERT(pcb != nullptr, "gpio_port_callback not found"); + pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); + __ASSERT(pcb != nullptr, "gpio_port_callback not found"); - pcb->pins |= BIT(arduino_pins[pinNumber].pin); - setInterruptHandler(pinNumber, callback); - enableInterrupt(pinNumber); + pcb->pins |= BIT(arduino_pins[pinNumber].pin); + setInterruptHandler(pinNumber, callback); + enableInterrupt(pinNumber); - gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin, intmode); - gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins); - gpio_add_callback(arduino_pins[pinNumber].port, &pcb->callback); + gpio_pin_interrupt_configure(arduino_pins[pinNumber].port, arduino_pins[pinNumber].pin, + intmode); + gpio_init_callback(&pcb->callback, handleGpioCallback, pcb->pins); + gpio_add_callback(arduino_pins[pinNumber].port, &pcb->callback); } -void detachInterrupt(pin_size_t pinNumber) -{ - setInterruptHandler(pinNumber, nullptr); - disableInterrupt(pinNumber); +void detachInterrupt(pin_size_t pinNumber) { + setInterruptHandler(pinNumber, nullptr); + disableInterrupt(pinNumber); } #ifndef CONFIG_MINIMAL_LIBC_RAND @@ -522,74 +505,76 @@ long random(long max) { #endif unsigned long pulseIn(pin_size_t pinNumber, uint8_t state, unsigned long timeout) { - struct k_timer timer; - int64_t start, end, delta = 0; - const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; - - if (!gpio_is_ready_dt(spec)) { - return 0; - } - - k_timer_init(&timer, NULL, NULL); - k_timer_start(&timer, K_MSEC(timeout), K_NO_WAIT); - - while(gpio_pin_get_dt(spec) == state && k_timer_status_get(&timer) == 0); - if (k_timer_status_get(&timer) > 0) { - goto cleanup; - } - - while(gpio_pin_get_dt(spec) != state && k_timer_status_get(&timer) == 0); - if (k_timer_status_get(&timer) > 0) { - goto cleanup; - } - - start = k_uptime_ticks(); - while(gpio_pin_get_dt(spec) == state && k_timer_status_get(&timer) == 0); - if (k_timer_status_get(&timer) > 0) { - goto cleanup; - } - end = k_uptime_ticks(); - - delta = k_ticks_to_us_floor64(end - start); + struct k_timer timer; + int64_t start, end, delta = 0; + const struct gpio_dt_spec *spec = &arduino_pins[pinNumber]; + + if (!gpio_is_ready_dt(spec)) { + return 0; + } + + k_timer_init(&timer, NULL, NULL); + k_timer_start(&timer, K_MSEC(timeout), K_NO_WAIT); + + while (gpio_pin_get_dt(spec) == state && k_timer_status_get(&timer) == 0) + ; + if (k_timer_status_get(&timer) > 0) { + goto cleanup; + } + + while (gpio_pin_get_dt(spec) != state && k_timer_status_get(&timer) == 0) + ; + if (k_timer_status_get(&timer) > 0) { + goto cleanup; + } + + start = k_uptime_ticks(); + while (gpio_pin_get_dt(spec) == state && k_timer_status_get(&timer) == 0) + ; + if (k_timer_status_get(&timer) > 0) { + goto cleanup; + } + end = k_uptime_ticks(); + + delta = k_ticks_to_us_floor64(end - start); cleanup: - k_timer_stop(&timer); - return (unsigned long)delta; + k_timer_stop(&timer); + return (unsigned long)delta; } void enableInterrupt(pin_size_t pinNumber) { - struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); - if (pcb) { - pcb->handlers[arduino_pins[pinNumber].pin].enabled = true; - } + if (pcb) { + pcb->handlers[arduino_pins[pinNumber].pin].enabled = true; + } } void disableInterrupt(pin_size_t pinNumber) { - struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pinNumber].port); - if (pcb) { - pcb->handlers[arduino_pins[pinNumber].pin].enabled = false; - } + if (pcb) { + pcb->handlers[arduino_pins[pinNumber].pin].enabled = false; + } } void interrupts(void) { - if (interrupts_disabled) { - irq_unlock(irq_key); - interrupts_disabled = false; - } + if (interrupts_disabled) { + irq_unlock(irq_key); + interrupts_disabled = false; + } } void noInterrupts(void) { - if (!interrupts_disabled) { - irq_key = irq_lock(); - interrupts_disabled = true; - } + if (!interrupts_disabled) { + irq_key = irq_lock(); + interrupts_disabled = true; + } } int digitalPinToInterrupt(pin_size_t pin) { - struct gpio_port_callback *pcb = - find_gpio_port_callback(arduino_pins[pin].port); + struct gpio_port_callback *pcb = find_gpio_port_callback(arduino_pins[pin].port); - return (pcb) ? pin : -1; + return (pcb) ? pin : -1; } diff --git a/cores/arduino/zephyrPrint.cpp b/cores/arduino/zephyrPrint.cpp index 2e07c2329..d192328e2 100644 --- a/cores/arduino/zephyrPrint.cpp +++ b/cores/arduino/zephyrPrint.cpp @@ -9,18 +9,14 @@ #include #include -namespace arduino -{ -namespace zephyr -{ +namespace arduino { +namespace zephyr { -int cbprintf_callback(int c, void *ctx) -{ +int cbprintf_callback(int c, void *ctx) { return reinterpret_cast(ctx)->write((unsigned char)c); } -size_t wrap_cbprintf(void *ctx, const char *format, ...) -{ +size_t wrap_cbprintf(void *ctx, const char *format, ...) { va_list ap; int rc; @@ -31,8 +27,7 @@ size_t wrap_cbprintf(void *ctx, const char *format, ...) return static_cast(rc > 0 ? rc : 0); } -size_t print_number_base_any(void *ctx, unsigned long long ull, int base) -{ +size_t print_number_base_any(void *ctx, unsigned long long ull, int base) { arduino::Print &print = *reinterpret_cast(ctx); char string[sizeof(unsigned long long) * 8] = {0}; size_t digit = 0; @@ -47,7 +42,7 @@ size_t print_number_base_any(void *ctx, unsigned long long ull, int base) if (value < 10) { string[sizeof(string) - digit] = '0' + value; } else { - string[sizeof(string) - digit] = 'A' + (value- 10); + string[sizeof(string) - digit] = 'A' + (value - 10); } digit++; @@ -57,8 +52,7 @@ size_t print_number_base_any(void *ctx, unsigned long long ull, int base) return print.write(string + (sizeof(string) - digit), digit + 1); } -size_t print_number_base_pow2(void *ctx, unsigned long long ull, unsigned bits) -{ +size_t print_number_base_pow2(void *ctx, unsigned long long ull, unsigned bits) { arduino::Print &print = *reinterpret_cast(ctx); const unsigned long long mask = (1 << bits) - 1; int digit = (((sizeof(unsigned long long) * 8) + bits) / bits); @@ -75,7 +69,7 @@ size_t print_number_base_pow2(void *ctx, unsigned long long ull, unsigned bits) if (value < 10) { print.write('0' + value); } else { - print.write('A' + (value- 10)); + print.write('A' + (value - 10)); } output_count++; } @@ -92,11 +86,10 @@ size_t print_number_base_pow2(void *ctx, unsigned long long ull, unsigned bits) * This is the default implementation. * It will be overridden by subclassese. */ -size_t arduino::Print::write(const uint8_t *buffer, size_t size) -{ - size_t i; - for (i=0; i #include -namespace arduino -{ -namespace zephyr -{ +namespace arduino { +namespace zephyr { int cbprintf_callback(int c, void *ctx); size_t wrap_cbprintf(void *ctx, const char *format, ...); size_t print_number_base_any(void *ctx, unsigned long long ull, int base); size_t print_number_base_pow2(void *ctx, unsigned long long ull, unsigned bits); -template size_t print_number(void *ctx, Number n, const int base, const char *decfmt) -{ +template +size_t print_number(void *ctx, Number n, const int base, const char *decfmt) { if (base == 0) { return reinterpret_cast(ctx)->write((char)n); } else if (base == 2) { @@ -46,63 +44,51 @@ template size_t print_number(void *ctx, Number n, const int base, } // namespace arduino -inline size_t arduino::Print::print(const __FlashStringHelper *fsh) -{ +inline size_t arduino::Print::print(const __FlashStringHelper *fsh) { return write(reinterpret_cast(fsh)); } -inline size_t arduino::Print::print(const String &s) -{ +inline size_t arduino::Print::print(const String &s) { return write(s.c_str(), s.length()); } -inline size_t arduino::Print::print(const char str[]) -{ +inline size_t arduino::Print::print(const char str[]) { return write(str); } -inline size_t arduino::Print::print(char c) -{ +inline size_t arduino::Print::print(char c) { return write(c); } -inline size_t arduino::Print::print(unsigned char n, int base) -{ +inline size_t arduino::Print::print(unsigned char n, int base) { return arduino::zephyr::print_number(this, n, base, "%hhu"); } -inline size_t arduino::Print::print(int n, int base) -{ +inline size_t arduino::Print::print(int n, int base) { return arduino::zephyr::print_number(this, n, base, "%d"); } -inline size_t arduino::Print::print(unsigned int n, int base) -{ +inline size_t arduino::Print::print(unsigned int n, int base) { return arduino::zephyr::print_number(this, n, base, "%u"); } -inline size_t arduino::Print::print(long n, int base) -{ +inline size_t arduino::Print::print(long n, int base) { return arduino::zephyr::print_number(this, n, base, "%ld"); } -inline size_t arduino::Print::print(unsigned long n, int base) -{ +inline size_t arduino::Print::print(unsigned long n, int base) { return arduino::zephyr::print_number(this, n, base, "%lu"); } -inline size_t arduino::Print::print(long long n, int base) -{ +inline size_t arduino::Print::print(long long n, int base) { return arduino::zephyr::print_number(this, n, base, "%lld"); } -inline size_t arduino::Print::print(unsigned long long n, int base) -{ +inline size_t arduino::Print::print(unsigned long long n, int base) { return arduino::zephyr::print_number(this, n, base, "%llu"); } -inline size_t arduino::Print::print(double n, int perception) -{ +inline size_t arduino::Print::print(double n, int perception) { if (perception < 10) { const char ch_perception = static_cast('0' + perception); const char format[] = {'%', '.', ch_perception, 'f', '\0'}; @@ -114,77 +100,62 @@ inline size_t arduino::Print::print(double n, int perception) } } -inline size_t arduino::Print::print(const Printable &printable) -{ +inline size_t arduino::Print::print(const Printable &printable) { return printable.printTo(*this); } -inline size_t arduino::Print::println(const __FlashStringHelper *fsh) -{ +inline size_t arduino::Print::println(const __FlashStringHelper *fsh) { return print(fsh) + println(); } -inline size_t arduino::Print::println(const String &s) -{ +inline size_t arduino::Print::println(const String &s) { return print(s) + println(); } -inline size_t arduino::Print::println(const char str[]) -{ +inline size_t arduino::Print::println(const char str[]) { return print(str) + println(); } -inline size_t arduino::Print::println(char c) -{ +inline size_t arduino::Print::println(char c) { return print(c) + println(); } -inline size_t arduino::Print::println(unsigned char uc, int base) -{ +inline size_t arduino::Print::println(unsigned char uc, int base) { return print(uc, base) + println(); } -inline size_t arduino::Print::println(int i, int base) -{ +inline size_t arduino::Print::println(int i, int base) { return print(i, base) + println(); } -inline size_t arduino::Print::println(unsigned int ui, int base) -{ +inline size_t arduino::Print::println(unsigned int ui, int base) { return print(ui, base) + println(); } -inline size_t arduino::Print::println(long l, int base) -{ +inline size_t arduino::Print::println(long l, int base) { return print(l, base) + println(); } -inline size_t arduino::Print::println(unsigned long ul, int base) -{ +inline size_t arduino::Print::println(unsigned long ul, int base) { return print(ul, base) + println(); } -inline size_t arduino::Print::println(long long ll, int base) -{ +inline size_t arduino::Print::println(long long ll, int base) { return print(ll, base) + println(); } -inline size_t arduino::Print::println(unsigned long long ull, int base) -{ +inline size_t arduino::Print::println(unsigned long long ull, int base) { return print(ull, base) + println(); } -inline size_t arduino::Print::println(double d, int perception) -{ +inline size_t arduino::Print::println(double d, int perception) { return print(d, perception) + println(); } -inline size_t arduino::Print::println(const Printable &printable) -{ +inline size_t arduino::Print::println(const Printable &printable) { return print(printable) + println(); } -inline size_t arduino::Print::println(void) -{ +inline size_t arduino::Print::println(void) { return write("\r\n", 2); } diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index b463615e6..f493047fa 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -11,11 +11,9 @@ #include #include -namespace -{ +namespace { -enum uart_config_parity conf_parity(uint16_t conf) -{ +enum uart_config_parity conf_parity(uint16_t conf) { switch (conf & SERIAL_PARITY_MASK) { case SERIAL_PARITY_EVEN: return UART_CFG_PARITY_EVEN; @@ -26,8 +24,7 @@ enum uart_config_parity conf_parity(uint16_t conf) } } -enum uart_config_stop_bits conf_stop_bits(uint16_t conf) -{ +enum uart_config_stop_bits conf_stop_bits(uint16_t conf) { switch (conf & SERIAL_STOP_BIT_MASK) { case SERIAL_STOP_BIT_1_5: return UART_CFG_STOP_BITS_1_5; @@ -38,8 +35,7 @@ enum uart_config_stop_bits conf_stop_bits(uint16_t conf) } } -enum uart_config_data_bits conf_data_bits(uint16_t conf) -{ +enum uart_config_data_bits conf_data_bits(uint16_t conf) { switch (conf & SERIAL_DATA_MASK) { case SERIAL_DATA_5: return UART_CFG_DATA_BITS_5; @@ -54,8 +50,7 @@ enum uart_config_data_bits conf_data_bits(uint16_t conf) } // anonymous namespace -void arduino::ZephyrSerial::begin(unsigned long baud, uint16_t conf) -{ +void arduino::ZephyrSerial::begin(unsigned long baud, uint16_t conf) { struct uart_config config = { .baudrate = static_cast(baud), .parity = conf_parity(conf), @@ -73,8 +68,7 @@ void arduino::ZephyrSerial::begin(unsigned long baud, uint16_t conf) uart_irq_rx_enable(uart); } -void arduino::ZephyrSerial::IrqHandler() -{ +void arduino::ZephyrSerial::IrqHandler() { uint8_t buf[8]; int length; int ret = 0; @@ -114,14 +108,12 @@ void arduino::ZephyrSerial::IrqHandler() k_sem_give(&tx.sem); } -void arduino::ZephyrSerial::IrqDispatch(const struct device *dev, void *data) -{ +void arduino::ZephyrSerial::IrqDispatch(const struct device *dev, void *data) { (void)dev; // unused reinterpret_cast(data)->IrqHandler(); } -int arduino::ZephyrSerial::available() -{ +int arduino::ZephyrSerial::available() { int ret; k_sem_take(&rx.sem, K_FOREVER); @@ -131,8 +123,7 @@ int arduino::ZephyrSerial::available() return ret; } -int arduino::ZephyrSerial::availableForWrite() -{ +int arduino::ZephyrSerial::availableForWrite() { int ret; k_sem_take(&tx.sem, K_FOREVER); @@ -142,35 +133,32 @@ int arduino::ZephyrSerial::availableForWrite() return ret; } -int arduino::ZephyrSerial::peek() -{ +int arduino::ZephyrSerial::peek() { uint8_t data; k_sem_take(&rx.sem, K_FOREVER); uint32_t cb_ret = ring_buf_peek(&rx.ringbuf, &data, 1); k_sem_give(&rx.sem); - return cb_ret? data : -1; + return cb_ret ? data : -1; } -int arduino::ZephyrSerial::read() -{ +int arduino::ZephyrSerial::read() { uint8_t data; k_sem_take(&rx.sem, K_FOREVER); uint32_t cb_ret = ring_buf_get(&rx.ringbuf, &data, 1); k_sem_give(&rx.sem); - return cb_ret? data : -1; + return cb_ret ? data : -1; } -size_t arduino::ZephyrSerial::write(const uint8_t *buffer, size_t size) -{ +size_t arduino::ZephyrSerial::write(const uint8_t *buffer, size_t size) { size_t idx = 0; while (1) { k_sem_take(&tx.sem, K_FOREVER); - auto ret = ring_buf_put(&tx.ringbuf, &buffer[idx], size-idx); + auto ret = ring_buf_put(&tx.ringbuf, &buffer[idx], size - idx); k_sem_give(&tx.sem); if (ret < 0) { return 0; @@ -194,7 +182,7 @@ void arduino::ZephyrSerial::flush() { while (ring_buf_size_get(&tx.ringbuf) > 0) { k_yield(); } - while (uart_irq_tx_complete(uart) == 0){ + while (uart_irq_tx_complete(uart) == 0) { k_yield(); } } @@ -206,9 +194,11 @@ void arduino::ZephyrSerial::flush() { #endif #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) -#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) +#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && \ + (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) // If CDC USB, use that object as Serial (and SerialUSB) -arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), serials, FIRST_UART_INDEX))); +arduino::ZephyrSerial + Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), serials, FIRST_UART_INDEX))); #endif #if (DT_PROP_LEN(DT_PATH(zephyr_user), serials) > 1) #define ARDUINO_SERIAL_DEFINED_0 1 @@ -220,13 +210,17 @@ arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user COND_CODE_1(ARDUINO_SERIAL_DEFINED_##i, (DECL_SERIAL_0(n, p, i)), (DECL_SERIAL_N(n, p, i))) #define CALL_EVENT_0(n, p, i) -#define CALL_EVENT_N(n, p, i) if (_CONCAT(Serial, i).available()) _CONCAT(_CONCAT(serial, i), Event)(); -#define CALL_SERIALEVENT_N(n, p, i) \ +#define CALL_EVENT_N(n, p, i) \ + if (_CONCAT(Serial, i).available()) \ + _CONCAT(_CONCAT(serial, i), Event)(); +#define CALL_SERIALEVENT_N(n, p, i) \ COND_CODE_1(ARDUINO_SERIAL_DEFINED_##i, (CALL_EVENT_0(n, p, i)), (CALL_EVENT_N(n, p, i))); #define DECL_EVENT_0(n, p, i) -#define DECL_EVENT_N(n, p, i) __attribute__((weak)) void serial##i##Event() { } -#define DECLARE_SERIALEVENT_N(n, p, i) \ +#define DECL_EVENT_N(n, p, i) \ + __attribute__((weak)) void serial##i##Event() { \ + } +#define DECLARE_SERIALEVENT_N(n, p, i) \ COND_CODE_1(ARDUINO_SERIAL_DEFINED_##i, (DECL_EVENT_0(n, p, i)), (DECL_EVENT_N(n, p, i))); DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), serials, DECLARE_SERIAL_N) @@ -238,15 +232,16 @@ arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_NODELABEL(arduino_serial))); arduino::ZephyrSerialStub Serial; #endif - -__attribute__((weak)) void serialEvent() { } +__attribute__((weak)) void serialEvent() { +} #if (DT_PROP_LEN(DT_PATH(zephyr_user), serials) > 1) DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), serials, DECLARE_SERIALEVENT_N) #endif -void arduino::serialEventRun(void) -{ - if (Serial.available()) serialEvent(); +void arduino::serialEventRun(void) { + if (Serial.available()) { + serialEvent(); + } #if (DT_PROP_LEN(DT_PATH(zephyr_user), serials) > 1) DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), serials, CALL_SERIALEVENT_N) #endif diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index ecc18a81b..5e1d15fe7 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -12,58 +12,84 @@ namespace arduino { -class ZephyrSerialStub : public HardwareSerial -{ +class ZephyrSerialStub : public HardwareSerial { public: - void begin(__attribute__((unused)) unsigned long baudRate) { } - void begin(__attribute__((unused)) unsigned long baudrate, __attribute__((unused)) uint16_t config) { } - void end() { } - int available() { return 0; } - int peek() { return 0; } - int read() { return 0; } - void flush() { } - size_t write(const uint8_t data) - { + void begin(__attribute__((unused)) unsigned long baudRate) { + } + + void begin(__attribute__((unused)) unsigned long baudrate, + __attribute__((unused)) uint16_t config) { + } + + void end() { + } + + int available() { + return 0; + } + + int peek() { + return 0; + } + + int read() { + return 0; + } + + void flush() { + } + + size_t write(const uint8_t data) { printk("%c", static_cast(data)); return 1; } - operator bool() { return true; } + operator bool() { + return true; + } }; -class ZephyrSerial : public HardwareSerial -{ +class ZephyrSerial : public HardwareSerial { public: - template - class ZephyrSerialBuffer - { + template class ZephyrSerialBuffer { friend arduino::ZephyrSerial; struct ring_buf ringbuf; uint8_t buffer[SZ]; struct k_sem sem; - ZephyrSerialBuffer() - { + ZephyrSerialBuffer() { k_sem_init(&sem, 1, 1); ring_buf_init(&ringbuf, sizeof(buffer), buffer); } }; - ZephyrSerial(const struct device *dev) : uart(dev) { } + ZephyrSerial(const struct device *dev) : uart(dev) { + } + void begin(unsigned long baudrate, uint16_t config); - void begin(unsigned long baudrate) { begin(baudrate, SERIAL_8N1); } + + void begin(unsigned long baudrate) { + begin(baudrate, SERIAL_8N1); + } + void flush(); - void end() { } + + void end() { + } + size_t write(const uint8_t *buffer, size_t size); - size_t write(const uint8_t data) { return write(&data, 1); } + + size_t write(const uint8_t data) { + return write(&data, 1); + } + using Print::write; // pull in write(str) and write(buf, size) from Print int available(); - int availableForWrite(); + int availableForWrite(); int peek(); int read(); - operator bool() - { + operator bool() { return true; } @@ -78,17 +104,17 @@ class ZephyrSerial : public HardwareSerial ZephyrSerialBuffer rx; }; - -} // namespace arduino +} // namespace arduino #if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) -#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) +#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && \ + (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) // If CDC USB, use that object as Serial (and SerialUSB) extern arduino::ZephyrSerial Serial; #endif #if (DT_PROP_LEN(DT_PATH(zephyr_user), serials) > 1) -#define SERIAL_DEFINED_0 1 -#define EXTERN_SERIAL_N(i) extern arduino::ZephyrSerial Serial##i; +#define SERIAL_DEFINED_0 1 +#define EXTERN_SERIAL_N(i) extern arduino::ZephyrSerial Serial##i; #define DECLARE_EXTERN_SERIAL_N(n, p, i) COND_CODE_1(SERIAL_DEFINED_##i, (), (EXTERN_SERIAL_N(i))) /* Declare Serial1, Serial2, ... */ From 768cd06a5da9bb62ab0dcd78906b5c2aee56b6c9 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Tue, 26 Aug 2025 13:59:21 +0200 Subject: [PATCH 37/44] unoq: implement analogReference Take into account the analog switch Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/zephyrCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index 15798fc62..7a746e0ee 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -377,7 +377,7 @@ void analogWrite(enum dacPins dacName, int value) { #ifdef CONFIG_ADC -void analogReference(uint8_t mode) { +void __attribute__((weak)) analogReference(uint8_t mode) { /* * The Arduino API not clearly defined what means of * the mode argument of analogReference(). From d1f2a24fd8679081c3f5add77992de180b50f9ce Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 17 Sep 2025 18:36:44 +0200 Subject: [PATCH 38/44] core: add macro to find pins by node Co-authored-by: Sebastian Romero Signed-off-by: TOKITA Hiroshi --- cores/arduino/Arduino.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index 34f436b17..358b52c1e 100644 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -37,6 +37,11 @@ #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) From 6fae725e9cda3d003420f1734d9633e710df4985 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 1 Oct 2025 15:31:07 +0200 Subject: [PATCH 39/44] cores: Remove redundant k_thread_start() calls for static threads. According to Zephyr documentation, k_thread_create() both initializes and starts the thread. The second loop that was calling k_thread_start() on each static thread was redundant. Signed-off-by: iabdalkader Signed-off-by: TOKITA Hiroshi --- cores/arduino/threads.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cores/arduino/threads.cpp b/cores/arduino/threads.cpp index f34a7f6d9..5a4e7a9b7 100644 --- a/cores/arduino/threads.cpp +++ b/cores/arduino/threads.cpp @@ -19,15 +19,5 @@ void start_static_threads() { k_thread_name_set(thread_data->init_thread, thread_data->init_name); thread_data->init_thread->init_data = thread_data; } - - /* - * Take a sched lock to prevent them from running - * until they are all started. - */ - k_sched_lock(); - _FOREACH_STATIC_THREAD(thread_data) { - k_thread_start(thread_data->init_thread); - } - k_sched_unlock(); } #endif From c1dcf6c7a7a64b12383c71d5adf8d381036e3472 Mon Sep 17 00:00:00 2001 From: Tamas Jozsi Date: Mon, 1 Sep 2025 10:37:09 +0200 Subject: [PATCH 40/44] nano_matter: add initial support for the Arduino Nano Matter Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Tamas Jozsi Signed-off-by: TOKITA Hiroshi --- cores/arduino/threads.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cores/arduino/threads.cpp b/cores/arduino/threads.cpp index 5a4e7a9b7..cf0d73767 100644 --- a/cores/arduino/threads.cpp +++ b/cores/arduino/threads.cpp @@ -12,10 +12,17 @@ void start_static_threads() { STRUCT_SECTION_FOREACH (_static_thread_data, thread_data) _FOREACH_STATIC_THREAD(thread_data) { +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + k_timeout_t init_delay = K_MSEC(thread_data->init_delay_ms); +#else + k_timeout_t init_delay = thread_data->init_delay; +#endif + k_thread_create(thread_data->init_thread, thread_data->init_stack, thread_data->init_stack_size, thread_data->init_entry, thread_data->init_p1, thread_data->init_p2, thread_data->init_p3, thread_data->init_prio, - thread_data->init_options, thread_data->init_delay); + thread_data->init_options, init_delay); + k_thread_name_set(thread_data->init_thread, thread_data->init_name); thread_data->init_thread->init_data = thread_data; } From 168bb07684d3f4a99620893a9f7c9c0241d9f79e Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 18 Sep 2025 15:12:15 +0200 Subject: [PATCH 41/44] static_build: fix bss initialization Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index bd37be8f6..87ac0f285 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -93,7 +93,7 @@ extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struc printk("Sketch Heap start: %p, size %p\n", &kheap_llext_heap, &kheap_llext_heap_size); memcpy(&_sdata, &_sidata, (&_edata - &_sdata) * sizeof(uint32_t)); - memset(&_sbss, 0, &_ebss - &_sbss); + memset(&_sbss, 0, (&_ebss - &_sbss) * sizeof(uint32_t)); __libc_init_array(); main(); } From dd24f6f5a3d3e9140f65fdbd81aab3b1561f1cad Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 3 Apr 2025 12:38:43 +0200 Subject: [PATCH 42/44] usb: refactor USBD_NEXT and implement 1200bps touch Note by committer: Only under the `cores/arduino` was picked. Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/SerialUSB.h | 16 ++++++++++--- cores/arduino/USB.cpp | 50 ++++++++------------------------------- cores/arduino/main.cpp | 3 ++- 3 files changed, 25 insertions(+), 44 deletions(-) diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h index f6459d3c4..ba2ac9c6c 100644 --- a/cores/arduino/SerialUSB.h +++ b/cores/arduino/SerialUSB.h @@ -8,6 +8,11 @@ #include +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) +#include +extern "C" struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb); +#endif + namespace arduino { class SerialUSB_ : public ZephyrSerial { @@ -34,12 +39,17 @@ class SerialUSB_ : public ZephyrSerial { protected: uint32_t dtr = 0; uint32_t baudrate; - void _baudChangeHandler(); - static void _baudChangeDispatch(struct k_timer *timer); + static void baudChangeHandler(const struct device *dev, uint32_t rate); private: - struct k_timer baud_timer; 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 diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 6e0179ea1..2b74c08d0 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -15,25 +15,11 @@ const struct device *const usb_dev = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), cdc_acm, 0)); -void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) { - (void)param; // unused - if (cb_status == USB_DC_CONFIGURED) { - } -} - void __attribute__((weak)) _on_1200_bps() { NVIC_SystemReset(); } -void arduino::SerialUSB_::_baudChangeHandler() { - uart_line_ctrl_get(uart, UART_LINE_CTRL_BAUD_RATE, &baudrate); - if (baudrate == 1200) { - usb_disable(); - _on_1200_bps(); - } -} - -static void _baudChangeHandler(const struct device *dev, uint32_t rate) { +void arduino::SerialUSB_::baudChangeHandler(const struct device *dev, uint32_t rate) { (void)dev; // unused if (rate == 1200) { usb_disable(); @@ -42,19 +28,11 @@ static void _baudChangeHandler(const struct device *dev, uint32_t rate) { } #if defined(CONFIG_USB_DEVICE_STACK_NEXT) - -extern "C" { -#include -struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb); +int arduino::SerialUSB_::usb_disable() { + return usbd_disable(Serial._usbd); } -struct usbd_context *_usbd; - -int usb_disable() { - return usbd_disable(_usbd); -} - -static void usbd_next_cb(struct usbd_context *const ctx, const struct usbd_msg *msg) { +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); @@ -67,16 +45,15 @@ static void usbd_next_cb(struct usbd_context *const ctx, const struct usbd_msg * if (msg->type == USBD_MSG_CDC_ACM_LINE_CODING) { uint32_t baudrate; - uart_line_ctrl_get(ctx->dev, UART_LINE_CTRL_BAUD_RATE, &baudrate); - _baudChangeHandler(nullptr, baudrate); + uart_line_ctrl_get(Serial.uart, UART_LINE_CTRL_BAUD_RATE, &baudrate); + Serial.baudChangeHandler(nullptr, baudrate); } } -static int enable_usb_device_next(void) { +int arduino::SerialUSB_::enable_usb_device_next(void) { int err; - //_usbd = usbd_init_device(usbd_next_cb); - _usbd = usbd_init_device(nullptr); + _usbd = usbd_init_device(arduino::SerialUSB_::usbd_next_cb); if (_usbd == NULL) { return -ENODEV; } @@ -91,21 +68,14 @@ static int enable_usb_device_next(void) { } #endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */ -void arduino::SerialUSB_::_baudChangeDispatch(struct k_timer *timer) { - arduino::SerialUSB_ *dev = (arduino::SerialUSB_ *)k_timer_user_data_get(timer); - dev->_baudChangeHandler(); -} - 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 - k_timer_init(&baud_timer, SerialUSB_::_baudChangeDispatch, NULL); - k_timer_user_data_set(&baud_timer, this); - k_timer_start(&baud_timer, K_MSEC(100), K_MSEC(100)); +#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, ::_baudChangeHandler); + cdc_acm_dte_rate_callback_set(usb_dev, SerialUSB_::baudChangeHandler); #endif #else enable_usb_device_next(); diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 87ac0f285..ead9c4e7f 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -20,7 +20,8 @@ void __attribute__((weak)) initVariant(void) { } int main(void) { -#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM) +#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && \ + (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) Serial.begin(115200); #endif From ce8b0f4e024e8f0a457257bec501157e3af3b8ea Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 10 Jul 2025 11:39:18 +0200 Subject: [PATCH 43/44] core: implement weak loop hook Co-authored-by: Martino Facchin Signed-off-by: TOKITA Hiroshi --- cores/arduino/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index ead9c4e7f..bab3b4100 100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -19,6 +19,10 @@ void start_static_threads(); void __attribute__((weak)) initVariant(void) { } +// This function can be overwriten by one library. +void __attribute__((weak)) __loopHook(void) { +} + int main(void) { #if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && \ (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS)) @@ -39,6 +43,7 @@ int main(void) { // DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials) if (arduino::serialEventRun) arduino::serialEventRun(); #endif + __loopHook(); } return 0; From 8f375db7ea886f19847698fe0264578637b0518a Mon Sep 17 00:00:00 2001 From: pennam Date: Fri, 22 Aug 2025 10:37:55 +0200 Subject: [PATCH 44/44] portentac33: add sleep to avoid dfu protocol error Co-authored-by: pennam Signed-off-by: TOKITA Hiroshi --- cores/arduino/USB.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cores/arduino/USB.cpp b/cores/arduino/USB.cpp index 2b74c08d0..fe3291887 100644 --- a/cores/arduino/USB.cpp +++ b/cores/arduino/USB.cpp @@ -29,6 +29,8 @@ void arduino::SerialUSB_::baudChangeHandler(const struct device *dev, uint32_t r #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); }