libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
hpm_gpio.cpp
1#include "hpm_gpio.hpp"
2
3#include "hpm_interrupt.h"
4#include "hpm_ioc_regs.h"
5
6using namespace LibXR;
7
15GPIO_Type* HPMGPIO::port_controller_map[HPMGPIO::kPortCount] = {};
16
27static inline void HPM_GPIO_ConfigMuxToGPIO(GPIO_Type* gpio, uint32_t port,
28 uint16_t pad_index,
29 bool enable_loopback = true)
30{
31 uint32_t func_ctl = IOC_PAD_FUNC_CTL_ALT_SELECT_SET(0);
32 if (enable_loopback)
33 {
34 func_ctl |= IOC_PAD_FUNC_CTL_LOOP_BACK_MASK;
35 }
36 HPM_IOC->PAD[pad_index].FUNC_CTL = func_ctl;
37
38 // GPIOY 端口需要额外通过 PIOC 选择 SOC GPIO 信号 / GPIOY needs extra PIOC routing.
39 if (port == GPIO_DI_GPIOY && (gpio == HPM_GPIO0 || gpio == HPM_FGPIO))
40 {
41 HPM_PIOC->PAD[pad_index].FUNC_CTL = IOC_PAD_FUNC_CTL_ALT_SELECT_SET(3);
42 }
43}
44
49HPMGPIO::HPMGPIO(GPIO_Type* gpio, uint32_t port, uint8_t pin, uint32_t irq,
50 uint16_t pad_index)
51 : gpio_(gpio),
52 port_(port),
53 pin_(pin),
54 irq_(irq),
55 pad_index_(pad_index == kInvalidPadIndex ? ResolvePadIndex(gpio, port, pin)
56 : pad_index)
57{
58 if (port_ < kPortCount && pin_ < kPinCount)
59 {
60 map[port_][pin_] = this;
61 if (port_controller_map[port_] == nullptr)
62 {
63 port_controller_map[port_] = gpio_;
64 }
65 }
66}
67
79{
80 if (irq_ == kInvalidIrq)
81 {
82 return ErrorCode::ARG_ERR;
83 }
84 gpio_enable_pin_interrupt(gpio_, port_, pin_);
85 intc_m_enable_irq_with_priority(irq_, 1);
86 return ErrorCode::OK;
87}
88
97{
98 if (irq_ == kInvalidIrq)
99 {
100 return ErrorCode::ARG_ERR;
101 }
102 gpio_disable_pin_interrupt(gpio_, port_, pin_);
103 intc_m_disable_irq(irq_);
104 return ErrorCode::OK;
105}
106
119{
120 if (port_ >= kPortCount || pin_ >= kPinCount)
121 {
122 return ErrorCode::ARG_ERR;
123 }
124
126 {
127 // 保持接口自洽:先确保 PAD 复用到 GPIO / Keep API self-contained: force GPIO mux
128 // first.
129 HPM_GPIO_ConfigMuxToGPIO(gpio_, port_, pad_index_);
130 }
131
132 switch (config.direction)
133 {
134 case Direction::INPUT:
135 gpio_set_pin_input(gpio_, port_, pin_);
136 break;
139 gpio_set_pin_output(gpio_, port_, pin_);
140 break;
142 gpio_set_pin_input(gpio_, port_, pin_);
143 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_falling);
144 break;
146 gpio_set_pin_input(gpio_, port_, pin_);
147 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_rising);
148 break;
150 gpio_set_pin_input(gpio_, port_, pin_);
151 gpio_config_pin_interrupt(gpio_, port_, pin_, gpio_interrupt_trigger_edge_both);
152 break;
153 default:
154 return ErrorCode::ARG_ERR;
155 }
156
158 {
159 uint32_t pad_ctl = HPM_IOC->PAD[pad_index_].PAD_CTL;
160
161 // 仅更新上下拉与开漏位,保留其他电气属性 / Update pull + open-drain bits only.
162 pad_ctl &=
163 ~(IOC_PAD_PAD_CTL_PE_MASK | IOC_PAD_PAD_CTL_PS_MASK | IOC_PAD_PAD_CTL_OD_MASK);
164
165 switch (config.pull)
166 {
167 case Pull::NONE:
168 break;
169 case Pull::UP:
170 pad_ctl |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1);
171 break;
172 case Pull::DOWN:
173 pad_ctl |= IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(0);
174 break;
175 default:
176 return ErrorCode::ARG_ERR;
177 }
178
180 {
181 pad_ctl |= IOC_PAD_PAD_CTL_OD_SET(1);
182 }
183
184 HPM_IOC->PAD[pad_index_].PAD_CTL = pad_ctl;
185 }
186
187 return ErrorCode::OK;
188}
189
201{
202 if (port_ >= kPortCount || pin_ >= kPinCount)
203 {
204 return ErrorCode::ARG_ERR;
205 }
206
208 {
209 return ErrorCode::NOT_SUPPORT;
210 }
211
212 gpio_disable_pin_interrupt(gpio_, port_, pin_);
213 gpio_set_pin_input(gpio_, port_, pin_);
214
215 HPM_IOC->PAD[pad_index_].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK;
216
217 uint32_t pad_ctl = HPM_IOC->PAD[pad_index_].PAD_CTL;
218 pad_ctl &= ~(IOC_PAD_PAD_CTL_PE_MASK | IOC_PAD_PAD_CTL_OD_MASK);
219 HPM_IOC->PAD[pad_index_].PAD_CTL = pad_ctl;
220
221 return ErrorCode::OK;
222}
223
238void HPMGPIO::CheckInterrupt(uint32_t port)
239{
240 if (port >= kPortCount)
241 {
242 return;
243 }
244
245 GPIO_Type* controller = port_controller_map[port];
246 if (controller == nullptr)
247 {
248 return;
249 }
250
251 const uint32_t flags = gpio_get_port_interrupt_flags(controller, port);
252 if (flags == 0u)
253 {
254 return;
255 }
256
257 for (uint8_t pin = 0; pin < kPinCount; ++pin)
258 {
259 if ((flags & (1u << pin)) == 0u)
260 {
261 continue;
262 }
263
264 gpio_clear_pin_interrupt_flag(controller, port, pin);
265 if (auto* gpio = map[port][pin])
266 {
267 gpio->callback_.Run(true);
268 }
269 }
270}
271
275uint16_t HPMGPIO::ResolvePadIndex(GPIO_Type* gpio, uint32_t port, uint8_t pin)
276{
277 if (gpio != HPM_GPIO0 && gpio != HPM_FGPIO)
278 {
279 return kInvalidPadIndex;
280 }
281
282 switch (port)
283 {
284 case GPIO_DI_GPIOA:
285 return static_cast<uint16_t>(IOC_PAD_PA00 + pin);
286 case GPIO_DI_GPIOB:
287 return static_cast<uint16_t>(IOC_PAD_PB00 + pin);
288 case GPIO_DI_GPIOX:
289 return pin < 8u ? static_cast<uint16_t>(IOC_PAD_PX00 + pin) : kInvalidPadIndex;
290 case GPIO_DI_GPIOY:
291 return pin < 8u ? static_cast<uint16_t>(IOC_PAD_PY00 + pin) : kInvalidPadIndex;
292 default:
293 return kInvalidPadIndex;
294 }
295}
296
301extern "C" void libxr_hpm_gpio_check_interrupt(uint32_t port)
302{
304}
@ 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.
@ NONE
无上拉或下拉。No pull-up or pull-down.
@ DOWN
下拉模式。Pull-down mode.
@ UP
上拉模式。Pull-up mode.
HPM 平台 GPIO 驱动实现 / GPIO driver implementation for HPM platform.
Definition hpm_gpio.hpp:21
static constexpr uint32_t kPortCount
支持的端口数量 / Supported port count.
Definition hpm_gpio.hpp:102
GPIO_Type * gpio_
GPIO 控制器实例 / GPIO controller instance.
Definition hpm_gpio.hpp:123
ErrorCode EnableInterrupt() override
使能当前引脚中断 / Enable GPIO interrupt for current pin.
Definition hpm_gpio.cpp:78
static constexpr uint16_t kInvalidPadIndex
无效 PAD 标记 / Invalid PAD marker.
Definition hpm_gpio.hpp:105
ErrorCode SetAnalogHighImpedance()
将当前 PAD 配置为模拟高阻 / Configure current pad to analog high-impedance.
Definition hpm_gpio.cpp:200
static uint16_t ResolvePadIndex(GPIO_Type *gpio, uint32_t port, uint8_t pin)
根据控制器与端口引脚推导 IOC PAD 编号 / Resolve IOC PAD index from controller/port/pin tuple.
Definition hpm_gpio.cpp:275
ErrorCode SetConfig(Configuration config) override
配置当前引脚模式 / Configure GPIO mode for current pin.
Definition hpm_gpio.cpp:118
uint16_t pad_index_
IOC PAD 编号 / IOC PAD index.
Definition hpm_gpio.hpp:127
static constexpr uint32_t kInvalidIrq
无效 IRQ 标记 / Invalid IRQ marker.
Definition hpm_gpio.hpp:104
static void CheckInterrupt(uint32_t port)
分发某一端口的 GPIO 中断回调 / Dispatch GPIO interrupt callbacks for one port.
Definition hpm_gpio.cpp:238
uint32_t irq_
引脚对应 IRQ 号 / IRQ number for this pin.
Definition hpm_gpio.hpp:126
ErrorCode DisableInterrupt() override
失能当前引脚中断 / Disable GPIO interrupt for current pin.
Definition hpm_gpio.cpp:96
HPMGPIO(GPIO_Type *gpio, uint32_t port, uint8_t pin, uint32_t irq=kInvalidIrq, uint16_t pad_index=kInvalidPadIndex)
构造 HPM GPIO 对象 / Construct an HPM GPIO object.
Definition hpm_gpio.cpp:49
static HPMGPIO * map[kPortCount][kPinCount]
GPIO 对象映射表 / GPIO object dispatch map.
Definition hpm_gpio.hpp:120
static constexpr uint32_t kPinCount
每个端口引脚数 / Pins per port.
Definition hpm_gpio.hpp:103
uint8_t pin_
GPIO 引脚号 / GPIO pin index.
Definition hpm_gpio.hpp:125
uint32_t port_
GPIO 端口号 / GPIO port index.
Definition hpm_gpio.hpp:124
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