libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_gpio.cpp
1// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
2#include "ch32_gpio.hpp"
3
4using namespace LibXR;
5
6uint32_t LibXR::ch32_get_gpio_periph(GPIO_TypeDef* port)
7{
8 if (false)
9 {
10 }
11#if defined(GPIOA)
12 else if (port == GPIOA)
13 {
14 return RCC_APB2Periph_GPIOA;
15#endif
16#if defined(GPIOB)
17 }
18 else if (port == GPIOB)
19 {
20 return RCC_APB2Periph_GPIOB;
21#endif
22#if defined(GPIOC)
23 }
24 else if (port == GPIOC)
25 {
26 return RCC_APB2Periph_GPIOC;
27#endif
28#if defined(GPIOD)
29 }
30 else if (port == GPIOD)
31 {
32 return RCC_APB2Periph_GPIOD;
33#endif
34#if defined(GPIOE)
35 }
36 else if (port == GPIOE)
37 {
38 return RCC_APB2Periph_GPIOE;
39 }
40#endif
41 return 0;
42}
43
44// NOLINTNEXTLINE(readability-identifier-naming)
45extern "C" void EXTI0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
46// NOLINTNEXTLINE(readability-identifier-naming)
47extern "C" void EXTI0_IRQHandler(void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line0); }
48
49// NOLINTNEXTLINE(readability-identifier-naming)
50extern "C" void EXTI1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
51// NOLINTNEXTLINE(readability-identifier-naming)
52extern "C" void EXTI1_IRQHandler(void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line1); }
53
54// NOLINTNEXTLINE(readability-identifier-naming)
55extern "C" void EXTI2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
56// NOLINTNEXTLINE(readability-identifier-naming)
57extern "C" void EXTI2_IRQHandler(void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line2); }
58
59// NOLINTNEXTLINE(readability-identifier-naming)
60extern "C" void EXTI3_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
61// NOLINTNEXTLINE(readability-identifier-naming)
62extern "C" void EXTI3_IRQHandler(void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line3); }
63
64// NOLINTNEXTLINE(readability-identifier-naming)
65extern "C" void EXTI4_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
66// NOLINTNEXTLINE(readability-identifier-naming)
67extern "C" void EXTI4_IRQHandler(void) { LibXR::CH32GPIO::CheckInterrupt(EXTI_Line4); }
68
69// NOLINTNEXTLINE(readability-identifier-naming)
70extern "C" void EXTI9_5_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
71// NOLINTNEXTLINE(readability-identifier-naming)
72extern "C" void EXTI9_5_IRQHandler(void)
73{
74 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line5);
75 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line6);
76 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line7);
77 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line8);
78 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line9);
79}
80
81// NOLINTNEXTLINE(readability-identifier-naming)
82extern "C" void EXTI15_10_IRQHandler(void)
83 __attribute__((interrupt("WCH-Interrupt-fast")));
84// NOLINTNEXTLINE(readability-identifier-naming)
85extern "C" void EXTI15_10_IRQHandler(void)
86{
87 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line10);
88 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line11);
89 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line12);
90 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line13);
91 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line14);
92 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line15);
93}
94
95CH32GPIO::CH32GPIO(GPIO_TypeDef* port, uint16_t pin, GPIO::Direction direction,
96 GPIO::Pull pull, IRQn_Type irq)
97 : port_(port), pin_(pin), irq_(irq)
98{
99 if (irq_ != NonMaskableInt_IRQn)
100 {
101 map_[GetEXTIID(pin)] = this;
102 }
103
104 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(port_), ENABLE);
105
106 GPIO_InitTypeDef gpio_init = {};
107 gpio_init.GPIO_Pin = pin_;
108 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
109
110 switch (direction)
111 {
115 case Direction::INPUT:
116 gpio_init.GPIO_Mode = (pull == Pull::UP) ? GPIO_Mode_IPU
117 : (pull == Pull::DOWN) ? GPIO_Mode_IPD
118 : GPIO_Mode_IN_FLOATING;
119 break;
121 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
122 break;
124 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
125 break;
126 }
127
128 GPIO_Init(port_, &gpio_init);
129
130 switch (direction)
131 {
133 ConfigureEXTI(EXTI_Trigger_Rising);
134 break;
136 ConfigureEXTI(EXTI_Trigger_Falling);
137 break;
139 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
140 break;
141 default:
142 break;
143 }
144}
145
147{
148 EXTI->INTENR |= static_cast<uint32_t>(pin_);
149 return ErrorCode::OK;
150}
151
153{
154 EXTI->INTENR &= ~static_cast<uint32_t>(pin_);
155 return ErrorCode::OK;
156}
157
158void CH32GPIO::OnInterrupt()
159{
160 if (!callback_.Empty())
161 {
162 callback_.Run(true);
163 }
164}
165
166void CH32GPIO::CheckInterrupt(uint32_t line)
167{
168 if (EXTI_GetITStatus(line) != RESET)
169 {
170 EXTI_ClearITPendingBit(line);
171
172 const uint8_t ID = GetEXTIID(static_cast<uint16_t>(line));
173 if (auto* gpio = map_[ID])
174 {
175 gpio->OnInterrupt();
176 }
177 }
178}
179
180void CH32GPIO::ConfigureEXTI(EXTITrigger_TypeDef trigger)
181{
182 EXTI_InitTypeDef exti = {};
183 uint8_t pin_source = GetEXTIID(pin_);
184 uint8_t port_source = 0xFF;
185
186#if defined(GPIOA)
187 if (port_ == GPIOA)
188 {
189 port_source = GPIO_PortSourceGPIOA;
190#endif
191#if defined(GPIOB)
192 }
193 else if (port_ == GPIOB)
194 {
195 port_source = GPIO_PortSourceGPIOB;
196 }
197#endif
198#if defined(GPIOC)
199 else if (port_ == GPIOC)
200 {
201 port_source = GPIO_PortSourceGPIOC;
202 }
203#endif
204#if defined(GPIOD)
205 else if (port_ == GPIOD)
206 {
207 port_source = GPIO_PortSourceGPIOD;
208 }
209#endif
210#if defined(GPIOE)
211 else if (port_ == GPIOE)
212 {
213 port_source = GPIO_PortSourceGPIOE;
214 }
215#endif
216#if defined(GPIOF)
217 else if (port_ == GPIOF)
218 {
219 port_source = GPIO_PortSourceGPIOF;
220 }
221#endif
222#if defined(GPIOG)
223 else if (port_ == GPIOG)
224 {
225 port_source = GPIO_PortSourceGPIOG;
226 }
227#endif
228#if defined(GPIOH)
229 else if (port_ == GPIOH)
230 {
231 port_source = GPIO_PortSourceGPIOH;
232 }
233#endif
234#if defined(GPIOI)
235 else if (port_ == GPIOI)
236 {
237 port_source = GPIO_PortSourceGPIOI;
238 }
239#endif
240
241 ASSERT(port_source != 0xFF);
242
243 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
244 GPIO_EXTILineConfig(port_source, pin_source);
245
246 exti.EXTI_Line = 1 << pin_source;
247 exti.EXTI_Mode = EXTI_Mode_Interrupt;
248 exti.EXTI_Trigger = trigger;
249 exti.EXTI_LineCmd = ENABLE;
250 EXTI_Init(&exti);
251
252 NVIC_EnableIRQ(irq_);
253}
254
255uint8_t CH32GPIO::GetEXTIID(uint16_t pin)
256{
257 ASSERT(pin != 0 && (pin & static_cast<uint16_t>(pin - 1)) == 0);
258 return __builtin_ctz(pin);
259}
260
261// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
ErrorCode DisableInterrupt() override
禁用 GPIO 引脚中断。Disables the GPIO pin interrupt.
CH32GPIO(GPIO_TypeDef *port, uint16_t pin, GPIO::Direction direction=GPIO::Direction::OUTPUT_PUSH_PULL, GPIO::Pull pull=GPIO::Pull::NONE, IRQn_Type irq=NonMaskableInt_IRQn)
构造 GPIO 对象 / Construct GPIO object
Definition ch32_gpio.cpp:95
ErrorCode EnableInterrupt() override
使能 GPIO 引脚中断。Enables the GPIO pin interrupt.
static CH32GPIO * map_[16]
EXTI 线路映射表 / EXTI line map.
bool Empty() const
检查回调是否为空 / Check whether the callback is empty
Definition libxr_cb.hpp:247
Callback callback_
GPIO 事件的回调函数。Callback function for GPIO events.
Definition gpio.hpp:56
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.
Pull
定义 GPIO 引脚的上拉/下拉模式。Defines the pull-up/pull-down configurations for GPIO pins.
Definition gpio.hpp:35
@ DOWN
下拉模式。Pull-down mode.
@ UP
上拉模式。Pull-up mode.
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
Definition libxr_def.hpp:64
@ OK
操作成功 | Operation successful