Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (27 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 22be62dc Thomas Schöpping
@@ -72,6 +78,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 22be62dc Thomas Schöpping
@@ -129,8 +149,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
@@ -235,14 +271,18 @@ static void i2c_lld_set_opmode(I2CDriver *i2cp) {
89
   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 22be62dc Thomas Schöpping
@@ -252,7 +292,7 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
110 732a4657 Thomas Schöpping
      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,7 +333,146 @@ 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
+#if (STM32_I2C_USE_I2C1 && !STM32_I2C_I2C1_USE_DMA) ||                      \
125
+    (STM32_I2C_USE_I2C2 && !STM32_I2C_I2C2_USE_DMA) ||                      \
126
+    (STM32_I2C_USE_I2C3 && !STM32_I2C_I2C3_USE_DMA) ||                      \
127
+    defined(__DOXYGEN__)
128
+/**
129
+ * @brief   I2C shared ISR code for non-DMA access.
130
+ *
131
+ * @param[in] i2cp      pointer to the @p I2CDriver object
132
+ *
133
+ * @notapi
134
+ */
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
+#if (STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) ||                      \
259
+    (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) ||                      \
260
+    (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA) ||                      \
261
+    defined(__DOXYGEN__)
262
 /**
263
  * @brief   DMA RX end IRQ handler.
264
  *
265
@@ -347,6 +526,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
266
      of R/W transaction itself.*/
267
   dp->CR2 |= I2C_CR2_ITEVTEN;
268
 }
269
+#endif /* any I2CDx uses DMA mode */
270
 
271
 /**
272
  * @brief   I2C error handler.
273
@@ -359,8 +539,24 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) {
274
 static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) {
275
 
276
   /* Clears interrupt flags just to be safe.*/
277
-  dmaStreamDisable(i2cp->dmatx);
278
-  dmaStreamDisable(i2cp->dmarx);
279
+#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
280
+  if (&I2CD1 == i2cp) {
281
+    dmaStreamDisable(i2cp->dmatx);
282
+    dmaStreamDisable(i2cp->dmarx);
283
+  }
284
+#endif
285
+#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
286
+  if (&I2CD2 == i2cp) {
287
+    dmaStreamDisable(i2cp->dmatx);
288
+    dmaStreamDisable(i2cp->dmarx);
289
+  }
290
+#endif
291
+#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
292
+  if (&I2CD3 == i2cp) {
293
+    dmaStreamDisable(i2cp->dmatx);
294
+    dmaStreamDisable(i2cp->dmarx);
295
+  }
296
+#endif
297
 
298
   i2cp->errors = I2C_NO_ERROR;
299
 
300
@@ -407,7 +603,11 @@ OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
301
 
302
   OSAL_IRQ_PROLOGUE();
303
 
304
-  i2c_lld_serve_event_interrupt(&I2CD1);
305
+#if STM32_I2C_I2C1_USE_DMA
306
+  i2c_lld_serve_event_interrupt_dma(&I2CD1);
307
+#else
308
+  i2c_lld_serve_event_interrupt_isr(&I2CD1);
309
+#endif
310
 
311
   OSAL_IRQ_EPILOGUE();
312
 }
313
@@ -437,7 +637,11 @@ OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
314
 
315
   OSAL_IRQ_PROLOGUE();
316
 
317
-  i2c_lld_serve_event_interrupt(&I2CD2);
318
+#if STM32_I2C_I2C2_USE_DMA
319
+  i2c_lld_serve_event_interrupt_dma(&I2CD2);
320
+#else
321
+  i2c_lld_serve_event_interrupt_isr(&I2CD2);
322
+#endif
323
 
324
   OSAL_IRQ_EPILOGUE();
325
 }
326
@@ -469,7 +673,11 @@ OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
327
 
328
   OSAL_IRQ_PROLOGUE();
329
 
330
-  i2c_lld_serve_event_interrupt(&I2CD3);
331
+#if STM32_I2C_I2C3_USE_DMA
332
+  i2c_lld_serve_event_interrupt_dma(&I2CD3);
333
+#else
334
+  i2c_lld_serve_event_interrupt_isr(&I2CD3);
335
+#endif
336
 
337
   OSAL_IRQ_EPILOGUE();
338
 }
