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) || defined(GPIO_MODER_MODER0) || \
16 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) || defined(GPIO_OTYPER_OT_0) || \
23 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) || defined(GPIO_PUPDR_PUPDR0) || \
30 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 && XR_STM32_GPIO_HAS_PUPDR_FIELD
37#define XR_STM32_GPIO_HAS_MODER_LAYOUT 1
38#else
39#define XR_STM32_GPIO_HAS_MODER_LAYOUT 0
40#endif
41
42#if defined(GPIO_OSPEEDR_OSPEED0) || defined(GPIO_OSPEEDR_OSPEED0_Msk) || \
43 defined(GPIO_OSPEEDR_OSPEEDR0) || defined(GPIO_OSPEEDR_OSPEEDR0_Msk) || \
44 defined(GPIO_OSPEEDER_OSPEEDR0) || defined(GPIO_OSPEEDER_OSPEEDR0_Msk)
45#define XR_STM32_GPIO_HAS_OSPEEDR 1
46#else
47#define XR_STM32_GPIO_HAS_OSPEEDR 0
48#endif
49
50#if XR_STM32_GPIO_HAS_F1_LAYOUT && XR_STM32_GPIO_HAS_MODER_LAYOUT
51#error "Ambiguous STM32 GPIO layout detection: both F1 and MODER layout signatures are present."
52#endif
53
54namespace LibXR
55{
59class STM32GPIO final : public GPIO
60{
61 public:
65 STM32GPIO(GPIO_TypeDef* port, uint16_t pin, IRQn_Type irq = NonMaskableInt_IRQn);
66
67 inline bool Read() { return (port_->IDR & pin_) != 0u; }
68
69 inline void Write(bool value)
70 {
71 if (value)
72 {
73 port_->BSRR = static_cast<uint32_t>(pin_);
74 }
75 else
76 {
77 port_->BSRR = static_cast<uint32_t>(pin_) << 16;
78 }
79 }
80
82
84
86 {
87 const bool IS_NON_IRQ_DIRECTION =
88 static_cast<uint8_t>(config.direction) <=
90
91 if (IS_NON_IRQ_DIRECTION)
92 {
93 const uint32_t PIN_POS = static_cast<uint32_t>(__builtin_ctz(pin_));
94
95#if XR_STM32_GPIO_HAS_F1_LAYOUT
96 // 寄存器快路径(F1 类):CRL/CRH 格式 / Register fast path (F1 class): CRL/CRH.
97 volatile uint32_t* cr = (PIN_POS < 8u) ? &port_->CRL : &port_->CRH;
98 const uint32_t SHIFT = (PIN_POS & 0x7u) * 4u;
99 uint32_t mode_cnf = 0u;
100
101 if (config.direction == Direction::INPUT)
102 {
103 if (config.pull == Pull::UP || config.pull == Pull::DOWN)
104 {
105 // MODE=00, CNF=10(上拉/下拉输入)/ Input with pull-up/pull-down.
106 mode_cnf = 0x8u;
107 if (config.pull == Pull::UP)
108 {
109 port_->BSRR = static_cast<uint32_t>(pin_);
110 }
111 else
112 {
113 port_->BSRR = static_cast<uint32_t>(pin_) << 16u;
114 }
115 }
116 else
117 {
118 // MODE=00, CNF=01(浮空输入)/ Floating input.
119 mode_cnf = 0x4u;
120 }
121 }
122 else if (config.direction == Direction::OUTPUT_PUSH_PULL)
123 {
124 // MODE=11(50MHz), CNF=00(推挽输出)/ General purpose output push-pull.
125 mode_cnf = 0x3u;
126 }
127 else
128 {
129 // MODE=11(50MHz), CNF=01(开漏输出)/ General purpose output open-drain.
130 mode_cnf = 0x7u;
131 }
132
133 uint32_t reg = *cr;
134 reg &= ~(0xFu << SHIFT);
135 reg |= (mode_cnf << SHIFT);
136 *cr = reg;
137 return ErrorCode::OK;
138
139#elif XR_STM32_GPIO_HAS_MODER_LAYOUT
140 // 寄存器快路径(MODER 类):MODER/OTYPER/PUPDR/OSPEEDR / Register fast path (MODER
141 // class).
142 const uint32_t SHIFT = PIN_POS * 2u;
143 const uint32_t MASK2 = 0x3u << SHIFT;
144
145 uint32_t moder = port_->MODER;
146 moder &= ~MASK2;
147 if (config.direction != Direction::INPUT)
148 {
149 moder |= (0x1u << SHIFT); // MODER=01:通用输出 / General purpose output.
150 }
151 port_->MODER = moder;
152
153 if (config.direction != Direction::INPUT)
154 {
155 const uint32_t PIN_MASK = 0x1u << PIN_POS;
157 {
158 port_->OTYPER |= PIN_MASK;
159 }
160 else
161 {
162 port_->OTYPER &= ~PIN_MASK;
163 }
164
165#if XR_STM32_GPIO_HAS_OSPEEDR
166 uint32_t ospeedr = port_->OSPEEDR;
167 ospeedr &= ~MASK2;
168 ospeedr |= (0x3u << SHIFT); // SWD 方向切换用最高速率 / Fastest slew for SWD.
169 port_->OSPEEDR = ospeedr;
170#endif
171 }
172
173 uint32_t pupdr = port_->PUPDR;
174 pupdr &= ~MASK2;
175 if (config.pull == Pull::UP)
176 {
177 pupdr |= (0x1u << SHIFT);
178 }
179 else if (config.pull == Pull::DOWN)
180 {
181 pupdr |= (0x2u << SHIFT);
182 }
183 port_->PUPDR = pupdr;
184 return ErrorCode::OK;
185#endif
186 }
187
188 GPIO_InitTypeDef gpio_init = {};
189
190 gpio_init.Pin = pin_;
191
192 switch (config.direction)
193 {
194 case Direction::INPUT:
195 gpio_init.Mode = GPIO_MODE_INPUT;
196 break;
198 gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
199 break;
201 gpio_init.Mode = GPIO_MODE_OUTPUT_OD;
202 break;
204 gpio_init.Mode = GPIO_MODE_IT_FALLING;
205 break;
207 gpio_init.Mode = GPIO_MODE_IT_RISING;
208 break;
210 gpio_init.Mode = GPIO_MODE_IT_RISING_FALLING;
211 break;
212 }
213
214 switch (config.pull)
215 {
216 case Pull::NONE:
217 gpio_init.Pull = GPIO_NOPULL;
218 break;
219 case Pull::UP:
220 gpio_init.Pull = GPIO_PULLUP;
221 break;
222 case Pull::DOWN:
223 gpio_init.Pull = GPIO_PULLDOWN;
224 break;
225 }
226
227 gpio_init.Speed = GPIO_SPEED_FREQ_HIGH;
228
229 HAL_GPIO_Init(port_, &gpio_init);
230
231 return ErrorCode::OK;
232 }
233
234 static STM32GPIO* map[16]; // NOLINT
235
236 private:
237 GPIO_TypeDef* port_;
238 uint16_t pin_;
239 IRQn_Type irq_;
240};
241
242} // namespace LibXR
243
244#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