libxr
Embedded C++ framework for bare-metal, RTOS and Linux
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:14
@ 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 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ OK
操作成功 / Operation successful
存储 GPIO 配置参数的结构体 / Structure storing GPIO configuration parameters.
Definition gpio.hpp:47
Pull pull
GPIO 上拉/下拉配置 / GPIO pull-up/pull-down configuration.
Definition gpio.hpp:49
Direction direction
GPIO 引脚方向 / GPIO pin direction.
Definition gpio.hpp:48