Revert "REVONANO - Workaround for the SBUS issue (use oversample 8 instead of 16...
[librepilot.git] / flight / pios / stm32f10x / pios_spi.c
blob21db6bd5ee8fcc8fab65cbb1cbbdb18394ef44c5
1 /**
2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
4 * @{
5 * @addtogroup PIOS_SPI SPI Functions
6 * @brief PIOS interface to read and write from SPI ports
7 * @{
9 * @file pios_spi.c
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
13 * @notes
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
29 * for more details.
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
36 #include <pios.h>
38 #ifdef PIOS_INCLUDE_SPI
40 #include <pios_spi_priv.h>
42 static bool PIOS_SPI_validate(__attribute__((unused)) struct pios_spi_dev *com_dev)
44 /* Should check device magic here */
45 return true;
48 #if defined(PIOS_INCLUDE_FREERTOS)
49 static struct pios_spi_dev *PIOS_SPI_alloc(void)
51 return pios_malloc(sizeof(struct pios_spi_dev));
53 #else
54 static struct pios_spi_dev pios_spi_devs[PIOS_SPI_MAX_DEVS];
55 static uint8_t pios_spi_num_devs;
56 static struct pios_spi_dev *PIOS_SPI_alloc(void)
58 if (pios_spi_num_devs >= PIOS_SPI_MAX_DEVS) {
59 return NULL;
62 return &pios_spi_devs[pios_spi_num_devs++];
64 #endif
66 /**
67 * Initialises SPI pins
68 * \param[in] mode currently only mode 0 supported
69 * \return < 0 if initialisation failed
71 int32_t PIOS_SPI_Init(uint32_t *spi_id, const struct pios_spi_cfg *cfg)
73 uint32_t init_ssel = 0;
75 PIOS_Assert(spi_id);
76 PIOS_Assert(cfg);
78 struct pios_spi_dev *spi_dev;
80 spi_dev = (struct pios_spi_dev *)PIOS_SPI_alloc();
81 if (!spi_dev) {
82 goto out_fail;
85 /* Bind the configuration to the device instance */
86 spi_dev->cfg = cfg;
88 #if defined(PIOS_INCLUDE_FREERTOS)
89 vSemaphoreCreateBinary(spi_dev->busy);
90 xSemaphoreGive(spi_dev->busy);
91 #else
92 spi_dev->busy = 0;
93 #endif
95 /* Disable callback function */
96 spi_dev->callback = NULL;
98 /* Set rx/tx dummy bytes to a known value */
99 spi_dev->rx_dummy_byte = 0xFF;
100 spi_dev->tx_dummy_byte = 0xFF;
102 switch (spi_dev->cfg->init.SPI_NSS) {
103 case SPI_NSS_Soft:
104 if (spi_dev->cfg->init.SPI_Mode == SPI_Mode_Master) {
105 /* We're a master in soft NSS mode, make sure we see NSS high at all times. */
106 SPI_NSSInternalSoftwareConfig(spi_dev->cfg->regs, SPI_NSSInternalSoft_Set);
107 /* Init as many slave selects as the config advertises. */
108 init_ssel = spi_dev->cfg->slave_count;
109 } else {
110 /* We're a slave in soft NSS mode, make sure we see NSS low at all times. */
111 SPI_NSSInternalSoftwareConfig(spi_dev->cfg->regs, SPI_NSSInternalSoft_Reset);
113 break;
114 case SPI_NSS_Hard:
115 /* only legal for single-slave config */
116 PIOS_Assert(spi_dev->cfg->slave_count == 1);
117 init_ssel = 1;
118 /* FIXME: Should this also call SPI_SSOutputCmd()? */
119 break;
121 default:
122 PIOS_Assert(0);
125 /* Initialize the GPIO pins */
126 GPIO_Init(spi_dev->cfg->sclk.gpio, &(spi_dev->cfg->sclk.init));
127 GPIO_Init(spi_dev->cfg->mosi.gpio, &(spi_dev->cfg->mosi.init));
128 GPIO_Init(spi_dev->cfg->miso.gpio, &(spi_dev->cfg->miso.init));
129 for (uint32_t i = 0; i < init_ssel; i++) {
130 /* Since we're driving the SSEL pin in software, ensure that the slave is deselected */
131 /* XXX multi-slave support - maybe have another SPI_NSS_ mode? */
132 GPIO_SetBits(spi_dev->cfg->ssel[i].gpio, spi_dev->cfg->ssel[i].init.GPIO_Pin);
133 GPIO_Init(spi_dev->cfg->ssel[i].gpio, (GPIO_InitTypeDef *)&(spi_dev->cfg->ssel[i].init));
136 /* Enable the associated peripheral clock */
137 switch ((uint32_t)spi_dev->cfg->regs) {
138 case (uint32_t)SPI1:
139 /* Enable SPI peripheral clock (APB2 == high speed) */
140 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
141 break;
142 case (uint32_t)SPI2:
143 /* Enable SPI peripheral clock (APB1 == slow speed) */
144 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
145 break;
146 case (uint32_t)SPI3:
147 /* Enable SPI peripheral clock (APB1 == slow speed) */
148 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
149 break;
152 /* Enable DMA clock */
153 RCC_AHBPeriphClockCmd(spi_dev->cfg->dma.ahb_clk, ENABLE);
155 /* Configure DMA for SPI Rx */
156 DMA_Cmd(spi_dev->cfg->dma.rx.channel, DISABLE);
157 DMA_Init(spi_dev->cfg->dma.rx.channel, &(spi_dev->cfg->dma.rx.init));
159 /* Configure DMA for SPI Tx */
160 DMA_Cmd(spi_dev->cfg->dma.tx.channel, DISABLE);
161 DMA_Init(spi_dev->cfg->dma.tx.channel, &(spi_dev->cfg->dma.tx.init));
163 /* Initialize the SPI block */
164 SPI_Init(spi_dev->cfg->regs, &(spi_dev->cfg->init));
166 /* Configure CRC calculation */
167 if (spi_dev->cfg->use_crc) {
168 SPI_CalculateCRC(spi_dev->cfg->regs, ENABLE);
169 } else {
170 SPI_CalculateCRC(spi_dev->cfg->regs, DISABLE);
173 /* Enable SPI */
174 SPI_Cmd(spi_dev->cfg->regs, ENABLE);
176 /* Enable SPI interrupts to DMA */
177 SPI_I2S_DMACmd(spi_dev->cfg->regs, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
179 /* Configure DMA interrupt */
180 NVIC_Init(&(spi_dev->cfg->dma.irq.init));
182 *spi_id = (uint32_t)spi_dev;
183 return 0;
185 out_fail:
186 return -1;
190 * (Re-)initialises SPI peripheral clock rate
192 * \param[in] spi SPI number (0 or 1)
193 * \param[in] spi_prescaler configures the SPI speed:
194 * <UL>
195 * <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)
196 * <LI>PIOS_SPI_PRESCALER_4: sets clock rate 55.5~ nS @ 72 MHz (18 MBit/s)
197 * <LI>PIOS_SPI_PRESCALER_8: sets clock rate 111.1~ nS @ 72 MHz (9 MBit/s)
198 * <LI>PIOS_SPI_PRESCALER_16: sets clock rate 222.2~ nS @ 72 MHz (4.5 MBit/s)
199 * <LI>PIOS_SPI_PRESCALER_32: sets clock rate 444.4~ nS @ 72 MHz (2.25 MBit/s)
200 * <LI>PIOS_SPI_PRESCALER_64: sets clock rate 888.8~ nS @ 72 MHz (1.125 MBit/s)
201 * <LI>PIOS_SPI_PRESCALER_128: sets clock rate 1.7~ nS @ 72 MHz (0.562 MBit/s)
202 * <LI>PIOS_SPI_PRESCALER_256: sets clock rate 3.5~ nS @ 72 MHz (0.281 MBit/s)
203 * </UL>
204 * \return 0 if no error
205 * \return -1 if disabled SPI port selected
206 * \return -3 if invalid spi_prescaler selected
208 int32_t PIOS_SPI_SetClockSpeed(uint32_t spi_id, SPIPrescalerTypeDef spi_prescaler)
210 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
212 bool valid = PIOS_SPI_validate(spi_dev);
214 PIOS_Assert(valid)
216 SPI_InitTypeDef SPI_InitStructure;
218 if (spi_prescaler >= 8) {
219 /* Invalid prescaler selected */
220 return -3;
223 /* Start with a copy of the default configuration for the peripheral */
224 SPI_InitStructure = spi_dev->cfg->init;
226 /* Adjust the prescaler for the peripheral's clock */
227 SPI_InitStructure.SPI_BaudRatePrescaler = ((uint16_t)spi_prescaler & 7) << 3;
229 /* Write back the new configuration */
230 SPI_Init(spi_dev->cfg->regs, &SPI_InitStructure);
232 PIOS_SPI_TransferByte(spi_id, 0xFF);
233 return 0;
237 * Claim the SPI bus semaphore. Calling the SPI functions does not require this
238 * \param[in] spi SPI number (0 or 1)
239 * \return 0 if no error
240 * \return -1 if timeout before claiming semaphore
242 int32_t PIOS_SPI_ClaimBus(uint32_t spi_id)
244 #if defined(PIOS_INCLUDE_FREERTOS)
245 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
247 bool valid = PIOS_SPI_validate(spi_dev);
248 PIOS_Assert(valid)
250 if (xSemaphoreTake(spi_dev->busy, 0xffff) != pdTRUE) {
251 return -1;
253 #else
254 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
255 uint32_t timeout = 0xffff;
256 while ((PIOS_SPI_Busy(spi_id) || spi_dev->busy) && --timeout) {
259 if (timeout == 0) { // timed out
260 return -1;
263 PIOS_IRQ_Disable();
264 if (spi_dev->busy) {
265 return -1;
267 spi_dev->busy = 1;
268 PIOS_IRQ_Enable();
269 #endif /* if defined(PIOS_INCLUDE_FREERTOS) */
270 return 0;
274 * Claim the SPI bus semaphore from an ISR. Has no timeout.
275 * \param[in] spi SPI number (0 or 1)
276 * \param woken[in,out] If non-NULL, will be set to true if woken was false and a higher priority
277 * task has is now eligible to run, else unchanged
278 * \return 0 if no error
279 * \return -1 if timeout before claiming semaphore
281 int32_t PIOS_SPI_ClaimBusISR(uint32_t spi_id, bool *woken)
283 #if defined(PIOS_INCLUDE_FREERTOS)
284 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
285 signed portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
287 bool valid = PIOS_SPI_validate(spi_dev);
288 PIOS_Assert(valid)
290 if (xSemaphoreTakeFromISR(spi_dev->busy, &higherPriorityTaskWoken) != pdTRUE) {
291 return -1;
293 if (woken) {
294 *woken = *woken || (higherPriorityTaskWoken == pdTRUE);
296 return 0;
298 #else
299 if (woken) {
300 *woken = false;
302 return PIOS_SPI_ClaimBus(spi_id);
304 #endif
308 * Release the SPI bus semaphore. Calling the SPI functions does not require this
309 * \param[in] spi SPI number (0 or 1)
310 * \return 0 if no error
312 int32_t PIOS_SPI_ReleaseBus(uint32_t spi_id)
314 #if defined(PIOS_INCLUDE_FREERTOS)
315 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
317 bool valid = PIOS_SPI_validate(spi_dev);
318 PIOS_Assert(valid)
320 xSemaphoreGive(spi_dev->busy);
321 #else
322 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
323 PIOS_IRQ_Disable();
324 spi_dev->busy = 0;
325 PIOS_IRQ_Enable();
326 #endif
327 return 0;
331 * Release the SPI bus semaphore from ISR. Calling the SPI functions does not require this
332 * \param[in] spi SPI number (0 or 1)
333 * \param woken[in,out] If non-NULL, will be set to true if woken was false and a higher priority
334 * task has is now eligible to run, else unchanged
335 * \return 0 if no error
337 int32_t PIOS_SPI_ReleaseBusISR(uint32_t spi_id, bool *woken)
339 #if defined(PIOS_INCLUDE_FREERTOS)
340 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
341 signed portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
343 bool valid = PIOS_SPI_validate(spi_dev);
344 PIOS_Assert(valid)
346 xSemaphoreGiveFromISR(spi_dev->busy, &higherPriorityTaskWoken);
347 if (woken) {
348 *woken = *woken || (higherPriorityTaskWoken == pdTRUE);
350 return 0;
352 #else
353 if (woken) {
354 *woken = false;
356 return PIOS_SPI_ReleaseBus(spi_id);
358 #endif
363 * Controls the RC (Register Clock alias Chip Select) pin of a SPI port
364 * \param[in] spi SPI number (0 or 1)
365 * \param[in] pin_value 0 or 1
366 * \return 0 if no error
368 int32_t PIOS_SPI_RC_PinSet(uint32_t spi_id, uint32_t slave_id, uint8_t pin_value)
370 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
372 bool valid = PIOS_SPI_validate(spi_dev);
374 PIOS_Assert(valid)
375 PIOS_Assert(slave_id <= spi_dev->cfg->slave_count)
377 /* XXX multi-slave support? */
378 if (pin_value) {
379 GPIO_SetBits(spi_dev->cfg->ssel[slave_id].gpio, spi_dev->cfg->ssel[slave_id].init.GPIO_Pin);
380 } else {
381 GPIO_ResetBits(spi_dev->cfg->ssel[slave_id].gpio, spi_dev->cfg->ssel[slave_id].init.GPIO_Pin);
384 return 0;
388 * Transfers a byte to SPI output and reads back the return value from SPI input
389 * \param[in] spi SPI number (0 or 1)
390 * \param[in] b the byte which should be transfered
392 static uint8_t dummy;
393 int32_t PIOS_SPI_TransferByte(uint32_t spi_id, uint8_t b)
395 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
397 bool valid = PIOS_SPI_validate(spi_dev);
399 PIOS_Assert(valid)
401 uint8_t rx_byte;
404 * Procedure taken from STM32F10xxx Reference Manual section 23.3.5
407 /* Make sure the RXNE flag is cleared by reading the DR register */
408 dummy = spi_dev->cfg->regs->DR;
410 /* Start the transfer */
411 spi_dev->cfg->regs->DR = b;
413 /* Wait until there is a byte to read */
414 while (!(spi_dev->cfg->regs->SR & SPI_I2S_FLAG_RXNE)) {
418 /* Read the rx'd byte */
419 rx_byte = spi_dev->cfg->regs->DR;
421 /* Wait until the TXE goes high */
422 while (!(spi_dev->cfg->regs->SR & SPI_I2S_FLAG_TXE)) {
426 /* Wait for SPI transfer to have fully completed */
427 while (spi_dev->cfg->regs->SR & SPI_I2S_FLAG_BSY) {
431 /* Return received byte */
432 return rx_byte;
436 * Transfers a block of bytes via DMA.
437 * \param[in] spi SPI number (0 or 1)
438 * \param[in] send_buffer pointer to buffer which should be sent.<BR>
439 * If NULL, 0xff (all-one) will be sent.
440 * \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
441 * If NULL, received bytes will be discarded.
442 * \param[in] len number of bytes which should be transfered
443 * \param[in] callback pointer to callback function which will be executed
444 * from DMA channel interrupt once the transfer is finished.
445 * If NULL, no callback function will be used, and PIOS_SPI_TransferBlock() will
446 * block until the transfer is finished.
447 * \return >= 0 if no error during transfer
448 * \return -1 if disabled SPI port selected
449 * \return -3 if function has been called during an ongoing DMA transfer
451 int32_t PIOS_SPI_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
453 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
455 bool valid = PIOS_SPI_validate(spi_dev);
457 PIOS_Assert(valid)
459 DMA_InitTypeDef dma_init;
461 /* Exit if ongoing transfer */
462 if (DMA_GetCurrDataCounter(spi_dev->cfg->dma.rx.channel)) {
463 return -3;
466 /* Disable the SPI peripheral */
467 SPI_Cmd(spi_dev->cfg->regs, DISABLE);
469 /* Disable the DMA channels */
470 DMA_Cmd(spi_dev->cfg->dma.rx.channel, DISABLE);
471 DMA_Cmd(spi_dev->cfg->dma.tx.channel, DISABLE);
473 /* Set callback function */
474 spi_dev->callback = callback;
477 * Configure Rx channel
480 /* Start with the default configuration for this peripheral */
481 dma_init = spi_dev->cfg->dma.rx.init;
483 if (receive_buffer != NULL) {
484 /* Enable memory addr. increment - bytes written into receive buffer */
485 dma_init.DMA_MemoryBaseAddr = (uint32_t)receive_buffer;
486 dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
487 } else {
488 /* Disable memory addr. increment - bytes written into dummy buffer */
489 spi_dev->rx_dummy_byte = 0xFF;
490 dma_init.DMA_MemoryBaseAddr = (uint32_t)&spi_dev->rx_dummy_byte;
491 dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
493 if (spi_dev->cfg->use_crc) {
494 /* Make sure the CRC error flag is cleared before we start */
495 SPI_I2S_ClearFlag(spi_dev->cfg->regs, SPI_FLAG_CRCERR);
498 dma_init.DMA_BufferSize = len;
499 DMA_Init(spi_dev->cfg->dma.rx.channel, &(dma_init));
502 * Configure Tx channel
505 /* Start with the default configuration for this peripheral */
506 dma_init = spi_dev->cfg->dma.tx.init;
508 if (send_buffer != NULL) {
509 /* Enable memory addr. increment - bytes written into receive buffer */
510 dma_init.DMA_MemoryBaseAddr = (uint32_t)send_buffer;
511 dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
512 } else {
513 /* Disable memory addr. increment - bytes written into dummy buffer */
514 spi_dev->tx_dummy_byte = 0xFF;
515 dma_init.DMA_MemoryBaseAddr = (uint32_t)&spi_dev->tx_dummy_byte;
516 dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
519 if (spi_dev->cfg->use_crc) {
520 /* The last byte of the payload will be replaced with the CRC8 */
521 dma_init.DMA_BufferSize = len - 1;
522 } else {
523 dma_init.DMA_BufferSize = len;
526 DMA_Init(spi_dev->cfg->dma.tx.channel, &(dma_init));
528 /* Enable DMA interrupt if callback function active */
529 DMA_ITConfig(spi_dev->cfg->dma.rx.channel, DMA_IT_TC, (callback != NULL) ? ENABLE : DISABLE);
531 /* Flush out the CRC registers */
532 SPI_CalculateCRC(spi_dev->cfg->regs, DISABLE);
533 (void)SPI_GetCRC(spi_dev->cfg->regs, SPI_CRC_Rx);
534 SPI_I2S_ClearFlag(spi_dev->cfg->regs, SPI_FLAG_CRCERR);
536 /* Make sure to flush out the receive buffer */
537 (void)SPI_I2S_ReceiveData(spi_dev->cfg->regs);
539 if (spi_dev->cfg->use_crc) {
540 /* Need a 0->1 transition to reset the CRC logic */
541 SPI_CalculateCRC(spi_dev->cfg->regs, ENABLE);
544 /* Start DMA transfers */
545 DMA_Cmd(spi_dev->cfg->dma.rx.channel, ENABLE);
546 DMA_Cmd(spi_dev->cfg->dma.tx.channel, ENABLE);
548 /* Reenable the SPI device */
549 SPI_Cmd(spi_dev->cfg->regs, ENABLE);
551 if (callback) {
552 /* User has requested a callback, don't wait for the transfer to complete. */
553 return 0;
556 /* Wait until all bytes have been transmitted/received */
557 while (DMA_GetCurrDataCounter(spi_dev->cfg->dma.rx.channel)) {
561 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
562 while (!(SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_I2S_FLAG_TXE))) {
566 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
567 while (SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_I2S_FLAG_BSY)) {
571 /* Check the CRC on the transfer if enabled. */
572 if (spi_dev->cfg->use_crc) {
573 /* Check the SPI CRC error flag */
574 if (SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_FLAG_CRCERR)) {
575 return -4;
579 /* No error */
580 return 0;
584 * Check if a transfer is in progress
585 * \param[in] spi SPI number (0 or 1)
586 * \return >= 0 if no transfer is in progress
587 * \return -1 if disabled SPI port selected
588 * \return -2 if unsupported SPI port selected
589 * \return -3 if function has been called during an ongoing DMA transfer
591 int32_t PIOS_SPI_Busy(uint32_t spi_id)
593 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
595 bool valid = PIOS_SPI_validate(spi_dev);
597 PIOS_Assert(valid)
599 /* DMA buffer has data or SPI transmit register not empty or SPI is busy*/
600 if (DMA_GetCurrDataCounter(spi_dev->cfg->dma.rx.channel) ||
601 !SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_I2S_FLAG_TXE) ||
602 SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_I2S_FLAG_BSY)) {
603 return -3;
606 return 0;
609 void PIOS_SPI_SetPrescalar(uint32_t spi_id, uint32_t prescaler)
611 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
613 bool valid = PIOS_SPI_validate(spi_dev);
615 PIOS_Assert(valid);
616 PIOS_Assert(IS_SPI_BAUDRATE_PRESCALER(prescaler));
618 spi_dev->cfg->regs->CR1 = (spi_dev->cfg->regs->CR1 & ~0x0038) | prescaler;
621 void PIOS_SPI_IRQ_Handler(uint32_t spi_id)
623 struct pios_spi_dev *spi_dev = (struct pios_spi_dev *)spi_id;
625 bool valid = PIOS_SPI_validate(spi_dev);
627 PIOS_Assert(valid)
629 DMA_ClearFlag(spi_dev->cfg->dma.irq.flags);
631 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
632 while (!(SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_I2S_FLAG_TXE))) {
636 /* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
637 while (SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_I2S_FLAG_BSY)) {
641 if (spi_dev->callback != NULL) {
642 bool crc_ok = TRUE;
643 uint8_t crc_val;
645 if (SPI_I2S_GetFlagStatus(spi_dev->cfg->regs, SPI_FLAG_CRCERR)) {
646 crc_ok = FALSE;
647 SPI_I2S_ClearFlag(spi_dev->cfg->regs, SPI_FLAG_CRCERR);
649 crc_val = SPI_GetCRC(spi_dev->cfg->regs, SPI_CRC_Rx);
650 spi_dev->callback(crc_ok, crc_val);
654 #endif /* PIOS_INCLUDE_SPI */
657 * @}
658 * @}