semf
stm32i2cmaster.cpp
Go to the documentation of this file.
1
12
13#if defined(STM32) && defined(HAL_I2C_MODULE_ENABLED)
14
15namespace semf
16{
17LinkedQueue<Stm32I2cMaster> Stm32I2cMaster::m_queue;
18Stm32I2cMaster::Stm32I2cMaster(I2C_HandleTypeDef& hwHandle)
19: m_hwHandle(&hwHandle)
20{
21 queue()->push(*this);
22 canceled.connect(m_canceledSlot);
23}
24
26{
27 SEMF_INFO("init");
28 HAL_StatusTypeDef state = HAL_I2C_Init(m_hwHandle);
29 if (state != HAL_OK)
30 {
31 if (state == HAL_ERROR)
32 {
33 SEMF_ERROR("hal error");
34 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalError)));
35 }
36 else if (state == HAL_BUSY)
37 {
38 SEMF_ERROR("hal busy");
39 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalBusy)));
40 }
41 else if (state == HAL_TIMEOUT)
42 {
43 SEMF_ERROR("hal timeout");
44 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalTimeout)));
45 }
46 return;
47 }
48}
49
51{
52 SEMF_INFO("deinit");
53 HAL_StatusTypeDef state = HAL_I2C_DeInit(m_hwHandle);
54 if (state != HAL_OK)
55 {
56 if (state == HAL_ERROR)
57 {
58 SEMF_ERROR("hal error");
59 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalError)));
60 }
61 else if (state == HAL_BUSY)
62 {
63 SEMF_ERROR("hal busy");
64 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalBusy)));
65 }
66 else if (state == HAL_TIMEOUT)
67 {
68 SEMF_ERROR("hal timeout");
69 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalTimeout)));
70 }
71 return;
72 }
73}
74
76{
77 if (!isBusyWriting())
78 {
79 SEMF_WARNING("device was not writing");
80 return;
81 }
82 m_canceledSlot.setObject(writeStopped);
83 HAL_StatusTypeDef state = HAL_I2C_Master_Abort_IT(m_hwHandle, address());
84 if (state != HAL_OK)
85 {
86 if (state == HAL_ERROR)
87 {
88 SEMF_ERROR("hal error");
89 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopWrite_HalError)));
90 }
91 else if (state == HAL_BUSY)
92 {
93 SEMF_ERROR("hal busy");
94 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopWrite_HalBusy)));
95 }
96 else if (state == HAL_TIMEOUT)
97 {
98 SEMF_ERROR("hal timeout");
99 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopWrite_HalTimeout)));
100 }
101 return;
102 }
103}
104
106{
107 if (!isBusyReading())
108 {
109 SEMF_WARNING("device was not reading");
110 return;
111 }
112 m_canceledSlot.setObject(readStopped);
113 HAL_StatusTypeDef state = HAL_I2C_Master_Abort_IT(m_hwHandle, address());
114 if (state != HAL_OK)
115 {
116 if (state == HAL_ERROR)
117 {
118 SEMF_ERROR("hal error");
119 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopRead_HalError)));
120 }
121 else if (state == HAL_BUSY)
122 {
123 SEMF_ERROR("hal busy");
124 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopRead_HalBusy)));
125 }
126 else if (state == HAL_TIMEOUT)
127 {
128 SEMF_ERROR("hal timeout");
129 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopRead_HalTimeout)));
130 }
131 return;
132 }
133}
134
136{
137 SEMF_INFO("set frequency to %d hz", hz);
138 if (isBusyReading() || isBusyWriting())
139 {
140 SEMF_ERROR("is busy");
141 error(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SetFrequency_IsBusy)));
142 return;
143 }
144 deinit();
146 init();
147}
148
149void Stm32I2cMaster::checkAddress(uint8_t address)
150{
153 setBusy(true);
154 dataAvailable.connect(m_onAddressCheckedSlot);
155 readHardware(nullptr, 0);
156}
157
159{
161 return &queue;
162}
163
164void Stm32I2cMaster::systemIsrRead(I2C_HandleTypeDef& i2c)
165{
166 for (Stm32I2cMaster& i : *(queue()))
167 i.isrRead(i2c);
168}
169
170void Stm32I2cMaster::systemIsrWritten(I2C_HandleTypeDef& i2c)
171{
172 for (Stm32I2cMaster& i : *(queue()))
173 i.isrWritten(i2c);
174}
175
176void Stm32I2cMaster::systemIsrError(I2C_HandleTypeDef& i2c)
177{
178 for (Stm32I2cMaster& i : *(queue()))
179 i.isrError(i2c);
180}
181
182void Stm32I2cMaster::systemIsrAbort(I2C_HandleTypeDef& i2c)
183{
184 for (Stm32I2cMaster& i : *(queue()))
185 i.isrAbort(i2c);
186}
187
188void Stm32I2cMaster::isrRead(I2C_HandleTypeDef& i2c)
189{
190 if (&i2c != m_hwHandle)
191 return;
192
193 SEMF_INFO("data available");
195}
196
197void Stm32I2cMaster::isrWritten(I2C_HandleTypeDef& i2c)
198{
199 if (&i2c != m_hwHandle)
200 return;
201
202 SEMF_INFO("data written");
204}
205
206void Stm32I2cMaster::isrError(I2C_HandleTypeDef& i2c)
207{
208 if (&i2c != m_hwHandle)
209 return;
210
211 SEMF_INFO("error");
212 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::IsrError_HalError)));
213}
214
215void Stm32I2cMaster::isrAbort(I2C_HandleTypeDef& i2c)
216{
217 if (&i2c != m_hwHandle)
218 return;
219
220 SEMF_INFO("abort");
221 setBusy(false);
222 canceled();
223}
224
226{
227 return m_hwHandle;
228}
229
231{
232 uint32_t mode;
233 switch (frame)
234 {
236 SEMF_INFO("frame mode: first");
237 mode = I2C_FIRST_FRAME;
238 break;
240 SEMF_INFO("frame mode: next");
241 mode = I2C_NEXT_FRAME;
242 break;
244 SEMF_INFO("frame mode: last");
245 mode = I2C_LAST_FRAME;
246 break;
248 default:
249 SEMF_INFO("frame mode: first and last");
250 mode = I2C_FIRST_AND_LAST_FRAME;
251 break;
252 }
253 return mode;
254}
255
256void Stm32I2cMaster::readHardware(uint8_t buffer[], size_t bufferSize)
257{
258 SEMF_INFO("data %p, size %p", buffer, bufferSize);
259 __HAL_UNLOCK(m_hwHandle);
260 HAL_StatusTypeDef state;
261 if (frame() == Frame::FirstAndLast)
262 {
263 state = HAL_I2C_Master_Receive_IT(m_hwHandle, static_cast<uint16_t>(address() << 1), buffer, static_cast<uint16_t>(bufferSize));
264 }
265 else
266 {
267 state =
268 HAL_I2C_Master_Seq_Receive_IT(m_hwHandle, static_cast<uint16_t>(address() << 1), buffer, static_cast<uint16_t>(bufferSize), hardwareFrame(frame()));
269 }
270 if (state != HAL_OK)
271 {
272 if (state == HAL_ERROR)
273 {
274 SEMF_ERROR("hal error");
275 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalError)));
276 }
277 else if (state == HAL_BUSY)
278 {
279 SEMF_ERROR("hal busy");
280 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalBusy)));
281 }
282 else if (state == HAL_TIMEOUT)
283 {
284 SEMF_ERROR("hal timeout");
285 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalTimeout)));
286 }
287 return;
288 }
289}
290
291void Stm32I2cMaster::writeHardware(const uint8_t data[], size_t dataSize)
292{
293 SEMF_INFO("data %p, size %u", data, dataSize);
294 __HAL_UNLOCK(m_hwHandle);
295 HAL_StatusTypeDef state;
296 if (frame() == Frame::FirstAndLast)
297 {
298 state = HAL_I2C_Master_Transmit_IT(m_hwHandle, static_cast<uint16_t>(address() << 1), const_cast<uint8_t*>(data), static_cast<uint16_t>(dataSize));
299 }
300 else
301 {
302 state = HAL_I2C_Master_Seq_Transmit_IT(m_hwHandle, static_cast<uint16_t>(address() << 1), const_cast<uint8_t*>(data), static_cast<uint16_t>(dataSize),
304 }
305
306 if (state != HAL_OK)
307 {
308 if (state == HAL_ERROR)
309 {
310 SEMF_ERROR("hal error");
311 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalError)));
312 }
313 else if (state == HAL_BUSY)
314 {
315 SEMF_ERROR("hal busy");
316 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalError)));
317 }
318 else if (state == HAL_TIMEOUT)
319 {
320 SEMF_ERROR("hal timeout");
321 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalError)));
322 }
323 return;
324 }
325}
326
327void Stm32I2cMaster::onAddressChecked()
328{
329 dataAvailable.disconnect(m_onAddressCheckedSlot);
330 setBusy(false);
331 addressFound();
332}
333} /* namespace semf */
334#endif
@ FirstAndLast
start AND stop condition
@ Next
no start AND no stop condition
@ First
start condition, but no stop condition
Class for representing errors. Every error should have a unique source code. As a user feel encourage...
Definition: error.h:22
void setAddress(uint8_t address) override
void setFrame(CommunicationHardware::Frame frame) override
Sets the selected usage of start and stop condition.
virtual void setFrequencyHardware(uint32_t hz)=0
Configures the frequency of the bus.
bool isBusyReading() const override
Communication hardware is busy reading at the moment.
CommunicationHardware::Frame frame() const
Returns the actual frame mode setting.
uint8_t address() const override
Returns the I2C slave device address.
void onError(Error thrown)
Is called if an error occurred by hardware read or write access. Will emit error signal.
bool isBusyWriting() const override
Communication hardware is busy writing at the moment.
void setBusy(bool isBusy)
Sets the busy flag.
LinkedQueue is an managed single linked queue implementation.
Definition: linkedqueue.h:38
void connect(SlotBase< Arguments... > &slot)
Connect a method to the signal.
Definition: signal.h:94
void disconnect(SlotBase< Arguments... > &slot)
Disonnect a method from the signal.
Definition: signal.h:107
I2cMasterHardware implementation for STM32.
void stopRead() override
void isrError(I2C_HandleTypeDef &i2c)
Interrupt service routine for i2c object error.
void writeHardware(const uint8_t data[], size_t dataSize) override
Hardware will write data. After finished write operation, onDataWritten() function will be called.
I2C_HandleTypeDef * hardwareHandle()
Returns the hardware handle.
virtual uint32_t hardwareFrame(CommunicationHardware::Frame frame) const
Converts the frame information from semf to STM.
void checkAddress(uint8_t address) override
Checks if the given address is available on the bus. Emits address found if successful (ACK)....
void init() override
void stopWrite() override
void isrWritten(I2C_HandleTypeDef &i2c)
Interrupt service routine for i2c object transmit.
static void systemIsrWritten(I2C_HandleTypeDef &i2c)
System-wide interrupt service routine for i2c transmit.
static LinkedQueue< Stm32I2cMaster > * queue()
Get the list with all i2c.
void readHardware(uint8_t buffer[], size_t bufferSize) override
Hardware will read data. After finished read operation, onDataAvailable() function will be called.
void setFrequency(uint32_t hz) override
Sets the speed (I2C baud rate).
void isrRead(I2C_HandleTypeDef &i2c)
Interrupt service routine for i2c object receive.
static void systemIsrError(I2C_HandleTypeDef &i2c)
System-wide interrupt service routine for i2c error.
void isrAbort(I2C_HandleTypeDef &i2c)
Interrupt service routine for i2c object abort.
Stm32I2cMaster(I2C_HandleTypeDef &hwHandle)
Constructor.
static void systemIsrAbort(I2C_HandleTypeDef &i2c)
System-wide interrupt service routine for process canceling.
static void systemIsrRead(I2C_HandleTypeDef &i2c)
System-wide interrupt service routine for i2c receive.
void deinit() override
Signal< Error > error
Definition: communication.h:64
#define SEMF_ERROR(...)
Definition: debug.h:39
#define SEMF_WARNING(...)
Definition: debug.h:40
#define SEMF_INFO(...)
Definition: debug.h:41