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 | + |