2525/*
2626 * Pinctrl configuration structures for dynamic pin switching.
2727 *
28- * Map deferred-init peripherals with their pinctrl configuration from devicetree.
28+ * Map deferred-init peripherals and zephyr,console (that is not deferred) with their
29+ * pinctrl configuration from devicetree.
2930 */
30- #define PINCTRL_NODE_DEFERRED (node_id ) DT_PROP_OR(node_id, zephyr_deferred_init, 0 )
31+ #define NODE_SELECTED (node_id ) \
32+ UTIL_OR (DT_PROP(node_id, zephyr_deferred_init), \
33+ DT_SAME_NODE(node_id, DT_CHOSEN(zephyr_console)))
3134
32- #define PINCTRL_DEFINE_IF_PRESENT (node_id ) \
33- COND_CODE_1 (PINCTRL_NODE_DEFERRED (node_id), (PINCTRL_DT_DEFINE(node_id);), ())
35+ #define PINCTRL_DEFINE_IF_SELECTED (node_id ) \
36+ COND_CODE_1 (NODE_SELECTED (node_id), (PINCTRL_DT_DEFINE(node_id);), ())
3437
35- DT_FOREACH_STATUS_OKAY_NODE (PINCTRL_DEFINE_IF_PRESENT )
38+ DT_FOREACH_STATUS_OKAY_NODE (PINCTRL_DEFINE_IF_SELECTED )
3639
3740struct pinctrl_map_entry {
3841 const struct device *dev;
@@ -41,7 +44,7 @@ struct pinctrl_map_entry {
4144
4245#define PINCTRL_MAP_ENTRY (node_id ) {DEVICE_DT_GET (node_id), PINCTRL_DT_DEV_CONFIG_GET (node_id)},
4346#define PINCTRL_MAP_ENTRY_IF_PRESENT (node_id ) \
44- COND_CODE_1 (PINCTRL_NODE_DEFERRED (node_id), (PINCTRL_MAP_ENTRY(node_id)), ())
47+ COND_CODE_1 (NODE_SELECTED (node_id), (PINCTRL_MAP_ENTRY(node_id)), ())
4548
4649static const struct pinctrl_map_entry pinctrl_map[] = {
4750 DT_FOREACH_STATUS_OKAY_NODE (PINCTRL_MAP_ENTRY_IF_PRESENT){NULL , NULL },
@@ -59,89 +62,89 @@ static const struct pinctrl_dev_config *get_known_pcfg(const struct device *dev)
5962 }
6063 }
6164
62- return NULL ;
65+ return nullptr ;
6366}
6467
6568/* *
66- * @brief Acquire a single pin of a peripheral to ARDUINO state.
69+ * @brief Initialize the peripheral and acquire a single pin to ARDUINO state.
6770 *
6871 * Switches peripheral pins back to ARDUINO pinctrl state (alternate function),
6972 * typically after a temporary transition to GPIO mode.
7073 *
71- * @param idx Index of the pin within the device's ARDUINO pinctrl state
7274 * @param dev Pointer to the peripheral device
75+ * @param state_pin_idx Index of the pin within the device's ARDUINO pinctrl state
7376 * @return 0 on success, negative on error
7477 */
75- int apply_dev_channel_pinctrl (size_t state_pin_idx, const struct device *dev) {
76-
77- const pinctrl_soc_pin_t *soc_pin = NULL ;
78- const struct pinctrl_state *state;
78+ int init_dev_apply_channel_pinctrl (const struct device *dev, size_t state_pin_idx) {
7979
80- if (dev == NULL || dev-> config == NULL ) {
80+ if (dev == nullptr ) {
8181 return -EINVAL;
8282 }
8383
84+ if (!device_is_ready (dev)) {
85+ // init device for first usage, if not ready
86+ int err = device_init (dev);
87+ if (err < 0 ) {
88+ return err;
89+ }
90+ }
91+
92+ const struct pinctrl_state *state;
8493 const struct pinctrl_dev_config *pcfg = get_known_pcfg (dev);
8594
86- if (pcfg == NULL ) {
95+ if (pcfg == nullptr ) {
96+ /* Device not in DT mapping - add to pinctrl_map if needed */
8797 return -ENOTSUP;
8898 }
8999
90100 int err = pinctrl_lookup_state (pcfg, PINCTRL_STATE_ARDUINO, &state);
91101 if (err < 0 ) {
92- return err;
102+ return err; /* Fails if the state is not defined in pinctrl-names */
93103 }
94104
105+ /* bounds check */
95106 if (state_pin_idx >= state->pin_cnt ) {
96107 return -ERANGE;
97108 }
98109
99- soc_pin = &state->pins [state_pin_idx];
100-
101110 /*
102- * On platforms where CONFIG_PINCTRL_STORE_REG is enabled (e.g. nRF),
103- * the peripheral's PSEL register must be written via the device base
104- * address stored in pcfg->reg.
105- * On platforms without CONFIG_PINCTRL_STORE_REG (e.g. STM32) the reg
106- * argument is ignored by their pinctrl driver, so passing PINCTRL_REG_NONE is safe.
111+ * On platforms without CONFIG_PINCTRL_STORE_REG (e.g. STM32) the pcfg->reg is not present but
112+ * the argument is ignored by their pinctrl driver, so passing PINCTRL_REG_NONE is safe.
107113 */
108114#ifdef CONFIG_PINCTRL_STORE_REG
109- err = pinctrl_configure_pins (soc_pin, 1 , pcfg->reg ) ;
115+ uintptr_t reg = pcfg->reg ;
110116#else
111- err = pinctrl_configure_pins (soc_pin, 1 , PINCTRL_REG_NONE) ;
117+ uintptr_t reg = PINCTRL_REG_NONE;
112118#endif
113- if (err < 0 ) {
114- return err;
115- }
116119
117- return 0 ;
120+ return pinctrl_configure_pins (&state-> pins [state_pin_idx], 1 , reg) ;
118121}
119122
120123/* *
121- * @brief Optimize peripheral transitions using pinctrl state switching .
124+ * @brief Optimize peripheral transitions applying pinctrl state PINCTRL_STATE_DEFAULT .
122125 *
123126 * @param dev Target peripheral device to acquire pin for
124- * @param target_state Desired pinctrl state (typically PINCTRL_STATE_DEFAULT or SLEEP)
125127 */
126- int apply_dev_pinctrl (const struct device *dev, uint8_t target_state ) {
128+ int init_dev_apply_pinctrl (const struct device *dev) {
127129
128- if (dev == NULL || dev-> config == NULL ) {
130+ if (dev == nullptr ) {
129131 return -EINVAL;
130132 }
131133
132- const struct pinctrl_dev_config *pcfg = get_known_pcfg (dev);
133- if (pcfg == NULL ) {
134- /* Device not in DT mapping - add to get_known_pcfg() if needed */
135- return -ENOTSUP;
134+ if (!device_is_ready (dev)) {
135+ int ret = device_init (dev);
136+ if (ret != 0 && ret != -EALREADY) {
137+ return ret;
138+ }
136139 }
137140
138- int ret = pinctrl_apply_state ( pcfg, target_state );
139-
140- if (ret < 0 && ret != -ENOENT) {
141- return ret ;
141+ const struct pinctrl_dev_config * pcfg = get_known_pcfg (dev );
142+ if (pcfg == nullptr ) {
143+ /* Device not in DT mapping - add to pinctrl_map if needed */
144+ return -ENOTSUP ;
142145 }
143146
144- return 0 ;
147+ return pinctrl_apply_state (pcfg, PINCTRL_STATE_DEFAULT) ;
145148}
146149
147150static const struct gpio_dt_spec arduino_pins[] = {
@@ -624,14 +627,15 @@ void analogWrite(pin_size_t pinNumber, int value) {
624627 return ;
625628 }
626629
630+ (void )init_dev_apply_channel_pinctrl (arduino_pwm[idx].dev ,
631+ state_pin_index_from_spec_index (arduino_pwm, idx));
632+
627633 if (!pwm_is_ready_dt (&arduino_pwm[idx])) {
628634 pinMode (pinNumber, OUTPUT);
629635 digitalWrite (pinNumber, value > 127 ? HIGH : LOW);
630636 return ;
631637 }
632638
633- (void )apply_dev_channel_pinctrl (state_pin_index_from_spec_index (arduino_pwm, idx),
634- arduino_pwm[idx].dev );
635639 value = CLAMP (value, 0 , maxInput);
636640
637641 const uint32_t pulse = map64 (value, 0 , maxInput, 0 , arduino_pwm[idx].period );
@@ -657,7 +661,7 @@ void analogWrite(enum dacPins dacName, int value) {
657661
658662 // TODO: add reverse map to find pin name from DAC* define
659663 // In the meantime, consider A0 == DAC0
660- apply_dev_pinctrl ( dac_dev, PINCTRL_STATE_DEFAULT );
664+ ( void ) init_dev_apply_pinctrl ( dac_dev);
661665
662666 ret = dac_channel_setup (dac_dev, &dac_ch_cfg[dacName]);
663667 if (ret != 0 ) {
@@ -711,14 +715,6 @@ int analogRead(pin_size_t pinNumber) {
711715 return -EINVAL;
712716 }
713717
714- if (!device_is_ready (arduino_adc[idx].dev )) {
715- // init device for first acquisition attempt, if not ready
716- err = device_init (arduino_adc[idx].dev );
717- if (err < 0 ) {
718- return err;
719- }
720- }
721-
722718 /*
723719 * ADC that is on MCU supported by Zephyr exists
724720 * only 16bit resolution, currently.
@@ -728,12 +724,13 @@ int analogRead(pin_size_t pinNumber) {
728724 }
729725
730726 /*
731- * Restore only this ADC pin to analog mode when transitioning from GPIO.
732- * The pin is selected from the ADC device "arduino" pinctrl state.
733- * Not checking the return value because the device might not have pinctrl (e.g. nRF SAADC).
727+ * Init the ADC device for the first acquisition and restore only the required pin to analog
728+ * mode when transitioning from GPIO. The pin is selected from the ADC device "arduino" pinctrl
729+ * state. Not checking the return value because the device might not have pinctrl (e.g. nRF
730+ * SAADC).
734731 */
735- (void )apply_dev_channel_pinctrl ( state_pin_index_from_spec_index ( arduino_adc, idx) ,
736- arduino_adc[ idx]. dev );
732+ (void )init_dev_apply_channel_pinctrl ( arduino_adc[ idx]. dev ,
733+ state_pin_index_from_spec_index ( arduino_adc, idx) );
737734
738735 err = adc_channel_setup (arduino_adc[idx].dev , &arduino_adc[idx].channel_cfg );
739736 if (err < 0 ) {
0 commit comments