amiro-os / kernel / patches / QEI-driver.patch @ 69b23c6c
History | View | Annotate | Download (56.6 KB)
1 | 69b23c6c | Marc Rothmann | commit a23878ddb85bb8fd069f02042f15ad4be2a0d709
|
---|---|---|---|
2 | Author: Marc Rothmann <mrothmann@techfak.uni-bielefeld.de>
|
||
3 | Date: Mon Sep 17 11:40:39 2018 +0200
|
||
4 | |||
5 | Added QEI driver to HAL. |
||
6 | |||
7 | diff --git a/os/hal/hal.mk b/os/hal/hal.mk
|
||
8 | index f177a3f..64d96d9 100644
|
||
9 | --- a/os/hal/hal.mk
|
||
10 | +++ b/os/hal/hal.mk
|
||
11 | @@ -41,6 +41,9 @@ endif
|
||
12 | ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),) |
||
13 | HALSRC += $(CHIBIOS)/os/hal/src/hal_icu.c |
||
14 | endif |
||
15 | +ifneq ($(findstring HAL_USE_QEI TRUE,$(HALCONF)),)
|
||
16 | +HALSRC += $(CHIBIOS)/os/hal/src/hal_qei.c
|
||
17 | +endif
|
||
18 | ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),) |
||
19 | HALSRC += $(CHIBIOS)/os/hal/src/hal_mac.c |
||
20 | endif |
||
21 | @@ -94,6 +97,7 @@ HALSRC = $(CHIBIOS)/os/hal/src/hal.c \
|
||
22 | $(CHIBIOS)/os/hal/src/hal_i2c.c \ |
||
23 | $(CHIBIOS)/os/hal/src/hal_i2s.c \ |
||
24 | $(CHIBIOS)/os/hal/src/hal_icu.c \ |
||
25 | + $(CHIBIOS)/os/hal/src/hal_qei.c \
|
||
26 | $(CHIBIOS)/os/hal/src/hal_mac.c \ |
||
27 | $(CHIBIOS)/os/hal/src/hal_mmc_spi.c \ |
||
28 | $(CHIBIOS)/os/hal/src/hal_pal.c \ |
||
29 | diff --git a/os/hal/include/hal_qei.h b/os/hal/include/hal_qei.h
|
||
30 | new file mode 100644
|
||
31 | index 0000000..aef5e62
|
||
32 | --- /dev/null
|
||
33 | +++ b/os/hal/include/hal_qei.h
|
||
34 | @@ -0,0 +1,148 @@
|
||
35 | +/*
|
||
36 | +AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
|
||
37 | +Copyright (C) 2016..2018 Thomas Schöpping et al.
|
||
38 | +
|
||
39 | +This program is free software: you can redistribute it and/or modify
|
||
40 | +it under the terms of the GNU General Public License as published by
|
||
41 | +the Free Software Foundation, either version 3 of the License, or
|
||
42 | +(at your option) any later version.
|
||
43 | +
|
||
44 | +This program is distributed in the hope that it will be useful,
|
||
45 | +but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
46 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
47 | +GNU General Public License for more details.
|
||
48 | +
|
||
49 | +You should have received a copy of the GNU General Public License
|
||
50 | +along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
51 | +*/
|
||
52 | +
|
||
53 | +/**
|
||
54 | + * @file hal_qei.h
|
||
55 | + * @brief QEI Driver macros and structures.
|
||
56 | + *
|
||
57 | + * @addtogroup QEI
|
||
58 | + * @{
|
||
59 | + */
|
||
60 | +
|
||
61 | +#ifndef _HAL_QEI_H_
|
||
62 | +#define _HAL_QEI_H_
|
||
63 | +
|
||
64 | +#if HAL_USE_QEI || defined(__DOXYGEN__)
|
||
65 | +
|
||
66 | +/*===========================================================================*/
|
||
67 | +/* Driver constants. */
|
||
68 | +/*===========================================================================*/
|
||
69 | +
|
||
70 | +/*===========================================================================*/
|
||
71 | +/* Driver pre-compile time settings. */
|
||
72 | +/*===========================================================================*/
|
||
73 | +
|
||
74 | +/*===========================================================================*/
|
||
75 | +/* Derived constants and error checks. */
|
||
76 | +/*===========================================================================*/
|
||
77 | +
|
||
78 | +/*===========================================================================*/
|
||
79 | +/* Driver data structures and types. */
|
||
80 | +/*===========================================================================*/
|
||
81 | +
|
||
82 | +/**
|
||
83 | + * @brief Driver state machine possible states.
|
||
84 | + */
|
||
85 | +typedef enum {
|
||
86 | + QEI_UNINIT = 0, /**< Not initialized. */
|
||
87 | + QEI_STOP = 1, /**< Stopped. */
|
||
88 | + QEI_READY = 2, /**< Ready. */
|
||
89 | + QEI_ACTIVE = 4, /**< Active. */
|
||
90 | +} qeistate_t;
|
||
91 | +
|
||
92 | +/**
|
||
93 | + * @brief Type of a structure representing an QEI driver.
|
||
94 | + */
|
||
95 | +typedef struct QEIDriver QEIDriver;
|
||
96 | +
|
||
97 | +#include "hal_qei_lld.h"
|
||
98 | +
|
||
99 | +/*===========================================================================*/
|
||
100 | +/* Driver macros. */
|
||
101 | +/*===========================================================================*/
|
||
102 | +
|
||
103 | +/**
|
||
104 | + * @name Macro Functions
|
||
105 | + * @{
|
||
106 | + */
|
||
107 | +/**
|
||
108 | + * @brief Enables the quadrature encoder.
|
||
109 | + *
|
||
110 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
111 | + *
|
||
112 | + * @iclass
|
||
113 | + */
|
||
114 | +#define qeiEnableI(qeip) qei_lld_enable(qeip)
|
||
115 | +
|
||
116 | +/**
|
||
117 | + * @brief Disables the quadrature encoder.
|
||
118 | + *
|
||
119 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
120 | + *
|
||
121 | + * @iclass
|
||
122 | + */
|
||
123 | +#define qeiDisableI(qeip) qei_lld_disable(qeip)
|
||
124 | +
|
||
125 | +/**
|
||
126 | + * @brief Returns the direction of the last transition.
|
||
127 | + * @details The direction is defined as boolean and is
|
||
128 | + * calculated at each transition on any input.
|
||
129 | + *
|
||
130 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
131 | + * @return The request direction.
|
||
132 | + * @retval FALSE Position counted up.
|
||
133 | + * @retval TRUE Position counted down.
|
||
134 | + * @iclass
|
||
135 | + */
|
||
136 | +#define qeiGetDirectionI(qeip) qei_lld_get_direction(qeip)
|
||
137 | +
|
||
138 | +/**
|
||
139 | + * @brief Returns the position of the encoder.
|
||
140 | + * @details The position is defined as number of pulses since last reset.
|
||
141 | + *
|
||
142 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
143 | + * @return The number of pulses.
|
||
144 | + *
|
||
145 | + * @iclass
|
||
146 | + */
|
||
147 | +#define qeiGetPositionI(qeip) qei_lld_get_position(qeip)
|
||
148 | +
|
||
149 | +/**
|
||
150 | + * @brief Returns the range of the encoder.
|
||
151 | + * @details The range is defined as number of maximum pulse count.
|
||
152 | + *
|
||
153 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
154 | + * @return The number of pulses.
|
||
155 | + *
|
||
156 | + * @iclass
|
||
157 | + */
|
||
158 | +#define qeiGetRangeI(qeip) qei_lld_get_range(qeip)
|
||
159 | +/** @} */
|
||
160 | +
|
||
161 | +/*===========================================================================*/
|
||
162 | +/* External declarations. */
|
||
163 | +/*===========================================================================*/
|
||
164 | +
|
||
165 | +#ifdef __cplusplus
|
||
166 | +extern "C" {
|
||
167 | +#endif
|
||
168 | + void qeiInit(void);
|
||
169 | + void qeiObjectInit(QEIDriver *qeip);
|
||
170 | + void qeiStart(QEIDriver *qeip, const QEIConfig *config);
|
||
171 | + void qeiStop(QEIDriver *qeip);
|
||
172 | + void qeiEnable(QEIDriver *qeip);
|
||
173 | + void qeiDisable(QEIDriver *qeip);
|
||
174 | +#ifdef __cplusplus
|
||
175 | +}
|
||
176 | +#endif
|
||
177 | +
|
||
178 | +#endif /* HAL_USE_QEI */
|
||
179 | +
|
||
180 | +#endif /* _HAL_QEI_H_ */
|
||
181 | +
|
||
182 | +/** @} */
|
||
183 | diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
|
||
184 | index 6ade226..96c9da0 100644
|
||
185 | --- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
|
||
186 | +++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c
|
||
187 | @@ -34,6 +34,7 @@
|
||
188 | /* Driver local definitions. */
|
||
189 | /*===========================================================================*/
|
||
190 | |||
191 | +#if STM32_I2C_I2C1_USE_DMA
|
||
192 | #define I2C1_RX_DMA_CHANNEL \ |
||
193 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \
|
||
194 | STM32_I2C1_RX_DMA_CHN) |
||
195 | @@ -41,7 +42,9 @@
|
||
196 | #define I2C1_TX_DMA_CHANNEL \ |
||
197 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \
|
||
198 | STM32_I2C1_TX_DMA_CHN) |
||
199 | +#endif
|
||
200 | |||
201 | +#if STM32_I2C_I2C2_USE_DMA
|
||
202 | #define I2C2_RX_DMA_CHANNEL \ |
||
203 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \
|
||
204 | STM32_I2C2_RX_DMA_CHN) |
||
205 | @@ -49,7 +52,9 @@
|
||
206 | #define I2C2_TX_DMA_CHANNEL \ |
||
207 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \
|
||
208 | STM32_I2C2_TX_DMA_CHN) |
||
209 | +#endif
|
||
210 | |||
211 | +#if STM32_I2C_I2C3_USE_DMA
|
||
212 | #define I2C3_RX_DMA_CHANNEL \ |
||
213 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \
|
||
214 | STM32_I2C3_RX_DMA_CHN) |
||
215 | @@ -57,6 +62,7 @@
|
||
216 | #define I2C3_TX_DMA_CHANNEL \ |
||
217 | STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \
|
||
218 | STM32_I2C3_TX_DMA_CHN) |
||
219 | +#endif
|
||
220 | |||
221 | /*===========================================================================*/
|
||
222 | /* Driver constants. */
|
||
223 | @@ -72,6 +78,20 @@
|
||
224 | #define I2C_EV6_MASTER_REC_MODE_SELECTED \ |
||
225 | ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_ADDR))
|
||
226 | |||
227 | +#define I2C_EV7_MASTER_REC_BYTE_RECEIVED \
|
||
228 | + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | I2C_SR1_RXNE))
|
||
229 | +
|
||
230 | +#define I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP \
|
||
231 | + ((uint32_t)(I2C_SR1_RXNE))
|
||
232 | +
|
||
233 | +#define I2C_EV7_2_EV7_3_MASTER_REC_BYTE_QUEUED \
|
||
234 | + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY)<< 16) | \
|
||
235 | + I2C_SR1_BTF | I2C_SR1_RXNE))
|
||
236 | +
|
||
237 | +#define I2C_EV8_MASTER_BYTE_TRANSMITTING \
|
||
238 | + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA)<< 16) | \
|
||
239 | + I2C_SR1_TXE))
|
||
240 | +
|
||
241 | #define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ |
||
242 | ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY | I2C_SR2_TRA) << 16) | \ |
||
243 | I2C_SR1_BTF | I2C_SR1_TXE)) |
||
244 | @@ -129,8 +149,24 @@ static void i2c_lld_abort_operation(I2CDriver *i2cp) { |
||
245 | dp->SR1 = 0;
|
||
246 | |||
247 | /* Stops the associated DMA streams.*/
|
||
248 | - dmaStreamDisable(i2cp->dmatx);
|
||
249 | - dmaStreamDisable(i2cp->dmarx);
|
||
250 | +#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
|
||
251 | + if (&I2CD1 == i2cp) {
|
||
252 | + dmaStreamDisable(i2cp->dmatx);
|
||
253 | + dmaStreamDisable(i2cp->dmarx);
|
||
254 | + }
|
||
255 | +#endif
|
||
256 | +#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
|
||
257 | + if (&I2CD2 == i2cp) {
|
||
258 | + dmaStreamDisable(i2cp->dmatx);
|
||
259 | + dmaStreamDisable(i2cp->dmarx);
|
||
260 | + }
|
||
261 | +#endif
|
||
262 | +#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
|
||
263 | + if (&I2CD3 == i2cp) {
|
||
264 | + dmaStreamDisable(i2cp->dmatx);
|
||
265 | + dmaStreamDisable(i2cp->dmarx);
|
||
266 | + }
|
||
267 | +#endif
|
||
268 | } |
||
269 | |||
270 | /**
|
||
271 | @@ -236,13 +272,17 @@ static void i2c_lld_set_opmode(I2CDriver *i2cp) { |
||
272 | } |
||
273 | |||
274 | /**
|
||
275 | - * @brief I2C shared ISR code.
|
||
276 | + * @brief I2C shared ISR code for DMA access.
|
||
277 | * |
||
278 | * @param[in] i2cp pointer to the @p I2CDriver object |
||
279 | * |
||
280 | * @notapi
|
||
281 | */ |
||
282 | -static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) {
|
||
283 | +#if (STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) || \
|
||
284 | + (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) || \
|
||
285 | + (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA) || \
|
||
286 | + defined(__DOXYGEN__)
|
||
287 | +static void i2c_lld_serve_event_interrupt_dma(I2CDriver *i2cp) {
|
||
288 | I2C_TypeDef *dp = i2cp->i2c; |
||
289 | uint32_t regSR2 = dp->SR2; |
||
290 | uint32_t event = dp->SR1; |
||
291 | @@ -252,7 +292,7 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { |
||
292 | done by the DMA.*/ |
||
293 | switch (I2C_EV_MASK & (event | (regSR2 << 16))) { |
||
294 | case I2C_EV5_MASTER_MODE_SELECT:
|
||
295 | - if ((i2cp->addr >> 8) > 0) {
|
||
296 | + if ((i2cp->addr >> 8) > 0) {
|
||
297 | /* 10-bit address: 1 1 1 1 0 X X R/W */
|
||
298 | dp->DR = 0xF0 | (0x6 & (i2cp->addr >> 8)) | (0x1 & i2cp->addr); |
||
299 | } else {
|
||
300 | @@ -293,6 +333,140 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { |
||
301 | if (event & (I2C_SR1_ADDR | I2C_SR1_ADD10))
|
||
302 | (void)dp->SR2;
|
||
303 | } |
||
304 | +#endif /* any I2CDx uses DMA mode */
|
||
305 | +
|
||
306 | +/**
|
||
307 | + * @brief I2C shared ISR code for non-DMA access.
|
||
308 | + *
|
||
309 | + * @param[in] i2cp pointer to the @p I2CDriver object
|
||
310 | + *
|
||
311 | + * @notapi
|
||
312 | + */
|
||
313 | +#if (STM32_I2C_USE_I2C1 && !STM32_I2C_I2C1_USE_DMA) || \
|
||
314 | + (STM32_I2C_USE_I2C2 && !STM32_I2C_I2C2_USE_DMA) || \
|
||
315 | + (STM32_I2C_USE_I2C3 && !STM32_I2C_I2C3_USE_DMA) || \
|
||
316 | + defined(__DOXYGEN__)
|
||
317 | +static void i2c_lld_serve_event_interrupt_isr(I2CDriver *i2cp) {
|
||
318 | + I2C_TypeDef *dp = i2cp->i2c;
|
||
319 | + uint32_t regSR2 = dp->SR2;
|
||
320 | + uint32_t event = dp->SR1;
|
||
321 | +
|
||
322 | + switch (I2C_EV_MASK & (event | (regSR2 << 16))) {
|
||
323 | + case I2C_EV5_MASTER_MODE_SELECT:
|
||
324 | + dp->CR2 |= I2C_CR2_ITBUFEN;
|
||
325 | + dp->DR = i2cp->addr;
|
||
326 | + break;
|
||
327 | + case I2C_EV6_MASTER_TRA_MODE_SELECTED:
|
||
328 | + (void)dp->SR2; // clear ADDR flag
|
||
329 | + /* EV8_1 */
|
||
330 | + dp->DR = *(i2cp->txbuf);
|
||
331 | +
|
||
332 | + ++i2cp->txbuf;
|
||
333 | + --i2cp->txbytes;
|
||
334 | +
|
||
335 | + /* if N == 1, skip the I2C_EV8_MASTER_BYTE_TRANSMITTING event
|
||
336 | + * but enter I2C_EV8_2_MASTER_BYTE_TRANSMITTED next */
|
||
337 | + if (i2cp->txbytes == 0) {
|
||
338 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
339 | + }
|
||
340 | + break;
|
||
341 | + case I2C_EV6_MASTER_REC_MODE_SELECTED:
|
||
342 | + switch (i2cp->rxbytes) {
|
||
343 | + case 1:
|
||
344 | + dp->CR1 &= ~I2C_CR1_ACK;
|
||
345 | + (void)dp->SR2; // clear ADDR flag
|
||
346 | + dp->CR1 |= I2C_CR1_STOP;
|
||
347 | + break;
|
||
348 | + case 2:
|
||
349 | + (void)dp->SR2; // clear ADDR flag
|
||
350 | + /* EV6_1 */
|
||
351 | + dp->CR1 |= I2C_CR1_POS;
|
||
352 | + dp->CR1 &= ~I2C_CR1_ACK;
|
||
353 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
354 | + break;
|
||
355 | + case 3: /* N == 3 is a very special case, since EV7 is completely skipped */
|
||
356 | + (void)dp->SR2; // clear ADDR flag
|
||
357 | + /* Disable the I2C_EV7_MASTER_REC_BYTE_RECEIVED event
|
||
358 | + * but enter I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP next */
|
||
359 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
360 | + break;
|
||
361 | + default: /* N > 2 */
|
||
362 | + (void)dp->SR2; // clear ADDR flag
|
||
363 | + break;
|
||
364 | + }
|
||
365 | + break;
|
||
366 | + case I2C_EV7_MASTER_REC_BYTE_RECEIVED:
|
||
367 | + if (i2cp->rxbytes > 3) {
|
||
368 | + *(i2cp->rxbuf) = dp->DR;
|
||
369 | + ++i2cp->rxbuf;
|
||
370 | + --i2cp->rxbytes;
|
||
371 | + }
|
||
372 | + if (i2cp->rxbytes == 3) {
|
||
373 | + /* Disable this event for DataN-2, but force into event
|
||
374 | + * I2C_EV7_2_EV7_3_MASTER_REC_BYTE_RECEIVED_QUEUED by not reading dp->DR. */
|
||
375 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
376 | + }
|
||
377 | + break;
|
||
378 | + case I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP:
|
||
379 | + osalDbgAssert(i2cp->rxbytes == 1, "more than 1 byte to be received");
|
||
380 | + *(i2cp->rxbuf) = dp->DR;
|
||
381 | + --i2cp->rxbytes;
|
||
382 | + dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
|
||
383 | + _i2c_wakeup_isr(i2cp);
|
||
384 | + break;
|
||
385 | + case I2C_EV7_2_EV7_3_MASTER_REC_BYTE_QUEUED:
|
||
386 | + if (i2cp->rxbytes == 3) {
|
||
387 | + /* EV7_2 (N > 2) */
|
||
388 | + dp->CR1 &= ~I2C_CR1_ACK;
|
||
389 | + *(i2cp->rxbuf) = dp->DR;
|
||
390 | + ++i2cp->rxbuf;
|
||
391 | + dp->CR1 |= I2C_CR1_STOP;
|
||
392 | + *(i2cp->rxbuf) = dp->DR;
|
||
393 | + ++i2cp->rxbuf;
|
||
394 | + i2cp->rxbytes -= 2;
|
||
395 | + /* enable I2C_EV7_MASTER_REC_BYTE_RECEIVED_STOP event */
|
||
396 | + dp->CR2 |= I2C_CR2_ITBUFEN;
|
||
397 | + } else {
|
||
398 | + /* EV7_3 (N == 2) */
|
||
399 | + dp->CR1 |= I2C_CR1_STOP;
|
||
400 | + *(i2cp->rxbuf) = dp->DR;
|
||
401 | + ++i2cp->rxbuf;
|
||
402 | + *(i2cp->rxbuf) = dp->DR;
|
||
403 | + i2cp->rxbytes -= 2;
|
||
404 | +
|
||
405 | + dp->CR1 &= ~I2C_CR1_POS;
|
||
406 | + dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
|
||
407 | +
|
||
408 | + _i2c_wakeup_isr(i2cp);
|
||
409 | + }
|
||
410 | + break;
|
||
411 | + case I2C_EV8_MASTER_BYTE_TRANSMITTING:
|
||
412 | + dp->DR = *(i2cp->txbuf);
|
||
413 | + ++i2cp->txbuf;
|
||
414 | + --i2cp->txbytes;
|
||
415 | +
|
||
416 | + /* if this was the last byte, ensure that this event is not entered again */
|
||
417 | + if (i2cp->txbytes == 0) {
|
||
418 | + dp->CR2 &= ~I2C_CR2_ITBUFEN;
|
||
419 | + }
|
||
420 | + break;
|
||
421 | + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED:
|
||
422 | + if (i2cp->rxbytes > 0) {
|
||
423 | + /* start "read after write" operation (LSB of address = 1 => read) */
|
||
424 | + i2cp->addr |= 0x01;
|
||
425 | + dp->CR1 |= I2C_CR1_START | I2C_CR1_ACK;
|
||
426 | + } else {
|
||
427 | + dp->CR1 |= I2C_CR1_STOP;
|
||
428 | + dp->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN);
|
||
429 | + _i2c_wakeup_isr(i2cp);
|
||
430 | + }
|
||
431 | + break;
|
||
432 | + default:
|
||
433 | + osalDbgAssert(i2cp->rxbytes != 1, "more than 1 byte to be received");
|
||
434 | + break;
|
||
435 | + }
|
||
436 | +}
|
||
437 | +#endif /* any I2CDx uses non-DMA mode */
|
||
438 | |||
439 | /**
|
||
440 | * @brief DMA RX end IRQ handler.
|
||
441 | @@ -302,6 +476,10 @@ static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) { |
||
442 | * |
||
443 | * @notapi
|
||
444 | */ |
||
445 | +#if (STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) || \
|
||
446 | + (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) || \
|
||
447 | + (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA) || \
|
||
448 | + defined(__DOXYGEN__)
|
||
449 | static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { |
||
450 | I2C_TypeDef *dp = i2cp->i2c; |
||
451 | |||
452 | @@ -347,6 +525,7 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { |
||
453 | of R/W transaction itself.*/ |
||
454 | dp->CR2 |= I2C_CR2_ITEVTEN; |
||
455 | } |
||
456 | +#endif /* any I2CDx uses DMA mode */
|
||
457 | |||
458 | /**
|
||
459 | * @brief I2C error handler.
|
||
460 | @@ -359,8 +538,24 @@ static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { |
||
461 | static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { |
||
462 | |||
463 | /* Clears interrupt flags just to be safe.*/
|
||
464 | - dmaStreamDisable(i2cp->dmatx);
|
||
465 | - dmaStreamDisable(i2cp->dmarx);
|
||
466 | +#if STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA
|
||
467 | + if (&I2CD1 == i2cp) {
|
||
468 | + dmaStreamDisable(i2cp->dmatx);
|
||
469 | + dmaStreamDisable(i2cp->dmarx);
|
||
470 | + }
|
||
471 | +#endif
|
||
472 | +#if STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA
|
||
473 | + if (&I2CD2 == i2cp) {
|
||
474 | + dmaStreamDisable(i2cp->dmatx);
|
||
475 | + dmaStreamDisable(i2cp->dmarx);
|
||
476 | + }
|
||
477 | +#endif
|
||
478 | +#if STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA
|
||
479 | + if (&I2CD3 == i2cp) {
|
||
480 | + dmaStreamDisable(i2cp->dmatx);
|
||
481 | + dmaStreamDisable(i2cp->dmarx);
|
||
482 | + }
|
||
483 | +#endif
|
||
484 | |||
485 | i2cp->errors = I2C_NO_ERROR; |
||
486 | |||
487 | @@ -407,7 +602,11 @@ OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) {
|
||
488 | |||
489 | OSAL_IRQ_PROLOGUE(); |
||
490 | |||
491 | - i2c_lld_serve_event_interrupt(&I2CD1);
|
||
492 | +#if STM32_I2C_I2C1_USE_DMA
|
||
493 | + i2c_lld_serve_event_interrupt_dma(&I2CD1);
|
||
494 | +#else
|
||
495 | + i2c_lld_serve_event_interrupt_isr(&I2CD1);
|
||
496 | +#endif
|
||
497 | |||
498 | OSAL_IRQ_EPILOGUE(); |
||
499 | } |
||
500 | @@ -437,7 +636,11 @@ OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) {
|
||
501 | |||
502 | OSAL_IRQ_PROLOGUE(); |
||
503 | |||
504 | - i2c_lld_serve_event_interrupt(&I2CD2);
|
||
505 | +#if STM32_I2C_I2C2_USE_DMA
|
||
506 | + i2c_lld_serve_event_interrupt_dma(&I2CD2);
|
||
507 | +#else
|
||
508 | + i2c_lld_serve_event_interrupt_isr(&I2CD2);
|
||
509 | +#endif
|
||
510 | |||
511 | OSAL_IRQ_EPILOGUE(); |
||
512 | } |
||
513 | @@ -469,7 +672,11 @@ OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) {
|
||
514 | |||
515 | OSAL_IRQ_PROLOGUE(); |
||
516 | |||
517 | - i2c_lld_serve_event_interrupt(&I2CD3);
|
||
518 | +#if STM32_I2C_I2C3_USE_DMA
|
||
519 | + i2c_lld_serve_event_interrupt_dma(&I2CD3);
|
||
520 | +#else
|
||
521 | + i2c_lld_serve_event_interrupt_isr(&I2CD3);
|
||
522 | +#endif
|
||
523 | |||
524 | OSAL_IRQ_EPILOGUE(); |
||
525 | } |
||
526 | @@ -506,24 +713,30 @@ void i2c_lld_init(void) { |
||
527 | i2cObjectInit(&I2CD1); |
||
528 | I2CD1.thread = NULL;
|
||
529 | I2CD1.i2c = I2C1; |
||
530 | +#if STM32_I2C_I2C1_USE_DMA
|
||
531 | I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); |
||
532 | I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); |
||
533 | +#endif
|
||
534 | #endif /* STM32_I2C_USE_I2C1 */ |
||
535 | |||
536 | #if STM32_I2C_USE_I2C2
|
||
537 | i2cObjectInit(&I2CD2); |
||
538 | I2CD2.thread = NULL;
|
||
539 | I2CD2.i2c = I2C2; |
||
540 | +#if STM32_I2C_I2C2_USE_DMA
|
||
541 | I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); |
||
542 | I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); |
||
543 | +#endif
|
||
544 | #endif /* STM32_I2C_USE_I2C2 */ |
||
545 | |||
546 | #if STM32_I2C_USE_I2C3
|
||
547 | i2cObjectInit(&I2CD3); |
||
548 | I2CD3.thread = NULL;
|
||
549 | I2CD3.i2c = I2C3; |
||
550 | +#if STM32_I2C_I2C3_USE_DMA
|
||
551 | I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); |
||
552 | I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); |
||
553 | +#endif
|
||
554 | #endif /* STM32_I2C_USE_I2C3 */ |
||
555 | } |
||
556 | |||
557 | @@ -540,20 +753,24 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
558 | /* If in stopped state then enables the I2C and DMA clocks.*/
|
||
559 | if (i2cp->state == I2C_STOP) {
|
||
560 | |||
561 | - i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
562 | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
563 | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
564 | - STM32_DMA_CR_DIR_M2P;
|
||
565 | - i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
566 | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
567 | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
568 | - STM32_DMA_CR_DIR_P2M;
|
||
569 | -
|
||
570 | #if STM32_I2C_USE_I2C1
|
||
571 | if (&I2CD1 == i2cp) {
|
||
572 | +#if STM32_I2C_I2C1_USE_DMA
|
||
573 | bool b;
|
||
574 | |||
575 | + i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
576 | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
577 | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
578 | + STM32_DMA_CR_DIR_M2P;
|
||
579 | + i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
580 | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
581 | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
582 | + STM32_DMA_CR_DIR_P2M;
|
||
583 | +#endif
|
||
584 | +
|
||
585 | rccResetI2C1(); |
||
586 | +
|
||
587 | +#if STM32_I2C_I2C1_USE_DMA
|
||
588 | b = dmaStreamAllocate(i2cp->dmarx, |
||
589 | STM32_I2C_I2C1_IRQ_PRIORITY, |
||
590 | (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, |
||
591 | @@ -564,22 +781,52 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
592 | (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, |
||
593 | (void *)i2cp);
|
||
594 | osalDbgAssert(!b, "stream already allocated");
|
||
595 | +#endif
|
||
596 | +
|
||
597 | rccEnableI2C1(true);
|
||
598 | nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); |
||
599 | nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); |
||
600 | |||
601 | +#if STM32_I2C_I2C1_USE_DMA
|
||
602 | i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | |
||
603 | STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); |
||
604 | i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | |
||
605 | STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); |
||
606 | +
|
||
607 | + /* I2C registers pointed by the DMA.*/
|
||
608 | + dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
|
||
609 | + dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
|
||
610 | +#endif
|
||
611 | +
|
||
612 | + /* Reset i2c peripheral.*/
|
||
613 | + dp->CR1 = I2C_CR1_SWRST;
|
||
614 | + dp->CR1 = 0;
|
||
615 | +#if STM32_I2C_I2C1_USE_DMA
|
||
616 | + dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
|
||
617 | +#else
|
||
618 | + dp->CR2 = I2C_CR2_ITERREN;
|
||
619 | +#endif
|
||
620 | } |
||
621 | #endif /* STM32_I2C_USE_I2C1 */ |
||
622 | |||
623 | #if STM32_I2C_USE_I2C2
|
||
624 | if (&I2CD2 == i2cp) {
|
||
625 | +#if STM32_I2C_I2C2_USE_DMA
|
||
626 | bool b;
|
||
627 | |||
628 | + i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
629 | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
630 | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
631 | + STM32_DMA_CR_DIR_M2P;
|
||
632 | + i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
633 | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
634 | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
635 | + STM32_DMA_CR_DIR_P2M;
|
||
636 | +#endif
|
||
637 | +
|
||
638 | rccResetI2C2(); |
||
639 | +
|
||
640 | +#if STM32_I2C_I2C2_USE_DMA
|
||
641 | b = dmaStreamAllocate(i2cp->dmarx, |
||
642 | STM32_I2C_I2C2_IRQ_PRIORITY, |
||
643 | (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, |
||
644 | @@ -590,22 +837,52 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
645 | (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, |
||
646 | (void *)i2cp);
|
||
647 | osalDbgAssert(!b, "stream already allocated");
|
||
648 | +#endif
|
||
649 | +
|
||
650 | rccEnableI2C2(true);
|
||
651 | nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); |
||
652 | nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); |
||
653 | |||
654 | +#if STM32_I2C_I2C2_USE_DMA
|
||
655 | i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | |
||
656 | STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); |
||
657 | i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | |
||
658 | STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); |
||
659 | +
|
||
660 | + /* I2C registers pointed by the DMA.*/
|
||
661 | + dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
|
||
662 | + dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
|
||
663 | +#endif
|
||
664 | +
|
||
665 | + /* Reset i2c peripheral.*/
|
||
666 | + dp->CR1 = I2C_CR1_SWRST;
|
||
667 | + dp->CR1 = 0;
|
||
668 | +#if STM32_I2C_I2C2_USE_DMA
|
||
669 | + dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
|
||
670 | +#else
|
||
671 | + dp->CR2 = I2C_CR2_ITERREN;
|
||
672 | +#endif
|
||
673 | } |
||
674 | #endif /* STM32_I2C_USE_I2C2 */ |
||
675 | |||
676 | #if STM32_I2C_USE_I2C3
|
||
677 | if (&I2CD3 == i2cp) {
|
||
678 | +#if STM32_I2C_I2C3_USE_DMA
|
||
679 | bool b;
|
||
680 | |||
681 | + i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
682 | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
683 | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
684 | + STM32_DMA_CR_DIR_M2P;
|
||
685 | + i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
|
||
686 | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE |
|
||
687 | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE |
|
||
688 | + STM32_DMA_CR_DIR_P2M;
|
||
689 | +#endif
|
||
690 | +
|
||
691 | rccResetI2C3(); |
||
692 | +
|
||
693 | +#if STM32_I2C_I2C3_USE_DMA
|
||
694 | b = dmaStreamAllocate(i2cp->dmarx, |
||
695 | STM32_I2C_I2C3_IRQ_PRIORITY, |
||
696 | (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, |
||
697 | @@ -616,27 +893,35 @@ void i2c_lld_start(I2CDriver *i2cp) { |
||
698 | (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, |
||
699 | (void *)i2cp);
|
||
700 | osalDbgAssert(!b, "stream already allocated");
|
||
701 | +#endif
|
||
702 | +
|
||
703 | rccEnableI2C3(true);
|
||
704 | nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); |
||
705 | nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); |
||
706 | |||
707 | +#if STM32_I2C_I2C3_USE_DMA
|
||
708 | i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | |
||
709 | STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); |
||
710 | i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | |
||
711 | STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); |
||
712 | +
|
||
713 | + /* I2C registers pointed by the DMA.*/
|
||
714 | + dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
|
||
715 | + dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
|
||
716 | +#endif
|
||
717 | +
|
||
718 | + /* Reset i2c peripheral.*/
|
||
719 | + dp->CR1 = I2C_CR1_SWRST;
|
||
720 | + dp->CR1 = 0;
|
||
721 | +#if STM32_I2C_I2C3_USE_DMA
|
||
722 | + dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
|
||
723 | +#else
|
||
724 | + dp->CR2 = I2C_CR2_ITERREN;
|
||
725 | +#endif
|
||
726 | } |
||
727 | #endif /* STM32_I2C_USE_I2C3 */ |
||
728 | } |
||
729 | |||
730 | - /* I2C registers pointed by the DMA.*/
|
||
731 | - dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR);
|
||
732 | - dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR);
|
||
733 | -
|
||
734 | - /* Reset i2c peripheral.*/
|
||
735 | - dp->CR1 = I2C_CR1_SWRST;
|
||
736 | - dp->CR1 = 0;
|
||
737 | - dp->CR2 = I2C_CR2_ITERREN | I2C_CR2_DMAEN;
|
||
738 | -
|
||
739 | /* Setup I2C parameters.*/
|
||
740 | i2c_lld_set_clock(i2cp); |
||
741 | i2c_lld_set_opmode(i2cp); |
||
742 | @@ -659,11 +944,13 @@ void i2c_lld_stop(I2CDriver *i2cp) { |
||
743 | |||
744 | /* I2C disable.*/
|
||
745 | i2c_lld_abort_operation(i2cp); |
||
746 | - dmaStreamRelease(i2cp->dmatx);
|
||
747 | - dmaStreamRelease(i2cp->dmarx);
|
||
748 | |||
749 | #if STM32_I2C_USE_I2C1
|
||
750 | if (&I2CD1 == i2cp) {
|
||
751 | +#if STM32_I2C_I2C1_USE_DMA
|
||
752 | + dmaStreamRelease(i2cp->dmatx);
|
||
753 | + dmaStreamRelease(i2cp->dmarx);
|
||
754 | + #endif
|
||
755 | nvicDisableVector(I2C1_EV_IRQn); |
||
756 | nvicDisableVector(I2C1_ER_IRQn); |
||
757 | rccDisableI2C1(); |
||
758 | @@ -672,6 +959,10 @@ void i2c_lld_stop(I2CDriver *i2cp) { |
||
759 | |||
760 | #if STM32_I2C_USE_I2C2
|
||
761 | if (&I2CD2 == i2cp) {
|
||
762 | +#if STM32_I2C_I2C2_USE_DMA
|
||
763 | + dmaStreamRelease(i2cp->dmatx);
|
||
764 | + dmaStreamRelease(i2cp->dmarx);
|
||
765 | + #endif
|
||
766 | nvicDisableVector(I2C2_EV_IRQn); |
||
767 | nvicDisableVector(I2C2_ER_IRQn); |
||
768 | rccDisableI2C2(); |
||
769 | @@ -680,6 +971,10 @@ void i2c_lld_stop(I2CDriver *i2cp) { |
||
770 | |||
771 | #if STM32_I2C_USE_I2C3
|
||
772 | if (&I2CD3 == i2cp) {
|
||
773 | +#if STM32_I2C_I2C3_USE_DMA
|
||
774 | + dmaStreamRelease(i2cp->dmatx);
|
||
775 | + dmaStreamRelease(i2cp->dmarx);
|
||
776 | + #endif
|
||
777 | nvicDisableVector(I2C3_EV_IRQn); |
||
778 | nvicDisableVector(I2C3_ER_IRQn); |
||
779 | rccDisableI2C3(); |
||
780 | @@ -730,10 +1025,43 @@ msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||
781 | /* Releases the lock from high level driver.*/
|
||
782 | osalSysUnlock(); |
||
783 | |||
784 | - /* RX DMA setup.*/
|
||
785 | - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
786 | - dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
787 | - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
788 | + /* RX (DMA) setup.*/
|
||
789 | +#if STM32_I2C_USE_I2C1
|
||
790 | + if (&I2CD1 == i2cp) {
|
||
791 | +#if STM32_I2C_I2C1_USE_DMA
|
||
792 | + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
793 | + dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
794 | + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
795 | +#else
|
||
796 | + i2cp->rxbuf = rxbuf;
|
||
797 | + i2cp->rxbytes = rxbytes;
|
||
798 | +#endif
|
||
799 | + }
|
||
800 | +#endif
|
||
801 | +#if STM32_I2C_USE_I2C2
|
||
802 | + if (&I2CD2 == i2cp) {
|
||
803 | +#if STM32_I2C_I2C2_USE_DMA
|
||
804 | + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
805 | + dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
806 | + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
807 | +#else
|
||
808 | + i2cp->rxbuf = rxbuf;
|
||
809 | + i2cp->rxbytes = rxbytes;
|
||
810 | +#endif
|
||
811 | + }
|
||
812 | +#endif
|
||
813 | +#if STM32_I2C_USE_I2C3
|
||
814 | + if (&I2CD3 == i2cp) {
|
||
815 | +#if STM32_I2C_I2C3_USE_DMA
|
||
816 | + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
817 | + dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
818 | + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
819 | +#else
|
||
820 | + i2cp->rxbuf = rxbuf;
|
||
821 | + i2cp->rxbytes = rxbytes;
|
||
822 | +#endif
|
||
823 | + }
|
||
824 | +#endif
|
||
825 | |||
826 | /* Calculating the time window for the timeout on the busy bus condition.*/
|
||
827 | start = osalOsGetSystemTimeX(); |
||
828 | @@ -810,15 +1138,61 @@ msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
|
||
829 | /* Releases the lock from high level driver.*/
|
||
830 | osalSysUnlock(); |
||
831 | |||
832 | - /* TX DMA setup.*/
|
||
833 | - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
|
||
834 | - dmaStreamSetMemory0(i2cp->dmatx, txbuf);
|
||
835 | - dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
|
||
836 | -
|
||
837 | - /* RX DMA setup.*/
|
||
838 | - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
839 | - dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
840 | - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
841 | + /* TX (DMA) and RX (DMA) setup */
|
||
842 | +#if STM32_I2C_USE_I2C1
|
||
843 | + if (&I2CD1 == i2cp) {
|
||
844 | +#if STM32_I2C_I2C1_USE_DMA
|
||
845 | + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
|
||
846 | + dmaStreamSetMemory0(i2cp->dmatx, txbuf);
|
||
847 | + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
|
||
848 | +
|
||
849 | + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
850 | + dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
851 | + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
852 | +#else
|
||
853 | + i2cp->txbuf = txbuf;
|
||
854 | + i2cp->txbytes = txbytes;
|
||
855 | + i2cp->rxbuf = rxbuf;
|
||
856 | + i2cp->rxbytes = rxbytes;
|
||
857 | +#endif
|
||
858 | + }
|
||
859 | +#endif
|
||
860 | +#if STM32_I2C_USE_I2C2
|
||
861 | + if (&I2CD2 == i2cp) {
|
||
862 | +#if STM32_I2C_I2C2_USE_DMA
|
||
863 | + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
|
||
864 | + dmaStreamSetMemory0(i2cp->dmatx, txbuf);
|
||
865 | + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
|
||
866 | +
|
||
867 | + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
868 | + dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
869 | + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
870 | +#else
|
||
871 | + i2cp->txbuf = txbuf;
|
||
872 | + i2cp->txbytes = txbytes;
|
||
873 | + i2cp->rxbuf = rxbuf;
|
||
874 | + i2cp->rxbytes = rxbytes;
|
||
875 | +#endif
|
||
876 | + }
|
||
877 | +#endif
|
||
878 | +#if STM32_I2C_USE_I2C3
|
||
879 | + if (&I2CD3 == i2cp) {
|
||
880 | +#if STM32_I2C_I2C3_USE_DMA
|
||
881 | + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode);
|
||
882 | + dmaStreamSetMemory0(i2cp->dmatx, txbuf);
|
||
883 | + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes);
|
||
884 | +
|
||
885 | + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode);
|
||
886 | + dmaStreamSetMemory0(i2cp->dmarx, rxbuf);
|
||
887 | + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes);
|
||
888 | +#else
|
||
889 | + i2cp->txbuf = txbuf;
|
||
890 | + i2cp->txbytes = txbytes;
|
||
891 | + i2cp->rxbuf = rxbuf;
|
||
892 | + i2cp->rxbytes = rxbytes;
|
||
893 | +#endif
|
||
894 | + }
|
||
895 | +#endif
|
||
896 | |||
897 | /* Calculating the time window for the timeout on the busy bus condition.*/
|
||
898 | start = osalOsGetSystemTimeX(); |
||
899 | diff --git a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
|
||
900 | index 1328d47..68f91e1 100644
|
||
901 | --- a/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
|
||
902 | +++ b/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.h
|
||
903 | @@ -104,6 +104,33 @@
|
||
904 | #endif
|
||
905 | |||
906 | /**
|
||
907 | + * @brief I2C1 DMA enable switch.
|
||
908 | + * @details If set to @p TRUE the I2C1 driver will use DMA.
|
||
909 | + * @note The default is @p TRUE.
|
||
910 | + */
|
||
911 | +#if !defined(STM32_I2C_I2C1_USE_DMA) || defined(__DOXYGEN__)
|
||
912 | +#define STM32_I2C_I2C1_USE_DMA TRUE
|
||
913 | +#endif
|
||
914 | +
|
||
915 | +/**
|
||
916 | + * @brief I2C2 DMA enable switch.
|
||
917 | + * @details If set to @p TRUE the I2C2 driver will use DMA.
|
||
918 | + * @note The default is @p TRUE.
|
||
919 | + */
|
||
920 | +#if !defined(STM32_I2C_I2C2_USE_DMA) || defined(__DOXYGEN__)
|
||
921 | +#define STM32_I2C_I2C2_USE_DMA TRUE
|
||
922 | +#endif
|
||
923 | +
|
||
924 | +/**
|
||
925 | + * @brief I2C3 DMA enable switch.
|
||
926 | + * @details If set to @p TRUE the I2C3 driver will use DMA.
|
||
927 | + * @note The default is @p TRUE.
|
||
928 | + */
|
||
929 | +#if !defined(STM32_I2C_I2C3_USE_DMA) || defined(__DOXYGEN__)
|
||
930 | +#define STM32_I2C_I2C3_USE_DMA TRUE
|
||
931 | +#endif
|
||
932 | +
|
||
933 | +/**
|
||
934 | * @brief I2C1 DMA priority (0..3|lowest..highest). |
||
935 | * @note The priority level is used for both the TX and RX DMA streams but |
||
936 | * because of the streams ordering the RX stream has always priority |
||
937 | @@ -250,16 +277,19 @@
|
||
938 | #endif
|
||
939 | |||
940 | #if STM32_I2C_USE_I2C1 && \ |
||
941 | + STM32_I2C_I2C1_USE_DMA && \
|
||
942 | !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) |
||
943 | #error "Invalid DMA priority assigned to I2C1" |
||
944 | #endif
|
||
945 | |||
946 | #if STM32_I2C_USE_I2C2 && \ |
||
947 | + STM32_I2C_I2C2_USE_DMA && \
|
||
948 | !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) |
||
949 | #error "Invalid DMA priority assigned to I2C2" |
||
950 | #endif
|
||
951 | |||
952 | #if STM32_I2C_USE_I2C3 && \ |
||
953 | + STM32_I2C_I2C3_USE_DMA && \
|
||
954 | !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) |
||
955 | #error "Invalid DMA priority assigned to I2C3" |
||
956 | #endif
|
||
957 | @@ -316,7 +346,10 @@
|
||
958 | #endif
|
||
959 | #endif /* STM32_ADVANCED_DMA */ |
||
960 | |||
961 | -#if !defined(STM32_DMA_REQUIRED)
|
||
962 | +#if ((STM32_I2C_USE_I2C1 && STM32_I2C_I2C1_USE_DMA) || \
|
||
963 | + (STM32_I2C_USE_I2C2 && STM32_I2C_I2C2_USE_DMA) || \
|
||
964 | + (STM32_I2C_USE_I2C3 && STM32_I2C_I2C3_USE_DMA)) && \
|
||
965 | + !defined(STM32_DMA_REQUIRED)
|
||
966 | #define STM32_DMA_REQUIRED
|
||
967 | #endif
|
||
968 | |||
969 | @@ -437,21 +470,52 @@ struct I2CDriver { |
||
970 | */ |
||
971 | i2caddr_t addr; |
||
972 | /**
|
||
973 | - * @brief RX DMA mode bit mask.
|
||
974 | - */
|
||
975 | - uint32_t rxdmamode;
|
||
976 | - /**
|
||
977 | - * @brief TX DMA mode bit mask.
|
||
978 | - */
|
||
979 | - uint32_t txdmamode;
|
||
980 | - /**
|
||
981 | - * @brief Receive DMA channel.
|
||
982 | - */
|
||
983 | - const stm32_dma_stream_t *dmarx;
|
||
984 | - /**
|
||
985 | - * @brief Transmit DMA channel.
|
||
986 | + * @brief Anonymous union to store transmission related data for either DMA or non-DMA mode.
|
||
987 | */ |
||
988 | - const stm32_dma_stream_t *dmatx;
|
||
989 | + union {
|
||
990 | + /**
|
||
991 | + * @brief Anonymous struct to store data for DMA mode.
|
||
992 | + */
|
||
993 | + struct {
|
||
994 | + /**
|
||
995 | + * @brief RX DMA mode bit mask.
|
||
996 | + */
|
||
997 | + uint32_t rxdmamode;
|
||
998 | + /**
|
||
999 | + * @brief TX DMA mode bit mask.
|
||
1000 | + */
|
||
1001 | + uint32_t txdmamode;
|
||
1002 | + /**
|
||
1003 | + * @brief Receive DMA channel.
|
||
1004 | + */
|
||
1005 | + const stm32_dma_stream_t *dmarx;
|
||
1006 | + /**
|
||
1007 | + * @brief Transmit DMA channel.
|
||
1008 | + */
|
||
1009 | + const stm32_dma_stream_t *dmatx;
|
||
1010 | + };
|
||
1011 | + /**
|
||
1012 | + * @brief Anonymous struct to store data for non-DMA mode.
|
||
1013 | + */
|
||
1014 | + struct {
|
||
1015 | + /**
|
||
1016 | + * @brief Receive buffer.
|
||
1017 | + */
|
||
1018 | + uint8_t *rxbuf;
|
||
1019 | + /**
|
||
1020 | + * @brief Size of the receive buffer.
|
||
1021 | + */
|
||
1022 | + size_t rxbytes;
|
||
1023 | + /**
|
||
1024 | + * @brief Transmit buffer.
|
||
1025 | + */
|
||
1026 | + const uint8_t *txbuf;
|
||
1027 | + /**
|
||
1028 | + * @brief Size of the transmit buffer.
|
||
1029 | + */
|
||
1030 | + size_t txbytes;
|
||
1031 | + };
|
||
1032 | + };
|
||
1033 | /**
|
||
1034 | * @brief Pointer to the I2Cx registers block.
|
||
1035 | */ |
||
1036 | diff --git a/os/hal/ports/STM32/LLD/TIMv1/driver.mk b/os/hal/ports/STM32/LLD/TIMv1/driver.mk
|
||
1037 | index 032d75a..13e3571 100644
|
||
1038 | --- a/os/hal/ports/STM32/LLD/TIMv1/driver.mk
|
||
1039 | +++ b/os/hal/ports/STM32/LLD/TIMv1/driver.mk
|
||
1040 | @@ -10,10 +10,14 @@ endif
|
||
1041 | ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),) |
||
1042 | PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c |
||
1043 | endif |
||
1044 | +ifneq ($(findstring HAL_USE_QEI TRUE,$(HALCONF)),)
|
||
1045 | +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
|
||
1046 | +endif
|
||
1047 | else |
||
1048 | PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_gpt_lld.c |
||
1049 | PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_icu_lld.c |
||
1050 | PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_pwm_lld.c |
||
1051 | +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
|
||
1052 | endif |
||
1053 | |||
1054 | PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/TIMv1 |
||
1055 | diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
|
||
1056 | new file mode 100644
|
||
1057 | index 0000000..700704a
|
||
1058 | --- /dev/null
|
||
1059 | +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.c
|
||
1060 | @@ -0,0 +1,302 @@
|
||
1061 | +/*
|
||
1062 | +AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
|
||
1063 | +Copyright (C) 2016..2018 Thomas Schöpping et al.
|
||
1064 | +
|
||
1065 | +This program is free software: you can redistribute it and/or modify
|
||
1066 | +it under the terms of the GNU General Public License as published by
|
||
1067 | +the Free Software Foundation, either version 3 of the License, or
|
||
1068 | +(at your option) any later version.
|
||
1069 | +
|
||
1070 | +This program is distributed in the hope that it will be useful,
|
||
1071 | +but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
1072 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
1073 | +GNU General Public License for more details.
|
||
1074 | +
|
||
1075 | +You should have received a copy of the GNU General Public License
|
||
1076 | +along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
1077 | +*/
|
||
1078 | +
|
||
1079 | +/**
|
||
1080 | + * @file STM32/hal_qei_lld.c
|
||
1081 | + * @brief STM32 QEI subsystem low level driver.
|
||
1082 | + *
|
||
1083 | + * @addtogroup QEI
|
||
1084 | + * @{
|
||
1085 | + */
|
||
1086 | +
|
||
1087 | +#include "hal.h"
|
||
1088 | +
|
||
1089 | +#include "hal_qei.h"
|
||
1090 | +
|
||
1091 | +#if HAL_USE_QEI || defined(__DOXYGEN__)
|
||
1092 | +
|
||
1093 | +/*===========================================================================*/
|
||
1094 | +/* Driver exported variables. */
|
||
1095 | +/*===========================================================================*/
|
||
1096 | +
|
||
1097 | +/**
|
||
1098 | + * @brief QEID1 driver identifier.
|
||
1099 | + * @note The driver QEID1 allocates the complex timer TIM1 when enabled.
|
||
1100 | + */
|
||
1101 | +#if STM32_QEI_USE_TIM1 || defined(__DOXYGEN__)
|
||
1102 | +QEIDriver QEID1;
|
||
1103 | +#endif
|
||
1104 | +
|
||
1105 | +/**
|
||
1106 | + * @brief QEID2 driver identifier.
|
||
1107 | + * @note The driver QEID1 allocates the timer TIM2 when enabled.
|
||
1108 | + */
|
||
1109 | +#if STM32_QEI_USE_TIM2 || defined(__DOXYGEN__)
|
||
1110 | +QEIDriver QEID2;
|
||
1111 | +#endif
|
||
1112 | +
|
||
1113 | +/**
|
||
1114 | + * @brief QEID3 driver identifier.
|
||
1115 | + * @note The driver QEID1 allocates the timer TIM3 when enabled.
|
||
1116 | + */
|
||
1117 | +#if STM32_QEI_USE_TIM3 || defined(__DOXYGEN__)
|
||
1118 | +QEIDriver QEID3;
|
||
1119 | +#endif
|
||
1120 | +
|
||
1121 | +/**
|
||
1122 | + * @brief QEID4 driver identifier.
|
||
1123 | + * @note The driver QEID4 allocates the timer TIM4 when enabled.
|
||
1124 | + */
|
||
1125 | +#if STM32_QEI_USE_TIM4 || defined(__DOXYGEN__)
|
||
1126 | +QEIDriver QEID4;
|
||
1127 | +#endif
|
||
1128 | +
|
||
1129 | +/**
|
||
1130 | + * @brief QEID5 driver identifier.
|
||
1131 | + * @note The driver QEID5 allocates the timer TIM5 when enabled.
|
||
1132 | + */
|
||
1133 | +#if STM32_QEI_USE_TIM5 || defined(__DOXYGEN__)
|
||
1134 | +QEIDriver QEID5;
|
||
1135 | +#endif
|
||
1136 | +
|
||
1137 | +/**
|
||
1138 | + * @brief QEID8 driver identifier.
|
||
1139 | + * @note The driver QEID8 allocates the timer TIM8 when enabled.
|
||
1140 | + */
|
||
1141 | +#if STM32_QEI_USE_TIM8 || defined(__DOXYGEN__)
|
||
1142 | +QEIDriver QEID8;
|
||
1143 | +#endif
|
||
1144 | +
|
||
1145 | +/*===========================================================================*/
|
||
1146 | +/* Driver local variables. */
|
||
1147 | +/*===========================================================================*/
|
||
1148 | +
|
||
1149 | +/*===========================================================================*/
|
||
1150 | +/* Driver local functions. */
|
||
1151 | +/*===========================================================================*/
|
||
1152 | +
|
||
1153 | +/*===========================================================================*/
|
||
1154 | +/* Driver interrupt handlers. */
|
||
1155 | +/*===========================================================================*/
|
||
1156 | +
|
||
1157 | +/*===========================================================================*/
|
||
1158 | +/* Driver exported functions. */
|
||
1159 | +/*===========================================================================*/
|
||
1160 | +
|
||
1161 | +/**
|
||
1162 | + * @brief Low level QEI driver initialization.
|
||
1163 | + *
|
||
1164 | + * @notapi
|
||
1165 | + */
|
||
1166 | +void qei_lld_init(void) {
|
||
1167 | +
|
||
1168 | +#if STM32_QEI_USE_TIM1
|
||
1169 | + /* Driver initialization.*/
|
||
1170 | + qeiObjectInit(&QEID1);
|
||
1171 | + QEID1.tim = STM32_TIM1;
|
||
1172 | +#endif
|
||
1173 | +
|
||
1174 | +#if STM32_QEI_USE_TIM2
|
||
1175 | + /* Driver initialization.*/
|
||
1176 | + qeiObjectInit(&QEID2);
|
||
1177 | + QEID2.tim = STM32_TIM2;
|
||
1178 | +#endif
|
||
1179 | +
|
||
1180 | +#if STM32_QEI_USE_TIM3
|
||
1181 | + /* Driver initialization.*/
|
||
1182 | + qeiObjectInit(&QEID3);
|
||
1183 | + QEID3.tim = STM32_TIM3;
|
||
1184 | +#endif
|
||
1185 | +
|
||
1186 | +#if STM32_QEI_USE_TIM4
|
||
1187 | + /* Driver initialization.*/
|
||
1188 | + qeiObjectInit(&QEID4);
|
||
1189 | + QEID4.tim = STM32_TIM4;
|
||
1190 | +#endif
|
||
1191 | +
|
||
1192 | +#if STM32_QEI_USE_TIM5
|
||
1193 | + /* Driver initialization.*/
|
||
1194 | + qeiObjectInit(&QEID5);
|
||
1195 | + QEID5.tim = STM32_TIM5;
|
||
1196 | +#endif
|
||
1197 | +
|
||
1198 | +#if STM32_QEI_USE_TIM8
|
||
1199 | + /* Driver initialization.*/
|
||
1200 | + qeiObjectInit(&QEID8);
|
||
1201 | + QEID8.tim = STM32_TIM8;
|
||
1202 | +#endif
|
||
1203 | +}
|
||
1204 | +
|
||
1205 | +/**
|
||
1206 | + * @brief Configures and activates the QEI peripheral.
|
||
1207 | + *
|
||
1208 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1209 | + *
|
||
1210 | + * @notapi
|
||
1211 | + */
|
||
1212 | +void qei_lld_start(QEIDriver *qeip) {
|
||
1213 | + uint32_t arr, ccer;
|
||
1214 | +
|
||
1215 | + if (qeip->state == QEI_STOP) {
|
||
1216 | + /* Clock activation and timer reset.*/
|
||
1217 | +#if STM32_QEI_USE_TIM1
|
||
1218 | + if (&QEID1 == qeip) {
|
||
1219 | + rccEnableTIM1();
|
||
1220 | + rccResetTIM1();
|
||
1221 | + }
|
||
1222 | +#endif
|
||
1223 | +#if STM32_QEI_USE_TIM2
|
||
1224 | + if (&QEID2 == qeip) {
|
||
1225 | + rccEnableTIM2();
|
||
1226 | + rccResetTIM2();
|
||
1227 | + }
|
||
1228 | +#endif
|
||
1229 | +#if STM32_QEI_USE_TIM3
|
||
1230 | + if (&QEID3 == qeip) {
|
||
1231 | + rccEnableTIM3();
|
||
1232 | + rccResetTIM3();
|
||
1233 | + }
|
||
1234 | +#endif
|
||
1235 | +#if STM32_QEI_USE_TIM4
|
||
1236 | + if (&QEID4 == qeip) {
|
||
1237 | + rccEnableTIM4();
|
||
1238 | + rccResetTIM4();
|
||
1239 | + }
|
||
1240 | +#endif
|
||
1241 | +
|
||
1242 | +#if STM32_QEI_USE_TIM5
|
||
1243 | + if (&QEID5 == qeip) {
|
||
1244 | + rccEnableTIM5();
|
||
1245 | + rccResetTIM5();
|
||
1246 | + }
|
||
1247 | +#endif
|
||
1248 | +#if STM32_QEI_USE_TIM8
|
||
1249 | + if (&QEID8 == qeip) {
|
||
1250 | + rccEnableTIM8();
|
||
1251 | + rccResetTIM8();
|
||
1252 | + }
|
||
1253 | +#endif
|
||
1254 | + }
|
||
1255 | + else {
|
||
1256 | + /* Driver re-configuration scenario, it must be stopped first.*/
|
||
1257 | + qeip->tim->CR1 = 0; /* Timer disabled. */
|
||
1258 | + qeip->tim->DIER = 0; /* All IRQs disabled. */
|
||
1259 | + qeip->tim->SR = 0; /* Clear eventual pending IRQs. */
|
||
1260 | + qeip->tim->CCR[0] = 0; /* Comparator 1 disabled. */
|
||
1261 | + qeip->tim->CCR[1] = 0; /* Comparator 2 disabled. */
|
||
1262 | + qeip->tim->CNT = 0; /* Counter reset to zero. */
|
||
1263 | + }
|
||
1264 | +
|
||
1265 | + /* Timer configuration.*/
|
||
1266 | + qeip->tim->PSC = 0;
|
||
1267 | + arr = qeip->config->range - 1;
|
||
1268 | + osalDbgAssert((arr <= 0xFFFF), "qei_lld_start(), #1" /*, "invalid range"*/);
|
||
1269 | + qeip->tim->ARR = arr & 0xFFFF;
|
||
1270 | +
|
||
1271 | + /* CCMR1_CC1S = 01 - CH1 Input on TI1.
|
||
1272 | + CCMR1_CC2S = 01 - CH2 Input on TI2.*/
|
||
1273 | + qeip->tim->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
|
||
1274 | +
|
||
1275 | + ccer = 0;
|
||
1276 | + if (qeip->config->channels[0].mode == QEI_INPUT_INVERTED)
|
||
1277 | + ccer |= TIM_CCER_CC1P;
|
||
1278 | + if (qeip->config->channels[1].mode == QEI_INPUT_INVERTED)
|
||
1279 | + ccer |= TIM_CCER_CC2P;
|
||
1280 | + qeip->tim->CCER = ccer;
|
||
1281 | +
|
||
1282 | + if (qeip->config->mode == QEI_COUNT_CH1)
|
||
1283 | + qeip->tim->SMCR = TIM_SMCR_SMS_1;
|
||
1284 | + else if (qeip->config->mode == QEI_COUNT_CH2)
|
||
1285 | + qeip->tim->SMCR = TIM_SMCR_SMS_0;
|
||
1286 | + else
|
||
1287 | + qeip->tim->SMCR = TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;
|
||
1288 | +}
|
||
1289 | +
|
||
1290 | +/**
|
||
1291 | + * @brief Deactivates the QEI peripheral.
|
||
1292 | + *
|
||
1293 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1294 | + *
|
||
1295 | + * @notapi
|
||
1296 | + */
|
||
1297 | +void qei_lld_stop(QEIDriver *qeip) {
|
||
1298 | +
|
||
1299 | + if (qeip->state == QEI_READY) {
|
||
1300 | + /* Clock deactivation.*/
|
||
1301 | + qeip->tim->CR1 = 0; /* Timer disabled. */
|
||
1302 | +
|
||
1303 | +#if STM32_QEI_USE_TIM1
|
||
1304 | + if (&QEID1 == qeip) {
|
||
1305 | + rccDisableTIM1();
|
||
1306 | + }
|
||
1307 | +#endif
|
||
1308 | +#if STM32_QEI_USE_TIM2
|
||
1309 | + if (&QEID2 == qeip) {
|
||
1310 | + rccDisableTIM2();
|
||
1311 | + }
|
||
1312 | +#endif
|
||
1313 | +#if STM32_QEI_USE_TIM3
|
||
1314 | + if (&QEID3 == qeip) {
|
||
1315 | + rccDisableTIM3();
|
||
1316 | + }
|
||
1317 | +#endif
|
||
1318 | +#if STM32_QEI_USE_TIM4
|
||
1319 | + if (&QEID4 == qeip) {
|
||
1320 | + rccDisableTIM4();
|
||
1321 | + }
|
||
1322 | +#endif
|
||
1323 | +#if STM32_QEI_USE_TIM5
|
||
1324 | + if (&QEID5 == qeip) {
|
||
1325 | + rccDisableTIM5();
|
||
1326 | + }
|
||
1327 | +#endif
|
||
1328 | + }
|
||
1329 | +#if STM32_QEI_USE_TIM8
|
||
1330 | + if (&QEID8 == qeip) {
|
||
1331 | + rccDisableTIM8();
|
||
1332 | + }
|
||
1333 | +#endif
|
||
1334 | +}
|
||
1335 | +
|
||
1336 | +/**
|
||
1337 | + * @brief Enables the quadrature encoder.
|
||
1338 | + *
|
||
1339 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1340 | + *
|
||
1341 | + * @notapi
|
||
1342 | + */
|
||
1343 | +void qei_lld_enable(QEIDriver *qeip) {
|
||
1344 | +
|
||
1345 | + qeip->tim->CR1 = TIM_CR1_CEN;
|
||
1346 | +}
|
||
1347 | +
|
||
1348 | +/**
|
||
1349 | + * @brief Disables the quadrature encoder.
|
||
1350 | + *
|
||
1351 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1352 | + *
|
||
1353 | + * @notapi
|
||
1354 | + */
|
||
1355 | +void qei_lld_disable(QEIDriver *qeip) {
|
||
1356 | +
|
||
1357 | + qeip->tim->CR1 = 0;
|
||
1358 | +}
|
||
1359 | +
|
||
1360 | +#endif /* HAL_USE_QEI */
|
||
1361 | +
|
||
1362 | +/** @} */
|
||
1363 | diff --git a/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h
|
||
1364 | new file mode 100644
|
||
1365 | index 0000000..d4b7acc
|
||
1366 | --- /dev/null
|
||
1367 | +++ b/os/hal/ports/STM32/LLD/TIMv1/hal_qei_lld.h
|
||
1368 | @@ -0,0 +1,302 @@
|
||
1369 | +/*
|
||
1370 | +AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
|
||
1371 | +Copyright (C) 2016..2018 Thomas Schöpping et al.
|
||
1372 | +
|
||
1373 | +This program is free software: you can redistribute it and/or modify
|
||
1374 | +it under the terms of the GNU General Public License as published by
|
||
1375 | +the Free Software Foundation, either version 3 of the License, or
|
||
1376 | +(at your option) any later version.
|
||
1377 | +
|
||
1378 | +This program is distributed in the hope that it will be useful,
|
||
1379 | +but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
1380 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
1381 | +GNU General Public License for more details.
|
||
1382 | +
|
||
1383 | +You should have received a copy of the GNU General Public License
|
||
1384 | +along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
1385 | +*/
|
||
1386 | +
|
||
1387 | +/**
|
||
1388 | + * @file STM32/hal_qei_lld.h
|
||
1389 | + * @brief STM32 QEI subsystem low level driver header.
|
||
1390 | + *
|
||
1391 | + * @addtogroup QEI
|
||
1392 | + * @{
|
||
1393 | + */
|
||
1394 | +
|
||
1395 | +#ifndef _HAL_QEI_LLD_H_
|
||
1396 | +#define _HAL_QEI_LLD_H_
|
||
1397 | +
|
||
1398 | +#include "stm32_tim.h"
|
||
1399 | +
|
||
1400 | +#if HAL_USE_QEI || defined(__DOXYGEN__)
|
||
1401 | +
|
||
1402 | +/*===========================================================================*/
|
||
1403 | +/* Driver constants. */
|
||
1404 | +/*===========================================================================*/
|
||
1405 | +
|
||
1406 | +/**
|
||
1407 | + * @brief Number of input channels per QEI driver.
|
||
1408 | + */
|
||
1409 | +#define QEI_CHANNELS 2
|
||
1410 | +
|
||
1411 | +/*===========================================================================*/
|
||
1412 | +/* Driver pre-compile time settings. */
|
||
1413 | +/*===========================================================================*/
|
||
1414 | +
|
||
1415 | +/**
|
||
1416 | + * @name Configuration options
|
||
1417 | + * @{
|
||
1418 | + */
|
||
1419 | +/**
|
||
1420 | + * @brief QEID1 driver enable switch.
|
||
1421 | + * @details If set to @p TRUE the support for QEID1 is included.
|
||
1422 | + * @note The default is @p TRUE.
|
||
1423 | + */
|
||
1424 | +#if !defined(STM32_QEI_USE_TIM1) || defined(__DOXYGEN__)
|
||
1425 | +#define STM32_QEI_USE_TIM1 TRUE
|
||
1426 | +#endif
|
||
1427 | +
|
||
1428 | +/**
|
||
1429 | + * @brief QEID2 driver enable switch.
|
||
1430 | + * @details If set to @p TRUE the support for QEID2 is included.
|
||
1431 | + * @note The default is @p TRUE.
|
||
1432 | + */
|
||
1433 | +#if !defined(STM32_QEI_USE_TIM2) || defined(__DOXYGEN__)
|
||
1434 | +#define STM32_QEI_USE_TIM2 TRUE
|
||
1435 | +#endif
|
||
1436 | +
|
||
1437 | +/**
|
||
1438 | + * @brief QEID3 driver enable switch.
|
||
1439 | + * @details If set to @p TRUE the support for QEID3 is included.
|
||
1440 | + * @note The default is @p TRUE.
|
||
1441 | + */
|
||
1442 | +#if !defined(STM32_QEI_USE_TIM3) || defined(__DOXYGEN__)
|
||
1443 | +#define STM32_QEI_USE_TIM3 TRUE
|
||
1444 | +#endif
|
||
1445 | +
|
||
1446 | +/**
|
||
1447 | + * @brief QEID4 driver enable switch.
|
||
1448 | + * @details If set to @p TRUE the support for QEID4 is included.
|
||
1449 | + * @note The default is @p TRUE.
|
||
1450 | + */
|
||
1451 | +#if !defined(STM32_QEI_USE_TIM4) || defined(__DOXYGEN__)
|
||
1452 | +#define STM32_QEI_USE_TIM4 TRUE
|
||
1453 | +#endif
|
||
1454 | +
|
||
1455 | +/**
|
||
1456 | + * @brief QEID5 driver enable switch.
|
||
1457 | + * @details If set to @p TRUE the support for QEID5 is included.
|
||
1458 | + * @note The default is @p TRUE.
|
||
1459 | + */
|
||
1460 | +#if !defined(STM32_QEI_USE_TIM5) || defined(__DOXYGEN__)
|
||
1461 | +#define STM32_QEI_USE_TIM5 TRUE
|
||
1462 | +#endif
|
||
1463 | +
|
||
1464 | +/**
|
||
1465 | + * @brief QEID8 driver enable switch.
|
||
1466 | + * @details If set to @p TRUE the support for QEID8 is included.
|
||
1467 | + * @note The default is @p TRUE.
|
||
1468 | + */
|
||
1469 | +#if !defined(STM32_QEI_USE_TIM8) || defined(__DOXYGEN__)
|
||
1470 | +#define STM32_QEI_USE_TIM8 TRUE
|
||
1471 | +#endif
|
||
1472 | +/** @} */
|
||
1473 | +
|
||
1474 | +/*===========================================================================*/
|
||
1475 | +/* Derived constants and error checks. */
|
||
1476 | +/*===========================================================================*/
|
||
1477 | +
|
||
1478 | +#if STM32_QEI_USE_TIM1 && !STM32_HAS_TIM1
|
||
1479 | +#error "TIM1 not present in the selected device"
|
||
1480 | +#endif
|
||
1481 | +
|
||
1482 | +#if STM32_QEI_USE_TIM2 && !STM32_HAS_TIM2
|
||
1483 | +#error "TIM2 not present in the selected device"
|
||
1484 | +#endif
|
||
1485 | +
|
||
1486 | +#if STM32_QEI_USE_TIM3 && !STM32_HAS_TIM3
|
||
1487 | +#error "TIM3 not present in the selected device"
|
||
1488 | +#endif
|
||
1489 | +
|
||
1490 | +#if STM32_QEI_USE_TIM4 && !STM32_HAS_TIM4
|
||
1491 | +#error "TIM4 not present in the selected device"
|
||
1492 | +#endif
|
||
1493 | +
|
||
1494 | +#if STM32_QEI_USE_TIM5 && !STM32_HAS_TIM5
|
||
1495 | +#error "TIM5 not present in the selected device"
|
||
1496 | +#endif
|
||
1497 | +
|
||
1498 | +#if STM32_QEI_USE_TIM8 && !STM32_HAS_TIM8
|
||
1499 | +#error "TIM8 not present in the selected device"
|
||
1500 | +#endif
|
||
1501 | +
|
||
1502 | +#if !STM32_QEI_USE_TIM1 && !STM32_QEI_USE_TIM2 && \
|
||
1503 | + !STM32_QEI_USE_TIM3 && !STM32_QEI_USE_TIM4 && \
|
||
1504 | + !STM32_QEI_USE_TIM5 && !STM32_QEI_USE_TIM8
|
||
1505 | +#error "QEI driver activated but no TIM peripheral assigned"
|
||
1506 | +#endif
|
||
1507 | +
|
||
1508 | +/*===========================================================================*/
|
||
1509 | +/* Driver data structures and types. */
|
||
1510 | +/*===========================================================================*/
|
||
1511 | +
|
||
1512 | +/**
|
||
1513 | + * @brief QEI driver mode.
|
||
1514 | + */
|
||
1515 | +typedef enum {
|
||
1516 | + QEI_COUNT_BOTH = 0,
|
||
1517 | + QEI_COUNT_CH1 = 1,
|
||
1518 | + QEI_COUNT_CH2 = 2,
|
||
1519 | +} qeimode_t;
|
||
1520 | +
|
||
1521 | +/**
|
||
1522 | + * @brief QEI input mode.
|
||
1523 | + */
|
||
1524 | +typedef enum {
|
||
1525 | + QEI_INPUT_NONINVERTED = 0, /**< Input channel noninverted.*/
|
||
1526 | + QEI_INPUT_INVERTED = 1, /**< Input channel inverted.*/
|
||
1527 | +} qeiinputmode_t;
|
||
1528 | +
|
||
1529 | +/**
|
||
1530 | + * @brief QEI count type.
|
||
1531 | + */
|
||
1532 | +typedef uint32_t qeicnt_t;
|
||
1533 | +
|
||
1534 | +/**
|
||
1535 | + * @brief Driver channel configuration structure.
|
||
1536 | + */
|
||
1537 | +typedef struct {
|
||
1538 | + /**
|
||
1539 | + * @brief Channel input logic.
|
||
1540 | + */
|
||
1541 | + qeiinputmode_t mode;
|
||
1542 | + /* End of the mandatory fields.*/
|
||
1543 | +} QEIChannelConfig;
|
||
1544 | +
|
||
1545 | +/**
|
||
1546 | + * @brief Driver configuration structure.
|
||
1547 | + */
|
||
1548 | +typedef struct {
|
||
1549 | + /**
|
||
1550 | + * @brief Driver mode.
|
||
1551 | + */
|
||
1552 | + qeimode_t mode;
|
||
1553 | + /**
|
||
1554 | + * @brief Channels configurations.
|
||
1555 | + */
|
||
1556 | + QEIChannelConfig channels[QEI_CHANNELS];
|
||
1557 | + /**
|
||
1558 | + * @brief Range in pulses.
|
||
1559 | + */
|
||
1560 | + qeicnt_t range;
|
||
1561 | + /* End of the mandatory fields.*/
|
||
1562 | +} QEIConfig;
|
||
1563 | +
|
||
1564 | +/**
|
||
1565 | + * @brief Structure representing an QEI driver.
|
||
1566 | + */
|
||
1567 | +struct QEIDriver {
|
||
1568 | + /**
|
||
1569 | + * @brief Driver state.
|
||
1570 | + */
|
||
1571 | + qeistate_t state;
|
||
1572 | + /**
|
||
1573 | + * @brief Current configuration data.
|
||
1574 | + */
|
||
1575 | + const QEIConfig *config;
|
||
1576 | +#if defined(QEI_DRIVER_EXT_FIELDS)
|
||
1577 | + QEI_DRIVER_EXT_FIELDS
|
||
1578 | +#endif
|
||
1579 | + /* End of the mandatory fields.*/
|
||
1580 | + /**
|
||
1581 | + * @brief Pointer to the TIMx registers block.
|
||
1582 | + */
|
||
1583 | + stm32_tim_t *tim;
|
||
1584 | +};
|
||
1585 | +
|
||
1586 | +/*===========================================================================*/
|
||
1587 | +/* Driver macros. */
|
||
1588 | +/*===========================================================================*/
|
||
1589 | +
|
||
1590 | +/**
|
||
1591 | + * @brief Returns the direction of the last transition.
|
||
1592 | + * @details The direction is defined as boolean and is
|
||
1593 | + * calculated at each transition on any input.
|
||
1594 | + *
|
||
1595 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1596 | + * @return The request direction.
|
||
1597 | + * @retval FALSE Position counted up.
|
||
1598 | + * @retval TRUE Position counted down.
|
||
1599 | + *
|
||
1600 | + * @iclass
|
||
1601 | + */
|
||
1602 | +#define qei_lld_get_direction(qeip) !!((qeip)->tim->CR1 & TIM_CR1_DIR)
|
||
1603 | +
|
||
1604 | +/**
|
||
1605 | + * @brief Returns the position of the encoder.
|
||
1606 | + * @details The position is defined as number of pulses since last reset.
|
||
1607 | + *
|
||
1608 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1609 | + * @return The number of pulses.
|
||
1610 | + *
|
||
1611 | + * @iclass
|
||
1612 | + */
|
||
1613 | +#define qei_lld_get_position(qeip) ((qeip)->tim->CNT)
|
||
1614 | +
|
||
1615 | +/**
|
||
1616 | + * @brief Returns the range of the encoder.
|
||
1617 | + * @details The range is defined as number of maximum pulse count.
|
||
1618 | + *
|
||
1619 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1620 | + * @return The number of pulses.
|
||
1621 | + *
|
||
1622 | + * @iclass
|
||
1623 | + */
|
||
1624 | +#define qei_lld_get_range(qeip) ((qeip)->tim->ARR + 1)
|
||
1625 | +
|
||
1626 | +/*===========================================================================*/
|
||
1627 | +/* External declarations. */
|
||
1628 | +/*===========================================================================*/
|
||
1629 | +
|
||
1630 | +#if STM32_QEI_USE_TIM1 && !defined(__DOXYGEN__)
|
||
1631 | +extern QEIDriver QEID1;
|
||
1632 | +#endif
|
||
1633 | +
|
||
1634 | +#if STM32_QEI_USE_TIM2 && !defined(__DOXYGEN__)
|
||
1635 | +extern QEIDriver QEID2;
|
||
1636 | +#endif
|
||
1637 | +
|
||
1638 | +#if STM32_QEI_USE_TIM3 && !defined(__DOXYGEN__)
|
||
1639 | +extern QEIDriver QEID3;
|
||
1640 | +#endif
|
||
1641 | +
|
||
1642 | +#if STM32_QEI_USE_TIM4 && !defined(__DOXYGEN__)
|
||
1643 | +extern QEIDriver QEID4;
|
||
1644 | +#endif
|
||
1645 | +
|
||
1646 | +#if STM32_QEI_USE_TIM5 && !defined(__DOXYGEN__)
|
||
1647 | +extern QEIDriver QEID5;
|
||
1648 | +#endif
|
||
1649 | +
|
||
1650 | +#if STM32_QEI_USE_TIM8 && !defined(__DOXYGEN__)
|
||
1651 | +extern QEIDriver QEID8;
|
||
1652 | +#endif
|
||
1653 | +
|
||
1654 | +#ifdef __cplusplus
|
||
1655 | +extern "C" {
|
||
1656 | +#endif
|
||
1657 | + void qei_lld_init(void);
|
||
1658 | + void qei_lld_start(QEIDriver *qeip);
|
||
1659 | + void qei_lld_stop(QEIDriver *qeip);
|
||
1660 | + void qei_lld_enable(QEIDriver *qeip);
|
||
1661 | + void qei_lld_disable(QEIDriver *qeip);
|
||
1662 | +#ifdef __cplusplus
|
||
1663 | +}
|
||
1664 | +#endif
|
||
1665 | +
|
||
1666 | +#endif /* HAL_USE_QEI */
|
||
1667 | +
|
||
1668 | +#endif /* _HAL_QEI_LLD_H_ */
|
||
1669 | +
|
||
1670 | +/** @} */
|
||
1671 | diff --git a/os/hal/src/hal_qei.c b/os/hal/src/hal_qei.c
|
||
1672 | new file mode 100644
|
||
1673 | index 0000000..c08d175
|
||
1674 | --- /dev/null
|
||
1675 | +++ b/os/hal/src/hal_qei.c
|
||
1676 | @@ -0,0 +1,156 @@
|
||
1677 | +/*
|
||
1678 | +AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
|
||
1679 | +Copyright (C) 2016..2018 Thomas Schöpping et al.
|
||
1680 | +
|
||
1681 | +This program is free software: you can redistribute it and/or modify
|
||
1682 | +it under the terms of the GNU General Public License as published by
|
||
1683 | +the Free Software Foundation, either version 3 of the License, or
|
||
1684 | +(at your option) any later version.
|
||
1685 | +
|
||
1686 | +This program is distributed in the hope that it will be useful,
|
||
1687 | +but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
1688 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
1689 | +GNU General Public License for more details.
|
||
1690 | +
|
||
1691 | +You should have received a copy of the GNU General Public License
|
||
1692 | +along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
1693 | +*/
|
||
1694 | +
|
||
1695 | +/**
|
||
1696 | + * @file hal_qei.c
|
||
1697 | + * @brief QEI Driver code.
|
||
1698 | + *
|
||
1699 | + * @addtogroup QEI
|
||
1700 | + * @{
|
||
1701 | + */
|
||
1702 | +
|
||
1703 | +#include "hal.h"
|
||
1704 | +#include "hal_qei.h"
|
||
1705 | +
|
||
1706 | +#if HAL_USE_QEI || defined(__DOXYGEN__)
|
||
1707 | +
|
||
1708 | +/*===========================================================================*/
|
||
1709 | +/* Driver local definitions. */
|
||
1710 | +/*===========================================================================*/
|
||
1711 | +
|
||
1712 | +/*===========================================================================*/
|
||
1713 | +/* Driver exported variables. */
|
||
1714 | +/*===========================================================================*/
|
||
1715 | +
|
||
1716 | +/*===========================================================================*/
|
||
1717 | +/* Driver local variables. */
|
||
1718 | +/*===========================================================================*/
|
||
1719 | +
|
||
1720 | +/*===========================================================================*/
|
||
1721 | +/* Driver local functions. */
|
||
1722 | +/*===========================================================================*/
|
||
1723 | +
|
||
1724 | +/*===========================================================================*/
|
||
1725 | +/* Driver exported functions. */
|
||
1726 | +/*===========================================================================*/
|
||
1727 | +
|
||
1728 | +/**
|
||
1729 | + * @brief QEI Driver initialization.
|
||
1730 | + * @note This function is implicitly invoked by @p halInit(), there is
|
||
1731 | + * no need to explicitly initialize the driver.
|
||
1732 | + *
|
||
1733 | + * @init
|
||
1734 | + */
|
||
1735 | +void qeiInit(void) {
|
||
1736 | +
|
||
1737 | + qei_lld_init();
|
||
1738 | +}
|
||
1739 | +
|
||
1740 | +/**
|
||
1741 | + * @brief Initializes the standard part of a @p QEIDriver structure.
|
||
1742 | + *
|
||
1743 | + * @param[out] qeip pointer to the @p QEIDriver object
|
||
1744 | + *
|
||
1745 | + * @init
|
||
1746 | + */
|
||
1747 | +void qeiObjectInit(QEIDriver *qeip) {
|
||
1748 | +
|
||
1749 | + qeip->state = QEI_STOP;
|
||
1750 | + qeip->config = NULL;
|
||
1751 | +}
|
||
1752 | +
|
||
1753 | +/**
|
||
1754 | + * @brief Configures and activates the QEI peripheral.
|
||
1755 | + *
|
||
1756 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1757 | + * @param[in] config pointer to the @p QEIConfig object
|
||
1758 | + *
|
||
1759 | + * @api
|
||
1760 | + */
|
||
1761 | +void qeiStart(QEIDriver *qeip, const QEIConfig *config) {
|
||
1762 | +
|
||
1763 | + chDbgCheck((qeip != NULL) && (config != NULL) /*, "qeiStart"*/);
|
||
1764 | +
|
||
1765 | + chSysLock();
|
||
1766 | + chDbgAssert((qeip->state == QEI_STOP) || (qeip->state == QEI_READY),
|
||
1767 | + "qeiStart(), #1" /*, "invalid state"*/);
|
||
1768 | + qeip->config = config;
|
||
1769 | + qei_lld_start(qeip);
|
||
1770 | + qeip->state = QEI_READY;
|
||
1771 | + chSysUnlock();
|
||
1772 | +}
|
||
1773 | +
|
||
1774 | +/**
|
||
1775 | + * @brief Deactivates the QEI peripheral.
|
||
1776 | + *
|
||
1777 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1778 | + *
|
||
1779 | + * @api
|
||
1780 | + */
|
||
1781 | +void qeiStop(QEIDriver *qeip) {
|
||
1782 | +
|
||
1783 | + chDbgCheck(qeip != NULL /*, "qeiStop"*/);
|
||
1784 | +
|
||
1785 | + chSysLock();
|
||
1786 | + chDbgAssert((qeip->state == QEI_STOP) || (qeip->state == QEI_READY),
|
||
1787 | + "qeiStop(), #1" /*, "invalid state"*/);
|
||
1788 | + qei_lld_stop(qeip);
|
||
1789 | + qeip->state = QEI_STOP;
|
||
1790 | + chSysUnlock();
|
||
1791 | +}
|
||
1792 | +
|
||
1793 | +/**
|
||
1794 | + * @brief Enables the quadrature encoder.
|
||
1795 | + *
|
||
1796 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1797 | + *
|
||
1798 | + * @api
|
||
1799 | + */
|
||
1800 | +void qeiEnable(QEIDriver *qeip) {
|
||
1801 | +
|
||
1802 | + chDbgCheck(qeip != NULL /*, "qeiEnable"*/);
|
||
1803 | +
|
||
1804 | + chSysLock();
|
||
1805 | + chDbgAssert(qeip->state == QEI_READY, "qeiEnable(), #1" /*, "invalid state"*/);
|
||
1806 | + qei_lld_enable(qeip);
|
||
1807 | + qeip->state = QEI_ACTIVE;
|
||
1808 | + chSysUnlock();
|
||
1809 | +}
|
||
1810 | +
|
||
1811 | +/**
|
||
1812 | + * @brief Disables the quadrature encoder.
|
||
1813 | + *
|
||
1814 | + * @param[in] qeip pointer to the @p QEIDriver object
|
||
1815 | + *
|
||
1816 | + * @api
|
||
1817 | + */
|
||
1818 | +void qeiDisable(QEIDriver *qeip) {
|
||
1819 | +
|
||
1820 | + chDbgCheck(qeip != NULL /*, "qeiDisable"*/);
|
||
1821 | +
|
||
1822 | + chSysLock();
|
||
1823 | + chDbgAssert((qeip->state == QEI_READY) || (qeip->state == QEI_ACTIVE),
|
||
1824 | + "qeiDisable(), #1" /*, "invalid state"*/);
|
||
1825 | + qei_lld_disable(qeip);
|
||
1826 | + qeip->state = QEI_READY;
|
||
1827 | + chSysUnlock();
|
||
1828 | +}
|
||
1829 | +
|
||
1830 | +#endif /* HAL_USE_QEI */
|
||
1831 | +
|
||
1832 | +/** @} */ |