libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_i2c.cpp
1#include "stm32_i2c.hpp"
2
3#ifdef HAL_I2C_MODULE_ENABLED
4
5using namespace LibXR;
6
7STM32I2C *STM32I2C::map[STM32_I2C_NUMBER] = {nullptr};
8
9stm32_i2c_id_t STM32_I2C_GetID(I2C_TypeDef *hi2c)
10{ // NOLINT
11 if (hi2c == nullptr)
12 {
13 return stm32_i2c_id_t::STM32_I2C_ID_ERROR;
14 }
15#ifdef I2C1
16 else if (hi2c == I2C1)
17 { // NOLINT
18 return stm32_i2c_id_t::STM32_I2C1;
19 }
20#endif
21#ifdef I2C2
22 else if (hi2c == I2C2)
23 { // NOLINT
24 return stm32_i2c_id_t::STM32_I2C2;
25 }
26#endif
27#ifdef I2C3
28 else if (hi2c == I2C3)
29 { // NOLINT
30 return stm32_i2c_id_t::STM32_I2C3;
31 }
32#endif
33#ifdef I2C4
34 else if (hi2c == I2C4)
35 { // NOLINT
36 return stm32_i2c_id_t::STM32_I2C4;
37 }
38#endif
39#ifdef I2C5
40 else if (hi2c == I2C5)
41 { // NOLINT
42 return stm32_i2c_id_t::STM32_I2C5;
43 }
44#endif
45#ifdef I2C6
46 else if (hi2c == I2C6)
47 { // NOLINT
48 return stm32_i2c_id_t::STM32_I2C6;
49 }
50#endif
51#ifdef I2C7
52 else if (hi2c == I2C7)
53 { // NOLINT
54 return stm32_i2c_id_t::STM32_I2C7;
55 }
56#endif
57#ifdef I2C8
58 else if (hi2c == I2C8)
59 { // NOLINT
60 return stm32_i2c_id_t::STM32_I2C8;
61 }
62#endif
63 return stm32_i2c_id_t::STM32_I2C_ID_ERROR;
64}
65
66STM32I2C::STM32I2C(I2C_HandleTypeDef *hi2c, RawData dma_buff,
67 uint32_t dma_enable_min_size)
68 : I2C(),
69 id_(STM32_I2C_GetID(hi2c->Instance)),
70 i2c_handle_(hi2c),
71 dma_enable_min_size_(dma_enable_min_size),
72 dma_buff_(dma_buff)
73{
74 map[id_] = this;
75}
76
77ErrorCode STM32I2C::Read(uint16_t slave_addr, RawData read_data, ReadOperation &op)
78{
79 if (i2c_handle_->State != HAL_I2C_STATE_READY)
80 {
81 return ErrorCode::BUSY;
82 }
83
84 read_ = true;
85
86 if (read_data.size_ > dma_enable_min_size_)
87 {
88 read_op_ = op;
89 HAL_I2C_Master_Receive_DMA(i2c_handle_, slave_addr,
90 reinterpret_cast<uint8_t *>(dma_buff_.addr_),
91 read_data.size_);
92 read_buff_ = read_data;
93 op.MarkAsRunning();
94 if (op.type == ReadOperation::OperationType::BLOCK)
95 {
96 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
97 }
98 return ErrorCode::OK;
99 }
100 else
101 {
102 auto ans = HAL_I2C_Master_Receive(i2c_handle_, slave_addr,
103 reinterpret_cast<uint8_t *>(read_data.addr_),
104 read_data.size_, 20) == HAL_OK
105 ? ErrorCode::OK
106 : ErrorCode::BUSY;
107 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
108 if (op.type == ReadOperation::OperationType::BLOCK)
109 {
110 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
111 }
112 return ans;
113 }
114}
115
116ErrorCode STM32I2C::Write(uint16_t slave_addr, ConstRawData write_data,
117 WriteOperation &op)
118{
119 if (i2c_handle_->State != HAL_I2C_STATE_READY)
120 {
121 return ErrorCode::BUSY;
122 }
123
124 read_ = false;
125
126 memcpy(dma_buff_.addr_, write_data.addr_, write_data.size_);
127
128 if (write_data.size_ > dma_enable_min_size_)
129 {
130 write_op_ = op;
131#if __DCACHE_PRESENT
132 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(dma_buff_.addr_),
133 write_data.size_);
134#endif
135 HAL_I2C_Master_Transmit_DMA(i2c_handle_, slave_addr,
136 reinterpret_cast<uint8_t *>(dma_buff_.addr_),
137 write_data.size_);
138 op.MarkAsRunning();
139 if (op.type == WriteOperation::OperationType::BLOCK)
140 {
141 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
142 }
143 return ErrorCode::OK;
144 }
145 else
146 {
147 auto ans = HAL_I2C_Master_Transmit(i2c_handle_, slave_addr,
148 reinterpret_cast<uint8_t *>(dma_buff_.addr_),
149 write_data.size_, 20) == HAL_OK
150 ? ErrorCode::OK
151 : ErrorCode::BUSY;
152 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
153 if (op.type == WriteOperation::OperationType::BLOCK)
154 {
155 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
156 }
157 return ans;
158 }
159}
160
161ErrorCode STM32I2C::MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
162 ReadOperation &op, MemAddrLength mem_addr_size)
163{
164 ASSERT(read_data.size_ <= dma_buff_.size_);
165
166 if (i2c_handle_->State != HAL_I2C_STATE_READY)
167 {
168 return ErrorCode::BUSY;
169 }
170
171 read_ = true;
172
173 if (read_data.size_ > dma_enable_min_size_)
174 {
175 read_op_ = op;
176 HAL_I2C_Mem_Read_DMA(i2c_handle_, slave_addr, mem_addr,
177 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
178 : I2C_MEMADD_SIZE_16BIT,
179 reinterpret_cast<uint8_t *>(dma_buff_.addr_), read_data.size_);
180 read_buff_ = read_data;
181 op.MarkAsRunning();
182 if (op.type == ReadOperation::OperationType::BLOCK)
183 {
184 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
185 }
186 return ErrorCode::OK;
187 }
188 else
189 {
190 auto ans =
191 HAL_I2C_Mem_Read(i2c_handle_, slave_addr, mem_addr,
192 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
193 : I2C_MEMADD_SIZE_16BIT,
194 reinterpret_cast<uint8_t *>(read_data.addr_), read_data.size_,
195 20) == HAL_OK
196 ? ErrorCode::OK
197 : ErrorCode::BUSY;
198
199 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
200 if (op.type == ReadOperation::OperationType::BLOCK)
201 {
202 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
203 }
204 return ans;
205 }
206}
207
208ErrorCode STM32I2C::MemWrite(uint16_t slave_addr, uint16_t mem_addr,
209 ConstRawData write_data, WriteOperation &op,
210 MemAddrLength mem_addr_size)
211{
212 ASSERT(write_data.size_ <= dma_buff_.size_);
213
214 if (i2c_handle_->State != HAL_I2C_STATE_READY)
215 {
216 return ErrorCode::BUSY;
217 }
218
219 read_ = false;
220
221 memcpy(dma_buff_.addr_, write_data.addr_, write_data.size_);
222
223 if (write_data.size_ > dma_enable_min_size_)
224 {
225 write_op_ = op;
226#if __DCACHE_PRESENT
227 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(dma_buff_.addr_),
228 write_data.size_);
229#endif
230 HAL_I2C_Mem_Write_DMA(i2c_handle_, slave_addr, mem_addr,
231 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
232 : I2C_MEMADD_SIZE_16BIT,
233 reinterpret_cast<uint8_t *>(dma_buff_.addr_), write_data.size_);
234 op.MarkAsRunning();
235 if (op.type == WriteOperation::OperationType::BLOCK)
236 {
237 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
238 }
239 return ErrorCode::OK;
240 }
241 else
242 {
243 auto ans =
244 HAL_I2C_Mem_Write(i2c_handle_, slave_addr, mem_addr,
245 mem_addr_size == MemAddrLength::BYTE_8 ? I2C_MEMADD_SIZE_8BIT
246 : I2C_MEMADD_SIZE_16BIT,
247 reinterpret_cast<uint8_t *>(dma_buff_.addr_), write_data.size_,
248 20) == HAL_OK
249 ? ErrorCode::OK
250 : ErrorCode::BUSY;
251
252 op.UpdateStatus(false, std::forward<ErrorCode>(ans));
253 if (op.type == WriteOperation::OperationType::BLOCK)
254 {
255 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
256 }
257 return ans;
258 }
259}
260
262{
263 if (HasClockSpeed<decltype(i2c_handle_)>::value)
264 {
265 SetClockSpeed<decltype(i2c_handle_)>(i2c_handle_, config);
266 }
267 else
268 {
269 return ErrorCode::NOT_SUPPORT;
270 }
271
272 if (HAL_I2C_Init(i2c_handle_) != HAL_OK)
273 {
274 return ErrorCode::INIT_ERR;
275 }
276 return ErrorCode::OK;
277}
278
279extern "C" void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
280{
281 STM32I2C *i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
282 if (i2c)
283 {
284#if __DCACHE_PRESENT
285 SCB_InvalidateDCache_by_Addr(i2c->dma_buff_.addr_, i2c->read_buff_.size_);
286#endif
287 memcpy(i2c->read_buff_.addr_, i2c->dma_buff_.addr_, i2c->read_buff_.size_);
288 i2c->read_op_.UpdateStatus(true, ErrorCode::OK);
289 }
290}
291
292extern "C" void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
293{
294 STM32I2C *i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
295 if (i2c)
296 {
297 i2c->write_op_.UpdateStatus(true, ErrorCode::OK);
298 }
299}
300
301extern "C" void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c)
302{
303 STM32I2C *i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
304 if (i2c)
305 {
306 i2c->write_op_.UpdateStatus(true, ErrorCode::OK);
307 }
308}
309
310extern "C" void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
311{
312 STM32I2C *i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
313 if (i2c)
314 {
315#if __DCACHE_PRESENT
316 SCB_InvalidateDCache_by_Addr(i2c->dma_buff_.addr_, i2c->read_buff_.size_);
317#endif
318 memcpy(i2c->read_buff_.addr_, i2c->dma_buff_.addr_, i2c->read_buff_.size_);
319 i2c->read_op_.UpdateStatus(true, ErrorCode::OK);
320 }
321}
322
323extern "C" void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
324{
325 STM32I2C *i2c = STM32I2C::map[STM32_I2C_GetID(hi2c->Instance)];
326
327 if (i2c)
328 {
329 if (i2c->read_)
330 {
331 i2c->read_op_.UpdateStatus(false, ErrorCode::FAILED);
332 }
333 else
334 {
335 i2c->write_op_.UpdateStatus(false, ErrorCode::FAILED);
336 }
337 }
338}
339
340#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
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:202
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
Definition libxr_rw.hpp:171
union LibXR::Operation::@4 data
OperationType type
Definition libxr_rw.hpp:225
原始数据封装类。 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 SetConfig(Configuration config) override
配置 I2C 设备参数。 Configures the I2C device settings.
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op) override
向 I2C 设备写入数据。 Writes data to an I2C device.
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 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 Read(uint16_t slave_addr, RawData read_data, ReadOperation &op) override
读取 I2C 设备的数据。 Reads data from an I2C device.
Definition stm32_i2c.cpp:77
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