339
@@ -540,19 +748,22 @@ void i2c_lld_start(I2CDriver *i2cp) {
340
   /* If in stopped state then enables the I2C and DMA clocks.*/
341
   if (i2cp->state == I2C_STOP) {
342
 
343
-    i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
344
-                      STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
345
-                      STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
346
-                      STM32_DMA_CR_DIR_M2P;
347
-    i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
348
-                      STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
349
-                      STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
350
-                      STM32_DMA_CR_DIR_P2M;
351
-
352
 #if STM32_I2C_USE_I2C1
353
     if (&I2CD1 == i2cp) {
354
+#if STM32_I2C_I2C1_USE_DMA
355
+      i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
356
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
357
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
358
+                        STM32_DMA_CR_DIR_M2P;
359
+      i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
360
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
361
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
362
+                        STM32_DMA_CR_DIR_P2M;
363
+#endif
364
+
365
       rccResetI2C1();
366
 
367
+#if STM32_I2C_I2C1_USE_DMA
368
       i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C1_RX_DMA_STREAM,
369
                                     STM32_I2C_I2C1_IRQ_PRIORITY,
370
                                     (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
371
@@ -563,22 +774,50 @@ void i2c_lld_start(I2CDriver *i2cp) {
372
                                     (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
373
                                     (void *)i2cp);
374
       osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
375
+#endif
376
 
377
       rccEnableI2C1(true);
378
       nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
379
       nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY);
380
 
381
+#if STM32_I2C_I2C1_USE_DMA
382
       i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) |
383
                        STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
384
       i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) |
385
                        STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY);
386
+
387
+      /* I2C registers pointed by the DMA.*/
388
+      dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
389
+      dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
390
+#endif
391
+
392
+      /* Reset i2c peripheral.*/
393
+      dp->CR1 = I2C_CR1_SWRST;
394
+      dp->CR1 = 0;
395
+#if STM32_I2C_I2C1_USE_DMA
396
+      dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
397
+#else
398
+      dp->CR2 = I2C_CR2_ITERREN;
399
+#endif
400
     }
401
 #endif /* STM32_I2C_USE_I2C1 */
402
 
403
 #if STM32_I2C_USE_I2C2
404
     if (&I2CD2 == i2cp) {
405
+#if STM32_I2C_I2C2_USE_DMA
406
+      i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
407
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
408
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
409
+                        STM32_DMA_CR_DIR_M2P;
410
+      i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
411
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
412
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
413
+                        STM32_DMA_CR_DIR_P2M;
414
+#endif
415
+
416
       rccResetI2C2();
417
 
418
+#if STM32_I2C_I2C2_USE_DMA
419
       i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C2_RX_DMA_STREAM,
420
                                     STM32_I2C_I2C2_IRQ_PRIORITY,
421
                                     (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
422
@@ -589,22 +828,50 @@ void i2c_lld_start(I2CDriver *i2cp) {
423
                                     (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
424
                                     (void *)i2cp);
425
       osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
426
+#endif
427
 
428
       rccEnableI2C2(true);
429
       nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
430
       nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY);
431
 
432
+#if STM32_I2C_I2C2_USE_DMA
433
       i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) |
434
                        STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
435
       i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) |
436
                        STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY);
437
+
438
+      /* I2C registers pointed by the DMA.*/
439
+      dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
440
+      dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
441
+#endif
442
+
443
+      /* Reset i2c peripheral.*/
444
+      dp->CR1 = I2C_CR1_SWRST;
445
+      dp->CR1 = 0;
446
+#if STM32_I2C_I2C2_USE_DMA
447
+      dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
448
+#else
449
+      dp->CR2 = I2C_CR2_ITERREN;
450
+#endif
451
     }
452
 #endif /* STM32_I2C_USE_I2C2 */
453
 
454
 #if STM32_I2C_USE_I2C3
455
     if (&I2CD3 == i2cp) {
456
+#if STM32_I2C_I2C3_USE_DMA
457
+      i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
458
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
459
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
460
+                        STM32_DMA_CR_DIR_M2P;
461
+      i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
462
+                        STM32_DMA_CR_MINC       | STM32_DMA_CR_DMEIE |
463
+                        STM32_DMA_CR_TEIE       | STM32_DMA_CR_TCIE |
464
+                        STM32_DMA_CR_DIR_P2M;
465
+#endif
466
+
467
       rccResetI2C3();
468
 
469
+#if STM32_I2C_I2C3_USE_DMA
470
       i2cp->dmarx = dmaStreamAllocI(STM32_I2C_I2C3_RX_DMA_STREAM,
471
                                     STM32_I2C_I2C3_IRQ_PRIORITY,
472
                                     (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq,
473
@@ -615,28 +882,35 @@ void i2c_lld_start(I2CDriver *i2cp) {
474
                                     (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq,
475
                                     (void *)i2cp);
476
       osalDbgAssert(i2cp->dmatx != NULL, "unable to allocate stream");
477
+#endif
478
 
479
       rccEnableI2C3(true);
480
       nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
481
       nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY);
482
 
483
+#if STM32_I2C_I2C3_USE_DMA
484
       i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) |
485
                        STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
486
       i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) |
487
                        STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY);
