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));
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));
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));
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));
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));
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));
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) __attribute__((interrupt));
83// NOLINTNEXTLINE(readability-identifier-naming)
84extern "C" void EXTI15_10_IRQHandler(void)
85{
86 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line10);
87 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line11);
88 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line12);
89 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line13);
90 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line14);
91 LibXR::CH32GPIO::CheckInterrupt(EXTI_Line15);
92}
93
94CH32GPIO::CH32GPIO(GPIO_TypeDef* port, uint16_t pin, GPIO::Direction direction,
95 GPIO::Pull pull, IRQn_Type irq)
96 : port_(port), pin_(pin), irq_(irq)
97{
98 if (irq_ != NonMaskableInt_IRQn)
99 {
100 map_[GetEXTIID(pin)] = this;
101 }
102
103 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(port_), ENABLE);
104
105 GPIO_InitTypeDef gpio_init = {};
106 gpio_init.GPIO_Pin = pin_;
107 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
108
109 switch (direction)
110 {
114 case Direction::INPUT:
115 gpio_init.GPIO_Mode = (pull == Pull::UP) ? GPIO_Mode_IPU
116 : (pull == Pull::DOWN) ? GPIO_Mode_IPD
117 : GPIO_Mode_IN_FLOATING;
118 break;
120 gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
121 break;
123 gpio_init.GPIO_Mode = GPIO_Mode_Out_OD;
124 break;
125 }
126
127 GPIO_Init(port_, &gpio_init);
128
129 switch (direction)
130 {
132 ConfigureEXTI(EXTI_Trigger_Rising);
133 break;
135 ConfigureEXTI(EXTI_Trigger_Falling);
136 break;
138 ConfigureEXTI(EXTI_Trigger_Rising_Falling);
139 break;
140 default:
141 break;
142 }
143}
144
146{
147 EXTI->INTENR |= static_cast<uint32_t>(pin_);
148 return ErrorCode::OK;
149}
150
152{
153 EXTI->INTENR &= ~static_cast<uint32_t>(pin_);
154 return ErrorCode::OK;
155}
156
157void CH32GPIO::OnInterrupt()
158{
159 if (!callback_.Empty())
160 {
161 callback_.Run(true);
162 }
163}
164
165void CH32GPIO::CheckInterrupt(uint32_t line)
166{
167 if (EXTI_GetITStatus(line) != RESET)
168 {
169 EXTI_ClearITPendingBit(line);
170
171 const uint8_t ID = GetEXTIID(static_cast<uint16_t>(line));
172 if (auto* gpio = map_[ID])
173 {
174 gpio->OnInterrupt();
175 }
176 }
177}
178
179void CH32GPIO::ConfigureEXTI(EXTITrigger_TypeDef trigger)
180{
181 EXTI_InitTypeDef exti = {};
182 uint8_t pin_source = GetEXTIID(pin_);
183 uint8_t port_source = 0xFF;
184
185#if defined(GPIOA)
186 if (port_ == GPIOA)
187 {
188 port_source = GPIO_PortSourceGPIOA;
189#endif
190#if defined(GPIOB)
191 }
192 else if (port_ == GPIOB)
193 {
194 port_source = GPIO_PortSourceGPIOB;
195 }
196#endif
197#if defined(GPIOC)
198 else if (port_ == GPIOC)
199 {
200 port_source = GPIO_PortSourceGPIOC;
201 }
202#endif
203#if defined(GPIOD)
204 else if (port_ == GPIOD)
205 {
206 port_source = GPIO_PortSourceGPIOD;
207 }
208#endif
209#if defined(GPIOE)
210 else if (port_ == GPIOE)
211 {
212 port_source = GPIO_PortSourceGPIOE;
213 }
214#endif
215#if defined(GPIOF)
216 else if (port_ == GPIOF)
217 {
218 port_source = GPIO_PortSourceGPIOF;
219 }
220#endif
221#if defined(GPIOG)
222 else if (port_ == GPIOG)
223 {
224 port_source = GPIO_PortSourceGPIOG;
225 }
226#endif
227#if defined(GPIOH)
228 else if (port_ == GPIOH)
229 {
230 port_source = GPIO_PortSourceGPIOH;
231 }
232#endif
233#if defined(GPIOI)
234 else if (port_ == GPIOI)
235 {
236 port_source = GPIO_PortSourceGPIOI;
237 }
238#endif
239
240 ASSERT(port_source != 0xFF);
241
242 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
243 GPIO_EXTILineConfig(port_source, pin_source);
244
245 exti.EXTI_Line = 1 << pin_source;
246 exti.EXTI_Mode = EXTI_Mode_Interrupt;
247 exti.EXTI_Trigger = trigger;
248 exti.EXTI_LineCmd = ENABLE;
249 EXTI_Init(&exti);
250
251 NVIC_EnableIRQ(irq_);
252}
253
254uint8_t CH32GPIO::GetEXTIID(uint16_t pin)
255{
256 ASSERT(pin != 0 && (pin & static_cast<uint16_t>(pin - 1)) == 0);
257 return __builtin_ctz(pin);
258}
259
260// 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:94
ErrorCode EnableInterrupt() override
使能 GPIO 引脚中断。Enables the GPIO pin interrupt.
static CH32GPIO * map_[16]
EXTI 线路映射表 / EXTI line map.
void Run(bool in_isr, PassArgs &&... args) const
执行回调函数并传递参数 / Execute the callback with arguments
Definition libxr_cb.hpp:225
bool Empty() const
检查回调是否为空 / Check whether the callback is empty
Definition libxr_cb.hpp:236
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