Skip to content

Commit 2867006

Browse files
committed
pinmux: some fixes after review
1 parent cd2e658 commit 2867006

15 files changed

Lines changed: 290 additions & 192 deletions

File tree

cores/arduino/zephyrCommon.cpp

Lines changed: 55 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
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

3740
struct 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

4649
static 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

147150
static 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) {

cores/arduino/zephyrInternal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extern "C" {
1515
void enableInterrupt(pin_size_t);
1616
void disableInterrupt(pin_size_t);
1717

18-
int apply_dev_pinctrl(const struct device *dev, uint8_t target_state);
18+
int init_dev_apply_pinctrl(const struct device *dev);
1919

2020
#ifdef __cplusplus
2121
} // extern "C"

cores/arduino/zephyrSerial.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
* SPDX-License-Identifier: Apache-2.0
66
*/
77

8-
#include "zephyrInternal.h"
9-
8+
#include "zephyrInternal.h"
9+
1010
#include <zephyr/devicetree.h>
11-
#include <zephyr/drivers/pinctrl.h>
1211
#include <zephyr/drivers/uart.h>
1312

1413
#include <api/HardwareSerial.h>
@@ -63,17 +62,10 @@ void arduino::ZephyrSerial::begin(unsigned long baud, uint16_t conf) {
6362
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE,
6463
};
6564

66-
if (!device_is_ready(uart)) {
67-
int ret = device_init(uart);
68-
if (ret != 0 && ret != -EALREADY) {
69-
return;
70-
}
71-
}
72-
7365
/* Re-apply DEFAULT pinctrl state so shared pins
74-
* are remuxed back to Serial after temporary GPIO/PWM usage.
66+
* are remuxed back to Serial after other peripherals have used them.
7567
*/
76-
(void)apply_dev_pinctrl(uart, PINCTRL_STATE_DEFAULT);
68+
(void)init_dev_apply_pinctrl(uart);
7769

7870
uart_configure(uart, &config);
7971
uart_irq_callback_user_data_set(uart, arduino::ZephyrSerial::IrqDispatch, this);

0 commit comments

Comments
 (0)