Statistics
| Branch: | Tag: | Revision:

amiro-os / kernel / patches / I2C-without-DMA.patch @ e189c0a6

History | View | Annotate | Download (29.719 KB)

1 22be62dc Thomas Schöpping
diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
2
--- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
3
+++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
4
@@ -34,6 +34,7 @@
5 732a4657 Thomas Schöpping
 /* Driver local definitions.                                                 */
6
 /*===========================================================================*/
7
 
8
+#if STM32_I2C_I2C1_USE_DMA
9
 #define I2C1_RX_DMA_CHANNEL                                                 \
10
   STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM,                        \
11
                        STM32_I2C1_RX_DMA_CHN)
12 22be62dc Thomas Schöpping
@@ -41,7 +42,9 @@
13 732a4657 Thomas Schöpping
 #define I2C1_TX_DMA_CHANNEL                                                 \
14
   STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM,                        \
15
                        STM32_I2C1_TX_DMA_CHN)
16
+#endif
17
 
18
+#if STM32_I2C_I2C2_USE_DMA
19
 #define I2C2_RX_DMA_CHANNEL                                                 \
20
   STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM,                        \
21
                        STM32_I2C2_RX_DMA_CHN)
22 22be62dc Thomas Schöpping
@@ -49,7 +52,9 @@
23 732a4657 Thomas Schöpping
 #define I2C2_TX_DMA_CHANNEL                                                 \
24
   STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM,                        \
25
                        STM32_I2C2_TX_DMA_CHN)
26
+#endif
27
 
28
+#if STM32_I2C_I2C3_USE_DMA
29
 #define I2C3_RX_DMA_CHANNEL                                                 \
30
   STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM,                        \
31
                        STM32_I2C3_RX_DMA_CHN)
32 22be62dc Thomas Schöpping
@@ -57,6 +62,7 @@
33 732a4657 Thomas Schöpping
 #define I2C3_TX_DMA_CHANNEL                                                 \
34
   STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM,                        \
35
                        STM32_I2C3_TX_DMA_CHN)
36
+#endif
37
 
38
 /*===========================================================================*/
39
 /* Driver constants.                                                         */
40 7368d8da Thomas Schöpping
@@ -75,6 +81,20 @@
41 732a4657 Thomas Schöpping
 #define I2C_EV6_MASTER_REC_MODE_SELECTED                                    \
42
   ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR))
43
 
44
+#define I2C_EV7_MASTER_REC_BYTE_RECEIVED                                    \
45
+  ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_RXNE))
46
+
47
+#define I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP                               \
48
+  ((uint32_t)(I2C_SR1_RXNE))
49
+
50
+#define I2C_EV7_2_EV7_3_MASTER_REC_BYTE_QUEUED                              \
51
+  ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) |                         \
52
+              I2C_SR1_BTF | I2C_SR1_RXNE))
53
+
54
+#define I2C_EV8_MASTER_BYTE_TRANSMITTING                                    \
55
+  ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA)<< 16) |           \
56
+              I2C_SR1_TXE))
57
+
58
 #define I2C_EV8_2_MASTER_BYTE_TRANSMITTED                                   \
59
   ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) |          \
60
               I2C_SR1_BTF | I2C_SR1_TXE))
61 7368d8da Thomas Schöpping
@@ -132,8 +152,24 @@ static void i2c_lld_abort_operation(I2CDriver *i2cp) {
62 732a4657 Thomas Schöpping
   dp->SR1 = 0;
63
 
64
   /* Stops the associated DMA streams.*/
65
-  dmaStreamDisable(i2cp->dmatx);
66
-  dmaStreamDisable(i2cp->dmarx);
67
+#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
68
+  if (&I2CD1 == i2cp) {
69
+    dmaStreamDisable(i2cp->dmatx);
70
+    dmaStreamDisable(i2cp->dmarx);
71
+  }
72
+#endif
73
+#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
74
+  if (&I2CD2 == i2cp) {
75
+    dmaStreamDisable(i2cp->dmatx);
76
+    dmaStreamDisable(i2cp->dmarx);
77
+  }
78
+#endif
79
+#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
80
+  if (&I2CD3 == i2cp) {
81
+    dmaStreamDisable(i2cp->dmatx);
82
+    dmaStreamDisable(i2cp->dmarx);
83
+  }
84
+#endif
85
 }
86
 
87
 /**
88 7368d8da Thomas Schöpping
@@ -238,14 +274,18 @@ static void i2c_lld_set_opmode(I2CDriver *i2cp) {
89 732a4657 Thomas Schöpping
   dp->CR1 = regCR1;
90
 }
91
 
92
+#if (STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) ||                       \
93
+    (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) ||                       \
94
+    (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA) ||                       \
95
+    defined(__DOXYGEN__)
96
 /**
97
- * @brief   I2C shared ISR code.
98
+ * @brief   I2C shared ISR code for DMA access.
99
  *
100
  * @param[in] i2cp      pointer to the @p I2CDriver object
101
  *
102
  * @notapi
103
  */
