1#include "ch32_gpio.hpp"
5uint32_t LibXR::CH32GetGPIOPeriph(GPIO_TypeDef* port)
11 else if (port == GPIOA)
12 return RCC_APB2Periph_GPIOA;
15 else if (port == GPIOB)
16 return RCC_APB2Periph_GPIOB;
19 else if (port == GPIOC)
20 return RCC_APB2Periph_GPIOC;
23 else if (port == GPIOD)
24 return RCC_APB2Periph_GPIOD;
27 else if (port == GPIOE)
28 return RCC_APB2Periph_GPIOE;
31 else if (port == GPIOF)
32 return RCC_APB2Periph_GPIOF;
35 else if (port == GPIOG)
36 return RCC_APB2Periph_GPIOG;
39 else if (port == GPIOH)
40 return RCC_APB2Periph_GPIOH;
43 else if (port == GPIOI)
44 return RCC_APB2Periph_GPIOI;
49extern "C" void EXTI0_IRQHandler(
void) __attribute__((interrupt));
50extern "C" void EXTI0_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line0); }
52extern "C" void EXTI1_IRQHandler(
void) __attribute__((interrupt));
53extern "C" void EXTI1_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line1); }
55extern "C" void EXTI2_IRQHandler(
void) __attribute__((interrupt));
56extern "C" void EXTI2_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line2); }
58extern "C" void EXTI3_IRQHandler(
void) __attribute__((interrupt));
59extern "C" void EXTI3_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line3); }
61extern "C" void EXTI4_IRQHandler(
void) __attribute__((interrupt));
62extern "C" void EXTI4_IRQHandler(
void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line4); }
64extern "C" void EXTI9_5_IRQHandler(
void) __attribute__((interrupt));
65extern "C" void EXTI9_5_IRQHandler(
void)
67 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line5);
68 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line6);
69 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line7);
70 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line8);
71 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line9);
74extern "C" void EXTI15_10_IRQHandler(
void) __attribute__((interrupt));
75extern "C" void EXTI15_10_IRQHandler(
void)
77 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line10);
78 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line11);
79 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line12);
80 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line13);
81 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line14);
82 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line15);
85CH32GPIO::CH32GPIO(GPIO_TypeDef* port, uint16_t pin,
GPIO::Direction direction,
87 : port_(port), pin_(pin), irq_(irq)
89 if (irq_ != NonMaskableInt_IRQn)
92 map[GetEXTIID(pin)] =
this;
95 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(port_), ENABLE);
97 GPIO_InitTypeDef gpio_init = {};
98 gpio_init.GPIO_Pin = pin_;
99 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
103 case Direction::RISING_INTERRUPT:
104 case Direction::FALL_INTERRUPT:
105 case Direction::FALL_RISING_INTERRUPT:
106 case Direction::INPUT:
107 gpio_init.GPIO_Mode = (pull == Pull::UP) ? GPIO_Mode_IPU
108 : (pull == Pull::DOWN) ? GPIO_Mode_IPD
109 : GPIO_Mode_IN_FLOATING;
111 case Direction::OUTPUT_PUSH_PULL:
112 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
114 case Direction::OUTPUT_OPEN_DRAIN:
115 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
119 GPIO_Init(port_, &gpio_init);
123 case Direction::RISING_INTERRUPT:
124 ConfigureEXTI(EXTI_Trigger_Rising);
126 case Direction::FALL_INTERRUPT:
127 ConfigureEXTI(EXTI_Trigger_Falling);
129 case Direction::FALL_RISING_INTERRUPT:
130 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
142 GPIO_SetBits(port_, pin_);
144 GPIO_ResetBits(port_, pin_);
145 return ErrorCode::OK;
150 EXTI->INTENR |= (1 << GetEXTIID(pin_));
151 return ErrorCode::OK;
156 EXTI->INTENR &= ~(1 << GetEXTIID(pin_));
157 return ErrorCode::OK;
162 GPIO_InitTypeDef gpio_init = {};
163 gpio_init.GPIO_Pin = pin_;
164 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
169 gpio_init.GPIO_Mode = (config.
pull ==
Pull::UP) ? GPIO_Mode_IPU
171 : GPIO_Mode_IN_FLOATING;
174 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
177 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
182 gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
186 GPIO_Init(port_, &gpio_init);
191 ConfigureEXTI(EXTI_Trigger_Rising);
194 ConfigureEXTI(EXTI_Trigger_Falling);
197 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
203 return ErrorCode::OK;
206void CH32GPIO::OnInterrupt()
214void CH32GPIO::CheckInterrupt(uint32_t line)
216 if (EXTI_GetITStatus(line) != RESET)
218 EXTI_ClearITPendingBit(line);
219 map[GetEXTIID(line)]->OnInterrupt();
223void CH32GPIO::ConfigureEXTI(EXTITrigger_TypeDef trigger)
225 EXTI_InitTypeDef exti = {};
226 uint8_t pin_source = __builtin_ctz(pin_);
227 uint8_t port_source = 0xFF;
230 if (port_ == GPIOA) port_source = GPIO_PortSourceGPIOA;
233 else if (port_ == GPIOB)
235 port_source = GPIO_PortSourceGPIOB;
239 else if (port_ == GPIOC)
241 port_source = GPIO_PortSourceGPIOC;
245 else if (port_ == GPIOD)
247 port_source = GPIO_PortSourceGPIOD;
251 else if (port_ == GPIOE)
253 port_source = GPIO_PortSourceGPIOE;
257 else if (port_ == GPIOF)
259 port_source = GPIO_PortSourceGPIOF;
263 else if (port_ == GPIOG)
265 port_source = GPIO_PortSourceGPIOG;
269 else if (port_ == GPIOH)
271 port_source = GPIO_PortSourceGPIOH;
275 else if (port_ == GPIOI)
277 port_source = GPIO_PortSourceGPIOI;
281 ASSERT(port_source != 0xFF);
283 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
284 GPIO_EXTILineConfig(port_source, pin_source);
286 exti.EXTI_Line = 1 << pin_source;
287 exti.EXTI_Mode = EXTI_Mode_Interrupt;
288 exti.EXTI_Trigger = trigger;
289 exti.EXTI_LineCmd = ENABLE;
292 NVIC_EnableIRQ(irq_);
295uint8_t CH32GPIO::GetEXTIID(uint16_t pin) {
return __builtin_ctz(pin); }
ErrorCode SetConfig(Configuration config) override
配置 GPIO 引脚参数。Configures the GPIO pin settings.
ErrorCode DisableInterrupt() override
禁用 GPIO 引脚中断。Disables the GPIO pin interrupt.
bool Read() override
读取 GPIO 引脚状态。Reads the GPIO pin state.
ErrorCode Write(bool value) override
写入 GPIO 引脚状态。Writes the GPIO pin state.
ErrorCode EnableInterrupt() override
使能 GPIO 引脚中断。Enables the GPIO pin interrupt.
void Run(bool in_isr, PassArgs &&...args) const
执行回调函数,并传递参数。 Executes the callback function, passing the arguments.
bool Empty() const
检查回调是否为空。 Checks if the callback is empty.
Callback callback_
GPIO 事件的回调函数。Callback function for GPIO events.
Direction
定义 GPIO 引脚的方向类型。Defines the direction types for GPIO pins.
@ 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.
@ FALL_INTERRUPT
下降沿中断模式。Falling edge interrupt mode.
Pull
定义 GPIO 引脚的上拉/下拉模式。Defines the pull-up/pull-down configurations for GPIO pins.
@ DOWN
下拉模式。Pull-down mode.
存储 GPIO 配置参数的结构体。Structure storing GPIO configuration parameters.
Pull pull
GPIO 上拉/下拉配置。GPIO pull-up/pull-down configuration.
Direction direction
GPIO 引脚方向。GPIO pin direction.