libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_gpio.hpp
1#pragma once
2
3#include "gpio.hpp"
4#include "main.h"
5
6#ifdef HAL_GPIO_MODULE_ENABLED
7
8#if (defined(GPIO_CRL_MODE0) || defined(GPIO_CRL_MODE0_Msk)) && \
9 (defined(GPIO_CRL_CNF0) || defined(GPIO_CRL_CNF0_Msk))
10#define XR_STM32_GPIO_HAS_F1_LAYOUT 1
11#else
12#define XR_STM32_GPIO_HAS_F1_LAYOUT 0
13#endif
14
15#if defined(GPIO_MODER_MODE0) || defined(GPIO_MODER_MODE0_Msk) || \
16 defined(GPIO_MODER_MODER0) || defined(GPIO_MODER_MODER0_Msk)
17#define XR_STM32_GPIO_HAS_MODER_FIELD 1
18#else
19#define XR_STM32_GPIO_HAS_MODER_FIELD 0
20#endif
21
22#if defined(GPIO_OTYPER_OT0) || defined(GPIO_OTYPER_OT0_Msk) || \
23 defined(GPIO_OTYPER_OT_0) || defined(GPIO_OTYPER_OT_0_Msk)
24#define XR_STM32_GPIO_HAS_OTYPER_FIELD 1
25#else
26#define XR_STM32_GPIO_HAS_OTYPER_FIELD 0
27#endif
28
29#if defined(GPIO_PUPDR_PUPD0) || defined(GPIO_PUPDR_PUPD0_Msk) || \
30 defined(GPIO_PUPDR_PUPDR0) || defined(GPIO_PUPDR_PUPDR0_Msk)
31#define XR_STM32_GPIO_HAS_PUPDR_FIELD 1
32#else
33#define XR_STM32_GPIO_HAS_PUPDR_FIELD 0
34#endif
35
36#if XR_STM32_GPIO_HAS_MODER_FIELD && XR_STM32_GPIO_HAS_OTYPER_FIELD && \
37 XR_STM32_GPIO_HAS_PUPDR_FIELD
38#define XR_STM32_GPIO_HAS_MODER_LAYOUT 1
39#else
40#define XR_STM32_GPIO_HAS_MODER_LAYOUT 0
41#endif
42
43#if defined(GPIO_OSPEEDR_OSPEED0) || defined(GPIO_OSPEEDR_OSPEED0_Msk) || \
44 defined(GPIO_OSPEEDR_OSPEEDR0) || defined(GPIO_OSPEEDR_OSPEEDR0_Msk) || \
45 defined(GPIO_OSPEEDER_OSPEEDR0) || defined(GPIO_OSPEEDER_OSPEEDR0_Msk)
46#define XR_STM32_GPIO_HAS_OSPEEDR 1
47#else
48#define XR_STM32_GPIO_HAS_OSPEEDR 0
49#endif
50
51#if XR_STM32_GPIO_HAS_F1_LAYOUT && XR_STM32_GPIO_HAS_MODER_LAYOUT
52#error \
53 "Ambiguous STM32 GPIO layout detection: both F1 and MODER layout signatures are present."
54#endif
55
56namespace LibXR
57{
61class STM32GPIO final : public GPIO
62{
63 public:
67 STM32GPIO(GPIO_TypeDef* port, uint16_t pin, IRQn_Type irq = NonMaskableInt_IRQn);
68
69 inline bool Read() { return (port_->IDR & pin_) != 0u; }
70
71 inline void Write(bool value)
72 {
73 if (value)
74 {
75 port_->BSRR = static_cast<uint32_t>(pin_);
76 }
77 else
78 {
79 port_->BSRR = static_cast<uint32_t>(pin_) << 16;
80 }
81 }
82
84
86
88 {
89 const bool IS_NON_IRQ_DIRECTION =
90 static_cast<uint8_t>(config.direction) <=
92
93 if (IS_NON_IRQ_DIRECTION)
94 {
95 const uint32_t PIN_POS = static_cast<uint32_t>(__builtin_ctz(pin_));
96
97#if XR_STM32_GPIO_HAS_F1_LAYOUT
98 // 寄存器快路径(F1 类):CRL/CRH 格式 / Register fast path (F1 class): CRL/CRH.
99 volatile uint32_t* cr = (PIN_POS < 8u) ? &port_->CRL : &port_->CRH;
100 const uint32_t SHIFT = (PIN_POS & 0x7u) * 4u;
101 uint32_t mode_cnf = 0u;
102
103 if (config.direction == Direction::INPUT)
104 {
105 if (config.pull == Pull::UP || config.pull == Pull::DOWN)
106 {
107 // MODE=00, CNF=10(上拉/下拉输入)/ Input with pull-up/pull-down.
108 mode_cnf = 0x8u;
109 if (config.pull == Pull::UP)
110 {
111 port_->BSRR = static_cast<uint32_t>(pin_);
112 }
113 else
114 {
115 port_->BSRR = static_cast<uint32_t>(pin_) << 16u;
116 }
117 }
118 else
119 {
120 // MODE=00, CNF=01(浮空输入)/ Floating input.
121 mode_cnf = 0x4u;
122 }
123 }
124 else if (config.direction == Direction::OUTPUT_PUSH_PULL)
125 {
126 // MODE=11(50MHz), CNF=00(推挽输出)/ General purpose output push-pull.
127 mode_cnf = 0x3u;
128 }
129 else
130 {
131 // MODE=11(50MHz), CNF=01(开漏输出)/ General purpose output open-drain.
132 mode_cnf = 0x7u;
133 }
134
135 uint32_t reg = *cr;
136 reg &= ~(0xFu << SHIFT);
137 reg |= (mode_cnf << SHIFT);
138 *cr = reg;
139 return ErrorCode::OK;
140
141#elif XR_STM32_GPIO_HAS_MODER_LAYOUT
142 // 寄存器快路径(MODER 类):MODER/OTYPER/PUPDR/OSPEEDR / Register fast path (MODER
143 // class).
144 const uint32_t SHIFT = PIN_POS * 2u;
145 const uint32_t MASK2 = 0x3u << SHIFT;
146
147 uint32_t moder = port_->MODER;
148 moder &= ~MASK2;
149 if (config.direction != Direction::INPUT)
150 {
151 moder |= (0x1u << SHIFT); // MODER=01:通用输出 / General purpose output.
152 }
153 port_->MODER = moder;
154
155 if (config.direction != Direction::INPUT)
156 {
157 const uint32_t PIN_MASK = 0x1u << PIN_POS;
159 {
160 port_->OTYPER |= PIN_MASK;
161 }
162 else
163 {
164 port_->OTYPER &= ~PIN_MASK;
165 }
166
167#if XR_STM32_GPIO_HAS_OSPEEDR
168 uint32_t ospeedr = port_->OSPEEDR;
169 ospeedr &= ~MASK2;
170 ospeedr |= (0x3u << SHIFT); // SWD 方向切换用最高速率 / Fastest slew for SWD.
171 port_->OSPEEDR = ospeedr;
172#endif
173 }
174
175 uint32_t pupdr = port_->PUPDR;
176 pupdr &= ~MASK2;
177 if (config.pull == Pull::UP)
178 {
179 pupdr |= (0x1u << SHIFT);
180 }
181 else if (config.pull == Pull::DOWN)
182 {
183 pupdr |= (0x2u << SHIFT);
184 }
185 port_->PUPDR = pupdr;
186 return ErrorCode::OK;
187#endif
188 }
189
190 GPIO_InitTypeDef gpio_init = {};
191
192 gpio_init.Pin = pin_;
193
194 switch (config.direction)
195 {
196 case Direction::INPUT:
197 gpio_init.Mode = GPIO_MODE_INPUT;
198 break;
200 gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
201 break;
203 gpio_init.Mode = GPIO_MODE_OUTPUT_OD;
204 break;
206 gpio_init.Mode = GPIO_MODE_IT_FALLING;
207 break;
209 gpio_init.Mode = GPIO_MODE_IT_RISING;
210 break;
212 gpio_init.Mode = GPIO_MODE_IT_RISING_FALLING;
213 break;
214 }
215
216 switch (config.pull)
217 {
218 case Pull::NONE:
219 gpio_init.Pull = GPIO_NOPULL;
220 break;
221 case Pull::UP:
222 gpio_init.Pull = GPIO_PULLUP;
223 break;
224 case Pull::DOWN:
225 gpio_init.Pull = GPIO_PULLDOWN;
226 break;
227 }
228
229 gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
230
231 HAL_GPIO_Init(port_, &gpio_init);
232
233 return ErrorCode::OK;
234 }
235
236 static STM32GPIO* map[16]; // NOLINT
237
238 private:
239 GPIO_TypeDef* port_;
240 uint16_t pin_;
241 IRQn_Type irq_;
242};
243
244} // namespace LibXR
245
246#endif
通用输入输出(GPIO)接口类。General Purpose Input/Output (GPIO) interface class.
Definition gpio.hpp:13
@ 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.
STM32 GPIO 驱动实现 / STM32 GPIO driver implementation.
bool Read()
读取 GPIO 引脚状态。Reads the GPIO pin state.
ErrorCode SetConfig(Configuration config)
配置 GPIO 引脚参数。Configures the GPIO pin settings.
STM32GPIO(GPIO_TypeDef *port, uint16_t pin, IRQn_Type irq=NonMaskableInt_IRQn)
构造 GPIO 对象 / Construct GPIO object
void Write(bool value)
写入 GPIO 引脚状态。Writes the GPIO pin state.
ErrorCode DisableInterrupt()
禁用 GPIO 引脚中断。Disables the GPIO pin interrupt.
ErrorCode EnableInterrupt()
使能 GPIO 引脚中断。Enables the GPIO pin interrupt.
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ OK
操作成功 | Operation successful
存储 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