488
+
489
+      /* I2C registers pointed by the DMA.*/
490
+      dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
491
+      dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
492
+#endif
493
+
494
+      /* Reset i2c peripheral.*/
495
+      dp->CR1 = I2C_CR1_SWRST;
496
+      dp->CR1 = 0;
497
+#if STM32_I2C_I2C3_USE_DMA
498
+      dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
499
+#else
500
+      dp->CR2 = I2C_CR2_ITERREN;
501
+#endif
502
     }
503
 #endif /* STM32_I2C_USE_I2C3 */
504
   }
505
 
506
-  /* I2C registers pointed by the DMA.*/
507
-  dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
508
-  dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
509
-
510
-  /* Reset i2c peripheral.*/
511
-  dp->CR1 = I2C_CR1_SWRST;
512
-  dp->CR1 = 0;
513
-  dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
514
-
515
   /* Setup I2C parameters.*/
516
   i2c_lld_set_clock(i2cp);
517
   i2c_lld_set_opmode(i2cp);
518
@@ -659,13 +933,15 @@ void i2c_lld_stop(I2CDriver *i2cp) {
519
 
520
     /* I2C disable.*/
521
     i2c_lld_abort_operation(i2cp);
522
-    dmaStreamFreeI(i2cp->dmatx);
523
-    dmaStreamFreeI(i2cp->dmarx);
524
-    i2cp->dmatx = NULL;
525
-    i2cp->dmarx = NULL;
526
 
527
 #if STM32_I2C_USE_I2C1
528
     if (&I2CD1 == i2cp) {
529
+#if STM32_I2C_I2C1_USE_DMA
530
+      dmaStreamFreeI(i2cp->dmatx);
531
+      dmaStreamFreeI(i2cp->dmarx);
532
+      i2cp->dmatx = NULL;
533
+      i2cp->dmarx = NULL;
534
+#endif
535
       nvicDisableVector(I2C1_EV_IRQn);
536
       nvicDisableVector(I2C1_ER_IRQn);
537
       rccDisableI2C1();
538
@@ -674,6 +950,12 @@ void i2c_lld_stop(I2CDriver *i2cp) {
539
 
540
 #if STM32_I2C_USE_I2C2
541
     if (&I2CD2 == i2cp) {
542
+#if STM32_I2C_I2C2_USE_DMA
543
+      dmaStreamFreeI(i2cp->dmatx);
544
+      dmaStreamFreeI(i2cp->dmarx);
545
+      i2cp->dmatx = NULL;
546
+      i2cp->dmarx = NULL;
547
+#endif
548
       nvicDisableVector(I2C2_EV_IRQn);
549
       nvicDisableVector(I2C2_ER_IRQn);
550
       rccDisableI2C2();
551
@@ -682,6 +964,12 @@ void i2c_lld_stop(I2CDriver *i2cp) {
552
 
553
 #if STM32_I2C_USE_I2C3
554
     if (&I2CD3 == i2cp) {
555
+#if STM32_I2C_I2C3_USE_DMA
556
+      dmaStreamFreeI(i2cp->dmatx);
557
+      dmaStreamFreeI(i2cp->dmarx);
558
+      i2cp->dmatx = NULL;
559
+      i2cp->dmarx = NULL;
560
+#endif
561
       nvicDisableVector(I2C3_EV_IRQn);
562
       nvicDisableVector(I2C3_ER_IRQn);
563
       rccDisableI2C3();
564
@@ -732,10 +1020,43 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
565
   /* Releases the lock from high level driver.*/
566
   osalSysUnlock();
567
 
568
-  /* RX DMA setup.*/
569
-  dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
570
-  dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
571
-  dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
572
+  /* RX (DMA) setup.*/
573
+#if STM32_I2C_USE_I2C1
574
+  if (&I2CD1 == i2cp) {
575
+#if STM32_I2C_I2C1_USE_DMA
576
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
577
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
578
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
579
+#else
580
+    i2cp->rxbuf = rxbuf;
581
+    i2cp->rxbytes = rxbytes;
582
+#endif
583
+  }
584
+#endif
585
+#if STM32_I2C_USE_I2C2
586
+  if (&I2CD2 == i2cp) {
587
+#if STM32_I2C_I2C2_USE_DMA
588
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
589
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
590
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
591
+#else
592
+    i2cp->rxbuf = rxbuf;
593
+    i2cp->rxbytes = rxbytes;
594
+#endif
595
+  }
596
+#endif
597
+#if STM32_I2C_USE_I2C3
598
+  if (&I2CD3 == i2cp) {
599
+#if STM32_I2C_I2C3_USE_DMA
600
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
601
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
602
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
603
+#else
604
+    i2cp->rxbuf = rxbuf;
605
+    i2cp->rxbytes = rxbytes;
606
+#endif
607
+  }
608
+#endif
609
 
610
   /* Calculating the time window for the timeout on the busy bus condition.*/
611
   start = osalOsGetSystemTimeX();
612
@@ -812,15 +1133,61 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
613
   /* Releases the lock from high level driver.*/
614
   osalSysUnlock();
615
 
616
-  /* TX DMA setup.*/
617
-  dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
618
-  dmaStreamSetMemory0(i2cp->dmatx, txbuf);
619
-  dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
620
-
621
-  /* RX DMA setup.*/
622
-  dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
623
-  dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
624
-  dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
625
+  /* TX (DMA) and RX (DMA) setup.*/
626
+#if STM32_I2C_USE_I2C1
627
+  if (&I2CD1 == i2cp) {
628
+#if STM32_I2C_I2C1_USE_DMA
629
+    dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
630
+    dmaStreamSetMemory0(i2cp->dmatx, txbuf);
631
+    dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
632
+
633
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
634
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
635
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
636
+#else
637
+    i2cp->txbuf = txbuf;
638
+    i2cp->txbytes = txbytes;
639
+    i2cp->rxbuf = rxbuf;
640
+    i2cp->rxbytes = rxbytes;
641
+#endif
642
+  }
643
+#endif
644
+#if STM32_I2C_USE_I2C2
645
+  if (&I2CD2 == i2cp) {
646
+#if STM32_I2C_I2C2_USE_DMA
647
+    dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
648
+    dmaStreamSetMemory0(i2cp->dmatx, txbuf);
649
+    dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
650
+
651
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
652
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
653
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
654
+#else
655
+    i2cp->txbuf = txbuf;
656
+    i2cp->txbytes = txbytes;
657
+    i2cp->rxbuf = rxbuf;
658
+    i2cp->rxbytes = rxbytes;
659
+#endif
660
+  }
661
+#endif
662
+#if STM32_I2C_USE_I2C3
663
+  if (&I2CD3 == i2cp) {
664
+#if STM32_I2C_I2C3_USE_DMA
665
+    dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
666
+    dmaStreamSetMemory0(i2cp->dmatx, txbuf);
667
+    dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
668
+
669
+    dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
670
+    dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
671
+    dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
672
+#else
673
+    i2cp->txbuf = txbuf;
674
+    i2cp->txbytes = txbytes;
675
+    i2cp->rxbuf = rxbuf;
676
+    i2cp->rxbytes = rxbytes;
677
+#endif
678
+  }
679
+#endif
680
 
681
   /* Calculating the time window for the timeout on the busy bus condition.*/
682
   start = osalOsGetSystemTimeX();
683 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
684
--- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
685
+++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
686 732a4657 Thomas Schöpping
@@ -103,6 +103,33 @@
687
 #define STM32_I2C_I2C3_IRQ_PRIORITY         10
688
 #endif
689
 
690
+/**
691
+ * @brief   I2C1 DMA enable switch.
692
+ * @details If set to @p TRUE the I2C1 driver will use DMA.
693
+ * @note    The default is @p TRUE.
694
+ */
695
+#if !defined(STM32_I2C_I2C1_USE_DMA) || defined(__DOXYGEN__)
696
+#define STM32_I2C_I2C1_USE_DMA              TRUE
697
+#endif
698
+
699
+/**
700
+ * @brief   I2C2 DMA enable switch.
701
+ * @details If set to @p TRUE the I2C2 driver will use DMA.
702
+ * @note    The default is @p TRUE.
703
+ */
704
+#if !defined(STM32_I2C_I2C2_USE_DMA) || defined(__DOXYGEN__)
705
+#define STM32_I2C_I2C2_USE_DMA              TRUE
706
+#endif
707
+
708
+/**
709
+ * @brief   I2C3 DMA enable switch.
710
+ * @details If set to @p TRUE the I2C3 driver will use DMA.
711
+ * @note    The default is @p TRUE.
712
+ */
713
+#if !defined(STM32_I2C_I2C3_USE_DMA) || defined(__DOXYGEN__)
714
+#define STM32_I2C_I2C3_USE_DMA              TRUE
715
+#endif
716
+
717
 /**
718
 * @brief   I2C1 DMA priority (0..3|lowest..highest).
719
 * @note    The priority level is used for both the TX and RX DMA streams but
720 22be62dc Thomas Schöpping
@@ -250,16 +277,19 @@
721 732a4657 Thomas Schöpping
 #endif
722
 
723
 #if STM32_I2C_USE_I2C1 &&                                                   \
724
+    STM32_I2C_I2C1_USE_DMA &&                                               \
725
     !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY)
726
 #error "Invalid DMA priority assigned to I2C1"
727
 #endif
728
 
729
 #if STM32_I2C_USE_I2C2 &&                                                   \
730
+    STM32_I2C_I2C2_USE_DMA &&                                               \
731
     !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY)
732
 #error "Invalid DMA priority assigned to I2C2"
733
 #endif
734
 
735
 #if STM32_I2C_USE_I2C3 &&                                                   \
736
+    STM32_I2C_I2C3_USE_DMA &&                                               \
737
     !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY)
738
 #error "Invalid DMA priority assigned to I2C3"
739
 #endif
740 22be62dc Thomas Schöpping
@@ -316,7 +346,10 @@
741 732a4657 Thomas Schöpping
 #endif
742
 #endif /* STM32_ADVANCED_DMA */
743
 
744
-#if !defined(STM32_DMA_REQUIRED)
745
+#if ((STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) ||                       \
746
+     (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) ||                       \
747
+     (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA)) &&                      \
748
+    !defined(STM32_DMA_REQUIRED)
749
 #define STM32_DMA_REQUIRED
750
 #endif
751
 
752 22be62dc Thomas Schöpping
@@ -437,21 +470,52 @@ struct I2CDriver {
753 732a4657 Thomas Schöpping
    */
754
   i2caddr_t                 addr;
755
   /**
756
-   * @brief RX DMA mode bit mask.
757
-   */
758
-  uint32_t                  rxdmamode;
759
-  /**
760
-   * @brief TX DMA mode bit mask.
761
-   */
762
-  uint32_t                  txdmamode;
763
-  /**
764
-   * @brief     Receive DMA channel.
765
-   */
766
-  const stm32_dma_stream_t  *dmarx;
767
-  /**
768
-   * @brief     Transmit DMA channel.
769
+   * @brief   Anonymous union to store transmission related data for either DMA or non-DMA mode.
770
    */
771
-  const stm32_dma_stream_t  *dmatx;
772
+  union {
773
+    /**
774
+     * @brief   Anonymous struct to store data for DMA mode.
775
+     */
776
+    struct {
777
+      /**
778
+       * @brief RX DMA mode bit mask.
779
+       */
780
+      uint32_t                  rxdmamode;
781
+      /**
782
+       * @brief TX DMA mode bit mask.
783
+       */
784
+      uint32_t                  txdmamode;
785
+      /**
786
+       * @brief     Receive DMA channel.
787
+       */
788
+      const stm32_dma_stream_t  *dmarx;
789
+      /**
790
+       * @brief     Transmit DMA channel.
791
+       */
792
+      const stm32_dma_stream_t  *dmatx;
793
+    };
794
+    /**
795
+     * @brief   Anonymous struct to store data for non-DMA mode.
796
+     */
797
+    struct {
798
+      /**
799
+       * @brief   Receive buffer.
800
+       */
801
+      uint8_t                   *rxbuf;
802
+      /**
803
+       * @brief   Size of the receive buffer.
804
+       */
805
+      size_t                    rxbytes;
806
+      /**
807
+       * @brief   Transmit buffer.
808
+       */
809
+      const uint8_t             *txbuf;
810
+      /**
811
+       * @brief   Size of the transmit buffer.
812
+       */
813
+      size_t                    txbytes;
814
+    };
815
+  };
816
   /**
817
    * @brief     Pointer to the I2Cx registers block.
818
    */