104
-static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
105
+static void i2c_lld_serve_event_interrupt_dma(I2CDriver *i2cp) {
106
   I2C_TypeDef *dp = i2cp->i2c;
107
   uint32_t regSR2 = dp->SR2;
108
   uint32_t event = dp->SR1;
109 7368d8da Thomas Schöpping
@@ -303,7 +343,146 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
110
     dp->SR1 &= ~I2C_SR1_BERR;
111
   }
112 732a4657 Thomas Schöpping
 }
113
+#endif /* any I2CDx uses DMA mode */
114
+
115
+#if (STM32_I2C_USE_I2C1 && !STM32_I2C_I2C1_USE_DMA) ||                      \
116
+    (STM32_I2C_USE_I2C2 && !STM32_I2C_I2C2_USE_DMA) ||                      \
117
+    (STM32_I2C_USE_I2C3 && !STM32_I2C_I2C3_USE_DMA) ||                      \
118
+    defined(__DOXYGEN__)
119
+/**
120
+ * @brief   I2C shared ISR code for non-DMA access.
121
+ *
122
+ * @param[in] i2cp      pointer to the @p I2CDriver object
123
+ *
124
+ * @notapi
125
+ */
126
+static void i2c_lld_serve_event_interrupt_isr(I2CDriver *i2cp) {
127
+  I2C_TypeDef *dp = i2cp->i2c;
128
+  uint32_t regSR2 = dp->SR2;
129
+  uint32_t event = dp->SR1;
130
+
131
+  switch (I2C_EV_MASK & (event | (regSR2 << 16))) {
132
+  case I2C_EV5_MASTER_MODE_SELECT:
133
+    dp->CR2 |= I2C_CR2_ITBUFEN;
134
+    dp->DR = i2cp->addr;
135
+    break;
136
+  case I2C_EV6_MASTER_TRA_MODE_SELECTED:
137
+    (void)dp->SR2; // clear ADDR flag
138
+    /* EV8_1 */
139
+    dp->DR = *(i2cp->txbuf);
140
+
141
+    ++i2cp->txbuf;
142
+    --i2cp->txbytes;
143
+
144
+    /* if N == 1, skip the I2C_EV8_MASTER_BYTE_TRANSMITTING event
145
+     * but enter I2C_EV8_2_MASTER_BYTE_TRANSMITTED next */
146
+    if (i2cp->txbytes == 0) {
147
+      dp->CR2 &= ~I2C_CR2_ITBUFEN;
148
+    }
149
+    break;
150
+  case I2C_EV6_MASTER_REC_MODE_SELECTED:
151
+    switch (i2cp->rxbytes) {
152
+    case 1:
153
+      dp->CR1 &= ~I2C_CR1_ACK;
154
+      (void)dp->SR2; // clear ADDR flag
155
+      dp->CR1 |= I2C_CR1_STOP;
156
+      break;
157
+    case 2:
158
+      (void)dp->SR2; // clear ADDR flag
159
+      /* EV6_1 */
160
+      dp->CR1 |= I2C_CR1_POS;
161
+      dp->CR1 &= ~I2C_CR1_ACK;
162
+      dp->CR2 &= ~I2C_CR2_ITBUFEN;
163
+      break;
164
+    case 3: /* N == 3 is a very special case, since EV7 is completely skipped */
165
+      (void)dp->SR2; // clear ADDR flag
166
+      /* Disable the I2C_EV7_MASTER_REC_BYTE_RECEIVED event
167
+       * but enter I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP next */
168
+      dp->CR2 &= ~I2C_CR2_ITBUFEN;
169
+      break;
170
+    default: /* N > 2 */
171
+      (void)dp->SR2; // clear ADDR flag
172
+      break;
173
+    }
174
+    break;
175
+  case I2C_EV7_MASTER_REC_BYTE_RECEIVED:
176
+    if (i2cp->rxbytes > 3) {
177
+      *(i2cp->rxbuf) = dp->DR;
178
+      ++i2cp->rxbuf;
179
+      --i2cp->rxbytes;
180
+    }
181
+    if (i2cp->rxbytes == 3) {
182
+      /* Disable this event for DataN-2, but force into event
183
+       * I2C_EV7_2_EV7_3_MASTER_REC_BYTE_RECEIVED_QUEUED by not reading dp->DR. */
184
+      dp->CR2 &= ~I2C_CR2_ITBUFEN;
185
+    }
186
+    break;
187
+  case I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP:
188
+    osalDbgAssert(i2cp->rxbytes == 1, "more than 1 byte to be received");
189
+    *(i2cp->rxbuf) = dp->DR;
190
+    --i2cp->rxbytes;
191
+    dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
192
+    _i2c_wakeup_isr(i2cp);
193
+    break;
194
+  case I2C_EV7_2_EV7_3_MASTER_REC_BYTE_QUEUED:
195
+    if (i2cp->rxbytes == 3) {
196
+      /* EV7_2 (N > 2) */
197
+      dp->CR1 &= ~I2C_CR1_ACK;
198
+      *(i2cp->rxbuf) = dp->DR;
199
+      ++i2cp->rxbuf;
200
+      dp->CR1 |= I2C_CR1_STOP;
201
+      *(i2cp->rxbuf) = dp->DR;
202
+      ++i2cp->rxbuf;
203
+      i2cp->rxbytes -= 2;
204
+      /* enable I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP event */
205
+      dp->CR2 |= I2C_CR2_ITBUFEN;
206
+    } else {
207
+      /* EV7_3 (N == 2) */
208
+      dp->CR1 |= I2C_CR1_STOP;
209
+      *(i2cp->rxbuf) = dp->DR;
210
+      ++i2cp->rxbuf;
211
+      *(i2cp->rxbuf) = dp->DR;
212
+      i2cp->rxbytes -= 2;
213
+
214
+      dp->CR1 &= ~I2C_CR1_POS;
215
+      dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
216
+
217
+      _i2c_wakeup_isr(i2cp);
218
+    }
219
+    break;
220
+  case I2C_EV8_MASTER_BYTE_TRANSMITTING:
221
+    dp->DR = *(i2cp->txbuf);
222
+    ++i2cp->txbuf;
223
+    --i2cp->txbytes;
224
+
225
+    /* if this was the last byte, ensure that this event is not entered again */
226
+    if (i2cp->txbytes == 0) {
227
+      dp->CR2 &= ~I2C_CR2_ITBUFEN;
228
+    }
229
+    break;
230
+  case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
231
+    if (i2cp->rxbytes > 0) {
232
+      /* start "read after write" operation (LSB of address = 1 => read) */
233
+      i2cp->addr |= 0x01;
234
+      dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
235
+    } else {
236
+      dp->CR1 |= I2C_CR1_STOP;
237
+      dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
238
+      _i2c_wakeup_isr(i2cp);
239
+    }
240
+    break;
241
+  default:
242
+    osalDbgAssert(i2cp->rxbytes != 1, "more than 1 byte to be received");
243
+    break;
244
+  }
245
+}
246
+#endif /* any I2CDx uses non-DMA mode */
247
+
248 7368d8da Thomas Schöpping
 
