2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
5 * @addtogroup PIOS_SPI SPI Functions
6 * @brief PIOS interface to read and write from SPI ports
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
11 * @brief Hardware Abstraction Layer for SPI ports of STM32
12 * @see The GNU Public License (GPL) Version 3
15 * Note that additional chip select lines can be easily added by using
16 * the remaining free GPIOs of the core module. Shared SPI ports should be
17 * arbitrated with (FreeRTOS based) Mutexes to avoid collisions!
19 *****************************************************************************/
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 3 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful, but
27 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
28 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31 * You should have received a copy of the GNU General Public License along
32 * with this program; if not, write to the Free Software Foundation, Inc.,
33 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #ifdef PIOS_INCLUDE_SPI
40 #include <pios_spi_priv.h>
42 #define SPI_MAX_BLOCK_PIO 12800
44 static bool PIOS_SPI_validate(__attribute__((unused
)) struct pios_spi_dev
*com_dev
)
46 /* Should check device magic here */
50 #if defined(PIOS_INCLUDE_FREERTOS)
51 static struct pios_spi_dev
*PIOS_SPI_alloc(void)
53 return pios_malloc(sizeof(struct pios_spi_dev
));
56 static struct pios_spi_dev pios_spi_devs
[PIOS_SPI_MAX_DEVS
];
57 static uint8_t pios_spi_num_devs
;
58 static struct pios_spi_dev
*PIOS_SPI_alloc(void)
60 if (pios_spi_num_devs
>= PIOS_SPI_MAX_DEVS
) {
64 return &pios_spi_devs
[pios_spi_num_devs
++];
69 * Initialises SPI pins
70 * \param[in] mode currently only mode 0 supported
71 * \return < 0 if initialisation failed
73 int32_t PIOS_SPI_Init(uint32_t *spi_id
, const struct pios_spi_cfg
*cfg
)
75 uint32_t init_ssel
= 0;
80 struct pios_spi_dev
*spi_dev
;
82 spi_dev
= (struct pios_spi_dev
*)PIOS_SPI_alloc();
87 /* Bind the configuration to the device instance */
90 #if defined(PIOS_INCLUDE_FREERTOS)
91 vSemaphoreCreateBinary(spi_dev
->busy
);
92 xSemaphoreGive(spi_dev
->busy
);
97 /* Disable callback function */
98 spi_dev
->callback
= NULL
;
100 /* Set rx/tx dummy bytes to a known value */
101 spi_dev
->rx_dummy_byte
= 0xFF;
102 spi_dev
->tx_dummy_byte
= 0xFF;
104 switch (spi_dev
->cfg
->init
.SPI_NSS
) {
106 if (spi_dev
->cfg
->init
.SPI_Mode
== SPI_Mode_Master
) {
107 /* We're a master in soft NSS mode, make sure we see NSS high at all times. */
108 SPI_NSSInternalSoftwareConfig(spi_dev
->cfg
->regs
, SPI_NSSInternalSoft_Set
);
109 /* Init as many slave selects as the config advertises. */
110 init_ssel
= spi_dev
->cfg
->slave_count
;
112 /* We're a slave in soft NSS mode, make sure we see NSS low at all times. */
113 SPI_NSSInternalSoftwareConfig(spi_dev
->cfg
->regs
, SPI_NSSInternalSoft_Reset
);
117 /* only legal for single-slave config */
118 PIOS_Assert(spi_dev
->cfg
->slave_count
== 1);
120 /* FIXME: Should this also call SPI_SSOutputCmd()? */
127 /* Initialize the GPIO pins */
128 /* note __builtin_ctz() due to the difference between GPIO_PinX and GPIO_PinSourceX */
129 if (spi_dev
->cfg
->remap
) {
130 GPIO_PinAFConfig(spi_dev
->cfg
->sclk
.gpio
,
131 __builtin_ctz(spi_dev
->cfg
->sclk
.init
.GPIO_Pin
),
132 spi_dev
->cfg
->remap
);
133 GPIO_PinAFConfig(spi_dev
->cfg
->mosi
.gpio
,
134 __builtin_ctz(spi_dev
->cfg
->mosi
.init
.GPIO_Pin
),
135 spi_dev
->cfg
->remap
);
136 GPIO_PinAFConfig(spi_dev
->cfg
->miso
.gpio
,
137 __builtin_ctz(spi_dev
->cfg
->miso
.init
.GPIO_Pin
),
138 spi_dev
->cfg
->remap
);
139 for (uint32_t i
= 0; i
< init_ssel
; i
++) {
140 GPIO_PinAFConfig(spi_dev
->cfg
->ssel
[i
].gpio
,
141 __builtin_ctz(spi_dev
->cfg
->ssel
[i
].init
.GPIO_Pin
),
142 spi_dev
->cfg
->remap
);
146 /* Initialize the GPIO pins */
147 GPIO_Init(spi_dev
->cfg
->sclk
.gpio
, (GPIO_InitTypeDef
*)&(spi_dev
->cfg
->sclk
.init
));
148 GPIO_Init(spi_dev
->cfg
->mosi
.gpio
, (GPIO_InitTypeDef
*)&(spi_dev
->cfg
->mosi
.init
));
149 GPIO_Init(spi_dev
->cfg
->miso
.gpio
, (GPIO_InitTypeDef
*)&(spi_dev
->cfg
->miso
.init
));
150 for (uint32_t i
= 0; i
< init_ssel
; i
++) {
151 /* Since we're driving the SSEL pin in software, ensure that the slave is deselected */
152 /* XXX multi-slave support - maybe have another SPI_NSS_ mode? */
153 GPIO_SetBits(spi_dev
->cfg
->ssel
[i
].gpio
, spi_dev
->cfg
->ssel
[i
].init
.GPIO_Pin
);
154 GPIO_Init(spi_dev
->cfg
->ssel
[i
].gpio
, (GPIO_InitTypeDef
*)&(spi_dev
->cfg
->ssel
[i
].init
));
157 /* Enable the associated peripheral clock */
158 switch ((uint32_t)spi_dev
->cfg
->regs
) {
160 /* Enable SPI peripheral clock (APB2 == high speed) */
161 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1
, ENABLE
);
164 /* Enable SPI peripheral clock (APB1 == slow speed) */
165 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2
, ENABLE
);
168 /* Enable SPI peripheral clock (APB1 == slow speed) */
169 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3
, ENABLE
);
173 bool use_dma
= spi_dev
->cfg
->dma
.rx
.channel
&& spi_dev
->cfg
->dma
.tx
.channel
;
175 /* Enable DMA clock */
177 RCC_AHBPeriphClockCmd(spi_dev
->cfg
->dma
.ahb_clk
, ENABLE
);
179 /* Configure DMA for SPI Rx */
180 DMA_Cmd(spi_dev
->cfg
->dma
.rx
.channel
, DISABLE
);
181 DMA_Init(spi_dev
->cfg
->dma
.rx
.channel
, (DMA_InitTypeDef
*)&(spi_dev
->cfg
->dma
.rx
.init
));
183 /* Configure DMA for SPI Tx */
184 DMA_Cmd(spi_dev
->cfg
->dma
.tx
.channel
, DISABLE
);
185 DMA_Init(spi_dev
->cfg
->dma
.tx
.channel
, (DMA_InitTypeDef
*)&(spi_dev
->cfg
->dma
.tx
.init
));
188 /* Initialize the SPI block */
189 SPI_I2S_DeInit(spi_dev
->cfg
->regs
);
190 SPI_Init(spi_dev
->cfg
->regs
, (SPI_InitTypeDef
*)&(spi_dev
->cfg
->init
));
192 /* Configure CRC calculation */
193 if (spi_dev
->cfg
->use_crc
) {
194 SPI_CalculateCRC(spi_dev
->cfg
->regs
, ENABLE
);
196 SPI_CalculateCRC(spi_dev
->cfg
->regs
, DISABLE
);
199 /* Configure the RX FIFO Threshold -- 8 bits */
200 SPI_RxFIFOThresholdConfig(spi_dev
->cfg
->regs
, SPI_RxFIFOThreshold_QF
);
203 SPI_Cmd(spi_dev
->cfg
->regs
, ENABLE
);
205 /* Enable SPI interrupts to DMA */
207 SPI_I2S_DMACmd(spi_dev
->cfg
->regs
, SPI_I2S_DMAReq_Tx
| SPI_I2S_DMAReq_Rx
, ENABLE
);
210 /* Configure DMA interrupt */
211 NVIC_Init((NVIC_InitTypeDef
*)&(spi_dev
->cfg
->dma
.irq
.init
));
213 *spi_id
= (uint32_t)spi_dev
;
221 * (Re-)initialises SPI peripheral clock rate
223 * \param[in] spi SPI number (0 or 1)
224 * \param[in] spi_prescaler configures the SPI speed:
226 * <LI>PIOS_SPI_PRESCALER_2: sets clock rate 27.7~ nS @ 72 MHz (36 MBit/s) (only supported for spi==0, spi1 uses 4 instead)
227 * <LI>PIOS_SPI_PRESCALER_4: sets clock rate 55.5~ nS @ 72 MHz (18 MBit/s)
228 * <LI>PIOS_SPI_PRESCALER_8: sets clock rate 111.1~ nS @ 72 MHz (9 MBit/s)
229 * <LI>PIOS_SPI_PRESCALER_16: sets clock rate 222.2~ nS @ 72 MHz (4.5 MBit/s)
230 * <LI>PIOS_SPI_PRESCALER_32: sets clock rate 444.4~ nS @ 72 MHz (2.25 MBit/s)
231 * <LI>PIOS_SPI_PRESCALER_64: sets clock rate 888.8~ nS @ 72 MHz (1.125 MBit/s)
232 * <LI>PIOS_SPI_PRESCALER_128: sets clock rate 1.7~ nS @ 72 MHz (0.562 MBit/s)
233 * <LI>PIOS_SPI_PRESCALER_256: sets clock rate 3.5~ nS @ 72 MHz (0.281 MBit/s)
235 * \return 0 if no error
236 * \return -1 if disabled SPI port selected
237 * \return -3 if invalid spi_prescaler selected
239 int32_t PIOS_SPI_SetClockSpeed(uint32_t spi_id
, SPIPrescalerTypeDef spi_prescaler
)
241 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
243 bool valid
= PIOS_SPI_validate(spi_dev
);
247 SPI_InitTypeDef SPI_InitStructure
;
249 if (spi_prescaler
>= 8) {
250 /* Invalid prescaler selected */
254 /* Start with a copy of the default configuration for the peripheral */
255 SPI_InitStructure
= spi_dev
->cfg
->init
;
257 /* Adjust the prescaler for the peripheral's clock */
258 SPI_InitStructure
.SPI_BaudRatePrescaler
= ((uint16_t)spi_prescaler
& 7) << 3;
260 /* Write back the new configuration */
261 SPI_Init(spi_dev
->cfg
->regs
, &SPI_InitStructure
);
263 PIOS_SPI_TransferByte(spi_id
, 0xFF);
268 * Claim the SPI bus semaphore. Calling the SPI functions does not require this
269 * \param[in] spi SPI number (0 or 1)
270 * \return 0 if no error
271 * \return -1 if timeout before claiming semaphore
273 int32_t PIOS_SPI_ClaimBus(uint32_t spi_id
)
275 #if defined(PIOS_INCLUDE_FREERTOS)
276 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
278 bool valid
= PIOS_SPI_validate(spi_dev
);
281 if (xSemaphoreTake(spi_dev
->busy
, 0xffff) != pdTRUE
) {
285 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
286 uint32_t timeout
= 0xffff;
287 while ((PIOS_SPI_Busy(spi_id
) || spi_dev
->busy
) && --timeout
) {
290 if (timeout
== 0) { // timed out
300 #endif /* if defined(PIOS_INCLUDE_FREERTOS) */
305 * Claim the SPI bus semaphore from an ISR. Has no timeout.
306 * \param[in] spi SPI number (0 or 1)
307 * \param woken[in,out] If non-NULL, will be set to true if woken was false and a higher priority
308 * task has is now eligible to run, else unchanged
309 * \return 0 if no error
310 * \return -1 if timeout before claiming semaphore
312 int32_t PIOS_SPI_ClaimBusISR(uint32_t spi_id
, bool *woken
)
314 #if defined(PIOS_INCLUDE_FREERTOS)
315 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
316 signed portBASE_TYPE higherPriorityTaskWoken
= pdFALSE
;
318 bool valid
= PIOS_SPI_validate(spi_dev
);
321 if (xSemaphoreTakeFromISR(spi_dev
->busy
, &higherPriorityTaskWoken
) != pdTRUE
) {
325 *woken
= *woken
|| (higherPriorityTaskWoken
== pdTRUE
);
333 return PIOS_SPI_ClaimBus(spi_id
);
339 * Release the SPI bus semaphore. Calling the SPI functions does not require this
340 * \param[in] spi SPI number (0 or 1)
341 * \return 0 if no error
343 int32_t PIOS_SPI_ReleaseBus(uint32_t spi_id
)
345 #if defined(PIOS_INCLUDE_FREERTOS)
346 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
348 bool valid
= PIOS_SPI_validate(spi_dev
);
351 xSemaphoreGive(spi_dev
->busy
);
353 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
362 * Release the SPI bus semaphore from ISR. Calling the SPI functions does not require this
363 * \param[in] spi SPI number (0 or 1)
364 * \param woken[in,out] If non-NULL, will be set to true if woken was false and a higher priority
365 * task has is now eligible to run, else unchanged
366 * \return 0 if no error
368 int32_t PIOS_SPI_ReleaseBusISR(uint32_t spi_id
, bool *woken
)
370 #if defined(PIOS_INCLUDE_FREERTOS)
371 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
372 signed portBASE_TYPE higherPriorityTaskWoken
= pdFALSE
;
374 bool valid
= PIOS_SPI_validate(spi_dev
);
377 xSemaphoreGiveFromISR(spi_dev
->busy
, &higherPriorityTaskWoken
);
379 *woken
= *woken
|| (higherPriorityTaskWoken
== pdTRUE
);
387 return PIOS_SPI_ReleaseBus(spi_id
);
394 * Controls the RC (Register Clock alias Chip Select) pin of a SPI port
395 * \param[in] spi SPI number (0 or 1)
396 * \param[in] pin_value 0 or 1
397 * \return 0 if no error
399 int32_t PIOS_SPI_RC_PinSet(uint32_t spi_id
, uint32_t slave_id
, uint8_t pin_value
)
401 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
403 bool valid
= PIOS_SPI_validate(spi_dev
);
406 PIOS_Assert(slave_id
<= spi_dev
->cfg
->slave_count
)
408 /* XXX multi-slave support? */
410 GPIO_SetBits(spi_dev
->cfg
->ssel
[slave_id
].gpio
, spi_dev
->cfg
->ssel
[slave_id
].init
.GPIO_Pin
);
412 GPIO_ResetBits(spi_dev
->cfg
->ssel
[slave_id
].gpio
, spi_dev
->cfg
->ssel
[slave_id
].init
.GPIO_Pin
);
419 * Transfers a byte to SPI output and reads back the return value from SPI input
420 * \param[in] spi SPI number (0 or 1)
421 * \param[in] b the byte which should be transfered
423 int32_t PIOS_SPI_TransferByte(uint32_t spi_id
, uint8_t b
)
425 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
427 bool valid
= PIOS_SPI_validate(spi_dev
);
433 /* Make sure the RXNE flag is cleared by reading the DR register */
434 SPI_ReceiveData8(spi_dev
->cfg
->regs
);
436 /* Wait until the TXE goes high */
437 while (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_TXE
) == RESET
) {
441 /* Start the transfer */
442 SPI_SendData8(spi_dev
->cfg
->regs
, b
);
444 /* Wait until there is a byte to read */
445 while (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_RXNE
) == RESET
) {
449 /* Read the rx'd byte */
450 rx_byte
= SPI_ReceiveData8(spi_dev
->cfg
->regs
);
452 /* Wait until the TXE goes high */
453 while (!(spi_dev
->cfg
->regs
->SR
& SPI_I2S_FLAG_TXE
)) {
457 /* Wait for SPI transfer to have fully completed */
458 while (spi_dev
->cfg
->regs
->SR
& SPI_I2S_FLAG_BSY
) {
462 /* Return received byte */
468 * Transfers a block of bytes via PIO.
470 * \param[in] spi_id SPI device handle
471 * \param[in] send_buffer pointer to buffer which should be sent.<BR>
472 * If NULL, 0xff (all-one) will be sent.
473 * \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
474 * If NULL, received bytes will be discarded.
475 * \param[in] len number of bytes which should be transfered
476 * \return >= 0 if no error during transfer
477 * \return -1 if disabled SPI port selected
479 static int32_t PIOS_SPI_TransferBlock_PIO(struct pios_spi_dev
*spi_dev
, const uint8_t *send_buffer
, uint8_t *receive_buffer
, uint16_t len
, __attribute__((unused
)) void *callback
)
484 /* get the byte to send */
485 b
= send_buffer
? *(send_buffer
++) : 0xff;
487 /* Wait until the TXE goes high */
488 while (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_TXE
) == RESET
) {
492 /* Start the transfer */
493 SPI_SendData8(spi_dev
->cfg
->regs
, b
);
495 /* Wait until there is a byte to read */
496 while (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_RXNE
) == RESET
) {
500 /* Read the rx'd byte */
501 b
= SPI_ReceiveData8(spi_dev
->cfg
->regs
);
503 /* save the received byte */
504 if (receive_buffer
) {
505 *(receive_buffer
++) = b
;
509 /* Wait for SPI transfer to have fully completed */
510 while (spi_dev
->cfg
->regs
->SR
& SPI_I2S_FLAG_BSY
) {
519 * Transfers a block of bytes via DMA.
520 * \param[in] spi SPI number (0 or 1)
521 * \param[in] send_buffer pointer to buffer which should be sent.<BR>
522 * If NULL, 0xff (all-one) will be sent.
523 * \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
524 * If NULL, received bytes will be discarded.
525 * \param[in] len number of bytes which should be transfered
526 * \param[in] callback pointer to callback function which will be executed
527 * from DMA channel interrupt once the transfer is finished.
528 * If NULL, no callback function will be used, and PIOS_SPI_TransferBlock() will
529 * block until the transfer is finished.
530 * \return >= 0 if no error during transfer
531 * \return -1 if disabled SPI port selected
532 * \return -3 if function has been called during an ongoing DMA transfer
534 static int32_t PIOS_SPI_TransferBlock_DMA(struct pios_spi_dev
*spi_dev
, const uint8_t *send_buffer
, uint8_t *receive_buffer
, uint16_t len
, void *callback
)
536 DMA_InitTypeDef dma_init
;
538 /* Exit if ongoing transfer */
539 if (DMA_GetCurrDataCounter(spi_dev
->cfg
->dma
.rx
.channel
)) {
543 /* Disable the SPI peripheral */
544 SPI_Cmd(spi_dev
->cfg
->regs
, DISABLE
);
546 /* Disable the DMA channels */
547 DMA_Cmd(spi_dev
->cfg
->dma
.rx
.channel
, DISABLE
);
548 DMA_Cmd(spi_dev
->cfg
->dma
.tx
.channel
, DISABLE
);
550 /* Set callback function */
551 spi_dev
->callback
= callback
;
554 * Configure Rx channel
557 /* Start with the default configuration for this peripheral */
558 dma_init
= spi_dev
->cfg
->dma
.rx
.init
;
560 if (receive_buffer
!= NULL
) {
561 /* Enable memory addr. increment - bytes written into receive buffer */
562 dma_init
.DMA_MemoryBaseAddr
= (uint32_t)receive_buffer
;
563 dma_init
.DMA_MemoryInc
= DMA_MemoryInc_Enable
;
565 /* Disable memory addr. increment - bytes written into dummy buffer */
566 spi_dev
->rx_dummy_byte
= 0xFF;
567 dma_init
.DMA_MemoryBaseAddr
= (uint32_t)&spi_dev
->rx_dummy_byte
;
568 dma_init
.DMA_MemoryInc
= DMA_MemoryInc_Disable
;
570 if (spi_dev
->cfg
->use_crc
) {
571 /* Make sure the CRC error flag is cleared before we start */
572 SPI_I2S_ClearFlag(spi_dev
->cfg
->regs
, SPI_FLAG_CRCERR
);
575 dma_init
.DMA_BufferSize
= len
;
576 DMA_Init(spi_dev
->cfg
->dma
.rx
.channel
, &(dma_init
));
579 * Configure Tx channel
582 /* Start with the default configuration for this peripheral */
583 dma_init
= spi_dev
->cfg
->dma
.tx
.init
;
585 if (send_buffer
!= NULL
) {
586 /* Enable memory addr. increment - bytes written into receive buffer */
587 dma_init
.DMA_MemoryBaseAddr
= (uint32_t)send_buffer
;
588 dma_init
.DMA_MemoryInc
= DMA_MemoryInc_Enable
;
590 /* Disable memory addr. increment - bytes written into dummy buffer */
591 spi_dev
->tx_dummy_byte
= 0xFF;
592 dma_init
.DMA_MemoryBaseAddr
= (uint32_t)&spi_dev
->tx_dummy_byte
;
593 dma_init
.DMA_MemoryInc
= DMA_MemoryInc_Disable
;
596 if (spi_dev
->cfg
->use_crc
) {
597 /* The last byte of the payload will be replaced with the CRC8 */
598 dma_init
.DMA_BufferSize
= len
- 1;
600 dma_init
.DMA_BufferSize
= len
;
603 DMA_Init(spi_dev
->cfg
->dma
.tx
.channel
, &(dma_init
));
605 /* Enable DMA interrupt if callback function active */
606 DMA_ITConfig(spi_dev
->cfg
->dma
.rx
.channel
, DMA_IT_TC
, (callback
!= NULL
) ? ENABLE
: DISABLE
);
608 /* Flush out the CRC registers */
609 SPI_CalculateCRC(spi_dev
->cfg
->regs
, DISABLE
);
610 (void)SPI_GetCRC(spi_dev
->cfg
->regs
, SPI_CRC_Rx
);
611 SPI_I2S_ClearFlag(spi_dev
->cfg
->regs
, SPI_FLAG_CRCERR
);
613 /* Make sure to flush out the receive buffer */
614 (void)SPI_I2S_ReceiveData16(spi_dev
->cfg
->regs
);
616 if (spi_dev
->cfg
->use_crc
) {
617 /* Need a 0->1 transition to reset the CRC logic */
618 SPI_CalculateCRC(spi_dev
->cfg
->regs
, ENABLE
);
621 /* Start DMA transfers */
622 DMA_Cmd(spi_dev
->cfg
->dma
.rx
.channel
, ENABLE
);
623 DMA_Cmd(spi_dev
->cfg
->dma
.tx
.channel
, ENABLE
);
625 /* Reenable the SPI device */
626 SPI_Cmd(spi_dev
->cfg
->regs
, ENABLE
);
629 /* User has requested a callback, don't wait for the transfer to complete. */
633 /* Wait until all bytes have been transmitted/received */
634 while (DMA_GetCurrDataCounter(spi_dev
->cfg
->dma
.rx
.channel
)) {
638 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
639 while (!(SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_TXE
))) {
643 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
644 while (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_BSY
)) {
648 /* Check the CRC on the transfer if enabled. */
649 if (spi_dev
->cfg
->use_crc
) {
650 /* Check the SPI CRC error flag */
651 if (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_FLAG_CRCERR
)) {
660 int32_t PIOS_SPI_TransferBlock(uint32_t spi_id
, const uint8_t *send_buffer
, uint8_t *receive_buffer
, uint16_t len
, void *callback
)
662 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
664 bool valid
= PIOS_SPI_validate(spi_dev
);
668 if ((len
> SPI_MAX_BLOCK_PIO
) && spi_dev
->cfg
->dma
.rx
.channel
&& spi_dev
->cfg
->dma
.tx
.channel
) {
669 return PIOS_SPI_TransferBlock_DMA(spi_dev
, send_buffer
, receive_buffer
, len
, callback
);
672 return PIOS_SPI_TransferBlock_PIO(spi_dev
, send_buffer
, receive_buffer
, len
, callback
);
676 * Check if a transfer is in progress
677 * \param[in] spi SPI number (0 or 1)
678 * \return >= 0 if no transfer is in progress
679 * \return -1 if disabled SPI port selected
680 * \return -2 if unsupported SPI port selected
681 * \return -3 if function has been called during an ongoing DMA transfer
683 int32_t PIOS_SPI_Busy(uint32_t spi_id
)
685 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
687 bool valid
= PIOS_SPI_validate(spi_dev
);
691 /* DMA buffer has data or SPI transmit register not empty or SPI is busy*/
692 if (DMA_GetCurrDataCounter(spi_dev
->cfg
->dma
.rx
.channel
) ||
693 !SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_TXE
) ||
694 SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_BSY
)) {
701 void PIOS_SPI_SetPrescalar(uint32_t spi_id
, uint32_t prescaler
)
703 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
705 bool valid
= PIOS_SPI_validate(spi_dev
);
708 PIOS_Assert(IS_SPI_BAUDRATE_PRESCALER(prescaler
));
710 spi_dev
->cfg
->regs
->CR1
= (spi_dev
->cfg
->regs
->CR1
& ~0x0038) | prescaler
;
713 void PIOS_SPI_IRQ_Handler(uint32_t spi_id
)
715 struct pios_spi_dev
*spi_dev
= (struct pios_spi_dev
*)spi_id
;
717 bool valid
= PIOS_SPI_validate(spi_dev
);
721 DMA_ClearFlag(spi_dev
->cfg
->dma
.irq
.flags
);
723 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
724 while (!(SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_TXE
))) {
728 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
729 while (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_I2S_FLAG_BSY
)) {
733 if (spi_dev
->callback
!= NULL
) {
737 if (SPI_I2S_GetFlagStatus(spi_dev
->cfg
->regs
, SPI_FLAG_CRCERR
)) {
739 SPI_I2S_ClearFlag(spi_dev
->cfg
->regs
, SPI_FLAG_CRCERR
);
741 crc_val
= SPI_GetCRC(spi_dev
->cfg
->regs
, SPI_CRC_Rx
);
742 spi_dev
->callback(crc_ok
, crc_val
);
746 #endif /* PIOS_INCLUDE_SPI */