libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
mspm0_gpio.cpp
1#include "mspm0_gpio.hpp"
2
3using namespace LibXR;
4
5MSPM0GPIO* MSPM0GPIO::instance_map_[MAX_PORTS][32] = {{nullptr}};
6
14static constexpr uint32_t MSPM0_GPIO_GetPolarityMask(uint8_t pin, // NOLINT
15 LibXR::GPIO::Direction direction)
16{
17 uint32_t config_bits = 0;
18 switch (direction)
19 {
21 config_bits = GPIO_POLARITY15_0_DIO0_RISE;
22 break;
24 config_bits = GPIO_POLARITY15_0_DIO0_FALL;
25 break;
27 config_bits = GPIO_POLARITY15_0_DIO0_RISE_FALL;
28 break;
29 default:
30 return 0;
31 }
32
33 uint32_t shift = (pin % 16) * 2;
34 return config_bits << shift;
35}
36
37MSPM0GPIO::MSPM0GPIO(GPIO_Regs* port, uint32_t pin_mask, uint32_t pincm)
38 : port_(port), pin_mask_(pin_mask), pincm_(pincm)
39{
40 int pin_idx = __builtin_ctz(pin_mask_);
41 int port_idx = GetPortIndex(reinterpret_cast<uint32_t>(port_));
42
43 ASSERT(port_idx >= 0 && port_idx < LibXR::MAX_PORTS);
44 ASSERT(instance_map_[port_idx][pin_idx] == nullptr);
45
46 instance_map_[port_idx][pin_idx] = this;
47
48 switch (port_idx)
49 {
50 case 0:
51#ifdef GPIOA_BASE
52 NVIC_EnableIRQ(GPIOA_INT_IRQn);
53#endif
54 break;
55
56 case 1:
57#ifdef GPIOB_BASE
58 NVIC_EnableIRQ(GPIOB_INT_IRQn);
59#endif
60 break;
61
62 case 2:
63#ifdef GPIOC_BASE
64 NVIC_EnableIRQ(GPIOC_INT_IRQn);
65#endif
66 break;
67 }
68}
69
70bool MSPM0GPIO::Read() { return DL_GPIO_readPins(port_, pin_mask_) == pin_mask_; }
71
72void MSPM0GPIO::Write(bool value)
73{
74 if (current_direction_ == LibXR::GPIO::Direction::OUTPUT_OPEN_DRAIN)
75 {
76 if (value)
77 {
78 DL_GPIO_disableOutput(port_, pin_mask_);
79 }
80 else
81 {
82 DL_GPIO_enableOutput(port_, pin_mask_);
83 }
84 }
85 else
86 {
87 if (value)
88 {
89 DL_GPIO_setPins(port_, pin_mask_);
90 }
91 else
92 {
93 DL_GPIO_clearPins(port_, pin_mask_);
94 }
95 }
96}
97
99{
100 DL_GPIO_enableInterrupt(port_, pin_mask_);
101 return ErrorCode::OK;
102}
103
105{
106 DL_GPIO_disableInterrupt(port_, pin_mask_);
107 return ErrorCode::OK;
108}
109
111{
112 current_direction_ = config.direction;
113
114 DL_GPIO_disableOutput(port_, pin_mask_);
115 DL_GPIO_disableInterrupt(port_, pin_mask_);
116 DL_GPIO_clearInterruptStatus(port_, pin_mask_);
117
118 switch (config.direction)
119 {
120 case Direction::INPUT:
121 {
122 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
123 if (config.pull == Pull::UP)
124 {
125 res = DL_GPIO_RESISTOR_PULL_UP;
126 }
127 else if (config.pull == Pull::DOWN)
128 {
129 res = DL_GPIO_RESISTOR_PULL_DOWN;
130 }
131 DL_GPIO_initDigitalInputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
132 DL_GPIO_HYSTERESIS_DISABLE,
133 DL_GPIO_WAKEUP_DISABLE);
134 break;
135 }
136
138 {
139 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
140 if (config.pull == Pull::UP)
141 {
142 res = DL_GPIO_RESISTOR_PULL_UP;
143 }
144 else if (config.pull == Pull::DOWN)
145 {
146 res = DL_GPIO_RESISTOR_PULL_DOWN;
147 }
148
149 DL_GPIO_initDigitalOutputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
150 DL_GPIO_DRIVE_STRENGTH_LOW, DL_GPIO_HIZ_DISABLE);
151
152 volatile uint32_t* pincm_reg = &IOMUX->SECCFG.PINCM[pincm_];
153 *pincm_reg |= IOMUX_PINCM_INENA_ENABLE;
154
155 DL_GPIO_clearPins(port_, pin_mask_);
156
157 DL_GPIO_enableOutput(port_, pin_mask_);
158 break;
159 }
160
162 {
163 /* 伪开漏:输入模式(高阻) + 软件控制拉低 / Pseudo open-drain: Input mode(HiZ) +
164 * software pull-low */
165 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
166 if (config.pull == Pull::UP)
167 {
168 res = DL_GPIO_RESISTOR_PULL_UP;
169 }
170
171 DL_GPIO_initDigitalInputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
172 DL_GPIO_HYSTERESIS_DISABLE,
173 DL_GPIO_WAKEUP_DISABLE);
174
175 DL_GPIO_clearPins(port_, pin_mask_);
176 DL_GPIO_disableOutput(port_, pin_mask_);
177 break;
178 }
179
183 {
184 DL_GPIO_RESISTOR res = DL_GPIO_RESISTOR_NONE;
185 if (config.pull == Pull::UP)
186 {
187 res = DL_GPIO_RESISTOR_PULL_UP;
188 }
189 else if (config.pull == Pull::DOWN)
190 {
191 res = DL_GPIO_RESISTOR_PULL_DOWN;
192 }
193
194 DL_GPIO_initDigitalInputFeatures(pincm_, DL_GPIO_INVERSION_DISABLE, res,
195 DL_GPIO_HYSTERESIS_DISABLE,
196 DL_GPIO_WAKEUP_DISABLE);
197
198 uint32_t pol_mask =
199 MSPM0_GPIO_GetPolarityMask(__builtin_ctz(pin_mask_), config.direction);
200 if (pol_mask)
201 {
202 uint32_t pin_idx = __builtin_ctz(pin_mask_);
203
204 constexpr uint32_t BITS_PER_PIN = 2;
205 constexpr uint32_t CLEAR_PATTERN = 0x3U;
206
207 uint32_t shift = (pin_idx % 16) * BITS_PER_PIN;
208 uint32_t clear_mask = CLEAR_PATTERN << shift;
209
210 if (pin_idx < 16)
211 {
212 uint32_t current_polarity = DL_GPIO_getLowerPinsPolarity(port_);
213 current_polarity &= ~clear_mask;
214 current_polarity |= pol_mask;
215 DL_GPIO_setLowerPinsPolarity(port_, current_polarity);
216 }
217 else
218 {
219 uint32_t current_polarity = DL_GPIO_getUpperPinsPolarity(port_);
220 current_polarity &= ~clear_mask;
221 current_polarity |= pol_mask;
222 DL_GPIO_setUpperPinsPolarity(port_, current_polarity);
223 }
224 }
225
226 DL_GPIO_clearInterruptStatus(port_, pin_mask_);
227 DL_GPIO_enableInterrupt(port_, pin_mask_);
228 }
229 break;
230
231 default:
232 return ErrorCode::FAILED;
233 }
234
235 return ErrorCode::OK;
236}
237
238void MSPM0GPIO::OnInterruptDispatch(GPIO_Regs* port, int port_idx)
239{
240 uint32_t pending_pins = DL_GPIO_getEnabledInterruptStatus(port, 0xFFFFFFFF);
241
242 if (pending_pins != 0)
243 {
244 DL_GPIO_clearInterruptStatus(port, pending_pins);
245 }
246
247 while (pending_pins)
248 {
249 uint32_t pin_idx = __builtin_ctz(pending_pins);
250 uint32_t pin_mask = (1U << pin_idx);
251
252 pending_pins &= ~pin_mask;
253
254 auto* instance = instance_map_[port_idx][pin_idx];
255 if (instance)
256 {
257 instance->callback_.Run(true);
258 }
259 }
260}
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
存储 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