249 732a4657 Thomas Schöpping
+#if (STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) ||                      \
250
+    (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) ||                      \
251
+    (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA) ||                      \
252
+    defined(__DOXYGEN__)
253
 /**
254
  * @brief   DMA RX end IRQ handler.
255
  *
256 7368d8da Thomas Schöpping
@@ -357,6 +536,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
257 732a4657 Thomas Schöpping
      of R/W transaction itself.*/
258
   dp->CR2 |= I2C_CR2_ITEVTEN;
259
 }
260
+#endif /* any I2CDx uses DMA mode */
261
 
262
 /**
263
  * @brief   I2C error handler.
264 7368d8da Thomas Schöpping
@@ -369,8 +549,24 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
265 732a4657 Thomas Schöpping
 static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) {
266
 
267
   /* Clears interrupt flags just to be safe.*/
268
-  dmaStreamDisable(i2cp->dmatx);
269
-  dmaStreamDisable(i2cp->dmarx);
270
+#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
271
+  if (&I2CD1 == i2cp) {
272
+    dmaStreamDisable(i2cp->dmatx);
273
+    dmaStreamDisable(i2cp->dmarx);
274
+  }
275
+#endif
276
+#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
277
+  if (&I2CD2 == i2cp) {
278
+    dmaStreamDisable(i2cp->dmatx);
279
+    dmaStreamDisable(i2cp->dmarx);
280
+  }
281
+#endif
282
+#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
283
+  if (&I2CD3 == i2cp) {
284
+    dmaStreamDisable(i2cp->dmatx);
285
+    dmaStreamDisable(i2cp->dmarx);
286
+  }
287
+#endif
288
 
289
   i2cp->errors = I2C_NO_ERROR;
290
 
291 7368d8da Thomas Schöpping
@@ -421,7 +617,11 @@ OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
292 732a4657 Thomas Schöpping
 
293
   OSAL_IRQ_PROLOGUE();
294
 
