Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (27.04 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
+