semf
stm32i2cslave.cpp
Go to the documentation of this file.
1
12
13#if defined(STM32) && defined(HAL_I2C_MODULE_ENABLED)
14namespace semf
15{
16LinkedQueue<Stm32I2cSlave> Stm32I2cSlave::m_queue;
17Stm32I2cSlave::Stm32I2cSlave(I2C_HandleTypeDef& hwHandle)
18: m_hwHandle{&hwHandle}
19{
20 m_queue.push(*this);
21}
22
24{
25 HAL_StatusTypeDef error = HAL_I2C_Init(m_hwHandle);
26 if (error != HAL_OK)
27 {
28 if (error == HAL_ERROR)
29 {
30 SEMF_ERROR("hal error");
31 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalError)));
32 }
33 else if (error == HAL_BUSY)
34 {
35 SEMF_ERROR("hal busy");
36 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalBusy)));
37 }
38 else if (error == HAL_TIMEOUT)
39 {
40 SEMF_ERROR("hal timeout");
41 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Init_HalTimeout)));
42 }
43 return;
44 }
45}
46
48{
49 HAL_StatusTypeDef error = HAL_I2C_DeInit(m_hwHandle);
50 if (error != HAL_OK)
51 {
52 if (error == HAL_ERROR)
53 {
54 SEMF_ERROR("hal error");
55 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalError)));
56 }
57 else if (error == HAL_BUSY)
58 {
59 SEMF_ERROR("hal busy");
60 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalBusy)));
61 }
62 else if (error == HAL_TIMEOUT)
63 {
64 SEMF_ERROR("hal timeout");
65 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::Deinit_HalTimeout)));
66 }
67 return;
68 }
69}
70
72{
73 SEMF_WARNING("this operation is not supported");
74}
75
77{
78 SEMF_WARNING("this operation is not supported");
79}
80
82{
84 {
85 SEMF_ERROR("is busy");
86 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SetFrequency_IsBusy)));
87 return;
88 }
90}
91
92void Stm32I2cSlave::systemIsrRead(I2C_HandleTypeDef& hwHandle)
93{
94 for (auto& i2c : m_queue)
95 {
96 if (i2c.m_hwHandle == &hwHandle)
97 {
98 i2c.onDataAvailable();
99 }
100 }
101}
102
103void Stm32I2cSlave::systemIsrWritten(I2C_HandleTypeDef& hwHandle)
104{
105 for (auto& i2c : m_queue)
106 {
107 if (i2c.m_hwHandle == &hwHandle)
108 {
109 i2c.onDataWritten();
110 }
111 }
112}
113
114void Stm32I2cSlave::systemIsrListen(I2C_HandleTypeDef& hwHandle)
115{
116 for (auto& i2c : m_queue)
117 {
118 if (i2c.m_hwHandle == &hwHandle)
119 {
120 HAL_StatusTypeDef error = HAL_I2C_EnableListen_IT(i2c.m_hwHandle);
121 if (error != HAL_OK)
122 {
123 if (error == HAL_ERROR)
124 {
125 SEMF_SINGLETON_ERROR(&i2c, "hal error");
126 i2c.onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SystemIsrListen_EnableListenHalError)));
127 }
128 else if (error == HAL_BUSY)
129 {
130 SEMF_SINGLETON_ERROR(&i2c, "hal busy");
131 i2c.onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SystemIsrListen_EnableListenHalBusy)));
132 }
133 else if (error == HAL_TIMEOUT)
134 {
135 SEMF_SINGLETON_ERROR(&i2c, "hal timeout");
136 i2c.onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SystemIsrListen_EnableListenHalTimeout)));
137 }
138 return;
139 }
140 }
141 }
142}
143
144void Stm32I2cSlave::systemIsrError(I2C_HandleTypeDef& hwHandle)
145{
146 for (auto& i2c : m_queue)
147 {
148 if (i2c.m_hwHandle == &hwHandle)
149 i2c.onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::SystemIsrError_HalError)));
150 }
151}
152
153void Stm32I2cSlave::systemIsrAddressing(I2C_HandleTypeDef& hwHandle, uint8_t direction, uint16_t addrMatchCode)
154{
155 for (auto& i2c : m_queue)
156 {
157 if (i2c.m_hwHandle == &hwHandle)
158 {
159 if (direction == I2C_DIRECTION_TRANSMIT)
160 i2c.readExpected();
161 else if (direction == I2C_DIRECTION_RECEIVE)
162 i2c.writeExpected();
163 }
164 }
165}
166
167void Stm32I2cSlave::readHardware(uint8_t buffer[], size_t bufferSize)
168{
169 SEMF_INFO("data %p, size %u", buffer, bufferSize);
170 __HAL_UNLOCK(m_hwHandle);
171 HAL_StatusTypeDef error = HAL_I2C_Slave_Seq_Receive_IT(m_hwHandle, buffer, static_cast<uint16_t>(bufferSize), hardwareFrame(frame()));
172 if (error != HAL_OK)
173 {
174 if (error == HAL_ERROR)
175 {
176 SEMF_ERROR("hal error");
177 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalError)));
178 }
179 else if (error == HAL_BUSY)
180 {
181 SEMF_ERROR("hal busy");
182 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalBusy)));
183 }
184 else if (error == HAL_TIMEOUT)
185 {
186 SEMF_ERROR("hal timeout");
187 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::ReadHardware_HalTimeout)));
188 }
189 return;
190 }
191}
192
193void Stm32I2cSlave::writeHardware(const uint8_t data[], size_t dataSize)
194{
195 SEMF_INFO("data %p, size %u", data, dataSize);
196 __HAL_UNLOCK(m_hwHandle);
197 HAL_StatusTypeDef error = HAL_I2C_Slave_Seq_Transmit_IT(m_hwHandle, const_cast<uint8_t*>(data), static_cast<uint16_t>(dataSize), hardwareFrame(frame()));
198 if (error != HAL_OK)
199 {
200 if (error == HAL_ERROR)
201 {
202 SEMF_ERROR("hal error");
203 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalError)));
204 }
205 else if (error == HAL_BUSY)
206 {
207 SEMF_ERROR("hal busy");
208 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalBusy)));
209 }
210 else if (error == HAL_TIMEOUT)
211 {
212 SEMF_ERROR("hal timeout");
213 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::WriteHardware_HalTimeout)));
214 }
215 return;
216 }
217}
218
220{
221 HAL_StatusTypeDef error = HAL_I2C_EnableListen_IT(m_hwHandle);
222 if (error != HAL_OK)
223 {
224 if (error == HAL_ERROR)
225 {
226 SEMF_ERROR("hal error");
227 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StartListeningHardware_HalError)));
228 }
229 else if (error == HAL_BUSY)
230 {
231 SEMF_ERROR("hal busy");
232 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StartListeningHardware_HalBusy)));
233 }
234 else if (error == HAL_TIMEOUT)
235 {
236 SEMF_ERROR("hal timeout");
237 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StartListeningHardware_HalTimeout)));
238 }
239 return;
240 }
241 setListening(true);
242}
243
245{
246 HAL_StatusTypeDef error = HAL_I2C_DisableListen_IT(m_hwHandle);
247 if (error != HAL_OK)
248 {
249 if (error == HAL_ERROR)
250 {
251 SEMF_ERROR("hal error");
252 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopListeningHardware_HalError)));
253 }
254 else if (error == HAL_BUSY)
255 {
256 SEMF_ERROR("hal busy");
257 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopListeningHardware_HalError)));
258 }
259 else if (error == HAL_TIMEOUT)
260 {
261 SEMF_ERROR("hal timeout");
262 onError(Error(kSemfClassId, static_cast<uint8_t>(ErrorCode::StopListeningHardware_HalError)));
263 }
264 return;
265 }
266 setListening(false);
267}
268
270{
271 deinit();
272 m_hwHandle->Init.OwnAddress1 = address << 1;
273 init();
274}
275
277{
279 {
280 return I2C_FIRST_FRAME;
281 }
283 {
284 return I2C_FIRST_AND_LAST_FRAME;
285 }
287 {
288 return I2C_NEXT_FRAME;
289 }
290 else // CommunicationHardware::Frame::LAST
291 {
292 return I2C_LAST_FRAME;
293 }
294}
295
297{
298 return m_hwHandle;
299}
300} /* namespace semf */
301#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 onError(Error thrown)
Is called if an error occurred by hardware read or write access. Will emit error signal.
bool isBusyReading() const override
Communication hardware is busy reading at the moment.
bool isBusyWriting() const override
Communication hardware is busy writing at the moment.
uint8_t address() const override
Returns the I2C slave device address.
CommunicationHardware::Frame frame() const
Returns the actual frame mode setting.
virtual void setFrequencyHardware(uint32_t hz)=0
Configures the frequency of the bus.
void setListening(bool listening)
Sets the listening flag.
void init() override
void stopListeningHardware() override
void writeHardware(const uint8_t data[], size_t dataSize) override
Hardware will write data. After finished write operation, onDataWritten() function will be called.
void setFrequency(uint32_t hz) override
Sets the speed (I2C baud rate).
static void systemIsrAddressing(I2C_HandleTypeDef &hwHandle, uint8_t direction, uint16_t addrMatchCode)
I2C_HandleTypeDef * hardwareHandle()
Returns the hardware Handle.
void readHardware(uint8_t buffer[], size_t bufferSize) override
Hardware will read data. After finished read operation, onDataAvailable() function will be called.
void stopRead() override
void setAddressHardware(uint8_t address) override
Sets the address of the i2c hardware.
static void systemIsrWritten(I2C_HandleTypeDef &hwHandle)
System-wide isr for data transmission on an I2C-bus.
static void systemIsrError(I2C_HandleTypeDef &hwHandle)
virtual uint32_t hardwareFrame(CommunicationHardware::Frame frame) const
Converts the frame information from semf to STM.
void deinit() override
static void systemIsrListen(I2C_HandleTypeDef &hwHandle)
System-wide isr for end of listening on an I2C-bus.
static void systemIsrRead(I2C_HandleTypeDef &hwHandle)
System-wide isr for data reception on an I2C-bus.
void stopWrite() override
Stm32I2cSlave(I2C_HandleTypeDef &hwHandle)
Constructor.
void startListeningHardware() override
Signal< Error > error
Definition: communication.h:64
#define SEMF_ERROR(...)
Definition: debug.h:39
#define SEMF_WARNING(...)
Definition: debug.h:40
#define SEMF_SINGLETON_ERROR(object,...)
Definition: debug.h:45
#define SEMF_INFO(...)
Definition: debug.h:41