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..f0a8ca2a3 100644 --- a/cores/arduino/zephyrCommon.cpp +++ b/cores/arduino/zephyrCommon.cpp @@ -6,20 +6,145 @@ #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 and zephyr,console (that is not deferred) with their + * pinctrl configuration from devicetree. + */ +#define NODE_SELECTED(node_id) \ + UTIL_OR(DT_PROP(node_id, zephyr_deferred_init), \ + DT_SAME_NODE(node_id, DT_CHOSEN(zephyr_console))) + +#define PINCTRL_DEFINE_IF_SELECTED(node_id) \ + COND_CODE_1(NODE_SELECTED(node_id), (PINCTRL_DT_DEFINE(node_id);), ()) + +DT_FOREACH_STATUS_OKAY_NODE(PINCTRL_DEFINE_IF_SELECTED) + +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(NODE_SELECTED(node_id), (PINCTRL_MAP_ENTRY(node_id)), ()) + +static const struct pinctrl_map_entry pinctrl_map[] = { + DT_FOREACH_STATUS_OKAY_NODE(PINCTRL_MAP_ENTRY_IF_PRESENT){NULL, NULL}, +}; + +#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); + + 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; + } -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 (!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 +268,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 +359,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 +393,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 +627,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 +659,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 +723,14 @@ 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..979c8abd4 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..7d3804477 100644 --- a/cores/arduino/zephyrSerial.cpp +++ b/cores/arduino/zephyrSerial.cpp @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "zephyrInternal.h" + #include #include @@ -60,7 +62,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..545aa6ca5 --- /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 (ADC/PWM/DAC) in the analogRead and analogWrite functions, allowing a single 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/CAN/CAN.cpp b/libraries/CAN/CAN.cpp index 3ed94d6e2..4e523e041 100644 --- a/libraries/CAN/CAN.cpp +++ b/libraries/CAN/CAN.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "zephyrInternal.h" #include #include #include @@ -33,11 +34,10 @@ bool arduino::ZephyrCAN::beginFD(CanBitRate arbitration_bitrate, uint32_t data_b bool arduino::ZephyrCAN::_begin(CanBitRate arbitration_bitrate, CanMode mode, uint32_t data_bitrate, bool bitrate_switch) { - if (!device_is_ready(_dev)) { - return false; - } - - _dev->ops.init(_dev); + /* Init device and re-apply DEFAULT pinctrl state so shared pins + * are remuxed back to CAN after other peripherals have used them. + */ + (void)init_dev_apply_pinctrl(_dev); /* Bitrate can only be changed while the controller is stopped. */ (void)can_stop(_dev); 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..41dd39baf 100644 --- a/libraries/SPI/SPI.cpp +++ b/libraries/SPI/SPI.cpp @@ -115,14 +115,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..3940797f4 100644 --- a/libraries/Wire/Wire.cpp +++ b/libraries/Wire/Wire.cpp @@ -5,6 +5,7 @@ */ #include +#include "zephyrInternal.h" #include #include @@ -57,10 +58,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 +81,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..a77d4b350 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,11 @@ 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); +#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..40bbfc7ed 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 */ @@ -161,6 +192,7 @@ &fdcan2 { status = "okay"; + zephyr,deferred-init; clocks = <&rcc STM32_CLOCK(APB1_2, 8)>, <&rcc STM32_SRC_HSE FDCAN_SEL(0)>; }; @@ -189,20 +221,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 +249,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 +349,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,6 +378,14 @@ }; }; +&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"; +}; + /{ chosen { zephyr,camera = &dcmi; @@ -536,12 +586,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..08f2cadc4 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 @@ -144,7 +144,7 @@ &adc { #address-cells = <1>; #size-cells = <0>; - + channel@0 { reg = <0>; zephyr,gain = "ADC_GAIN_1_6"; @@ -219,6 +219,12 @@ }; &pinctrl { + empty_default: empty_default { + group1 { + psels = <>; + }; + }; + pwm1_default: pwm1_default { group1 { psels = , /* keep original config */ @@ -262,30 +268,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 +307,7 @@ clock-frequency = <32768>; prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs }; +&spi2 { + zephyr,deferred-init; +}; + diff --git a/variants/arduino_nicla_vision_stm32h747xx_m7/arduino_nicla_vision_stm32h747xx_m7.overlay b/variants/arduino_nicla_vision_stm32h747xx_m7/arduino_nicla_vision_stm32h747xx_m7.overlay index a840729fd..41954a198 100644 --- a/variants/arduino_nicla_vision_stm32h747xx_m7/arduino_nicla_vision_stm32h747xx_m7.overlay +++ b/variants/arduino_nicla_vision_stm32h747xx_m7/arduino_nicla_vision_stm32h747xx_m7.overlay @@ -12,26 +12,36 @@ }; }; +&lpuart1 { + status = "okay"; + /* lpuart1 is not set as deferred-init to catch early boot logs since it is assigned to zephyr,console */ +}; + /* I2C buses */ &i2c1 { status = "okay"; + zephyr,deferred-init; }; &i2c2 { status = "okay"; + zephyr,deferred-init; }; &i2c3 { status = "okay"; + zephyr,deferred-init; }; /* SPI buses */ &spi4 { status = "okay"; + zephyr,deferred-init; }; &spi5 { status = "okay"; + zephyr,deferred-init; }; &rtc { @@ -48,8 +58,11 @@ pwm1: pwm { status = "okay"; - pinctrl-0 = <&tim1_ch3_pj9 &tim1_ch1_pk1>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <&tim1_ch1_pk1 &tim1_ch3_pj9>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -61,8 +74,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 = <>; + pinctrl-2 = <&tim8_ch2_pj10 &tim8_ch3n_ph15>; + pinctrl-names = "default", "sleep", "arduino"; }; }; @@ -72,14 +88,20 @@ pwm12: pwm { status = "okay"; - pinctrl-0 = <&tim12_ch1_ph6>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <&tim12_ch1_ph6>; + pinctrl-names = "default", "sleep", "arduino"; }; }; &adc1 { - pinctrl-0 = <&adc1_inp4_pc4>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <&adc1_inp4_pc4>; + pinctrl-names = "default", "sleep", "arduino"; st,adc-clock-source = "SYNC"; st,adc-prescaler = <4>; status = "okay"; @@ -105,8 +127,11 @@ }; &adc2 { - pinctrl-0 = <&adc2_inp2_pf13>; - pinctrl-names = "default"; + zephyr,deferred-init; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <&adc2_inp2_pf13>; + pinctrl-names = "default", "sleep", "arduino"; st,adc-clock-source = "SYNC"; st,adc-prescaler = <4>; status = "okay"; @@ -125,8 +150,10 @@ &adc3 { zephyr,deferred-init; - pinctrl-0 = <&adc3_inp5_pf3>; - pinctrl-names = "default"; + pinctrl-0 = <>; + pinctrl-1 = <>; + pinctrl-2 = <&adc3_inp5_pf3>; + pinctrl-names = "default", "sleep", "arduino"; st,adc-clock-source = "SYNC"; st,adc-prescaler = <4>; status = "okay"; @@ -144,6 +171,7 @@ }; / { + chosen { zephyr,console = &lpuart1; zephyr,shell-uart = &lpuart1; @@ -212,29 +240,32 @@ }; zephyr,user { - digital-pin-gpios = <&gpiog 12 GPIO_ACTIVE_HIGH>, /* D0 PG_12 */ - <&gpioa 9 GPIO_ACTIVE_HIGH>, /* D1 PA_9 */ - <&gpioa 10 GPIO_ACTIVE_HIGH>, /* D2 PA_10 */ - <&gpiog 1 GPIO_ACTIVE_HIGH>, /* D3 PG_1 */ - <&gpioe 3 GPIO_ACTIVE_HIGH>, /* Red LED PE_3 */ - <&gpioc 13 GPIO_ACTIVE_HIGH>, /* Green LED PC_13 */ - <&gpiof 4 GPIO_ACTIVE_HIGH>, /* Blue LED PF_4 */ - <&gpiog 0 GPIO_ACTIVE_HIGH>, /* SE05X_EN */ - <&gpioc 4 GPIO_ACTIVE_HIGH>, /* PC4 A0 ADC1 ch4 */ - <&gpiof 13 GPIO_ACTIVE_HIGH>, /* PF13 A1 ADC2 ch2 */ - <&gpiof 3 GPIO_ACTIVE_HIGH>; /* PF3 A2 ADC3 ch5 */ + digital-pin-gpios = <&gpiog 12 GPIO_ACTIVE_HIGH>, /* D0 PG12 */ + <&gpioa 9 GPIO_ACTIVE_HIGH>, /* D1 PA9 */ + <&gpioa 10 GPIO_ACTIVE_HIGH>, /* D2 PA10 */ + <&gpiog 1 GPIO_ACTIVE_HIGH>, /* D3 PG1 */ + <&gpioe 3 GPIO_ACTIVE_HIGH>, /* D4 PE3 Red LED */ + <&gpioc 13 GPIO_ACTIVE_HIGH>, /* D5 PC13 Green LED */ + <&gpiof 4 GPIO_ACTIVE_HIGH>, /* D6 PF4 Blue LED */ + <&gpiog 0 GPIO_ACTIVE_HIGH>, /* D7 PG0 SE05X_EN */ + <&gpiok 1 GPIO_ACTIVE_HIGH>, /* D8 PK1 tim1 ch1 */ + <&gpioj 9 GPIO_ACTIVE_HIGH>, /* D9 PJ9 tim1 ch3 */ + <&gpioj 10 GPIO_ACTIVE_HIGH>, /* D10 PJ10 tim8 ch2 */ + <&gpioh 15 GPIO_ACTIVE_HIGH>, /* D11 PH15 tim8 ch3n */ + <&gpioh 6 GPIO_ACTIVE_HIGH>, /* D12 PH6 tim12 ch1 */ + <&gpioc 4 GPIO_ACTIVE_HIGH>, /* D13 PC4 A0 ADC1 ch4 */ + <&gpiof 13 GPIO_ACTIVE_HIGH>, /* D14 PF13 A1 ADC2 ch2 */ + <&gpiof 3 GPIO_ACTIVE_HIGH>; /* D15 PF3 A2 ADC3 ch5 */ adc-pin-gpios = <&gpioc 4 GPIO_ACTIVE_HIGH>, /* A0 PC4 */ <&gpiof 13 GPIO_ACTIVE_HIGH>, /* A1 PF13 */ <&gpiof 3 GPIO_ACTIVE_HIGH>; /* A2 PF3 */ - pwm-pin-gpios = <&gpioa 8 GPIO_ACTIVE_HIGH>, - <&gpioc 6 GPIO_ACTIVE_HIGH>, - <&gpioc 7 GPIO_ACTIVE_HIGH>, - <&gpioh 15 GPIO_ACTIVE_HIGH>, - <&gpioj 7 GPIO_ACTIVE_HIGH>, - <&gpioj 10 GPIO_ACTIVE_HIGH>, - <&gpioh 6 GPIO_ACTIVE_HIGH>; + pwm-pin-gpios = <&gpiok 1 GPIO_ACTIVE_HIGH>, /* D8 PK1 pwm1 ch1 */ + <&gpioj 9 GPIO_ACTIVE_HIGH>, /* D9 PJ9 pwm1 ch3 */ + <&gpioj 10 GPIO_ACTIVE_HIGH>, /* D10 PJ10 pwm8 ch2 */ + <&gpioh 15 GPIO_ACTIVE_HIGH>, /* D11 PH15 pwm8 ch3n */ + <&gpioh 6 GPIO_ACTIVE_HIGH>; /* D12 PH6 pwm12 ch1 */ serials = <&board_cdc_acm_uart>, <&usart1>, <&lpuart1>; cdc-acm-serial = <&board_cdc_acm_uart>; @@ -250,7 +281,7 @@ <&gpioe 3 GPIO_ACTIVE_HIGH>, /* Red LED PE_3 */ <&gpiof 4 GPIO_ACTIVE_HIGH>; /* Blue LED PF_4 */ - /* PWM channels: timers1(ch1,ch3), timers8(ch2,ch2n,ch3n), timers12(ch1) */ + /* PWM channels: timers1(ch1,ch3), timers8(ch2,ch3n), timers12(ch1) */ pwms = <&pwm1 1 PWM_HZ(1000) PWM_POLARITY_NORMAL>, <&pwm1 3 PWM_HZ(1000) PWM_POLARITY_NORMAL>, <&pwm8 2 PWM_HZ(1000) PWM_POLARITY_NORMAL>, 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..e0bd256e3 100644 --- a/variants/arduino_portenta_c33_r7fa6m5bh3cfc/arduino_portenta_c33_r7fa6m5bh3cfc.overlay +++ b/variants/arduino_portenta_c33_r7fa6m5bh3cfc/arduino_portenta_c33_r7fa6m5bh3cfc.overlay @@ -50,6 +50,9 @@ status = "okay"; uart7: uart { + zephyr,deferred-init; + pinctrl-0 = <&sci7_default>; + pinctrl-names = "default"; status = "okay"; current-speed = <115200>; }; @@ -61,6 +64,9 @@ pinctrl-names = "default"; uart6: uart { + zephyr,deferred-init; + pinctrl-0 = <&sci6_default>; + pinctrl-names = "default"; status = "okay"; current-speed = <115200>; }; @@ -72,12 +78,76 @@ pinctrl-names = "default"; uart5: uart { + zephyr,deferred-init; + pinctrl-0 = <&sci5_default>; + pinctrl-names = "default"; status = "okay"; current-speed = <115200>; }; }; +&uart9 { + status = "okay"; + /* usart9 is not set as deferred-init to catch early boot logs since it is assigned to zephyr,console */ +}; + +&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 +160,7 @@ &iic0 { status = "okay"; + zephyr,deferred-init; #address-cells = <1>; #size-cells = <0>; interrupts = <87 1>, <88 1>, <89 1>, <90 1>; @@ -110,7 +181,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 +421,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..c484ee066 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 { @@ -29,12 +32,14 @@ &fdcan1 { status = "okay"; + zephyr,deferred-init; clocks = <&rcc STM32_CLOCK(APB1_2, 8)>, <&rcc STM32_SRC_HSE FDCAN_SEL(0)>; }; &i2c3 { status = "okay"; + zephyr,deferred-init; gc2145: gc2145@3c { compatible = "galaxycore,gc2145"; @@ -68,14 +73,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 +95,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 +109,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 +123,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 +137,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 +194,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 +263,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"; 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..204193fc1 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; }; }; @@ -210,12 +236,31 @@ &fdcan1 { status = "okay"; + zephyr,deferred-init; pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; pinctrl-names = "default"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>, <&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; +}; + / { zephyr,user { digital-pin-gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>, /* D0 - PB7 */