libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
mspm0_gpio.cpp
1#include "mspm0_gpio.hpp"
2
3#include "mspm0_group1_shared.hpp"
4
5using namespace LibXR;
6
7MSPM0GPIO* MSPM0GPIO::instance_map_[MAX_PORTS][32] = {{nullptr}};
8
16static constexpr uint32_t MSPM0_GPIO_GetPolarityMask(uint8_t pin, // NOLINT
17 LibXR::GPIO::Direction direction)
18{
19 uint32_t config_bits = 0;
20 switch (direction)
21 {
23 config_bits = GPIO_POLARITY15_0_DIO0_RISE;
24 break;
26 config_bits = GPIO_POLARITY15_0_DIO0_FALL;
27 break;
29 config_bits = GPIO_POLARITY15_0_DIO0_RISE_FALL;
30 break;
31 default:
32 return 0;
33 }
34
35 uint32_t shift = (pin % 16) * 2;
36 return config_bits << shift;
37}
38#ifdef GPIOA_BASE
39static void gpioa_irq_thunk() { LibXR::MSPM0GPIO::OnInterrupt(GPIOA); }
40#endif
41
42#ifdef GPIOB_BASE
43static void gpiob_irq_thunk() { LibXR::MSPM0GPIO::OnInterrupt(GPIOB); }
44#endif
45
46#ifdef GPIOC_BASE
47static void gpioc_irq_thunk() { LibXR::MSPM0GPIO::OnInterrupt(GPIOC); }
48#endif
49
50MSPM0GPIO::MSPM0GPIO(GPIO_Regs* port, uint32_t pin_mask, uint32_t pincm)
51 : port_(port), pin_mask_(pin_mask), pincm_(pincm)
52{
53 int pin_idx = __builtin_ctz(pin_mask_);
54 int port_idx = GetPortIndex(reinterpret_cast<uint32_t>(port_));
55
56 ASSERT(port_idx >= 0 && port_idx < LibXR::MAX_PORTS);
57 ASSERT(instance_map_[port_idx][pin_idx] == nullptr);
58
59 instance_map_[port_idx][pin_idx] = this;
60
61 switch (port_idx)
62 {
63 case 0:
64#ifdef GPIOA_BASE
65 LibXR::MSPM0Group1Shared::RegisterGPIOA(&gpioa_irq_thunk);
66#endif
67 break;
68
69 case 1:
70#ifdef GPIOB_BASE
71 LibXR::MSPM0Group1Shared::RegisterGPIOB(&gpiob_irq_thunk);
72#endif
73 break;
74
75 case 2:
76#ifdef GPIOC_BASE
77 LibXR::MSPM0Group1Shared::RegisterGPIOC(&gpioc_irq_thunk);
78#endif
79 break;
80 default:
81 return;
82 }
83}
84
85bool MSPM0GPIO::Read() { return DL_GPIO_readPins(port_, pin_mask_) == pin_mask_; }
86
87void MSPM0GPIO::Write(bool value)
88{
89 if (current_direction_ == LibXR::GPIO::Direction::OUTPUT_OPEN_DRAIN)
90 {
91 if (value)
92 {
93 DL_GPIO_disableOutput(port_, pin_mask_);
94 }
95 else
96 {
97 DL_GPIO_enableOutput(port_, pin_mask_);
98 }
99 }
100 else
101 {
102 if (value)
103 {
104 DL_GPIO_setPins(port_, pin_mask_);
105 }
106 else
107 {
108 DL_GPIO_clearPins(port_, pin_mask_);
109 }
110 }
111}
112
114{
115 DL_GPIO_enableInterrupt(port_, pin_mask_);
116 return ErrorCode::OK;
117}
118
120{
121 DL_GPIO_disableInterrupt(port_, pin_mask_);
122 return ErrorCode::OK;
123}
124
126{
127 current_direction_ = config.direction;
128
129 DL_GPIO_disableOutput(port_, pin_mask_);
130 DL_GPIO_disableInterrupt(port_, pin_mask_);
131 DL_GPIO_clearInterruptStatus(port_, pin_mask_);
132
133 switch (config.direction)
134 {
135 case Direction::INPUT:
136 {
137 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
138 if (config.pull == Pull::UP)
139 {
140 res = DL_GPIO_RESISTOR_PULL_UP;
141 }
142 else if (config.pull == Pull::DOWN)
143 {
144 res = DL_GPIO_RESISTOR_PULL_DOWN;
145 }
146 DL_GPIO_initDigitalInputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
147 DL_GPIO_HYSTERESIS_DISABLE,
148 DL_GPIO_WAKEUP_DISABLE);
149 break;
150 }
151
153 {
154 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
155 if (config.pull == Pull::UP)
156 {
157 res = DL_GPIO_RESISTOR_PULL_UP;
158 }
159 else if (config.pull == Pull::DOWN)
160 {
161 res = DL_GPIO_RESISTOR_PULL_DOWN;
162 }
163
164 DL_GPIO_initDigitalOutputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
165 DL_GPIO_DRIVE_STRENGTH_LOW, DL_GPIO_HIZ_DISABLE);
166
167 volatile uint32_t* pincm_reg = &IOMUX->SECCFG.PINCM[pincm_];
168 *pincm_reg |= IOMUX_PINCM_INENA_ENABLE;
169
170 DL_GPIO_clearPins(port_, pin_mask_);
171
172 DL_GPIO_enableOutput(port_, pin_mask_);
173 break;
174 }
175
177 {
178 /* 伪开漏:输入模式(高阻) + 软件控制拉低 / Pseudo open-drain: Input mode(HiZ) +
179 * software pull-low */
180 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
181 if (config.pull == Pull::UP)
182 {
183 res = DL_GPIO_RESISTOR_PULL_UP;
184 }
185
186 DL_GPIO_initDigitalInputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
187 DL_GPIO_HYSTERESIS_DISABLE,
188 DL_GPIO_WAKEUP_DISABLE);
189
190 DL_GPIO_clearPins(port_, pin_mask_);
191 DL_GPIO_disableOutput(port_, pin_mask_);
192 break;
193 }
194
198 {
199 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
200 if (config.pull == Pull::UP)
201 {
202 res = DL_GPIO_RESISTOR_PULL_UP;
203 }
204 else if (config.pull == Pull::DOWN)
205 {
206 res = DL_GPIO_RESISTOR_PULL_DOWN;
207 }
208
209 DL_GPIO_initDigitalInputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
210 DL_GPIO_HYSTERESIS_DISABLE,
211 DL_GPIO_WAKEUP_DISABLE);
212
213 uint32_t pol_mask =
214 MSPM0_GPIO_GetPolarityMask(__builtin_ctz(pin_mask_), config.direction);
215 if (pol_mask)
216 {
217 uint32_t pin_idx = __builtin_ctz(pin_mask_);
218
219 constexpr uint32_t BITS_PER_PIN = 2;
220 constexpr uint32_t CLEAR_PATTERN = 0x3U;
221
222 uint32_t shift = (pin_idx % 16) * BITS_PER_PIN;
223 uint32_t clear_mask = CLEAR_PATTERN << shift;
224
225 if (pin_idx < 16)
226 {
227 uint32_t current_polarity = DL_GPIO_getLowerPinsPolarity(port_);
228 current_polarity &= ~clear_mask;
229 current_polarity |= pol_mask;
230 port_->POLARITY15_0 = current_polarity;
231 }
232 else
233 {
234 uint32_t current_polarity = DL_GPIO_getUpperPinsPolarity(port_);
235 current_polarity &= ~clear_mask;
236 current_polarity |= pol_mask;
237 port_->POLARITY31_16 = current_polarity;
238 }
239 }
240
241 DL_GPIO_clearInterruptStatus(port_, pin_mask_);
242 DL_GPIO_enableInterrupt(port_, pin_mask_);
243 }
244 break;
245
246 default:
247 return ErrorCode::FAILED;
248 }
249
250 return ErrorCode::OK;
251}
252
253void MSPM0GPIO::OnInterruptDispatch(GPIO_Regs* port, int port_idx)
254{
255 if (port_idx < 0 || port_idx >= LibXR::MAX_PORTS)
256 {
257 return;
258 }
259
260 uint32_t pending_pins = DL_GPIO_getEnabledInterruptStatus(port, 0xFFFFFFFF);
261
262 if (pending_pins != 0)
263 {
264 DL_GPIO_clearInterruptStatus(port, pending_pins);
265 }
266
267 while (pending_pins)
268 {
269 uint32_t pin_idx = __builtin_ctz(pending_pins);
270 uint32_t pin_mask = (1U << pin_idx);
271
272 pending_pins &= ~pin_mask;
273
274 auto* instance = instance_map_[port_idx][pin_idx];
275 if (instance)
276 {
277 instance->callback_.Run(true);
278 }
279 }
280}
Direction
定义 GPIO 引脚的方向类型。Defines the direction types for GPIO pins.
Definition gpio.hpp:20
@ OUTPUT_PUSH_PULL
推挽输出模式。Push-pull output mode.
@ RISING_INTERRUPT
上升沿中断模式。Rising edge interrupt mode.
@ FALL_RISING_INTERRUPT
双沿触发中断模式。Both edge interrupt mode.
@ OUTPUT_OPEN_DRAIN
开漏输出模式。Open-drain output mode.
@ INPUT
输入模式。Input mode.
@ FALL_INTERRUPT
下降沿中断模式。Falling edge interrupt mode.
@ DOWN
下拉模式。Pull-down mode.
@ UP
上拉模式。Pull-up mode.
ErrorCode DisableInterrupt() override
禁用 GPIO 引脚中断。Disables the GPIO pin interrupt.
bool Read() override
读取 GPIO 引脚状态。Reads the GPIO pin state.
ErrorCode EnableInterrupt() override
使能 GPIO 引脚中断。Enables the GPIO pin interrupt.
void Write(bool value) override
写入 GPIO 引脚状态。Writes the GPIO pin state.
ErrorCode SetConfig(Configuration config) override
配置 GPIO 引脚参数。Configures the GPIO pin settings.
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
存储 GPIO 配置参数的结构体。Structure storing GPIO configuration parameters.
Definition gpio.hpp:46
Pull pull
GPIO 上拉/下拉配置。GPIO pull-up/pull-down configuration.
Definition gpio.hpp:48
Direction direction
GPIO 引脚方向。GPIO pin direction.
Definition gpio.hpp:47