295
-  i2c_lld_serve_event_interrupt(&I2CD1);
296
+#if STM32_I2C_I2C1_USE_DMA
297
+  i2c_lld_serve_event_interrupt_dma(&I2CD1);
298
+#else
299
+  i2c_lld_serve_event_interrupt_isr(&I2CD1);
300
+#endif
301
 
302
   OSAL_IRQ_EPILOGUE();
303
 }
304 7368d8da Thomas Schöpping
@@ -451,7 +651,11 @@ OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
305 732a4657 Thomas Schöpping
 
306
   OSAL_IRQ_PROLOGUE();
307
 
308
-  i2c_lld_serve_event_interrupt(&I2CD2);
309
+#if STM32_I2C_I2C2_USE_DMA
310
+  i2c_lld_serve_event_interrupt_dma(&I2CD2);
311
+#else
312
+  i2c_lld_serve_event_interrupt_isr(&I2CD2);
313
+#endif
314
 
315
   OSAL_IRQ_EPILOGUE();
316
 }
317 7368d8da Thomas Schöpping
@@ -483,7 +687,11 @@ OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
318 732a4657 Thomas Schöpping
 
319
   OSAL_IRQ_PROLOGUE();
320
 
321
-  i2c_lld_serve_event_interrupt(&I2CD3);
322
+#if STM32_I2C_I2C3_USE_DMA
323
+  i2c_lld_serve_event_interrupt_dma(&I2CD3);
324
+#else
325
+  i2c_lld_serve_event_interrupt_isr(&I2CD3);
326
+#endif
327
 
328
   OSAL_IRQ_EPILOGUE();
329
 }
