Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (28.653 KB)

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