diff --git a/cores/arduino/SerialUSB.h b/cores/arduino/SerialUSB.h index 80ff85ae3..3be3f419f 100644 --- a/cores/arduino/SerialUSB.h +++ b/cores/arduino/SerialUSB.h @@ -41,10 +41,6 @@ class SerialUSB_ : public ZephyrSerial { uint32_t baudrate; static void baudChangeHandler(const struct device *dev, uint32_t rate); - void _reinit_if_needed() override { - /* prevent reinit: USB device is always available */ - } - private: bool started = false; diff --git a/cores/arduino/zephyrCommon.cpp b/cores/arduino/zephyrCommon.cpp index bdb7dafc1..d13f31da0 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -6,20 +6,152 @@ #include #include "zephyrInternal.h" +#include #include -// create an array of arduino_pins with functions to reinitialize pins if needed -static const struct device *pinmux_array[DT_PROP_LEN(DT_PATH(zephyr_user), digital_pin_gpios)] = { - nullptr}; +#if defined(ARDUINO) +/* + * The global ARDUINO macro is numeric (e.g. 10607) in Arduino builds. + * Temporarily hide it so pinctrl token concatenation can use the literal + * custom state name "ARDUINO" from devicetree pinctrl-names. + * Otherwise, the generated pinctrl state identifiers would be like PINCTRL_STATE_10607 instead of + * PINCTRL_STATE_ARDUINO. + */ +#pragma push_macro("ARDUINO") +#undef ARDUINO +#endif + +/* + * Pinctrl configuration structures for dynamic pin switching. + * + * Map deferred-init peripherals with their pinctrl configuration from devicetree. + */ +#define PINCTRL_NODE_DEFERRED(node_id) DT_PROP(node_id, zephyr_deferred_init) + +#define PINCTRL_DECLARE_IF_DEFERRED(node_id) \ + COND_CODE_1(PINCTRL_NODE_DEFERRED(node_id), (PINCTRL_DT_DEV_CONFIG_DECLARE(node_id);), ()) + +DT_FOREACH_STATUS_OKAY_NODE(PINCTRL_DECLARE_IF_DEFERRED) + +#if DT_HAS_ALIAS(arduino_log_uart) +PINCTRL_DT_DEV_CONFIG_DECLARE(DT_ALIAS(arduino_log_uart)); +#endif + +struct pinctrl_map_entry { + const struct device *dev; + const struct pinctrl_dev_config *pcfg; +}; + +#define PINCTRL_MAP_ENTRY(node_id) {DEVICE_DT_GET(node_id), PINCTRL_DT_DEV_CONFIG_GET(node_id)}, +#define PINCTRL_MAP_ENTRY_IF_PRESENT(node_id) \ + COND_CODE_1(PINCTRL_NODE_DEFERRED(node_id), (PINCTRL_MAP_ENTRY(node_id)), ()) + +/* Add the pinctrl_dev_config for the log-uart nodes, that are not deferred init */ +#if DT_HAS_ALIAS(arduino_log_uart) +#define PINCTRL_MAP_LOG_UART_ENTRY PINCTRL_MAP_ENTRY(DT_ALIAS(arduino_log_uart)) +#else +#define PINCTRL_MAP_LOG_UART_ENTRY +#endif + +static const struct pinctrl_map_entry pinctrl_map[] = {DT_FOREACH_STATUS_OKAY_NODE( + PINCTRL_MAP_ENTRY_IF_PRESENT) PINCTRL_MAP_LOG_UART_ENTRY{nullptr, nullptr}}; + +#if defined(ARDUINO) +#pragma pop_macro("ARDUINO") +#endif + +/* Get pinctrl_dev_config for a device from the generated map. */ +static const struct pinctrl_dev_config *get_known_pcfg(const struct device *dev) { + for (size_t i = 0; i < ARRAY_SIZE(pinctrl_map); i++) { + if (pinctrl_map[i].dev == dev) { + return pinctrl_map[i].pcfg; + } + } + + return nullptr; +} + +/** + * @brief Initialize the peripheral and acquire a single pin to ARDUINO state. + * + * Switches peripheral pins back to ARDUINO pinctrl state (alternate function), + * typically after a temporary transition to GPIO mode. + * + * @param dev Pointer to the peripheral device + * @param state_pin_idx Index of the pin within the device's ARDUINO pinctrl state + * @return 0 on success, negative on error + */ +int init_dev_apply_channel_pinctrl(const struct device *dev, size_t state_pin_idx) { + + if (dev == nullptr) { + return -EINVAL; + } + + if (!device_is_ready(dev)) { + // init device for first usage, if not ready + int err = device_init(dev); + if (err < 0) { + return err; + } + } + + const struct pinctrl_state *state; + const struct pinctrl_dev_config *pcfg = get_known_pcfg(dev); -void _reinit_peripheral_if_needed(pin_size_t pin, const struct device *dev) { - if (pinmux_array[pin] != dev) { - pinmux_array[pin] = dev; - if (dev != NULL) { - dev->ops.init(dev); + if (pcfg == nullptr) { + /* Device not in DT mapping - add to pinctrl_map if needed */ + return -ENOTSUP; + } + + int err = pinctrl_lookup_state(pcfg, PINCTRL_STATE_ARDUINO, &state); + if (err < 0) { + return err; /* Fails if the state is not defined in pinctrl-names */ + } + + /* bounds check */ + if (state_pin_idx >= state->pin_cnt) { + return -ERANGE; + } + + /* + * On platforms without CONFIG_PINCTRL_STORE_REG (e.g. STM32) the pcfg->reg is not present but + * the argument is ignored by their pinctrl driver, so passing PINCTRL_REG_NONE is safe. + */ +#ifdef CONFIG_PINCTRL_STORE_REG + uintptr_t reg = pcfg->reg; +#else + uintptr_t reg = PINCTRL_REG_NONE; +#endif + + return pinctrl_configure_pins(&state->pins[state_pin_idx], 1, reg); +} + +/** + * @brief Optimize peripheral transitions applying pinctrl state PINCTRL_STATE_DEFAULT. + * + * @param dev Target peripheral device to acquire pin for + */ +int init_dev_apply_pinctrl(const struct device *dev) { + + if (dev == nullptr) { + return -EINVAL; + } + + if (!device_is_ready(dev)) { + int ret = device_init(dev); + if (ret != 0 && ret != -EALREADY) { + return ret; } } + + const struct pinctrl_dev_config *pcfg = get_known_pcfg(dev); + if (pcfg == nullptr) { + /* Device not in DT mapping - add to pinctrl_map if needed */ + return -ENOTSUP; + } + + return pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); } static const struct gpio_dt_spec arduino_pins[] = { @@ -143,6 +275,24 @@ void handleGpioCallback(const struct device *port, struct gpio_callback *cb, uin } } +/* + * Resolve pin index in a device ARDUINO pinctrl state from a DT spec array. + * The resulting index is the per-device ordinal at spec_idx. + */ +template +static size_t state_pin_index_from_spec_index(const DT_SPEC (&specs)[N], size_t spec_idx) { + const struct device *dev = specs[spec_idx].dev; + size_t state_pin_idx = 0; + + for (size_t i = 0; i < spec_idx; i++) { + if (specs[i].dev == dev) { + state_pin_idx++; + } + } + + return state_pin_idx; +} + #ifdef CONFIG_PWM #define PWM_DT_SPEC(n, p, i) PWM_DT_SPEC_GET_BY_IDX(n, i), @@ -216,7 +366,6 @@ static const struct device *const dac_dev = DEVICE_DT_GET(DAC_NODE); static const struct dac_channel_cfg dac_ch_cfg[] = { DT_FOREACH_PROP_ELEM(DT_PATH(zephyr_user), dac_channels, DAC_CHANNEL_DEFINE)}; -static bool dac_channel_initialized[NUM_OF_DACS]; #endif #endif @@ -251,7 +400,6 @@ int digitalPinToPinIndex(pin_size_t pinNumber) { void pinMode(pin_size_t pinNumber, PinMode pinMode) { RETURN_ON_INVALID_PIN(pinNumber); - _reinit_peripheral_if_needed(pinNumber, NULL); if (pinMode == INPUT) { // input mode gpio_pin_configure_dt(&arduino_pins[pinNumber], GPIO_INPUT | GPIO_ACTIVE_HIGH); } else if (pinMode == INPUT_PULLUP) { // input with internal pull-up @@ -486,13 +634,15 @@ void analogWrite(pin_size_t pinNumber, int value) { return; } + (void)init_dev_apply_channel_pinctrl(arduino_pwm[idx].dev, + state_pin_index_from_spec_index(arduino_pwm, idx)); + if (!pwm_is_ready_dt(&arduino_pwm[idx])) { pinMode(pinNumber, OUTPUT); digitalWrite(pinNumber, value > 127 ? HIGH : LOW); return; } - _reinit_peripheral_if_needed(pinNumber, arduino_pwm[idx].dev); value = CLAMP(value, 0, maxInput); const uint32_t pulse = map64(value, 0, maxInput, 0, arduino_pwm[idx].period); @@ -516,19 +666,13 @@ void analogWrite(enum dacPins dacName, int value) { return; } - if (!dac_channel_initialized[dacName]) { - if (!device_is_ready(dac_dev)) { - return; - } + // TODO: add reverse map to find pin name from DAC* define + // In the meantime, consider A0 == DAC0 + (void)init_dev_apply_pinctrl(dac_dev); - // TODO: add reverse map to find pin name from DAC* define - // In the meantime, consider A0 == DAC0 - _reinit_peripheral_if_needed((pin_size_t)(dacName + A0), dac_dev); - ret = dac_channel_setup(dac_dev, &dac_ch_cfg[dacName]); - if (ret != 0) { - return; - } - dac_channel_initialized[dacName] = true; + ret = dac_channel_setup(dac_dev, &dac_ch_cfg[dacName]); + if (ret != 0) { + return; } value = CLAMP(value, 0, maxInput); @@ -586,7 +730,13 @@ int analogRead(pin_size_t pinNumber) { return -ENOTSUP; } - _reinit_peripheral_if_needed(pinNumber, arduino_adc[idx].dev); + /* + * Init the ADC device for the first acquisition and restore only the required pin to analog mode when + * transitioning from GPIO. The pin is selected from the ADC device "arduino" pinctrl state. Not + * checking the return value because the device might not have pinctrl (e.g. nRF SAADC). + */ + (void)init_dev_apply_channel_pinctrl(arduino_adc[idx].dev, + state_pin_index_from_spec_index(arduino_adc, idx)); err = adc_channel_setup(arduino_adc[idx].dev, &arduino_adc[idx].channel_cfg); if (err < 0) { diff --git a/cores/arduino/zephyrInternal.h b/cores/arduino/zephyrInternal.h index e3938e603..9742d1268 100644 --- a/cores/arduino/zephyrInternal.h +++ b/cores/arduino/zephyrInternal.h @@ -14,7 +14,8 @@ extern "C" { void enableInterrupt(pin_size_t); void disableInterrupt(pin_size_t); -void _reinit_peripheral_if_needed(pin_size_t pin, const struct device *dev); + +int init_dev_apply_pinctrl(const struct device *dev); #ifdef __cplusplus } // extern "C" diff --git a/cores/arduino/zephyrSerial.cpp b/cores/arduino/zephyrSerial.cpp index 78d8f1fea..4f4711bc1 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -5,7 +5,10 @@ * SPDX-License-Identifier: Apache-2.0 */ + #include "zephyrInternal.h" + #include +#include #include #include @@ -60,7 +63,10 @@ void arduino::ZephyrSerial::begin(unsigned long baud, uint16_t conf) { .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, }; - _reinit_if_needed(); + /* Re-apply DEFAULT pinctrl state so shared pins + * are remuxed back to Serial after other peripherals have used them. + */ + (void)init_dev_apply_pinctrl(uart); uart_configure(uart, &config); uart_irq_callback_user_data_set(uart, arduino::ZephyrSerial::IrqDispatch, this); diff --git a/cores/arduino/zephyrSerial.h b/cores/arduino/zephyrSerial.h index b0bb3de6d..67f0768d7 100644 --- a/cores/arduino/zephyrSerial.h +++ b/cores/arduino/zephyrSerial.h @@ -77,9 +77,7 @@ class ZephyrSerial : public HardwareSerial { void end() { #ifdef CONFIG_DEVICE_DEINIT_SUPPORT - if (uart->ops.deinit) { - uart->ops.deinit(uart); - } + (void)device_deinit(uart); #endif } @@ -108,10 +106,6 @@ class ZephyrSerial : public HardwareSerial { const struct device *uart; ZephyrSerialBuffer tx; ZephyrSerialBuffer rx; - - virtual void _reinit_if_needed() { - uart->ops.init(uart); - } }; } // namespace arduino diff --git a/documentation/dynamic_pinmux.md b/documentation/dynamic_pinmux.md new file mode 100644 index 000000000..6a2a7c5d0 --- /dev/null +++ b/documentation/dynamic_pinmux.md @@ -0,0 +1,202 @@ +# Dynamic Pinmux Design - ArduinoCore-zephyr + +## What Is Pinmux / Dynamic Pin Control? + +On MCUs, each physical pad can usually serve multiple alternate functions (GPIO, UART, SPI, PWM, ADC, etc.). +Pinmux (pin multiplexing) is the mechanism that selects which peripheral currently owns that pad. + +Dynamic pin control means we can switch pad ownership at runtime, so the same physical pin can be reused by different peripherals at different times. + +Why this matters in Arduino-like APIs: + +- Users expect to call, for example, `analogRead(A0)` and later `digitalWrite(A0, HIGH)` on the same pin. +- Users expect to call `analogWrite(Dx, value)` on one PWM pin without disturbing other PWM-capable pins on the same timer block. +- The core must safely remap pins without requiring users to manually manage pinctrl states. + +This is especially important for channel-based peripherals such as ADC and PWM, where one hardware block owns multiple channels/pads but user APIs usually target one pin at a time. + +The solution is: + +- defer peripheral init/pinctrl ownership until runtime, +- keep a custom pinctrl state (`"arduino"`) containing peripheral pads, +- when one channel is requested, configure only that pin from the custom state. + +## Zephyr States Used by the Core + +```text +PINCTRL_STATE_DEFAULT = 0 +PINCTRL_STATE_SLEEP = 1 +PINCTRL_STATE_PRIV_START = 2 +``` + +Custom state name arduino is defined in devicetree and mapped to PINCTRL_STATE_ARDUINO. + +Typical mapping: + +- default: peripheral operational state (SPI/I2C/UART normal routing) +- sleep: optional low-power/disconnected state (not used) +- arduino: custom channel list used for per-pin restore (mainly ADC/PWM/DAC) + +## Runtime Infrastructure in zephyrCommon.cpp + +The core builds a runtime map between devices and pinctrl configs. + +Selection rule for nodes included in the map is node is zephyr,deferred-init. +Because the Zephyr logging UART is intentionally not marked with zephyr,deferred-init for easier debugging, it is added to the pinctrl map via a dedicated mapping entry. + +The map is then used by APIs: + +- init_dev_apply_pinctrl(dev) +- init_dev_apply_channel_pinctrl(dev, state_pin_idx) + +If a device has no known pinctrl config in the map, APIs return -ENOTSUP. + +## Dynamic Pinmux APIs and Runtime Flow + +### init_dev_apply_pinctrl(dev) + +Purpose: apply the whole pinctrl PINCTRL_STATE_DEFAULT state to a device. + +Used for full peripheral remux, to restore the default state. + +SPI (SPI.begin), I2C (Wire.begin) and UART (ZephyrSerial::begin) calls init_dev_apply_pinctrl(dev), without taking care of device readiness/init. + +Behavior details: + +- initializes the device on first use if needed, +- applies PINCTRL_STATE_DEFAULT from the device pinctrl config. + +### init_dev_apply_channel_pinctrl(dev, state_pin_idx) + +Purpose: apply only one pin from the device arduino state. + +Used for channel-based peripherals by analogRead and analogWrite (ADC/PWM/DAC) so one channel can be remuxed without touching sibling channels. + +Behavior details: + +- initializes the device on first use if needed, +- resolves PINCTRL_STATE_ARDUINO, +- applies only one pin entry (state_pin_idx), with bounds checking. + +Implementation pattern: + +- resolve analog/pwm index from pin, +- compute a per-device ordinal index with state_pin_index_from_spec_index(arduino_adc/arduino_pwm, idx), +- call init_dev_apply_channel_pinctrl(dev, per_dev_idx), + +How state_pin_index_from_spec_index works: + +- spec_idx is the global position in the zephyr,user array (io-channels for ADC or pwms for PWM). For example, A1/D1 maps to spec_idx = 1 (second entry); +- state_pin_index_from_spec_index(...) scans previous entries [0..spec_idx-1] and counts only those that reference the same device (i.e. the same PWM/ADC controller instance, such as pwm4); +- the resulting count is the per-device ordinal (0, 1, 2, ...) used as state_pin_idx in the device arduino pinctrl state. + +Example (GIGA PWM list in zephyr,user): + +```dts +pwms = <&pwm1 3 PWM_HZ(12000000) PWM_POLARITY_NORMAL>, + <&pwm2 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm2 3 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm8 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm3 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm4 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm3 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm4 3 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm4 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm1 1 PWM_HZ(5000) PWM_POLARITY_NORMAL>, + <&pwm8 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm1 2 PWM_HZ(5000) PWM_POLARITY_NORMAL>, + <&pwm12 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm1 1 PWM_HZ(5000) PWM_POLARITY_NORMAL>; +``` + +If analogWrite() resolves to spec_idx = 8 (9th entry, `&pwm4 4`): + +- device = pwm4 +- previous pwm4 entries are at spec_idx 5 and 7 +- count of previous same-device entries = 2 +- state_pin_idx = 2 (zero-based) + +Then init_dev_apply_channel_pinctrl(pwm4, 2) selects the 3rd entry of pwm4 `pinctrl-2`. + +```dts +pwm4: pwm { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pd13 &analog_pb8 &analog_pb9>; + pinctrl-2 = <&tim4_ch2_pd13 &tim4_ch3_pb8 &tim4_ch4_pb9>; + pinctrl-names = "default", "sleep", "arduino"; +}; +``` + +In this example, the selected pin is `tim4_ch4_pb9`. + +Effect: + +- only the requested ADC pad or PWM pad is remuxed to analog function. + +## Devicetree Requirements + +### For SPI/I2C/UART nodes + +Use deferred init and provide usual default/sleep states. + +```dts +&spiX { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <...>; /* default */ + pinctrl-1 = <...>; /* sleep or empty */ + pinctrl-names = "default", "sleep"; +}; +``` + +Same pattern applies to i2cX and uartX. + +Recommendation: keep the UART selected as `zephyr,log-uart` out of deferred-init. +If it is marked as deferred-init, early error logs generated during system startup or sketch load may not be visible. + +### For channel-based ADC/PWM/DAC nodes + +Use deferred init and keep channel pads in pinctrl-2 and name it arduino. + +```dts +&periphN { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <...>; /* ordered channel pads */ + pinctrl-names = "default", "sleep", "arduino"; +}; +``` + +## Ordering Contract + +For each ADC/PWM device, ordering must match between: + +- zephyr,user spec arrays (io-channels or pwms), and +- that device arduino pin list (pinctrl-2). + +state_pin_index_from_spec_index() assumes this ordinal alignment to map a logical channel entry to the correct pin in the arduino state. + +## Known limitation - Nordic nRF + +On Nordic nRF targets, switching a pin from PWM back to another peripheral may leave PWM still affecting that pin unless PWM is explicitly stopped first. + +The reason is architectural: in the nRF pinctrl/driver model, pin routing is programmed per peripheral by writing that peripheral’s PSEL registers. Reconfiguring the new peripheral (i.e. SPI) updates SPI’s PSEL, but it does not automatically clear PWM’s PSEL ownership for the same physical pin. +In our current core flow, we do not keep global runtime ownership tracking across peripherals for each pin, so we cannot reliably force-release the previous owner in all cases. + +This limitation is relevant only when the same pin was previously configured/driven by PWM and is now being reassigned to another peripheral. + +Workaround: +Before re-enabling a different peripheral function on a PWM shared pin, explicitly stop PWM on that pin first: + +``` +// Example sequence: PWM -> SPI on the same pin +analogWrite(Dx, value); +... +analogWrite(Dx, 0); +SPI.begin(); +... +``` diff --git a/libraries/Camera/src/camera.cpp b/libraries/Camera/src/camera.cpp index 078fd8093..5959ac568 100644 --- a/libraries/Camera/src/camera.cpp +++ b/libraries/Camera/src/camera.cpp @@ -55,10 +55,12 @@ bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byt this->vdev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); #endif - if (!this->vdev || !device_is_ready(this->vdev)) { + if (!this->vdev) { return false; } + (void)init_dev_apply_pinctrl(this->vdev); + switch (pixformat) { case CAMERA_RGB565: this->byte_swap = byte_swap; diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp index cbcaa1b22..a1254e83c 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -6,6 +6,7 @@ #include "SPI.h" #include "zephyrInternal.h" +#include #include arduino::ZephyrSPI::ZephyrSPI(const struct device *spi) : spi_dev(spi) { @@ -115,14 +116,16 @@ void arduino::ZephyrSPI::detachInterrupt() { } void arduino::ZephyrSPI::begin() { - spi_dev->ops.init(spi_dev); + + /* Re-apply DEFAULT pinctrl state so shared pins + * are remuxed back to SPI after other peripherals have used them. + */ + (void)init_dev_apply_pinctrl(spi_dev); } void arduino::ZephyrSPI::end() { #ifdef CONFIG_DEVICE_DEINIT_SUPPORT - if (spi_dev->ops.deinit) { - spi_dev->ops.deinit(spi_dev); - } + (void)device_deinit(spi_dev); #endif } diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp index ecb60a784..dfbe35845 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -5,7 +5,9 @@ */ #include +#include "zephyrInternal.h" #include +#include #include // Helper function to get ZephyrI2C instance from config pointer. @@ -57,10 +59,15 @@ arduino::ZephyrI2C::ZephyrI2C(const struct device *i2c) : i2c_cfg({0}), i2c_dev( } void arduino::ZephyrI2C::begin() { - i2c_dev->ops.init(i2c_dev); + + /* Re-apply DEFAULT pinctrl state so shared pins + * are remuxed back to I2C after other peripherals have used them. + */ + (void)init_dev_apply_pinctrl(i2c_dev); } void arduino::ZephyrI2C::begin(uint8_t slaveAddr) { + begin(); i2c_cfg.address = slaveAddr; i2c_cfg.callbacks = &target_callbacks; @@ -75,9 +82,7 @@ void arduino::ZephyrI2C::end() { memset(&i2c_cfg, 0, sizeof(i2c_cfg)); } #ifdef CONFIG_DEVICE_DEINIT_SUPPORT - if (i2c_dev->ops.deinit) { - i2c_dev->ops.deinit(i2c_dev); - } + (void)device_deinit(i2c_dev); #endif } diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 428885a70..aa670dfa4 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -14,6 +14,10 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(app LANGUAGES C CXX) +# Define custom pinctrl state "arduino" for dynamic pin multiplexing +# Must be set before Zephyr drivers are compiled +zephyr_compile_options(-DPINCTRL_STATE_ARDUINO=PINCTRL_STATE_PRIV_START) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/blobs) # Memory region relocation based on Kconfig diff --git a/loader/Kconfig b/loader/Kconfig index c7d6c4069..216d0d959 100644 --- a/loader/Kconfig +++ b/loader/Kconfig @@ -4,6 +4,9 @@ # SPDX-License-Identifier: Apache-2.0 # +config PINCTRL + select PINCTRL_NON_STATIC + source "Kconfig.zephyr" config LLEXT_HEAP_REGION diff --git a/loader/llext_exports.c b/loader/llext_exports.c index 10e9e3cc9..49d392cfc 100644 --- a/loader/llext_exports.c +++ b/loader/llext_exports.c @@ -14,6 +14,7 @@ #include #include #include +#include #define FORCE_EXPORT_SYM(name) \ extern void name(void); \ @@ -122,6 +123,29 @@ EXPORT_SYMBOL(k_msgq_get); EXPORT_SYMBOL(k_msgq_num_used_get); EXPORT_SYMBOL(k_sys_work_q); +#if defined(CONFIG_PINCTRL) +EXPORT_SYMBOL(pinctrl_lookup_state); +EXPORT_SYMBOL(pinctrl_configure_pins); + +/* + * Export the pinctrl_dev_config objects for all deferred-init peripherals. + */ +#define Z_EXPORT_PINCTRL_IF_DEFERRED(node_id) \ + COND_CODE_1(DT_PROP(node_id, zephyr_deferred_init), \ + (PINCTRL_DT_DEV_CONFIG_DECLARE(node_id); \ + EXPORT_SYMBOL(Z_PINCTRL_DEV_CONFIG_NAME(node_id));), \ + ()) + +DT_FOREACH_STATUS_OKAY_NODE(Z_EXPORT_PINCTRL_IF_DEFERRED) + +/* Export the pinctrl_dev_config for the log-uart node that is not deferred init */ +#if DT_HAS_ALIAS(arduino_log_uart) +PINCTRL_DT_DEV_CONFIG_DECLARE(DT_ALIAS(arduino_log_uart)); +EXPORT_SYMBOL(Z_PINCTRL_DEV_CONFIG_NAME(DT_ALIAS(arduino_log_uart))); +#endif + +#endif + #if defined(CONFIG_USB_DEVICE_STACK) EXPORT_SYMBOL(usb_enable); EXPORT_SYMBOL(usb_disable); diff --git a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay index 6c1f5c84b..ca1cac6dd 100644 --- a/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay +++ b/variants/arduino_giga_r1_stm32h747xx_m7/arduino_giga_r1_stm32h747xx_m7.overlay @@ -13,24 +13,36 @@ &usart1 { status = "okay"; + /* usart1 is not set as deferred-init to catch early boot logs since it is assigned to zephyr,console */ + pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pb7>; + pinctrl-1 = <&analog_pa9 &analog_pb7>; + pinctrl-names = "default", "sleep"; }; &usart2 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; - pinctrl-names = "default"; + pinctrl-1 = <&analog_pd5 &analog_pd6>; + pinctrl-names = "default", "sleep"; current-speed = <115200>; }; &uart4 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&uart4_tx_ph13 &uart4_rx_pi9>; - pinctrl-names = "default"; + pinctrl-1 = <&analog_ph13 &analog_pi9>; + pinctrl-names = "default", "sleep"; current-speed = <115200>; }; &usart6 { status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <&usart6_tx_pg14 &usart6_rx_pc7>; + pinctrl-1 = <&analog_pg14 &analog_pc7>; + pinctrl-names = "default", "sleep"; }; &rtc { @@ -42,6 +54,7 @@ &i2c4 { status = "okay"; + zephyr,deferred-init; gc2145: gc2145@3c { compatible = "galaxycore,gc2145"; reg = <0x3c>; @@ -58,15 +71,19 @@ &i2c1 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&i2c1_scl_pb8 &i2c1_sda_pb9>; - pinctrl-names = "default"; + pinctrl-1 = <&analog_pb8 &analog_pb9>; + pinctrl-names = "default", "sleep"; clock-frequency = ; }; &i2c2 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&i2c2_scl_ph4 &i2c2_sda_pb11>; - pinctrl-names = "default"; + pinctrl-1 = <&analog_ph4 &analog_pb11>; + pinctrl-names = "default", "sleep"; clock-frequency = ; }; @@ -76,10 +93,11 @@ pwm1: pwm { status = "okay"; - /* Temporarily removed SPI1 pins */ - /* pinctrl-0 = <&tim1_ch3_pj9 &tim1_ch1_pk1 &tim1_ch2_pj11>; */ - pinctrl-0 = <&tim1_ch3_pj9 &tim1_ch1_pk1>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pj9 &analog_pk1 &analog_pj11>; + pinctrl-2 = <&tim1_ch3_pj9 &tim1_ch1_pk1 &tim1_ch2_pj11>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -89,8 +107,11 @@ pwm2: pwm { status = "okay"; - pinctrl-0 = <&tim2_ch4_pa3 &tim2_ch3_pa2>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pa3 &analog_pa2>; + pinctrl-2 = <&tim2_ch4_pa3 &tim2_ch3_pa2>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -100,8 +121,11 @@ pwm3: pwm { status = "okay"; - pinctrl-0 = <&tim3_ch2_pa7 &tim3_ch1_pb4>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pa7 &analog_pb4>; + pinctrl-2 = <&tim3_ch2_pa7 &tim3_ch1_pb4>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -111,8 +135,11 @@ pwm4: pwm { status = "okay"; - pinctrl-0 = <&tim4_ch2_pd13 &tim4_ch3_pb8 &tim4_ch4_pb9>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pd13 &analog_pb8 &analog_pb9>; + pinctrl-2 = <&tim4_ch2_pd13 &tim4_ch3_pb8 &tim4_ch4_pb9>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -122,23 +149,27 @@ pwm8: pwm { status = "okay"; - /* Temporarily removed SPI1 pins */ - /* pinctrl-0 = <&tim8_ch1_pj8 &tim8_ch2_pj10>; */ - pinctrl-0 = <&tim8_ch1_pj8>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pj8 &analog_pj10>; + pinctrl-2 = <&tim8_ch1_pj8 &tim8_ch2_pj10>; + pinctrl-names = "default", "sleep", "arduino"; }; }; -/* Temporarily removed SPI1 pins */ -/* &timers12 { */ -/* status = "okay"; */ -/* st,prescaler = <100>; */ -/* pwm12: pwm { */ -/* status = "okay"; */ -/* pinctrl-0 = <&tim12_ch1_ph6>; */ -/* pinctrl-names = "default"; */ -/* }; */ -/*}; */ +&timers12 { + status = "okay"; + st,prescaler = <100>; + + pwm12: pwm { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_ph6>; + pinctrl-2 = <&tim12_ch1_ph6>; + pinctrl-names = "default", "sleep", "arduino"; + }; +}; &pwm1 { /* Use the pwmclock node to start the clock generation */ @@ -189,20 +220,27 @@ &spi1 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&spi1_sck_pb3 &spi1_miso_pg9 &spi1_mosi_pd7>; - pinctrl-names = "default"; + pinctrl-1 = <&analog_pb3 &analog_pg9 &analog_pd7>; + pinctrl-names = "default", "sleep"; }; &spi5 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&spi5_sck_ph6 &spi5_miso_pj11 &spi5_mosi_pj10>; - pinctrl-names = "default"; + pinctrl-1 = <&analog_ph6 &analog_pj11 &analog_pj10>; + pinctrl-names = "default", "sleep"; }; &adc1 { - pinctrl-0 = <&adc1_inp4_pc4 + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <&adc1_inp4_pc4 &adc1_inp8_pc5 &adc1_inp9_pb0 &adc1_inp5_pb1 @@ -210,11 +248,11 @@ &adc1_inp12_pc2 &adc1_inp10_pc0 &adc1_inp16_pa0 - &adc1_inp18_pa4 - &adc1_inp19_pa5 + &adc1_inp1_pa1_c &adc1_inp0_pa0_c - &adc1_inp1_pa1_c>; - pinctrl-names = "default"; + &adc1_inp18_pa4 + &adc1_inp19_pa5>; + pinctrl-names = "default", "sleep", "arduino"; st,adc-clock-source = "SYNC"; st,adc-prescaler = <4>; status = "okay"; @@ -310,9 +348,12 @@ }; &adc3 { - pinctrl-0 = <&adc3_inp0_pc2_c + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <&adc3_inp0_pc2_c &adc3_inp1_pc3_c>; - pinctrl-names = "default"; + pinctrl-names = "default", "sleep", "arduino"; st,adc-clock-source = "SYNC"; st,adc-prescaler = <4>; status = "okay"; @@ -336,7 +377,19 @@ }; }; +&dac1 { + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pa4 &analog_pa5>; + pinctrl-2 = <&dac1_out1_pa4 &dac1_out2_pa5>; + pinctrl-names = "default", "sleep", "arduino"; +}; + /{ + aliases { + arduino-log-uart = &usart1; + }; + chosen { zephyr,camera = &dcmi; zephyr,log-uart = &log_uarts; @@ -536,12 +589,12 @@ <&pwm3 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, <&pwm4 3 PWM_HZ(500) PWM_POLARITY_NORMAL>, <&pwm4 4 PWM_HZ(500) PWM_POLARITY_NORMAL>, - /* Temporarily removed SPI1 pins */ - /* <&pwm1 1 PWM_HZ(5000) PWM_POLARITY_NORMAL>, */ - /* <&pwm8 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, */ - /* <&pwm1 2 PWM_HZ(5000) PWM_POLARITY_NORMAL>, */ - /* <&pwm12 1 PWM_HZ(500) PWM_POLARITY_NORMAL>; */ - <&pwm1 1 PWM_HZ(5000) PWM_POLARITY_NORMAL>; + /* D10-D13 in arduino_header order */ + <&pwm1 1 PWM_HZ(5000) PWM_POLARITY_NORMAL>, + <&pwm8 2 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm1 2 PWM_HZ(5000) PWM_POLARITY_NORMAL>, + <&pwm12 1 PWM_HZ(500) PWM_POLARITY_NORMAL>, + <&pwm1 1 PWM_HZ(5000) PWM_POLARITY_NORMAL>; io-channels = <&adc1 4>, <&adc1 8>, diff --git a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay index aa12af82a..7ec566265 100644 --- a/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay +++ b/variants/arduino_nano_33_ble_nrf52840_sense/arduino_nano_33_ble_nrf52840_sense.overlay @@ -49,6 +49,10 @@ }; /{ + aliases { + arduino-log-uart = &uart0; + }; + chosen { zephyr,log-uart = &log_uarts; }; @@ -144,7 +148,7 @@ &adc { #address-cells = <1>; #size-cells = <0>; - + channel@0 { reg = <0>; zephyr,gain = "ADC_GAIN_1_6"; @@ -219,6 +223,12 @@ }; &pinctrl { + empty_default: empty_default { + group1 { + psels = <>; + }; + }; + pwm1_default: pwm1_default { group1 { psels = , /* keep original config */ @@ -262,30 +272,36 @@ &pwm1 { status = "okay"; - pinctrl-0 = <&pwm1_default>; + zephyr,deferred-init; + pinctrl-0 = <&empty_default>; pinctrl-1 = <&pwm1_sleep>; - pinctrl-names = "default", "sleep"; + pinctrl-2 = <&pwm1_default>; + pinctrl-names = "default", "sleep", "arduino"; }; &pwm2 { status = "okay"; - pinctrl-0 = <&pwm2_default>; + zephyr,deferred-init; + pinctrl-0 = <&empty_default>; pinctrl-1 = <&pwm2_sleep>; - pinctrl-names = "default", "sleep"; + pinctrl-2 = <&pwm2_default>; + pinctrl-names = "default", "sleep", "arduino"; }; &i2c0 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&i2c0_default>; - pinctrl-1 = <&i2c0_sleep>; + pinctrl-1 = <&empty_default>; pinctrl-names = "default", "sleep"; clock-frequency = ; }; &i2c1 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&i2c1_default>; - pinctrl-1 = <&i2c1_sleep>; + pinctrl-1 = <&empty_default>; pinctrl-names = "default", "sleep"; clock-frequency = ; }; @@ -295,3 +311,7 @@ clock-frequency = <32768>; prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs }; +&spi2 { + zephyr,deferred-init; +}; + diff --git a/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay b/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay index b73d69cc9..5cef3b520 100644 --- a/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay +++ b/variants/arduino_opta_stm32h747xx_m7/arduino_opta_stm32h747xx_m7.overlay @@ -49,6 +49,10 @@ }; /{ + aliases { + arduino-log-uart = &usart6; + }; + chosen { zephyr,console = &usart6; zephyr,shell-uart = &usart6; diff --git a/variants/arduino_portenta_c33_r7fa6m5bh3cfc/arduino_portenta_c33_r7fa6m5bh3cfc.overlay b/variants/arduino_portenta_c33_r7fa6m5bh3cfc/arduino_portenta_c33_r7fa6m5bh3cfc.overlay index a6fb6898b..f90d52f7e 100644 --- a/variants/arduino_portenta_c33_r7fa6m5bh3cfc/arduino_portenta_c33_r7fa6m5bh3cfc.overlay +++ b/variants/arduino_portenta_c33_r7fa6m5bh3cfc/arduino_portenta_c33_r7fa6m5bh3cfc.overlay @@ -77,7 +77,63 @@ }; }; +&spi1 { + zephyr,deferred-init; +}; + +&sci3 { + status = "okay"; + i2c3: i2c { + status = "okay"; + }; +}; + +&iic1 { + zephyr,deferred-init; +}; + &pinctrl { + empty_default: empty_default { + group1 { + psels = <>; + }; + }; + + adc0_arduino: adc0_arduino { + group1 { + psels = ; /* A0 - AN006 */ + renesas,analog-enable; + }; + group2 { + psels = ; /* A1 - AN005 */ + renesas,analog-enable; + }; + group3 { + psels = ; /* A2 - AN004 */ + renesas,analog-enable; + }; + group4 { + psels = ; /* A3 - AN002 */ + renesas,analog-enable; + }; + group5 { + psels = ; /* A4 - AN001 */ + renesas,analog-enable; + }; + group6 { + psels = ; /* A5 - AN013/P015 */ + renesas,analog-enable; + }; + group7 { + psels = ; /* A6 - AN012/P014 */ + renesas,analog-enable; + }; + group8 { + psels = ; /* A7 - AN000 */ + renesas,analog-enable; + }; + }; + iic0_default: iic0_default { group1 { /* SCL0 SDA0 */ @@ -90,6 +146,7 @@ &iic0 { status = "okay"; + zephyr,deferred-init; #address-cells = <1>; #size-cells = <0>; interrupts = <87 1>, <88 1>, <89 1>, <90 1>; @@ -110,7 +167,56 @@ }; }; +&pwm1 { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <&empty_default>; + pinctrl-1 = <&empty_default>; + pinctrl-2 = <&pwm1_default>; + pinctrl-names = "default", "sleep", "arduino"; + interrupts = <71 1>, <72 1>; + interrupt-names = "gtioca", "overflow"; +}; + +&pwm3 { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <&empty_default>; + pinctrl-1 = <&empty_default>; + pinctrl-2 = <&pwm3_default>; + pinctrl-names = "default", "sleep", "arduino"; + interrupts = <65 1>, <66 1>; + interrupt-names = "gtioca", "overflow"; +}; + +&pwm7 { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <&empty_default>; + pinctrl-1 = <&empty_default>; + pinctrl-2 = <&pwm7_default>; + pinctrl-names = "default", "sleep", "arduino"; + interrupts = <67 1>, <68 1>; + interrupt-names = "gtioca", "overflow"; +}; + +&pwm8 { + status = "okay"; + zephyr,deferred-init; + pinctrl-0 = <&empty_default>; + pinctrl-1 = <&empty_default>; + pinctrl-2 = <&pwm8_default>; + pinctrl-names = "default", "sleep", "arduino"; + interrupts = <69 1>, <70 1>; + interrupt-names = "gtioca", "overflow"; +}; + &adc0 { + zephyr,deferred-init; + pinctrl-0 = <&empty_default>; + pinctrl-1 = <&empty_default>; + pinctrl-2 = <&adc0_arduino>; + pinctrl-names = "default", "sleep", "arduino"; status = "okay"; #address-cells = <1>; #size-cells = <0>; @@ -301,14 +407,22 @@ <&ioport4 0 GPIO_ACTIVE_LOW>, <&ioport8 0 GPIO_ACTIVE_LOW>; - pwm-pin-gpios = <&ioport6 0 0>; + pwm-pin-gpios = <&ioport1 5 0>, + <&ioport1 6 0>, + <&ioport1 11 0>, + <&ioport3 3 0>, + <&ioport6 1 0>; /* D6 - P601: shares GPT6B with D4; also eth_clock pin */ cdc-acm-serial = <&board_cdc_acm_uart>; /* 'Serial' object is managed by SerialUSB */ serials = <&uart9>, <&uart7>, <&uart6>, <&uart5>; /* 'Serial1' onwards */ i2cs = <&iic0>, <&iic1>, <&i2c3>; spis = <&spi1>; - pwms = <&pwm6 1 PWM_HZ(25000000) PWM_POLARITY_NORMAL>; cans = <&canfd0>; + pwms = <&pwm1 0 PWM_HZ(25000000) PWM_POLARITY_NORMAL>, + <&pwm8 1 PWM_HZ(25000000) PWM_POLARITY_NORMAL>, + <&pwm3 0 PWM_HZ(25000000) PWM_POLARITY_NORMAL>, + <&pwm7 1 PWM_HZ(25000000) PWM_POLARITY_NORMAL>, + <&pwm6 1 PWM_HZ(25000000) PWM_POLARITY_NORMAL>; /* D6 - same channel as D4 */ io-channels = <&adc0 6>, <&adc0 5>, diff --git a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay index 7cebfd507..581c4c224 100644 --- a/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay +++ b/variants/arduino_portenta_h7_stm32h747xx_m7/arduino_portenta_h7_stm32h747xx_m7.overlay @@ -10,14 +10,17 @@ &usart1 { status = "okay"; + zephyr,deferred-init; }; &uart4 { status = "okay"; + zephyr,deferred-init; }; &usart6 { status = "okay"; + /* usart6 is not set as deferred-init to catch early boot logs since it is assigned to zephyr,console */ }; &rtc { @@ -35,6 +38,7 @@ &i2c3 { status = "okay"; + zephyr,deferred-init; gc2145: gc2145@3c { compatible = "galaxycore,gc2145"; @@ -68,14 +72,17 @@ &i2c1 { status = "okay"; + zephyr,deferred-init; }; &i2c4 { status = "okay"; + zephyr,deferred-init; }; &spi2 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&spi2_sck_pi1 &spi2_miso_pc2 &spi2_mosi_pc3>; pinctrl-names = "default"; @@ -87,8 +94,11 @@ pwm1: pwm { status = "okay"; - pinctrl-0 = <&tim1_ch1_pa8 &tim1_ch2_pj11>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pa8 &analog_pj11>; + pinctrl-2 = <&tim1_ch1_pa8 &tim1_ch2_pj11>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -98,8 +108,11 @@ pwm3: pwm { status = "okay"; - pinctrl-0 = <&tim3_ch1_pc6 &tim3_ch2_pc7>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pc6 &analog_pc7>; + pinctrl-2 = <&tim3_ch1_pc6 &tim3_ch2_pc7>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -109,8 +122,11 @@ pwm8: pwm { status = "okay"; - pinctrl-0 = <&tim8_ch3n_ph15 &tim8_ch2_pj10 &tim8_ch2n_pj7>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_ph15 &analog_pj7>; + pinctrl-2 = <&tim8_ch3n_ph15 &tim8_ch2_pj10 &tim8_ch2n_pj7>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -120,8 +136,11 @@ pwm12: pwm { status = "okay"; - pinctrl-0 = <&tim12_ch1_ph6>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_ph6>; + pinctrl-2 = <&tim12_ch1_ph6>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -174,13 +193,21 @@ &adc1 { - pinctrl-0 = <&adc1_inp12_pc2 - &adc1_inp13_pc3 - &adc1_inp18_pa4 - &adc1_inp3_pa6 - &adc1_inp0_pa0_c - &adc1_inp1_pa1_c>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pc2 + &analog_pc3 + &analog_pa4 + &analog_pa6 + &analog_pa0_c + &analog_pa1_c>; + pinctrl-2 = <&adc1_inp12_pc2 + &adc1_inp13_pc3 + &adc1_inp18_pa4 + &adc1_inp3_pa6 + &adc1_inp0_pa0_c + &adc1_inp1_pa1_c>; + pinctrl-names = "default", "sleep", "arduino"; st,adc-clock-source = "SYNC"; st,adc-prescaler = <4>; status = "okay"; @@ -235,9 +262,13 @@ }; &adc3 { - pinctrl-0 = <&adc3_inp0_pc2_c + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pc2_c + &analog_pc3_c>; + pinctrl-2 = <&adc3_inp0_pc2_c &adc3_inp1_pc3_c>; - pinctrl-names = "default"; + pinctrl-names = "default", "sleep", "arduino"; st,adc-clock-source = "SYNC"; st,adc-prescaler = <4>; status = "okay"; @@ -262,6 +293,10 @@ }; / { + aliases { + arduino-log-uart = &usart6; + }; + chosen { zephyr,camera = &dcmi; zephyr,console = &usart6; diff --git a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay index 5ef0b7eef..c157d493a 100644 --- a/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay +++ b/variants/arduino_uno_q_stm32u585xx/arduino_uno_q_stm32u585xx.overlay @@ -6,6 +6,7 @@ #include &i2c4 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&i2c4_scl_pd12 &i2c4_sda_pd13>; pinctrl-1 = <&i2c4_scl_pf14 &i2c4_sda_pf15>; pinctrl-names = "default", "sleep"; /* TODO: sleep is jmisc mux */ @@ -30,8 +31,10 @@ &i2c3 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&i2c3_scl_pc0 &i2c3_sda_pc1>; - pinctrl-names = "default"; + pinctrl-1 = <&analog_pc0 &analog_pc1>; + pinctrl-names = "default", "sleep"; clock-frequency = ; }; @@ -106,9 +109,11 @@ pwm1: pwm { status = "okay"; /* tim1_etr_pa12 is not available for PWM */ - /* Currently only the pins marked with ~ on the pin headers are enabled */ - pinctrl-0 = <&tim1_ch4_pa11 &tim1_ch3n_pb15 &tim1_ch2n_pb14 &tim1_ch1n_pb13>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pa11 &analog_pb15 &analog_pb13 &analog_pb14>; + pinctrl-2 = <&tim1_ch4_pa11 &tim1_ch3n_pb15 &tim1_ch1n_pb13 &tim1_ch2n_pb14>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -120,8 +125,11 @@ pwm2: pwm { status = "okay"; - pinctrl-0 = <&tim2_ch2_pb3 &tim2_ch3_pb10 &tim2_ch4_pb11>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pb3 &analog_pb10 &analog_pb11>; + pinctrl-2 = <&tim2_ch2_pb3 &tim2_ch3_pb10 &tim2_ch4_pb11>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -131,9 +139,11 @@ pwm3: pwm { status = "okay"; - /* Currently only the pins marked with ~ on the pin headers are enabled */ - pinctrl-0 = <&tim3_ch3_pb0 &tim3_ch4_pb1 &tim3_ch1_pb4>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pb0 &analog_pb1 &analog_pb4>; + pinctrl-2 = <&tim3_ch3_pb0 &tim3_ch4_pb1 &tim3_ch1_pb4>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -143,10 +153,11 @@ pwm4: pwm { status = "okay"; - /* PB6 PB7 not usable for PWM until dynamic pin muxing works */ - /* Currently only the pins marked with ~ on the pin headers are enabled */ - pinctrl-0 = <&tim4_ch3_pb8 &tim4_ch4_pb9 /*&tim4_ch1_pb6 &tim4_ch2_pb7*/>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pb8 &analog_pb9 /*&analog_pb6 &analog_pb7*/>; + pinctrl-2 = <&tim4_ch3_pb8 &tim4_ch4_pb9 /*&tim4_ch1_pb6 &tim4_ch2_pb7*/>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -156,11 +167,23 @@ pwm5: pwm { status = "okay"; - pinctrl-0 = <&tim5_ch1_ph10 &tim5_ch2_ph11 &tim5_ch3_ph12>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_ph10 &analog_ph11 &analog_ph12>; + pinctrl-2 = <&tim5_ch1_ph10 &tim5_ch2_ph11 &tim5_ch3_ph12>; + pinctrl-names = "default", "sleep", "arduino"; }; }; +&adc1 { + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pa4 &analog_pa5 &analog_pa6 &analog_pa7 &analog_pc1 &analog_pc0>; + pinctrl-2 = <&adc1_in9_pa4 &adc1_in10_pa5 &adc1_in11_pa6 &adc1_in12_pa7 &adc1_in2_pc1 &adc1_in1_pc0>; + pinctrl-names = "default", "sleep", "arduino"; + status = "okay"; +}; + /* Currently only the pins marked with ~ on the pin headers are enabled */ &timers8 { status = "okay"; @@ -168,8 +191,11 @@ pwm8: pwm { status = "okay"; - pinctrl-0 = <&tim8_ch4n_pb2>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <&analog_pb2>; + pinctrl-2 = <&tim8_ch4n_pb2>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -195,10 +221,10 @@ }; &spi3 { + zephyr,deferred-init; device0: device@0 { compatible = "zephyr,spi-slave"; reg = <0>; - zephyr,deferred-init; }; }; @@ -216,6 +242,30 @@ <&rcc STM32_SRC_PLL1_Q FDCAN1_SEL(1)>; }; +&spi2 { + zephyr,deferred-init; +}; + +&i2c2 { + zephyr,deferred-init; +}; + +&usart1 { + /* usart1 is not set as deferred-init to catch early boot logs since it is assigned to zephyr,console */ + status = "okay"; +}; + +&lpuart1 { + status = "okay"; + zephyr,deferred-init; +}; + +/ { + aliases { + arduino-log-uart = &usart1; + }; +}; + / { zephyr,user { digital-pin-gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>, /* D0 - PB7 */