amiro-os / patches / 0007-SMT32-add-optional-I2C-non-DMA-driver-option.patch @ c0757912
History | View | Annotate | Download (17.143 KB)
1 | 58fe0e0b | Thomas Schöpping | From: Thomas SCHÖPPING <tschoepp@techfak.uni-bielefeld.de>
|
---|---|---|---|
2 | Date: Wed, 29 Apr 2015 18:15:23 +0200
|
||
3 | Subject: [PATCH] STM32/I2Cv1: added the option to use I2C without DMA
|
||
4 | |||
5 | Signed-off-by: Thomas SCHÖPPING <tschoepp@techfak.uni-bielefeld.de>
|
||
6 | ---
|
||
7 | diff --git a/os/hal/platforms/STM32/I2Cv1/i2c_lld.c b/os/hal/platforms/STM32/I2Cv1/i2c_lld.c
|
||
8 | index 2a36776..4a27942 100644
|
||
9 | --- a/os/hal/platforms/STM32/I2Cv1/i2c_lld.c
|
||
10 | +++ b/os/hal/platforms/STM32/I2Cv1/i2c_lld.c
|
||
11 | @@ -35,6 +35,7 @@
|
||
12 | /* Driver local definitions. */
|
||
13 | /*===========================================================================*/
|
||
14 | |||
15 | +#if STM32_I2C_USE_DMA
|
||
16 | #define I2C1_RX_DMA_CHANNEL \ |
||
17 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \
|
||
18 | STM32_I2C1_RX_DMA_CHN) |
||
19 | @@ -58,6 +59,7 @@
|
||
20 | #define I2C3_TX_DMA_CHANNEL \ |
||
21 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \
|
||
22 | STM32_I2C3_TX_DMA_CHN) |
||
23 | +#endif /* STM32_I2C_USE_DMA */
|
||
24 | |||
25 | /*===========================================================================*/
|
||
26 | /* Driver constants. */
|
||
27 | @@ -73,6 +75,20 @@
|
||
28 | #define I2C_EV6_MASTER_REC_MODE_SELECTED \ |
||
29 | ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR))
|
||
30 | |||
31 | +#define I2C_EV7_MASTER_REC_BYTE_RECEIVED \
|
||
32 | + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_RXNE))
|
||
33 | +
|
||
34 | +#define I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP \
|
||
35 | + ((uint32_t)( I2C_SR1_RXNE))
|
||
36 | +
|
||
37 | +#define I2C_EV7_2_EV7_3_MASTER_REC_BYTE_QUEUED \
|
||
38 | + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | \
|
||
39 | + I2C_SR1_BTF | I2C_SR1_RXNE))
|
||
40 | +
|
||
41 | +#define I2C_EV8_MASTER_BYTE_TRANSMITTING \
|
||
42 | + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA)<< 16) | \
|
||
43 | + I2C_SR1_TXE))
|
||
44 | +
|
||
45 | #define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ |
||
46 | ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ |
||
47 | I2C_SR1_BTF | I2C_SR1_TXE)) |
||
48 | @@ -148,9 +164,11 @@ static void i2c_lld_abort_operation(I2CDriver *i2cp) { |
||
49 | dp->CR2 = 0;
|
||
50 | dp->SR1 = 0;
|
||
51 | |||
52 | +#if STM32_I2C_USE_DMA
|
||
53 | /* Stops the associated DMA streams.*/
|
||
54 | dmaStreamDisable(i2cp->dmatx); |
||
55 | dmaStreamDisable(i2cp->dmarx); |
||
56 | +#endif /* STM32_I2C_USE_DMA */
|
||
57 | } |
||
58 | |||
59 | /**
|
||
60 | @@ -242,7 +260,7 @@ static void i2c_lld_set_clock(I2CDriver *i2cp) { |
||
61 | |||
62 | chDbgAssert(clock_div >= 0x01,
|
||
63 | "i2c_lld_set_clock(), #7",
|
||
64 | - "Clock divider less then 0x04 not allowed");
|
||
65 | + "Clock divider less then 0x01 not allowed");
|
||
66 | regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); |
||
67 | |||
68 | /* Sets the Maximum Rise Time for fast mode.*/
|
||
69 | @@ -295,12 +313,13 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { |
||
70 | uint32_t regSR2 = dp->SR2; |
||
71 | uint32_t event = dp->SR1; |
||
72 | |||
73 | +#if STM32_I2C_USE_DMA
|
||
74 | /* Interrupts are disabled just before dmaStreamEnable() because there
|
||
75 | is no need of interrupts until next transaction begin. All the work is |
||
76 | done by the DMA.*/ |
||
77 | switch (I2C_EV_MASK & (event | (regSR2 << 16))) { |
||
78 | case I2C_EV5_MASTER_MODE_SELECT:
|
||
79 | - if ((i2cp->addr >> 8) > 0) {
|
||
80 | + if ((i2cp->addr >> 8) > 0) {
|
||
81 | /* 10-bit address: 1 1 1 1 0 X X R/W */
|
||
82 | dp->DR = 0xF0 | (0x6 & (i2cp->addr >> 8)) | (0x1 & i2cp->addr); |
||
83 | } else {
|
||
84 | @@ -340,8 +359,129 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { |
||
85 | /* Clear ADDR flag. */
|
||
86 | if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10))
|
||
87 | (void)dp->SR2;
|
||
88 | +#else
|
||
89 | + switch (I2C_EV_MASK & (event | (regSR2 << 16))) {
|
||
90 | + case I2C_EV5_MASTER_MODE_SELECT:
|
||
91 | + dp->CR2 |= I2C_CR2_ITBUFEN;
|
||
92 | + dp->DR = i2cp->addr;
|
||
93 | + break;
|
||
94 | + case I2C_EV6_MASTER_TRA_MODE_SELECTED:
|
||
95 | + (void)dp->SR2; // clear ADDR flag
|
||
96 | + /* EV8_1 */
|
||
97 | + dp->DR = *(i2cp->txbuf);
|
||
98 | +
|
||
99 | + ++i2cp->txbuf;
|
||
100 | + --i2cp->txbytes;
|
||
101 | +
|
||
102 | + /* if N == 1, skip the I2C_EV8_MASTER_BYTE_TRANSMITTING event
|
||
103 | + * but enter I2C_EV8_2_MASTER_BYTE_TRANSMITTED next */
|
||
104 | + if (i2cp->txbytes == 0) {
|
||
105 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
106 | + }
|
||
107 | + break;
|
||
108 | + case I2C_EV6_MASTER_REC_MODE_SELECTED:
|
||
109 | + switch (i2cp->rxbytes) {
|
||
110 | + case 1:
|
||
111 | + dp->CR1 &= ~I2C_CR1_ACK;
|
||
112 | + (void)dp->SR2; // clear ADDR flag
|
||
113 | + dp->CR1 |= I2C_CR1_STOP;
|
||
114 | + break;
|
||
115 | + case 2:
|
||
116 | + (void)dp->SR2; // clear ADDR flag
|
||
117 | + /* EV6_1 */
|
||
118 | + dp->CR1 |= I2C_CR1_POS;
|
||
119 | + dp->CR1 &= ~I2C_CR1_ACK;
|
||
120 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
121 | + break;
|
||
122 | + case 3: /* N == 3 is a very special case, since EV7 is completely skipped */
|
||
123 | + (void)dp->SR2; // clear ADDR flag
|
||
124 | + /* Disable the I2C_EV7_MASTER_REC_BYTE_RECEIVED event
|
||
125 | + * but enter I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP next */
|
||
126 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
127 | + break;
|
||
128 | + default: /* N > 2 */
|
||
129 | + (void)dp->SR2; // clear ADDR flag
|
||
130 | + break;
|
||
131 | + }
|
||
132 | + break;
|
||
133 | + case I2C_EV7_MASTER_REC_BYTE_RECEIVED:
|
||
134 | + if (i2cp->rxbytes > 3) {
|
||
135 | + *(i2cp->rxbuf) = dp->DR;
|
||
136 | + ++i2cp->rxbuf;
|
||
137 | + --i2cp->rxbytes;
|
||
138 | + }
|
||
139 | + if (i2cp->rxbytes == 3) {
|
||
140 | + /* Disable this event for DataN-2, but force into event
|
||
141 | + * I2C_EV7_2_EV7_3_MASTER_REC_BYTE_RECEIVED_QUEUED by not reading dp->DR. */
|
||
142 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
143 | + }
|
||
144 | + break;
|
||
145 | + case I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP:
|
||
146 | + chDbgAssert(i2cp->rxbytes == 1, "i2c_lld_serve_event_interrupt(), #1",
|
||
147 | + "more than 1 byte to be received");
|
||
148 | + *(i2cp->rxbuf) = dp->DR;
|
||
149 | + --i2cp->rxbytes;
|
||
150 | + dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
|
||
151 | + wakeup_isr(i2cp, RDY_OK);
|
||
152 | + break;
|
||
153 | + case I2C_EV7_2_EV7_3_MASTER_REC_BYTE_QUEUED:
|
||
154 | + if (i2cp->rxbytes == 3) {
|
||
155 | + /* EV7_2 (N > 2) */
|
||
156 | + dp->CR1 &= ~I2C_CR1_ACK;
|
||
157 | + *(i2cp->rxbuf) = dp->DR;
|
||
158 | + ++i2cp->rxbuf;
|
||
159 | + dp->CR1 |= I2C_CR1_STOP;
|
||
160 | + *(i2cp->rxbuf) = dp->DR;
|
||
161 | + ++i2cp->rxbuf;
|
||
162 | + i2cp->rxbytes -= 2;
|
||
163 | + /* enable I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP event */
|
||
164 | + dp->CR2 |= I2C_CR2_ITBUFEN;
|
||
165 | + } else {
|
||
166 | + /* EV7_3 (N == 2) */
|
||
167 | + dp->CR1 |= I2C_CR1_STOP;
|
||
168 | + *(i2cp->rxbuf) = dp->DR;
|
||
169 | + ++i2cp->rxbuf;
|
||
170 | + *(i2cp->rxbuf) = dp->DR;
|
||
171 | + i2cp->rxbytes -= 2;
|
||
172 | +
|
||
173 | + dp->CR1 &= ~I2C_CR1_POS;
|
||
174 | + dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
|
||
175 | +
|
||
176 | + wakeup_isr(i2cp, RDY_OK);
|
||
177 | + }
|
||
178 | + break;
|
||
179 | + case I2C_EV8_MASTER_BYTE_TRANSMITTING:
|
||
180 | + dp->DR = *(i2cp->txbuf);
|
||
181 | + ++i2cp->txbuf;
|
||
182 | + --i2cp->txbytes;
|
||
183 | +
|
||
184 | + /* if this was the last byte, ensure that this event is not entered again */
|
||
185 | + if (i2cp->txbytes == 0) {
|
||
186 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
187 | + }
|
||
188 | + break;
|
||
189 | + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
|
||
190 | + if (i2cp->rxbytes > 0) {
|
||
191 | + /* start "read after write" operation (LSB of address = 1 -> read) */
|
||
192 | + i2cp-> addr |= 0x01;
|
||
193 | + dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
|
||
194 | + } else {
|
||
195 | + dp->CR1 |= I2C_CR1_STOP;
|
||
196 | +
|
||
197 | + dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
|
||
198 | +
|
||
199 | + wakeup_isr(i2cp, RDY_OK);
|
||
200 | + }
|
||
201 | + break;
|
||
202 | + default:
|
||
203 | + chDbgAssert(i2cp->rxbytes != 1, "i2c_lld_serve_event_interrupt(), #1",
|
||
204 | + "more than 1 byte to be received");
|
||
205 | + break;
|
||
206 | + }
|
||
207 | +#endif /* STM32_I2C_USE_DMA */
|
||
208 | } |
||
209 | |||
210 | +#if STM32_I2C_USE_DMA
|
||
211 | /**
|
||
212 | * @brief DMA RX end IRQ handler.
|
||
213 | * |
||
214 | @@ -395,6 +535,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { |
||
215 | of R/W transaction itself.*/ |
||
216 | dp->CR2 |= I2C_CR2_ITEVTEN; |
||
217 | } |
||
218 | +#endif /* STM32_I2C_USE_DMA */
|
||
219 | |||
220 | /**
|
||
221 | * @brief I2C error handler.
|
||
222 | @@ -406,9 +547,11 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { |
||
223 | */ |
||
224 | static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { |
||
225 | |||
226 | +#if STM32_I2C_USE_DMA
|
||
227 | /* Clears interrupt flags just to be safe.*/
|
||
228 | dmaStreamDisable(i2cp->dmatx); |
||
229 | dmaStreamDisable(i2cp->dmarx); |
||
230 | +#endif /* STM32_I2C_USE_DMA */
|
||
231 | |||
232 | i2cp->errors = I2CD_NO_ERROR; |
||
233 | |||
234 | @@ -554,24 +697,30 @@ void i2c_lld_init(void) { |
||
235 | i2cObjectInit(&I2CD1); |
||
236 | I2CD1.thread = NULL;
|
||
237 | I2CD1.i2c = I2C1; |
||
238 | +#if STM32_I2C_USE_DMA
|
||
239 | I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); |
||
240 | I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); |
||
241 | +#endif /* STM32_I2C_USE_DMA */
|
||
242 | #endif /* STM32_I2C_USE_I2C1 */ |
||
243 | |||
244 | #if STM32_I2C_USE_I2C2
|
||
245 | i2cObjectInit(&I2CD2); |
||
246 | I2CD2.thread = NULL;
|
||
247 | I2CD2.i2c = I2C2; |
||
248 | +#if STM32_I2C_USE_DMA
|
||
249 | I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); |
||
250 | I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); |
||
251 | +#endif /* STM32_I2C_USE_DMA */
|
||
252 | #endif /* STM32_I2C_USE_I2C2 */ |
||
253 | |||
254 | #if STM32_I2C_USE_I2C3
|
||
255 | i2cObjectInit(&I2CD3); |
||
256 | I2CD3.thread = NULL;
|
||
257 | I2CD3.i2c = I2C3; |
||
258 | +#if STM32_I2C_USE_DMA
|
||
259 | I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); |
||
260 | I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); |
||
261 | +#endif /* STM32_I2C_USE_DMA */
|
||
262 | #endif /* STM32_I2C_USE_I2C3 */ |
||
263 | } |
||
264 | |||
265 | @@ -585,6 +734,7 @@ void i2c_lld_init(void) { |
||
266 | void i2c_lld_start(I2CDriver *i2cp) {
|
||
267 | I2C_TypeDef *dp = i2cp->i2c; |
||
268 | |||
269 | +#if STM32_I2C_USE_DMA
|
||
270 | i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | |
||
271 | STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | |
||
272 | STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | |
||
273 | @@ -593,15 +743,17 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
274 | STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | |
||
275 | STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | |
||
276 | STM32_DMA_CR_DIR_P2M; |
||
277 | +#endif /* STM32_I2C_USE_DMA */
|
||
278 | |||
279 | /* If in stopped state then enables the I2C and DMA clocks.*/
|
||
280 | if (i2cp->state == I2C_STOP) {
|
||
281 | |||
282 | #if STM32_I2C_USE_I2C1
|
||
283 | if (&I2CD1 == i2cp) {
|
||
284 | - bool_t b;
|
||
285 | |||
286 | rccResetI2C1(); |
||
287 | +#if STM32_I2C_USE_DMA
|
||
288 | + bool_t b;
|
||
289 | b = dmaStreamAllocate(i2cp->dmarx, |
||
290 | STM32_I2C_I2C1_IRQ_PRIORITY, |
||
291 | (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, |
||
292 | @@ -612,24 +764,28 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
293 | (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, |
||
294 | (void *)i2cp);
|
||
295 | chDbgAssert(!b, "i2c_lld_start(), #2", "stream already allocated"); |
||
296 | +#endif /* STM32_I2C_USE_DMA */
|
||
297 | rccEnableI2C1(FALSE); |
||
298 | nvicEnableVector(I2C1_EV_IRQn, |
||
299 | CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); |
||
300 | nvicEnableVector(I2C1_ER_IRQn, |
||
301 | CORTEX_PRIORITY_MASK(STM32_I2C_I2C1_IRQ_PRIORITY)); |
||
302 | |||
303 | +#if STM32_I2C_USE_DMA
|
||
304 | i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | |
||
305 | STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); |
||
306 | i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | |
||
307 | STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); |
||
308 | +#endif /* STM32_I2C_USE_DMA */
|
||
309 | } |
||
310 | #endif /* STM32_I2C_USE_I2C1 */ |
||
311 | |||
312 | #if STM32_I2C_USE_I2C2
|
||
313 | if (&I2CD2 == i2cp) {
|
||
314 | - bool_t b;
|
||
315 | |||
316 | rccResetI2C2(); |
||
317 | +#if STM32_I2C_USE_DMA
|
||
318 | + bool_t b;
|
||
319 | b = dmaStreamAllocate(i2cp->dmarx, |
||
320 | STM32_I2C_I2C2_IRQ_PRIORITY, |
||
321 | (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, |
||
322 | @@ -640,24 +796,28 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
323 | (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, |
||
324 | (void *)i2cp);
|
||
325 | chDbgAssert(!b, "i2c_lld_start(), #4", "stream already allocated"); |
||
326 | +#endif /* STM32_I2C_USE_DMA */
|
||
327 | rccEnableI2C2(FALSE); |
||
328 | nvicEnableVector(I2C2_EV_IRQn, |
||
329 | CORTEX_PRIORITY_MASK(STM32_I2C_I2C2_IRQ_PRIORITY)); |
||
330 | nvicEnableVector(I2C2_ER_IRQn, |
||
331 | CORTEX_PRIORITY_MASK(STM32_I2C_I2C2_IRQ_PRIORITY)); |
||
332 | |||
333 | +#if STM32_I2C_USE_DMA
|
||
334 | i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | |
||
335 | STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); |
||
336 | i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | |
||
337 | STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); |
||
338 | +#endif /* STM32_I2C_USE_DMA */
|
||
339 | } |
||
340 | #endif /* STM32_I2C_USE_I2C2 */ |
||
341 | |||
342 | #if STM32_I2C_USE_I2C3
|
||
343 | if (&I2CD3 == i2cp) {
|
||
344 | - bool_t b;
|
||
345 | |||
346 | rccResetI2C3(); |
||
347 | +#if STM32_I2C_USE_DMA
|
||
348 | + bool_t b;
|
||
349 | b = dmaStreamAllocate(i2cp->dmarx, |
||
350 | STM32_I2C_I2C3_IRQ_PRIORITY, |
||
351 | (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, |
||
352 | @@ -668,28 +828,37 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
353 | (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, |
||
354 | (void *)i2cp);
|
||
355 | chDbgAssert(!b, "i2c_lld_start(), #6", "stream already allocated"); |
||
356 | +#endif /* STM32_I2C_USE_DMA */
|
||
357 | rccEnableI2C3(FALSE); |
||
358 | nvicEnableVector(I2C3_EV_IRQn, |
||
359 | CORTEX_PRIORITY_MASK(STM32_I2C_I2C3_IRQ_PRIORITY)); |
||
360 | nvicEnableVector(I2C3_ER_IRQn, |
||
361 | CORTEX_PRIORITY_MASK(STM32_I2C_I2C3_IRQ_PRIORITY)); |
||
362 | |||
363 | +#if STM32_I2C_USE_DMA
|
||
364 | i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | |
||
365 | STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); |
||
366 | i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | |
||
367 | STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); |
||
368 | +#endif /* STM32_I2C_USE_DMA */
|
||
369 | } |
||
370 | #endif /* STM32_I2C_USE_I2C3 */ |
||
371 | } |
||
372 | |||
373 | +#if STM32_I2C_USE_DMA
|
||
374 | /* I2C registers pointed by the DMA.*/
|
||
375 | dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); |
||
376 | dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); |
||
377 | +#endif /* STM32_I2C_USE_DMA */
|
||
378 | |||
379 | /* Reset i2c peripheral.*/
|
||
380 | dp->CR1 = I2C_CR1_SWRST; |
||
381 | dp->CR1 = 0;
|
||
382 | +#if STM32_I2C_USE_DMA
|
||
383 | dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN; |
||
384 | +#else
|
||
385 | + dp->CR2 = I2C_CR2_ITERREN;
|
||
386 | +#endif /* STM32_I2C_USE_DMA */
|
||
387 | |||
388 | /* Setup I2C parameters.*/
|
||
389 | i2c_lld_set_clock(i2cp); |
||
390 | @@ -713,8 +882,10 @@ void i2c_lld_stop(I2CDriver *i2cp) { |
||
391 | |||
392 | /* I2C disable.*/
|
||
393 | i2c_lld_abort_operation(i2cp); |
||
394 | +#if STM32_I2C_USE_DMA
|
||
395 | dmaStreamRelease(i2cp->dmatx); |
||
396 | dmaStreamRelease(i2cp->dmarx); |
||
397 | +#endif /* STM32_I2C_USE_DMA */
|
||
398 | |||
399 | #if STM32_I2C_USE_I2C1
|
||
400 | if (&I2CD1 == i2cp) {
|
||
401 | @@ -786,10 +957,15 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||
402 | i2cp->addr = (addr << 1) | 0x01; |
||
403 | i2cp->errors = 0;
|
||
404 | |||
405 | +#if STM32_I2C_USE_DMA
|
||
406 | /* RX DMA setup.*/
|
||
407 | dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); |
||
408 | dmaStreamSetMemory0(i2cp->dmarx, rxbuf); |
||
409 | dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); |
||
410 | +#else
|
||
411 | + i2cp->rxbuf = rxbuf;
|
||
412 | + i2cp->rxbytes = rxbytes;
|
||
413 | +#endif /* STM32_I2C_USE_DMA */
|
||
414 | |||
415 | /* Waits until BUSY flag is reset and the STOP from the previous operation
|
||
416 | is completed, alternatively for a timeout condition.*/
|
||
417 | @@ -869,6 +1045,7 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||
418 | i2cp->addr = addr << 1;
|
||
419 | i2cp->errors = 0;
|
||
420 | |||
421 | +#if STM32_I2C_USE_DMA
|
||
422 | /* TX DMA setup.*/
|
||
423 | dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); |
||
424 | dmaStreamSetMemory0(i2cp->dmatx, txbuf); |
||
425 | @@ -878,6 +1055,13 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||
426 | dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); |
||
427 | dmaStreamSetMemory0(i2cp->dmarx, rxbuf); |
||
428 | dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); |
||
429 | +#else
|
||
430 | + i2cp->txbuf = txbuf;
|
||
431 | + i2cp->txbytes = txbytes;
|
||
432 | +
|
||
433 | + i2cp->rxbuf = rxbuf;
|
||
434 | + i2cp->rxbytes = rxbytes;
|
||
435 | +#endif /* STM32_I2C_USE_DMA */
|
||
436 | |||
437 | /* Waits until BUSY flag is reset and the STOP from the previous operation
|
||
438 | is completed, alternatively for a timeout condition.*/
|
||
439 | diff --git a/os/hal/platforms/STM32/I2Cv1/i2c_lld.h b/os/hal/platforms/STM32/I2Cv1/i2c_lld.h
|
||
440 | index 6b192dc..27b1263 100644
|
||
441 | --- a/os/hal/platforms/STM32/I2Cv1/i2c_lld.h
|
||
442 | +++ b/os/hal/platforms/STM32/I2Cv1/i2c_lld.h
|
||
443 | @@ -76,6 +76,15 @@
|
||
444 | #endif
|
||
445 | |||
446 | /**
|
||
447 | + * @brief I2C data transfer use dma switch.
|
||
448 | + * @details If set to @p TRUE the support for I2C DMA is included.
|
||
449 | + * @note The default is @p FALSE.
|
||
450 | + */
|
||
451 | +#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__)
|
||
452 | +#define STM32_I2C_USE_DMA TRUE
|
||
453 | +#endif
|
||
454 | +
|
||
455 | +/**
|
||
456 | * @brief I2C1 interrupt priority level setting.
|
||
457 | */ |
||
458 | #if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||
459 | @@ -227,6 +236,7 @@
|
||
460 | #error "I2C driver activated but no I2C peripheral assigned" |
||
461 | #endif
|
||
462 | |||
463 | +#if STM32_I2C_USE_DMA
|
||
464 | #if STM32_I2C_USE_I2C1 && \ |
||
465 | !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \
|
||
466 | STM32_I2C1_RX_DMA_MSK) |
||
467 | @@ -266,6 +276,7 @@
|
||
468 | #if !defined(STM32_DMA_REQUIRED)
|
||
469 | #define STM32_DMA_REQUIRED
|
||
470 | #endif
|
||
471 | +#endif /* STM32_I2C_USE_DMA */
|
||
472 | |||
473 | /* Check clock range. */
|
||
474 | #if defined(STM32F4XX)
|
||
475 | @@ -386,6 +397,7 @@ struct I2CDriver { |
||
476 | * @brief Current slave address without R/W bit.
|
||
477 | */ |
||
478 | i2caddr_t addr; |
||
479 | +#if STM32_I2C_USE_DMA
|
||
480 | /**
|
||
481 | * @brief RX DMA mode bit mask.
|
||
482 | */ |
||
483 | @@ -402,6 +414,24 @@ struct I2CDriver { |
||
484 | * @brief Transmit DMA channel.
|
||
485 | */ |
||
486 | const stm32_dma_stream_t *dmatx;
|
||
487 | +#else
|
||
488 | + /**
|
||
489 | + * @brief Receive buffer.
|
||
490 | + */
|
||
491 | + uint8_t *rxbuf;
|
||
492 | + /**
|
||
493 | + * @brief Receive buffer size.
|
||
494 | + */
|
||
495 | + size_t rxbytes;
|
||
496 | + /**
|
||
497 | + * @brief Transmit buffer.
|
||
498 | + */
|
||
499 | + const uint8_t *txbuf;
|
||
500 | + /**
|
||
501 | + * @brief Transmit buffer size.
|
||
502 | + */
|
||
503 | + size_t txbytes;
|
||
504 | +#endif /* STM32_I2C_USE_DMA */
|
||
505 | /**
|
||
506 | * @brief Pointer to the I2Cx registers block.
|
||
507 | */ |