330 7368d8da Thomas Schöpping
@@ -554,19 +762,22 @@ void i2c_lld_start(I2CDriver *i2cp) {
331 732a4657 Thomas Schöpping
   /* If in stopped state then enables the I2C and DMA clocks.*/
332
   if (i2cp->state == I2C_STOP) {
333
 
334
-    i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
335
-                      STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
336
-                      STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
337
-                      STM32_DMA_CR_DIR_M2P;
338
-    i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
339
-                      STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
340
-                      STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
341
-                      STM32_DMA_CR_DIR_P2M;
342
-
343
 #if STM32_I2C_USE_I2C1
344
     if (&I2CD1 == i2cp) {
345
+#if STM32_I2C_I2C1_USE_DMA
346
+      i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
347
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
348
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
349
+                        STM32_DMA_CR_DIR_M2P;
350
+      i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
351
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
352
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
353
+                        STM32_DMA_CR_DIR_P2M;
354
+#endif
355
+
356
       rccResetI2C1();
357
 
358
+#if STM32_I2C_I2C1_USE_DMA
359
       i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM,
360
                                     STM32_I2C_I2C1_IRQ_PRIORITY,
361
                                     (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
362 7368d8da Thomas Schöpping
@@ -577,22 +788,50 @@ void i2c_lld_start(I2CDriver *i2cp) {
363 732a4657 Thomas Schöpping
                                     (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
364
                                     (void *)i2cp);
365
       osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
366
+#endif
367
 
368
       rccEnableI2C1(true);
369
       nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
370
       nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
371
 
372
+#if STM32_I2C_I2C1_USE_DMA
373
       i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
374
                        STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
375
       i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
376
                        STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
377
+
378
+      /* I2C registers pointed by the DMA.*/
379
+      dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
380
+      dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
381
+#endif
382
+
383
+      /* Reset i2c peripheral.*/
384
+      dp->CR1 = I2C_CR1_SWRST;
385
+      dp->CR1 = 0;
386
+#if STM32_I2C_I2C1_USE_DMA
387
+      dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
388
+#else
389
+      dp->CR2 = I2C_CR2_ITERREN;
390
+#endif
391
     }
392
 #endif /* STM32_I2C_USE_I2C1 */
393
 
394
 #if STM32_I2C_USE_I2C2
395
     if (&I2CD2 == i2cp) {
396
+#if STM32_I2C_I2C2_USE_DMA
397
+      i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
398
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
399
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
400
+                        STM32_DMA_CR_DIR_M2P;
401
+      i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
402
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
403
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
404
+                        STM32_DMA_CR_DIR_P2M;
405
+#endif
406
+
407
       rccResetI2C2();
408
 
409
+#if STM32_I2C_I2C2_USE_DMA
410
       i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM,
411
                                     STM32_I2C_I2C2_IRQ_PRIORITY,
412
                                     (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
413 7368d8da Thomas Schöpping
@@ -603,22 +842,50 @@ void i2c_lld_start(I2CDriver *i2cp) {
414 732a4657 Thomas Schöpping
                                     (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
415
                                     (void *)i2cp);
416
       osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
417
+#endif
418
 
419
       rccEnableI2C2(true);
420
       nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
421
       nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
422
 
423
+#if STM32_I2C_I2C2_USE_DMA
424
       i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) |
425
                        STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
426
       i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) |
427
                        STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
428
+
429
+      /* I2C registers pointed by the DMA.*/
430
+      dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
431
+      dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
432
+#endif
433
+
434
+      /* Reset i2c peripheral.*/
435
+      dp->CR1 = I2C_CR1_SWRST;
436
+      dp->CR1 = 0;
437
+#if STM32_I2C_I2C2_USE_DMA
438
+      dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
439
+#else
440
+      dp->CR2 = I2C_CR2_ITERREN;
441
+#endif
442
     }
443
 #endif /* STM32_I2C_USE_I2C2 */
444
 
445
 #if STM32_I2C_USE_I2C3
446
     if (&I2CD3 == i2cp) {
447
+#if STM32_I2C_I2C3_USE_DMA
448
+      i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
449
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
450
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
451
+                        STM32_DMA_CR_DIR_M2P;
452
+      i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
453
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
454
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
455
+                        STM32_DMA_CR_DIR_P2M;
456
+#endif
457
+
458
       rccResetI2C3();
459
 
460
+#if STM32_I2C_I2C3_USE_DMA
461
       i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM,
462
                                     STM32_I2C_I2C3_IRQ_PRIORITY,
463
                                     (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
464 7368d8da Thomas Schöpping
@@ -629,28 +896,35 @@ void i2c_lld_start(I2CDriver *i2cp) {
465 732a4657 Thomas Schöpping
                                     (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
466
                                     (void *)i2cp);
467
       osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
468
+#endif
469
 
470
       rccEnableI2C3(true);
471
       nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
472
       nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
473
 
474
+#if STM32_I2C_I2C3_USE_DMA
475
       i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) |
476
                        STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
477
       i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) |
478
                        STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
479
+
480
+      /* I2C registers pointed by the DMA.*/
481
+      dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
482
+      dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
483
+#endif
484
+
485
+      /* Reset i2c peripheral.*/
486
+      dp->CR1 = I2C_CR1_SWRST;
487
+      dp->CR1 = 0;
488
+#if STM32_I2C_I2C3_USE_DMA
489
+      dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
490
+#else
491
+      dp->CR2 = I2C_CR2_ITERREN;
492
+#endif
493
     }
494
 #endif /* STM32_I2C_USE_I2C3 */
495
   }
496
 
497
-  /* I2C registers pointed by the DMA.*/
498
-  dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
499
-  dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
500
-
501
-  /* Reset i2c peripheral.*/
502
-  dp->CR1 = I2C_CR1_SWRST;
503
-  dp->CR1 = 0;
504
-  dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
505
-
506
   /* Setup I2C parameters.*/
507
   i2c_lld_set_clock(i2cp);
508
   i2c_lld_set_opmode(i2cp);
509 7368d8da Thomas Schöpping
@@ -673,13 +947,15 @@ void i2c_lld_stop(I2CDriver *i2cp) {
510 732a4657 Thomas Schöpping
 
511
     /* I2C disable.*/
512
     i2c_lld_abort_operation(i2cp);
513
-    dmaStreamFreeI(i2cp->dmatx);
514
-    dmaStreamFreeI(i2cp->dmarx);
515
-    i2cp->dmatx = NULL;
516
-    i2cp->dmarx = NULL;
517
 
518
 #if STM32_I2C_USE_I2C1
519
     if (&I2CD1 == i2cp) {
520
+#if STM32_I2C_I2C1_USE_DMA
521
+      dmaStreamFreeI(i2cp->dmatx);
522
+      dmaStreamFreeI(i2cp->dmarx);
523
+      i2cp->dmatx = NULL;
524
+      i2cp->dmarx = NULL;
525
+#endif
526
       nvicDisableVector(I2C1_EV_IRQn);
527
       nvicDisableVector(I2C1_ER_IRQn);
528
       rccDisableI2C1();
529 7368d8da Thomas Schöpping
@@ -688,6 +964,12 @@ void i2c_lld_stop(I2CDriver *i2cp) {
530 732a4657 Thomas Schöpping
 
531
 #if STM32_I2C_USE_I2C2
532
     if (&I2CD2 == i2cp) {
533
+#if STM32_I2C_I2C2_USE_DMA
534
+      dmaStreamFreeI(i2cp->dmatx);
535
+      dmaStreamFreeI(i2cp->dmarx);
536
+      i2cp->dmatx = NULL;
537
+      i2cp->dmarx = NULL;
538
+#endif
539
       nvicDisableVector(I2C2_EV_IRQn);
540
       nvicDisableVector(I2C2_ER_IRQn);
541
       rccDisableI2C2();
542 7368d8da Thomas Schöpping
@@ -696,6 +978,12 @@ void i2c_lld_stop(I2CDriver *i2cp) {
543 732a4657 Thomas Schöpping
 
544
 #if STM32_I2C_USE_I2C3
545
     if (&I2CD3 == i2cp) {
546
+#if STM32_I2C_I2C3_USE_DMA
547
+      dmaStreamFreeI(i2cp->dmatx);
548
+      dmaStreamFreeI(i2cp->dmarx);
549
+      i2cp->dmatx = NULL;
550
+      i2cp->dmarx = NULL;
551
+#endif
552
       nvicDisableVector(I2C3_EV_IRQn);
553
       nvicDisableVector(I2C3_ER_IRQn);
554
       rccDisableI2C3();
555 7368d8da Thomas Schöpping
@@ -747,10 +1035,43 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
556 732a4657 Thomas Schöpping
   /* Releases the lock from high level driver.*/
557
   osalSysUnlock();
558
 
559
-  /* RX DMA setup.*/
560
-  dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
561
-  dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
562
-  dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
563
+  /* RX (DMA) setup.*/
564
+#if STM32_I2C_USE_I2C1
565
+  if (&I2CD1 == i2cp) {
566
+#if STM32_I2C_I2C1_USE_DMA
567
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
568
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
569
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
570
+#else
571
+    i2cp->rxbuf = rxbuf;
572
+    i2cp->rxbytes = rxbytes;
573
+#endif
574
+  }
575
+#endif
576
+#if STM32_I2C_USE_I2C2
577
+  if (&I2CD2 == i2cp) {
578
+#if STM32_I2C_I2C2_USE_DMA
579
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
580
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
581
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
582
+#else
583
+    i2cp->rxbuf = rxbuf;
584
+    i2cp->rxbytes = rxbytes;
585
+#endif
586
+  }
587
+#endif
588
+#if STM32_I2C_USE_I2C3
589
+  if (&I2CD3 == i2cp) {
590
+#if STM32_I2C_I2C3_USE_DMA
591
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
592
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
593
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
594
+#else
595
+    i2cp->rxbuf = rxbuf;
596
+    i2cp->rxbytes = rxbytes;
597
+#endif
598
+  }
599
+#endif
600
 
601
   /* Calculating the time window for the timeout on the busy bus condition.*/
602
   start = osalOsGetSystemTimeX();
603 7368d8da Thomas Schöpping
@@ -769,7 +1090,21 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
604
     /* If the system time went outside the allowed window then a timeout
605
        condition is returned.*/
606
     if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
607
-      dmaStreamDisable(i2cp->dmarx);
608
+#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
609
+      if (&I2CD1 == i2cp) {
610
+        dmaStreamDisable(i2cp->dmarx);
611
+      }
612
+#endif
613
+#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
614
+      if (&I2CD2 == i2cp) {
615
+        dmaStreamDisable(i2cp->dmarx);
616
+      }
617
+#endif
618
+#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
619
+      if (&I2CD3 == i2cp) {
620
+        dmaStreamDisable(i2cp->dmarx);
621
+      }
622
+#endif
623
       return MSG_TIMEOUT;
624
     }
625
 
626
@@ -783,7 +1118,21 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
627
   /* Waits for the operation completion or a timeout.*/
628
   msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
629
   if (msg != MSG_OK) {
630
-    dmaStreamDisable(i2cp->dmarx);
631
+#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
632
+    if (&I2CD1 == i2cp) {
633
+      dmaStreamDisable(i2cp->dmarx);
634
+    }
635
+#endif
636
+#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
637
+    if (&I2CD2 == i2cp) {
638
+      dmaStreamDisable(i2cp->dmarx);
639
+    }
640
+#endif
641
+#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
642
+    if (&I2CD3 == i2cp) {
643
+      dmaStreamDisable(i2cp->dmarx);
644
+    }
645
+#endif
646
   }
647
 
648
   return msg;
649
@@ -835,15 +1184,61 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
650 732a4657 Thomas Schöpping
   /* Releases the lock from high level driver.*/
651
   osalSysUnlock();
652
 
653
-  /* TX DMA setup.*/
654
-  dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
655
-  dmaStreamSetMemory0(i2cp->dmatx, txbuf);
656
-  dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
657
-
658
-  /* RX DMA setup.*/
659
-  dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
660
-  dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
661
-  dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
662
+  /* TX (DMA) and RX (DMA) setup.*/
663
+#if STM32_I2C_USE_I2C1
664
+  if (&I2CD1 == i2cp) {
665
+#if STM32_I2C_I2C1_USE_DMA
666
+    dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
667
+    dmaStreamSetMemory0(i2cp->dmatx, txbuf);
668
+    dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
669
+
670
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
671
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
672
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
673
+#else
674
+    i2cp->txbuf = txbuf;
675
+    i2cp->txbytes = txbytes;
676
+    i2cp->rxbuf = rxbuf;
677
+    i2cp->rxbytes = rxbytes;
678
+#endif
679
+  }
680
+#endif
681
+#if STM32_I2C_USE_I2C2
682
+  if (&I2CD2 == i2cp) {
683
+#if STM32_I2C_I2C2_USE_DMA
684
+    dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
685
+    dmaStreamSetMemory0(i2cp->dmatx, txbuf);
686
+    dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
687
+
688
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
689
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
690
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
691
+#else
692
+    i2cp->txbuf = txbuf;
693
+    i2cp->txbytes = txbytes;
694
+    i2cp->rxbuf = rxbuf;
695
+    i2cp->rxbytes = rxbytes;
696
+#endif
697
+  }
698
+#endif
699
+#if STM32_I2C_USE_I2C3
700
+  if (&I2CD3 == i2cp) {
701
+#if STM32_I2C_I2C3_USE_DMA
702
+    dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
703
+    dmaStreamSetMemory0(i2cp->dmatx, txbuf);
704
+    dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
705
+
706
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
707
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
708
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
709
+#else
710
+    i2cp->txbuf = txbuf;
711
+    i2cp->txbytes = txbytes;
712
+    i2cp->rxbuf = rxbuf;
713
+    i2cp->rxbytes = rxbytes;
714
+#endif
715
+  }
716
+#endif
717
 
718
   /* Calculating the time window for the timeout on the busy bus condition.*/
719
   start = osalOsGetSystemTimeX();
720 7368d8da Thomas Schöpping
@@ -862,8 +1257,24 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
721
     /* If the system time went outside the allowed window then a timeout
722
        condition is returned.*/
723
     if (!osalTimeIsInRangeX(osalOsGetSystemTimeX(), start, end)) {
724
-      dmaStreamDisable(i2cp->dmatx);
725
-      dmaStreamDisable(i2cp->dmarx);
726
+#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
727
+      if (&I2CD1 == i2cp) {
728
+        dmaStreamDisable(i2cp->dmatx);
729
+        dmaStreamDisable(i2cp->dmarx);
730
+      }
731
+#endif
732
+#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
733
+      if (&I2CD2 == i2cp) {
734
+        dmaStreamDisable(i2cp->dmatx);
735
+        dmaStreamDisable(i2cp->dmarx);
736
+      }
737
+#endif
738
+#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
739
+      if (&I2CD3 == i2cp) {
740
+        dmaStreamDisable(i2cp->dmatx);
741
+        dmaStreamDisable(i2cp->dmarx);
742
+      }
743
+#endif
744
       return MSG_TIMEOUT;
745
     }
746
 
747
@@ -877,8 +1288,24 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
748
   /* Waits for the operation completion or a timeout.*/
749
   msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
750
   if (msg != MSG_OK) {
751
-    dmaStreamDisable(i2cp->dmatx);
752
-    dmaStreamDisable(i2cp->dmarx);
753
+#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
754
+    if (&I2CD1 == i2cp) {
755
+      dmaStreamDisable(i2cp->dmatx);
756
+      dmaStreamDisable(i2cp->dmarx);
757
+    }
758
+#endif
759
+#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
760
+    if (&I2CD2 == i2cp) {
761
+      dmaStreamDisable(i2cp->dmatx);
762
+      dmaStreamDisable(i2cp->dmarx);
763
+    }
764
+#endif
765
+#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
766
+    if (&I2CD3 == i2cp) {
767
+      dmaStreamDisable(i2cp->dmatx);
768
+      dmaStreamDisable(i2cp->dmarx);
769
+    }
770
+#endif
771
   }
772
 
773
   return msg;
774 22be62dc Thomas Schöpping
diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
775
--- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
776
+++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
777 732a4657 Thomas Schöpping
@@ -103,6 +103,33 @@
778
 #define STM32_I2C_I2C3_IRQ_PRIORITY         10
779
 #endif
780
 
781
+/**
782
+ * @brief   I2C1 DMA enable switch.
783
+ * @details If set to @p TRUE the I2C1 driver will use DMA.
784
+ * @note    The default is @p TRUE.
785
+ */
786
+#if !defined(STM32_I2C_I2C1_USE_DMA) || defined(__DOXYGEN__)
787
+#define STM32_I2C_I2C1_USE_DMA              TRUE
788
+#endif
789
+
790
+/**
791
+ * @brief   I2C2 DMA enable switch.
792
+ * @details If set to @p TRUE the I2C2 driver will use DMA.
793
+ * @note    The default is @p TRUE.
794
+ */
795
+#if !defined(STM32_I2C_I2C2_USE_DMA) || defined(__DOXYGEN__)
796
+#define STM32_I2C_I2C2_USE_DMA              TRUE
797
+#endif
798
+
799
+/**
800
+ * @brief   I2C3 DMA enable switch.
801
+ * @details If set to @p TRUE the I2C3 driver will use DMA.
802
+ * @note    The default is @p TRUE.
803
+ */
804
+#if !defined(STM32_I2C_I2C3_USE_DMA) || defined(__DOXYGEN__)
805
+#define STM32_I2C_I2C3_USE_DMA              TRUE
806
+#endif
807
+
808
 /**
809
 * @brief   I2C1 DMA priority (0..3|lowest..highest).
810
 * @note    The priority level is used for both the TX and RX DMA streams but
811 22be62dc Thomas Schöpping
@@ -250,16 +277,19 @@
812 732a4657 Thomas Schöpping
 #endif
813
 
814
 #if STM32_I2C_USE_I2C1 &&                                                   \
815
+    STM32_I2C_I2C1_USE_DMA &&                                               \
816
     !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY)
817
 #error "Invalid DMA priority assigned to I2C1"
818
 #endif
819
 
820
 #if STM32_I2C_USE_I2C2 &&                                                   \
821
+    STM32_I2C_I2C2_USE_DMA &&                                               \
822
     !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY)
823
 #error "Invalid DMA priority assigned to I2C2"
824
 #endif
825
 
826
 #if STM32_I2C_USE_I2C3 &&                                                   \
827
+    STM32_I2C_I2C3_USE_DMA &&                                               \
828
     !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY)
829
 #error "Invalid DMA priority assigned to I2C3"
830
 #endif
831 22be62dc Thomas Schöpping
@@ -316,7 +346,10 @@
832 732a4657 Thomas Schöpping
 #endif
833
 #endif /* STM32_ADVANCED_DMA */
834
 
835
-#if !defined(STM32_DMA_REQUIRED)
836
+#if ((STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) ||                       \
837
+     (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) ||                       \
838
+     (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA)) &&                      \
839
+    !defined(STM32_DMA_REQUIRED)
840
 #define STM32_DMA_REQUIRED
841
 #endif
842
 
843 22be62dc Thomas Schöpping
@@ -437,21 +470,52 @@ struct I2CDriver {
844 732a4657 Thomas Schöpping
    */
845
   i2caddr_t                 addr;
846
   /**
847
-   * @brief RX DMA mode bit mask.
848
-   */
849
-  uint32_t                  rxdmamode;
850
-  /**
851
-   * @brief TX DMA mode bit mask.
852
-   */
853
-  uint32_t                  txdmamode;
854
-  /**
855
-   * @brief     Receive DMA channel.
856
-   */
857
-  const stm32_dma_stream_t  *dmarx;
858
-  /**
859
-   * @brief     Transmit DMA channel.
860
+   * @brief   Anonymous union to store transmission related data for either DMA or non-DMA mode.
861
    */
862
-  const stm32_dma_stream_t  *dmatx;
863
+  union {
864
+    /**
865
+     * @brief   Anonymous struct to store data for DMA mode.
866
+     */
867
+    struct {
868
+      /**
869
+       * @brief RX DMA mode bit mask.
870
+       */
871
+      uint32_t                  rxdmamode;
872
+      /**
873
+       * @brief TX DMA mode bit mask.
874
+       */
875
+      uint32_t                  txdmamode;
876
+      /**
877
+       * @brief     Receive DMA channel.
878
+       */
879
+      const stm32_dma_stream_t  *dmarx;
880
+      /**
881
+       * @brief     Transmit DMA channel.
882
+       */
883
+      const stm32_dma_stream_t  *dmatx;
884
+    };
885
+    /**
886
+     * @brief   Anonymous struct to store data for non-DMA mode.
887
+     */
888
+    struct {
889
+      /**
890
+       * @brief   Receive buffer.
891
+       */
892
+      uint8_t                   *rxbuf;
893
+      /**
894
+       * @brief   Size of the receive buffer.
895
+       */
896
+      size_t                    rxbytes;
897
+      /**
898
+       * @brief   Transmit buffer.
899
+       */
900
+      const uint8_t             *txbuf;
901
+      /**
902
+       * @brief   Size of the transmit buffer.
903
+       */
904
+      size_t                    txbytes;
905
+    };
906
+  };
907
   /**
908
    * @brief     Pointer to the I2Cx registers block.
909
    */