90 CH32GPIO(GPIO_TypeDef* port, uint16_t pin,
93 : port_(port), pin_(pin), irq_(irq)
95 if (irq_ != NonMaskableInt_IRQn)
98 map[GetEXTIID(pin)] =
this;
101 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(port_), ENABLE);
103 GPIO_InitTypeDef gpio_init = {};
104 gpio_init.GPIO_Pin = pin_;
105 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
113 gpio_init.GPIO_Mode = (pull ==
Pull::UP) ? GPIO_Mode_IPU
115 : GPIO_Mode_IN_FLOATING;
118 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
121 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
125 GPIO_Init(port_, &gpio_init);
130 ConfigureEXTI(EXTI_Trigger_Rising);
133 ConfigureEXTI(EXTI_Trigger_Falling);
136 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
143 bool Read()
override {
return GPIO_ReadInputDataBit(port_, pin_) == Bit_SET; }
145 ErrorCode
Write(
bool value)
override
148 GPIO_SetBits(port_, pin_);
150 GPIO_ResetBits(port_, pin_);
151 return ErrorCode::OK;
156 EXTI->INTENR |= (1 << GetEXTIID(pin_));
157 return ErrorCode::OK;
162 EXTI->INTENR &= ~(1 << GetEXTIID(pin_));
163 return ErrorCode::OK;
168 GPIO_InitTypeDef gpio_init = {};
169 gpio_init.GPIO_Pin = pin_;
170 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
175 gpio_init.GPIO_Mode = (config.
pull ==
Pull::UP) ? GPIO_Mode_IPU
177 : GPIO_Mode_IN_FLOATING;
180 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
183 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
188 gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
192 GPIO_Init(port_, &gpio_init);
197 ConfigureEXTI(EXTI_Trigger_Rising);
200 ConfigureEXTI(EXTI_Trigger_Falling);
203 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
209 return ErrorCode::OK;
220 static void CheckInterrupt(uint32_t line)
222 if (EXTI_GetITStatus(line) != RESET)
224 EXTI_ClearITPendingBit(line);
225 map[GetEXTIID(line)]->OnInterrupt();
229 static inline CH32GPIO* map[16] = {
nullptr};
236 void ConfigureEXTI(EXTITrigger_TypeDef trigger)
238 EXTI_InitTypeDef exti = {};
239 uint8_t pin_source = __builtin_ctz(pin_);
240 uint8_t port_source = 0xFF;
243 if (port_ == GPIOA) port_source = GPIO_PortSourceGPIOA;
246 else if (port_ == GPIOB)
248 port_source = GPIO_PortSourceGPIOB;
252 else if (port_ == GPIOC)
254 port_source = GPIO_PortSourceGPIOC;
258 else if (port_ == GPIOD)
260 port_source = GPIO_PortSourceGPIOD;
264 else if (port_ == GPIOE)
266 port_source = GPIO_PortSourceGPIOE;
270 else if (port_ == GPIOF)
272 port_source = GPIO_PortSourceGPIOF;
276 else if (port_ == GPIOG)
278 port_source = GPIO_PortSourceGPIOG;
282 else if (port_ == GPIOH)
284 port_source = GPIO_PortSourceGPIOH;
288 else if (port_ == GPIOI)
290 port_source = GPIO_PortSourceGPIOI;
294 ASSERT(port_source != 0xFF);
296 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
297 GPIO_EXTILineConfig(port_source, pin_source);
299 exti.EXTI_Line = 1 << pin_source;
300 exti.EXTI_Mode = EXTI_Mode_Interrupt;
301 exti.EXTI_Trigger = trigger;
302 exti.EXTI_LineCmd = ENABLE;
305 NVIC_EnableIRQ(irq_);
308 static uint8_t GetEXTIID(uint16_t pin) {
return __builtin_ctz(pin); }