libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_i2c.hpp
1#pragma once
2
3#include "main.h"
4
5#ifdef HAL_I2C_MODULE_ENABLED
6
7#ifdef I2C
8#undef I2C
9#endif
10
11#include "i2c.hpp"
12#include "libxr.hpp"
13
14typedef enum
15{
16#ifdef I2C1
17 STM32_I2C1,
18#endif
19#ifdef I2C2
20 STM32_I2C2,
21#endif
22#ifdef I2C3
23 STM32_I2C3,
24#endif
25#ifdef I2C4
26 STM32_I2C4,
27#endif
28#ifdef I2C5
29 STM32_I2C5,
30#endif
31#ifdef I2C6
32 STM32_I2C6,
33#endif
34#ifdef I2C7
35 STM32_I2C7,
36#endif
37#ifdef I2C8
38 STM32_I2C8,
39#endif
40 STM32_I2C_NUMBER,
41 STM32_I2C_ID_ERROR
42} stm32_i2c_id_t;
43
44stm32_i2c_id_t STM32_I2C_GetID(I2C_TypeDef *hi2c); // NOLINT
45
46namespace LibXR
47{
48class STM32I2C : public I2C
49{
50 public:
51 STM32I2C(I2C_HandleTypeDef *hi2c, RawData dma_buff, uint32_t dma_enable_min_size = 3)
52 : I2C(),
53 id_(STM32_I2C_GetID(hi2c->Instance)),
54 i2c_handle_(hi2c),
55 dma_enable_min_size_(dma_enable_min_size),
56 dma_buff_(dma_buff)
57 {
58 map[id_] = this;
59 }
60
61 ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op) override
62 {
63 if (i2c_handle_->State != HAL_I2C_STATE_READY)
64 {
65 return ErrorCode::BUSY;
66 }
67
68 read_ = true;
69
70 if (read_data.size_ > dma_enable_min_size_)
71 {
72 read_op_ = op;
73 HAL_I2C_Master_Receive_DMA(i2c_handle_, slave_addr,
74 reinterpret_cast<uint8_t *>(dma_buff_.addr_),
75 read_data.size_);
76 read_buff_ = read_data;
77 op.MarkAsRunning();
78 if (op.type == ReadOperation::OperationType::BLOCK)
79 {
80 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
81 }
82 return ErrorCode::OK;
83 }
84 else
85 {
86 auto ans = HAL_I2C_Master_Receive(i2c_handle_, slave_addr,
87 reinterpret_cast<uint8_t *>(read_data.addr_),
88 read_data.size_, 20) == HAL_OK
89 ? ErrorCode::OK
90 : ErrorCode::BUSY;
91 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
92 if (op.type == ReadOperation::OperationType::BLOCK)
93 {
94 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
95 }
96 return ans;
97 }
98 }
99
100 ErrorCode Write(uint16_t slave_addr, ConstRawData write_data,
101 WriteOperation &op) override
102 {
103 if (i2c_handle_->State != HAL_I2C_STATE_READY)
104 {
105 return ErrorCode::BUSY;
106 }
107
108 read_ = false;
109
110 memcpy(dma_buff_.addr_, write_data.addr_, write_data.size_);
111
112 if (write_data.size_ > dma_enable_min_size_)
113 {
114 write_op_ = op;
115#if __DCACHE_PRESENT
116 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(dma_buff_.addr_), write_data.size_);
117#endif
118 HAL_I2C_Master_Transmit_DMA(i2c_handle_, slave_addr,
119 reinterpret_cast<uint8_t *>(dma_buff_.addr_),
120 write_data.size_);
121 op.MarkAsRunning();
122 if (op.type == WriteOperation::OperationType::BLOCK)
123 {
124 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
125 }
126 return ErrorCode::OK;
127 }
128 else
129 {
130 auto ans = HAL_I2C_Master_Transmit(i2c_handle_, slave_addr,
131 reinterpret_cast<uint8_t *>(dma_buff_.addr_),
132 write_data.size_, 20) == HAL_OK
133 ? ErrorCode::OK
134 : ErrorCode::BUSY;
135 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
136 if (op.type == WriteOperation::OperationType::BLOCK)
137 {
138 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
139 }
140 return ans;
141 }
142 }
143
144 ErrorCode MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
145 ReadOperation &op, MemAddrLength mem_addr_size) override
146 {
147 ASSERT(read_data.size_ <= dma_buff_.size_);
148
149 if (i2c_handle_->State != HAL_I2C_STATE_READY)
150 {
151 return ErrorCode::BUSY;
152 }
153
154 read_ = true;
155
156 if (read_data.size_ > dma_enable_min_size_)
157 {
158 read_op_ = op;
159 HAL_I2C_Mem_Read_DMA(i2c_handle_, slave_addr, mem_addr,
160 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
161 : I2C_MEMADD_SIZE_16BIT,
162 reinterpret_cast<uint8_t *>(dma_buff_.addr_), read_data.size_);
163 read_buff_ = read_data;
164 op.MarkAsRunning();
165 if (op.type == ReadOperation::OperationType::BLOCK)
166 {
167 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
168 }
169 return ErrorCode::OK;
170 }
171 else
172 {
173 auto ans =
174 HAL_I2C_Mem_Read(i2c_handle_, slave_addr, mem_addr,
175 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
176 : I2C_MEMADD_SIZE_16BIT,
177 reinterpret_cast<uint8_t *>(read_data.addr_), read_data.size_,
178 20) == HAL_OK
179 ? ErrorCode::OK
180 : ErrorCode::BUSY;
181
182 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
183 if (op.type == ReadOperation::OperationType::BLOCK)
184 {
185 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
186 }
187 return ans;
188 }
189 }
190
191 ErrorCode MemWrite(uint16_t slave_addr, uint16_t mem_addr, ConstRawData write_data,
192 WriteOperation &op, MemAddrLength mem_addr_size) override
193 {
194 ASSERT(write_data.size_ <= dma_buff_.size_);
195
196 if (i2c_handle_->State != HAL_I2C_STATE_READY)
197 {
198 return ErrorCode::BUSY;
199 }
200
201 read_ = false;
202
203 memcpy(dma_buff_.addr_, write_data.addr_, write_data.size_);
204
205 if (write_data.size_ > dma_enable_min_size_)
206 {
207 write_op_ = op;
208#if __DCACHE_PRESENT
209 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(dma_buff_.addr_), write_data.size_);
210#endif
211 HAL_I2C_Mem_Write_DMA(
212 i2c_handle_, slave_addr, mem_addr,
213 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
214 : I2C_MEMADD_SIZE_16BIT,
215 reinterpret_cast<uint8_t *>(dma_buff_.addr_), write_data.size_);
216 op.MarkAsRunning();
217 if (op.type == WriteOperation::OperationType::BLOCK)
218 {
219 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
220 }
221 return ErrorCode::OK;
222 }
223 else
224 {
225 auto ans = HAL_I2C_Mem_Write(i2c_handle_, slave_addr, mem_addr,
226 mem_addr_size == MemAddrLength::BYTE_8
227 ? I2C_MEMADD_SIZE_8BIT
228 : I2C_MEMADD_SIZE_16BIT,
229 reinterpret_cast<uint8_t *>(dma_buff_.addr_),
230 write_data.size_, 20) == HAL_OK
231 ? ErrorCode::OK
232 : ErrorCode::BUSY;
233
234 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
235 if (op.type == WriteOperation::OperationType::BLOCK)
236 {
237 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
238 }
239 return ans;
240 }
241 }
242
243 template <typename, typename = void>
244 struct HasClockSpeed : std::false_type
245 {
246 };
247
248 template <typename T>
249 struct HasClockSpeed<T, std::void_t<decltype(std::declval<T>()->Init.ClockSpeed)>>
250 : std::true_type
251 {
252 };
253
254 template <typename T>
255 typename std::enable_if<!HasClockSpeed<T>::value>::type SetClockSpeed(
256 T &, const Configuration &)
257 {
258 }
259
260 template <typename T>
261 typename std::enable_if<HasClockSpeed<T>::value>::type SetClockSpeed(
262 T &i2c_handle, const Configuration &config)
263 {
264 i2c_handle->Init.ClockSpeed = config.clock_speed;
265 }
266
267 ErrorCode SetConfig(Configuration config) override
268 {
269 if (HasClockSpeed<decltype(i2c_handle_)>::value)
270 {
271 SetClockSpeed<decltype(i2c_handle_)>(i2c_handle_, config);
272 }
273 else
274 {
275 return ErrorCode::NOT_SUPPORT;
276 }
277
278 if (HAL_I2C_Init(i2c_handle_) != HAL_OK)
279 {
280 return ErrorCode::INIT_ERR;
281 }
282 return ErrorCode::OK;
283 }
284
285 stm32_i2c_id_t id_;
286 I2C_HandleTypeDef *i2c_handle_;
287 uint32_t dma_enable_min_size_;
288
289 RawData dma_buff_;
290
291 ReadOperation read_op_;
292 WriteOperation write_op_;
293 RawData read_buff_;
294
295 bool read_ = false;
296
297 static STM32I2C *map[STM32_I2C_NUMBER]; // NOLINT
298};
299} // namespace LibXR
300
301#endif
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
I2C(Inter-Integrated Circuit)接口类。 I2C (Inter-Integrated Circuit) interface class.
Definition i2c.hpp:17
I2C()
默认构造函数。 Default constructor.
Definition i2c.hpp:39
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:204
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
Definition libxr_rw.hpp:173
union LibXR::Operation::@4 data
OperationType type
Definition libxr_rw.hpp:227
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ErrorCode MemWrite(uint16_t slave_addr, uint16_t mem_addr, ConstRawData write_data, WriteOperation &op, MemAddrLength mem_addr_size) override
向 I2C 设备指定寄存器写入数据。 Writes data to a specific register of an I2C device.
ErrorCode SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
ErrorCode MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data, ReadOperation &op, MemAddrLength mem_addr_size) override
从 I2C 设备指定寄存器读取数据。 Reads data from a specific register of an I2C device.
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op) override
向 I2C 设备写入数据。 Writes data to an I2C device.
ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op) override
读取 I2C 设备的数据。 Reads data from an I2C device.
Definition stm32_i2c.hpp:61
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
LibXR 命名空间
Definition ch32_gpio.hpp:9
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.
Definition i2c.hpp:24