Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
spi_arch.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2005-2013 The Paparazzi Team
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 *
21 */
22
54#include <libopencm3/cm3/nvic.h>
55#include <libopencm3/stm32/gpio.h>
56#include <libopencm3/stm32/rcc.h>
57#include <libopencm3/stm32/exti.h>
58#include <libopencm3/stm32/spi.h>
59#include <libopencm3/stm32/dma.h>
60
61#include "mcu_periph/spi.h"
62#include "mcu_periph/gpio.h"
63
64#include BOARD_CONFIG
65
66#ifdef SPI_MASTER
67
68#ifndef NVIC_SPI_IRQ_PRIO
69#define NVIC_SPI_IRQ_PRIO 0
70#endif
71
72
83
106
107
108#if USE_SPI0
109#error "The STM32 doesn't have SPI0"
110#endif
111#if USE_SPI1
113#endif
114#if USE_SPI2
116#endif
117#if USE_SPI3
118static struct spi_periph_dma spi3_dma;
119#endif
120
121static void spi_start_dma_transaction(struct spi_periph *periph, struct spi_transaction *_trans);
122static void spi_next_transaction(struct spi_periph *periph);
124 uint16_t len, enum SPIDataSizeSelect dss, bool increment);
125static void __attribute__((unused)) process_rx_dma_interrupt(struct spi_periph *periph);
126static void __attribute__((unused)) process_tx_dma_interrupt(struct spi_periph *periph);
127static void spi_arch_int_enable(struct spi_periph *spi);
128static void spi_arch_int_disable(struct spi_periph *spi);
129
130
131/******************************************************************************
132 *
133 * Handling of Slave Select outputs
134 *
135 *****************************************************************************/
136
137static inline void SpiSlaveUnselect(uint8_t slave)
138{
139 switch (slave) {
140#if USE_SPI_SLAVE0
141 case 0:
143 break;
144#endif // USE_SPI_SLAVE0
145#if USE_SPI_SLAVE1
146 case 1:
148 break;
149#endif //USE_SPI_SLAVE1
150#if USE_SPI_SLAVE2
151 case 2:
153 break;
154#endif //USE_SPI_SLAVE2
155#if USE_SPI_SLAVE3
156 case 3:
158 break;
159#endif //USE_SPI_SLAVE3
160#if USE_SPI_SLAVE4
161 case 4:
163 break;
164#endif //USE_SPI_SLAVE4
165#if USE_SPI_SLAVE5
166 case 5:
168 break;
169#endif //USE_SPI_SLAVE5
170 default:
171 break;
172 }
173}
174
175static inline void SpiSlaveSelect(uint8_t slave)
176{
177 switch (slave) {
178#if USE_SPI_SLAVE0
179 case 0:
181 break;
182#endif // USE_SPI_SLAVE0
183#if USE_SPI_SLAVE1
184 case 1:
186 break;
187#endif //USE_SPI_SLAVE1
188#if USE_SPI_SLAVE2
189 case 2:
191 break;
192#endif //USE_SPI_SLAVE2
193#if USE_SPI_SLAVE3
194 case 3:
196 break;
197#endif //USE_SPI_SLAVE3
198#if USE_SPI_SLAVE4
199 case 4:
201 break;
202#endif //USE_SPI_SLAVE4
203#if USE_SPI_SLAVE5
204 case 5:
206 break;
207#endif //USE_SPI_SLAVE5
208 default:
209 break;
210 }
211}
212
217
222
224{
225
226#if USE_SPI_SLAVE0
229#endif
230
231#if USE_SPI_SLAVE1
234#endif
235
236#if USE_SPI_SLAVE2
239#endif
240
241#if USE_SPI_SLAVE3
244#endif
245
246#if USE_SPI_SLAVE4
249#endif
250
251#if USE_SPI_SLAVE5
254#endif
255}
256
257
258/******************************************************************************
259 *
260 * Implementation of the generic SPI functions
261 *
262 *****************************************************************************/
264{
265 uint8_t idx;
266 idx = p->trans_insert_idx + 1;
267 if (idx >= SPI_TRANSACTION_QUEUE_LEN) { idx = 0; }
268 if ((idx == p->trans_extract_idx) || ((t->input_length == 0) && (t->output_length == 0))) {
269 t->status = SPITransFailed;
270 return false; /* queue full or input_length and output_length both 0 */
271 // TODO can't tell why it failed here if it does
272 }
273
274 t->status = SPITransPending;
275
276 //Disable interrupts to avoid race conflict with end of DMA transfer interrupt
277 //FIXME
279
280 // GT: no copy? There's a queue implying a copy here...
281 p->trans[p->trans_insert_idx] = t;
282 p->trans_insert_idx = idx;
283
284 /* if peripheral is idle, start the transaction */
285 if (p->status == SPIIdle && !p->suspend) {
286 spi_start_dma_transaction(p, p->trans[p->trans_extract_idx]);
287 }
288 //FIXME
290 return true;
291}
292
294{
296 if (slave < 254 && p->suspend == 0) {
297 p->suspend = slave + 1; // 0 is reserved for unlock state
299 return true;
300 }
302 return false;
303}
304
306{
308 if (p->suspend == slave + 1) {
309 // restart fifo
310 p->suspend = 0;
311 if (p->trans_extract_idx != p->trans_insert_idx && p->status == SPIIdle) {
312 spi_start_dma_transaction(p, p->trans[p->trans_extract_idx]);
313 }
315 return true;
316 }
318 return false;
319}
320
321
322/******************************************************************************
323 *
324 * Transaction configuration helper functions
325 *
326 *****************************************************************************/
335
337{
338 return ((t->dss << 6) | (t->cdiv << 3) | (t->bitorder << 2) |
339 (t->cpha << 1) | (t->cpol));
340}
341
343{
344 uint8_t sig = 0;
347 } else {
349 }
351 sig |= (SPICphaEdge1 << 1);
352 } else {
353 sig |= (SPICphaEdge2 << 1);
354 }
355 if (c->lsbfirst == SPI_CR1_MSBFIRST) {
356 sig |= (SPIMSBFirst << 2);
357 } else {
358 sig |= (SPILSBFirst << 2);
359 }
360 uint8_t cdiv = SPIDiv256;
361 switch (c->br) {
363 cdiv = SPIDiv2;
364 break;
366 cdiv = SPIDiv4;
367 break;
369 cdiv = SPIDiv8;
370 break;
372 cdiv = SPIDiv16;
373 break;
375 cdiv = SPIDiv32;
376 break;
378 cdiv = SPIDiv64;
379 break;
381 cdiv = SPIDiv128;
382 break;
384 cdiv = SPIDiv256;
385 break;
386 default:
387 break;
388 }
389 sig |= (cdiv << 3);
390 if (c->dff == SPI_CR1_DFF_8BIT) {
391 sig |= (SPIDss8bit << 6);
392 } else {
393 sig |= (SPIDss16bit << 6);
394 }
395 return sig;
396}
397
400{
401 if (t->dss == SPIDss8bit) {
403 } else {
405 }
406 if (t->bitorder == SPIMSBFirst) {
408 } else {
410 }
411 if (t->cpha == SPICphaEdge1) {
413 } else {
415 }
416 if (t->cpol == SPICpolIdleLow) {
418 } else {
420 }
421
422 switch (t->cdiv) {
423 case SPIDiv2:
425 break;
426 case SPIDiv4:
428 break;
429 case SPIDiv8:
431 break;
432 case SPIDiv16:
434 break;
435 case SPIDiv32:
437 break;
438 case SPIDiv64:
440 break;
441 case SPIDiv128:
443 break;
444 case SPIDiv256:
446 break;
447 default:
448 break;
449 }
450}
451
452
453/******************************************************************************
454 *
455 * Helpers for SPI transactions with DMA
456 *
457 *****************************************************************************/
459 uint16_t len, enum SPIDataSizeSelect dss, bool increment)
460{
462#ifdef STM32F1
464#elif defined STM32F4
466#endif
470
471 /* Set the dma transfer size based on SPI transaction DSS */
472#ifdef STM32F1
473 if (dss == SPIDss8bit) {
476 } else {
479 }
480#elif defined STM32F4
481 if (dss == SPIDss8bit) {
484 } else {
487 }
488#endif
489
490 if (increment) {
492 } else {
494 }
495}
496
499{
501 // enable receive interrupt
502 nvic_set_priority(((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq, NVIC_SPI_IRQ_PRIO);
503 nvic_enable_irq(((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq);
504 // enable transmit interrupt
505 nvic_set_priority(((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq, NVIC_SPI_IRQ_PRIO);
506 nvic_enable_irq(((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq);
507}
508
511{
512 nvic_disable_irq(((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq);
513 nvic_disable_irq(((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq);
514}
515
517static void spi_next_transaction(struct spi_periph *periph)
518{
519 /* Increment the transaction to handle */
520 periph->trans_extract_idx++;
521
522 /* wrap read index of circular buffer */
524 periph->trans_extract_idx = 0;
525 }
526
527 /* Check if there is another pending SPI transaction */
528 if ((periph->trans_extract_idx == periph->trans_insert_idx) || periph->suspend) {
529 periph->status = SPIIdle;
530 } else {
531 spi_start_dma_transaction(periph, periph->trans[periph->trans_extract_idx]);
532 }
533}
534
535
539static void spi_start_dma_transaction(struct spi_periph *periph, struct spi_transaction *trans)
540{
541 struct spi_periph_dma *dma;
542 uint8_t sig = 0x00;
543
544 /* Store local copy to notify of the results */
545 trans->status = SPITransRunning;
546 periph->status = SPIRunning;
547
548 dma = periph->init_struct;
549
550 /*
551 * Check if we need to reconfigure the spi peripheral for this transaction
552 */
554 if (sig != dma->comm_sig) {
555 /* A different config is required in this transaction... */
556 set_comm_from_transaction(&(dma->comm), trans);
557
558 /* remember the new conf signature */
559 dma->comm_sig = sig;
560
561 /* apply the new configuration */
562 spi_disable((uint32_t)periph->reg_addr);
563 spi_init_master((uint32_t)periph->reg_addr, dma->comm.br, dma->comm.cpol,
564 dma->comm.cpha, dma->comm.dff, dma->comm.lsbfirst);
567 spi_enable((uint32_t)periph->reg_addr);
568 }
569
570 /*
571 * Select the slave after reconfiguration of the peripheral
572 */
573 if (trans->select == SPISelectUnselect || trans->select == SPISelect) {
575 }
576
577 /* Run the callback AFTER selecting the slave */
578 if (trans->before_cb != 0) {
579 trans->before_cb(trans);
580 }
581
582 /*
583 * Receive DMA channel configuration ----------------------------------------
584 *
585 * We always run the receive DMA until the very end!
586 * This is done so we can use the transfer complete interrupt
587 * of the RX DMA to signal the end of the transaction.
588 *
589 * If we want to receive less than we transmit, a dummy buffer
590 * for the rx DMA is used after for the remaining data.
591 *
592 * In the transmit only case (input_length == 0),
593 * the dummy is used right from the start.
594 */
595 if (trans->input_length == 0) {
596 /* run the dummy rx dma for the complete transaction length */
597 spi_configure_dma(dma->dma, dma->rcc_dma, dma->rx_chan, (uint32_t)dma->spidr,
598 (uint32_t) & (dma->rx_dummy_buf), trans->output_length, trans->dss, FALSE);
599 } else {
600 /* run the real rx dma for input_length */
601 spi_configure_dma(dma->dma, dma->rcc_dma, dma->rx_chan, (uint32_t)dma->spidr,
602 (uint32_t)trans->input_buf, trans->input_length, trans->dss, TRUE);
603 /* use dummy rx dma for the rest */
604 if (trans->output_length > trans->input_length) {
605 /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
606 dma->rx_extra_dummy_dma = true;
607 }
608 }
609#ifdef STM32F1
610 dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
612#elif defined STM32F4
613 dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
616#endif
617
618
619 /*
620 * Transmit DMA channel configuration ---------------------------------------
621 *
622 * We always run the transmit DMA!
623 * To receive data, the clock must run, so something has to be transmitted.
624 * If needed, use a dummy DMA transmitting zeros for the remaining length.
625 *
626 * In the receive only case (output_length == 0),
627 * the dummy is used right from the start.
628 */
629 if (trans->output_length == 0) {
630 spi_configure_dma(dma->dma, dma->rcc_dma, dma->tx_chan, (uint32_t)dma->spidr,
631 (uint32_t) & (dma->tx_dummy_buf), trans->input_length, trans->dss, FALSE);
632 } else {
633 spi_configure_dma(dma->dma, dma->rcc_dma, dma->tx_chan, (uint32_t)dma->spidr,
634 (uint32_t)trans->output_buf, trans->output_length, trans->dss, TRUE);
635 if (trans->input_length > trans->output_length) {
636 /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
637 dma->tx_extra_dummy_dma = true;
638 }
639 }
640#ifdef STM32F1
641 dma_set_read_from_memory(dma->dma, dma->tx_chan);
642 dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
643#elif defined STM32F4
644 dma_channel_select(dma->dma, dma->tx_chan, dma->tx_chan_sel);
647#endif
648
649 /* Enable DMA transfer complete interrupts. */
652
653 /* Enable DMA channels */
654#ifdef STM32F1
655 dma_enable_channel(dma->dma, dma->rx_chan);
656 dma_enable_channel(dma->dma, dma->tx_chan);
657#elif defined STM32F4
658 dma_enable_stream(dma->dma, dma->rx_chan);
659 dma_enable_stream(dma->dma, dma->tx_chan);
660#endif
661
662 /* Enable SPI transfers via DMA */
665}
666
667
668
669/******************************************************************************
670 *
671 * Initialization of each SPI peripheral
672 *
673 *****************************************************************************/
674#if USE_SPI1
676{
677
678 // set dma options
680#ifdef STM32F1
681 spi1_dma.dma = DMA1;
687#elif defined STM32F4
688 spi1_dma.dma = DMA2;
690 // TODO make a macro to configure this from board/airframe file ?
697#endif
702
703 // set the default configuration
706
707 // set init struct, indices and status
708 spi1.reg_addr = (void *)SPI1;
709 spi1.init_struct = &spi1_dma;
710 spi1.trans_insert_idx = 0;
711 spi1.trans_extract_idx = 0;
712 spi1.status = SPIIdle;
713
714
715 // Enable SPI1 Periph and gpio clocks
717
718 // Configure GPIOs: SCK, MISO and MOSI
719#ifdef STM32F1
723#elif defined STM32F4
727
730#endif
731
732 // reset SPI
734
735 // Disable SPI peripheral
737
738 // Force SPI mode over I2S.
739 SPI1_I2SCFGR = 0;
740
741 // configure master SPI.
744 /*
745 * Set NSS management to software.
746 *
747 * Note:
748 * Setting nss high is very important, even if we are controlling the GPIO
749 * ourselves this bit needs to be at least set to 1, otherwise the spi
750 * peripheral will not send any data out.
751 */
754
755 // Enable SPI_1 DMA clock
757
758 // Enable SPI1 periph.
760
762}
763#endif
764
765#if USE_SPI2
767{
768
769 // set dma options
771 spi2_dma.dma = DMA1;
773#ifdef STM32F1
778#elif defined STM32F4
785#endif
790
791 // set the default configuration
794
795 // set init struct, indices and status
796 spi2.reg_addr = (void *)SPI2;
797 spi2.init_struct = &spi2_dma;
798 spi2.trans_insert_idx = 0;
799 spi2.trans_extract_idx = 0;
800 spi2.status = SPIIdle;
801
802
803 // Enable SPI2 Periph and gpio clocks
805
806 // Configure GPIOs: SCK, MISO and MOSI
807#ifdef STM32F1
811#elif defined STM32F4
815
818#endif
819
820 // reset SPI
822
823 // Disable SPI peripheral
825
826 // Force SPI mode over I2S.
827 SPI2_I2SCFGR = 0;
828
829 // configure master SPI.
832
833 /*
834 * Set NSS management to software.
835 * Setting nss high is very important, even if we are controlling the GPIO
836 * ourselves this bit needs to be at least set to 1, otherwise the spi
837 * peripheral will not send any data out.
838 */
841
842 // Enable SPI_2 DMA clock
844
845 // Enable SPI2 periph.
847
849}
850#endif
851
852#if USE_SPI3
853void spi3_arch_init(void)
854{
855
856 // set the default configuration
857 spi3_dma.spidr = (uint32_t)&SPI3_DR;
858#ifdef STM32F1
859 spi3_dma.dma = DMA2;
860 spi3_dma.rcc_dma = RCC_DMA2;
861 spi3_dma.rx_chan = DMA_CHANNEL1;
862 spi3_dma.tx_chan = DMA_CHANNEL2;
863 spi3_dma.rx_nvic_irq = NVIC_DMA2_CHANNEL1_IRQ;
864 spi3_dma.tx_nvic_irq = NVIC_DMA2_CHANNEL2_IRQ;
865#elif defined STM32F4
866 spi3_dma.dma = DMA1;
867 spi3_dma.rcc_dma = RCC_DMA1;
868 spi3_dma.rx_chan = DMA_STREAM0;
869 spi3_dma.tx_chan = DMA_STREAM5;
870 spi3_dma.rx_chan_sel = DMA_SxCR_CHSEL_0;
871 spi3_dma.tx_chan_sel = DMA_SxCR_CHSEL_0;
872 spi3_dma.rx_nvic_irq = NVIC_DMA1_STREAM0_IRQ;
873 spi3_dma.tx_nvic_irq = NVIC_DMA1_STREAM5_IRQ;
874#endif
875 spi3_dma.tx_dummy_buf = 0;
876 spi3_dma.tx_extra_dummy_dma = false;
877 spi3_dma.rx_dummy_buf = 0;
878 spi3_dma.rx_extra_dummy_dma = false;
879
880 // set the default configuration
882 spi3_dma.comm_sig = get_comm_signature(&spi3_dma.comm);
883
884 // set init struct, indices and status
885 spi3.reg_addr = (void *)SPI3;
886 spi3.init_struct = &spi3_dma;
887 spi3.trans_insert_idx = 0;
888 spi3.trans_extract_idx = 0;
889 spi3.status = SPIIdle;
890
891
892 // Enable SPI3 Periph and gpio clocks
894
895 // Configure GPIOs: SCK, MISO and MOSI
896#ifdef STM32F1
900#elif defined STM32F4
904
907#endif
908
910
911 // reset SPI
913
914 // Disable SPI peripheral
916
917 // Force SPI mode over I2S.
918 SPI3_I2SCFGR = 0;
919
920 // configure master SPI.
921 spi_init_master(SPI3, spi3_dma.comm.br, spi3_dma.comm.cpol, spi3_dma.comm.cpha,
922 spi3_dma.comm.dff, spi3_dma.comm.lsbfirst);
923
924 /*
925 * Set NSS management to software.
926 * Setting nss high is very important, even if we are controlling the GPIO
927 * ourselves this bit needs to be at least set to 1, otherwise the spi
928 * peripheral will not send any data out.
929 */
932
933 // Enable SPI_3 DMA clock
935
936 // Enable SPI3 periph.
938
940}
941#endif
942
943
944
945
946/******************************************************************************
947 *
948 * DMA Interrupt service routines
949 *
950 *****************************************************************************/
951#ifdef USE_SPI1
953#ifdef STM32F1
954void dma1_channel2_isr(void)
955{
956 if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) {
957 // clear int pending bit
959 }
960#elif defined STM32F4
961void dma2_stream0_isr(void) {
962 if ((DMA2_LISR & DMA_LISR_TCIF0) != 0) {
963 // clear int pending bit
965 }
966#endif
968}
969
971#ifdef STM32F1
972void dma1_channel3_isr(void) {
973 if ((DMA1_ISR & DMA_ISR_TCIF3) != 0) {
974 // clear int pending bit
976 }
977#elif defined STM32F4
978void dma2_stream5_isr(void) {
979 if ((DMA2_HISR & DMA_HISR_TCIF5) != 0) {
980 // clear int pending bit
982 }
983#endif
985}
986
987#endif
988
989#ifdef USE_SPI2
991#ifdef STM32F1
992void dma1_channel4_isr(void) {
993 if ((DMA1_ISR & DMA_ISR_TCIF4) != 0) {
994 // clear int pending bit
996 }
997#elif defined STM32F4
998void dma1_stream3_isr(void) {
999 if ((DMA1_LISR & DMA_LISR_TCIF3) != 0) {
1000 // clear int pending bit
1002 }
1003#endif
1005}
1006
1008#ifdef STM32F1
1009void dma1_channel5_isr(void) {
1010 if ((DMA1_ISR & DMA_ISR_TCIF5) != 0) {
1011 // clear int pending bit
1013 }
1014#elif defined STM32F4
1015void dma1_stream4_isr(void) {
1016 if ((DMA1_HISR & DMA_HISR_TCIF4) != 0) {
1017 // clear int pending bit
1019 }
1020#endif
1022}
1023
1024#endif
1025
1026#if USE_SPI3
1028#ifdef STM32F1
1029void dma2_channel1_isr(void) {
1030 if ((DMA2_ISR & DMA_ISR_TCIF1) != 0) {
1031 // clear int pending bit
1033 }
1034#elif defined STM32F4
1035void dma1_stream0_isr(void) {
1036 if ((DMA1_LISR & DMA_LISR_TCIF0) != 0) {
1037 // clear int pending bit
1039 }
1040#endif
1042}
1043
1045#ifdef STM32F1
1046void dma2_channel2_isr(void) {
1047 if ((DMA2_ISR & DMA_ISR_TCIF2) != 0) {
1048 // clear int pending bit
1050 }
1051#elif defined STM32F4
1052void dma1_stream5_isr(void) {
1053 if ((DMA1_HISR & DMA_HISR_TCIF5) != 0) {
1054 // clear int pending bit
1056 }
1057#endif
1059}
1060
1061#endif
1062
1065 struct spi_periph_dma *dma = periph->init_struct;
1066 struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
1067
1068 /* Disable DMA Channel */
1070
1071 /* Disable SPI Rx request */
1073
1074 /* Disable DMA rx channel */
1075#ifdef STM32F1
1076 dma_disable_channel(dma->dma, dma->rx_chan);
1077#elif defined STM32F4
1078 dma_disable_stream(dma->dma, dma->rx_chan);
1079#endif
1080
1081
1082 if (dma->rx_extra_dummy_dma) {
1083 /*
1084 * We are finished the first part of the receive with real data,
1085 * but still need to run the dummy to get a transfer complete interrupt
1086 * after the complete transaction is done.
1087 */
1088
1089 /* Reset the flag so this only happens once in a transaction */
1090 dma->rx_extra_dummy_dma = false;
1091
1092 /* Use the difference in length between rx and tx */
1094
1095 spi_configure_dma(dma->dma, dma->rcc_dma, dma->rx_chan, (uint32_t)dma->spidr,
1096 (uint32_t) & (dma->rx_dummy_buf), len_remaining, trans->dss, FALSE);
1097#ifdef STM32F1
1100#elif defined STM32F4
1101 dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
1104#endif
1105
1106 /* Enable DMA transfer complete interrupts. */
1108 /* Enable DMA channels */
1109#ifdef STM32F1
1110 dma_enable_channel(dma->dma, dma->rx_chan);
1111#elif defined STM32F4
1112 dma_enable_stream(dma->dma, dma->rx_chan);
1113#endif
1114 /* Enable SPI transfers via DMA */
1116 } else {
1117 /*
1118 * Since the receive DMA is always run until the very end
1119 * and this interrupt is triggered after the last data word was read,
1120 * we now know that this transaction is finished.
1121 */
1122
1123 /* Run the callback */
1124 trans->status = SPITransSuccess;
1125 if (trans->after_cb != 0) {
1126 trans->after_cb(trans);
1127 }
1128
1129 /* AFTER the callback, then unselect the slave if required */
1130 if (trans->select == SPISelectUnselect || trans->select == SPIUnselect) {
1132 }
1133
1134 spi_next_transaction(periph);
1135 }
1136}
1137
1140 struct spi_periph_dma *dma = periph->init_struct;
1141 struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
1142
1143 /* Disable DMA Channel */
1145
1146 /* Disable SPI TX request */
1148
1149 /* Disable DMA tx channel */
1150#ifdef STM32F1
1151 dma_disable_channel(dma->dma, dma->tx_chan);
1152#elif defined STM32F4
1153 dma_disable_stream(dma->dma, dma->tx_chan);
1154#endif
1155
1156 if (dma->tx_extra_dummy_dma) {
1157 /*
1158 * We are finished the first part of the transmit with real data,
1159 * but still need to clock in the rest of the receive data.
1160 * Set up a dummy dma transmit transfer to accomplish this.
1161 */
1162
1163 /* Reset the flag so this only happens once in a transaction */
1164 dma->tx_extra_dummy_dma = false;
1165
1166 /* Use the difference in length between tx and rx */
1168
1169 spi_configure_dma(dma->dma, dma->rcc_dma, dma->tx_chan, (uint32_t)dma->spidr,
1170 (uint32_t) & (dma->tx_dummy_buf), len_remaining, trans->dss, FALSE);
1171#ifdef STM32F1
1174#elif defined STM32F4
1175 dma_channel_select(dma->dma, dma->tx_chan, dma->tx_chan_sel);
1178#endif
1179
1180 /* Enable DMA transfer complete interrupts. */
1182 /* Enable DMA channels */
1183#ifdef STM32F1
1184 dma_enable_channel(dma->dma, dma->tx_chan);
1185#elif defined STM32F4
1186 dma_enable_stream(dma->dma, dma->tx_chan);
1187#endif
1188 /* Enable SPI transfers via DMA */
1190
1191 }
1192}
1193
1194#endif
1197/*
1198 *
1199 * SPI Slave code
1200 * Currently only for F1
1201 *
1202 */
1203#ifdef SPI_SLAVE
1204
1205static void process_slave_tx_dma_interrupt(struct spi_periph * periph);
1206static void process_slave_rx_dma_interrupt(struct spi_periph * periph);
1207
1208/****************** Slave 1 ******************/
1209#if USE_SPI1_SLAVE
1210#warning "SPI1 slave: Untested code!"
1211
1212#if USE_SPI1
1213#error "Using SPI1 as a slave and master at the same time is not possible."
1214#endif
1215
1216static struct spi_periph_dma spi1_dma;
1217
1218void spi1_slave_arch_init(void) {
1219 // set dma options
1221#ifdef STM32F1
1222 spi1_dma.dma = DMA1;
1228#elif defined STM32F4
1229 spi1_dma.dma = DMA2;
1237#endif
1242
1243 // set the default configuration
1246
1247 // set init struct, indices and status
1248 spi1.reg_addr = (void *)SPI1;
1249 spi1.init_struct = &spi1_dma;
1250 spi1.trans_insert_idx = 0;
1251 spi1.trans_extract_idx = 0;
1252 spi1.status = SPIIdle;
1253
1254 // Enable SPI1 Periph and gpio clocks
1256
1257 // Configure GPIOs: SCK, MISO and MOSI
1258#if defined STM32F1
1263#elif defined STM32F4
1268
1270#endif
1271
1272 // reset SPI
1273 spi_reset(SPI1);
1274
1275 // Disable SPI peripheral
1277
1278 // Force SPI mode over I2S
1279 SPI1_I2SCFGR = 0;
1280
1281 // configure default spi settings
1284
1285 // configure slave select management
1287
1288 // set slave mode
1290
1291 // Enable SPI_1 DMA clock
1293
1294 // Enable SPI1 periph.
1296}
1297
1299#ifdef STM32F1
1300void dma1_channel2_isr(void) {
1301 if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) {
1302 // clear int pending bit
1304 }
1305#elif defined STM32F4
1306void dma2_stream0_isr(void) {
1307 if ((DMA2_LISR & DMA_LISR_TCIF0) != 0) {
1308 // clear int pending bit
1310 }
1311#endif
1313}
1314
1316#ifdef STM32F1
1317void dma1_channel3_isr(void) {
1318 if ((DMA1_ISR & DMA_ISR_TCIF3) != 0) {
1319 // clear int pending bit
1321 }
1322#elif defined STM32F4
1323void dma2_stream5_isr(void) {
1324 if ((DMA2_HISR & DMA_HISR_TCIF5) != 0) {
1325 // clear int pending bit
1327 }
1328#endif
1330}
1331
1332#endif /* USE_SPI1_SLAVE */
1333
1334/****************** Slave 2 ******************/
1335#if USE_SPI2_SLAVE
1336#ifndef STM32F1
1337#warning "SPI2 slave only tested on STM32F1!"
1338#endif
1339
1340#if USE_SPI2
1341#error "Using SPI2 as a slave and master at the same time is not possible."
1342#endif
1343
1344static struct spi_periph_dma spi2_dma;
1345
1346void spi2_slave_arch_init(void) {
1347 // set dma options
1349 spi2_dma.dma = DMA1;
1351#ifdef STM32F1
1356#elif defined STM32F4
1363#endif
1368
1369 // set the default configuration
1372
1373 // set init struct, indices and status
1374 spi2.reg_addr = (void *)SPI2;
1375 spi2.init_struct = &spi2_dma;
1376 spi2.trans_insert_idx = 0;
1377 spi2.trans_extract_idx = 0;
1378 spi2.status = SPIIdle;
1379
1380 // Enable SPI2 Periph and gpio clocks
1382
1383 // Configure GPIOs: SCK, MISO and MOSI
1384#ifdef STM32F1
1389#elif defined STM32F4
1394
1396#endif
1397
1398 // reset SPI
1399 spi_reset(SPI2);
1400
1401 // Disable SPI peripheral
1403
1404 // Force SPI mode over I2S
1405 SPI2_I2SCFGR = 0;
1406
1407 // configure default spi settings
1410
1411 // configure slave select management
1413
1414 // set slave mode
1416
1417 // Enable SPI_2 DMA clock
1419
1420 // Enable SPI2 periph
1422}
1423
1425#ifdef STM32F1
1426void dma1_channel4_isr(void) {
1427 if ((DMA1_ISR & DMA_ISR_TCIF4) != 0) {
1428 // clear int pending bit
1430 }
1431#elif defined STM32F4
1432void dma1_stream3_isr(void) {
1433 if ((DMA1_LISR & DMA_LISR_TCIF3) != 0) {
1434 // clear int pending bit
1436 }
1437#endif
1439}
1440
1442#ifdef STM32F1
1443void dma1_channel5_isr(void) {
1444 if ((DMA1_ISR & DMA_ISR_TCIF5) != 0) {
1445 // clear int pending bit
1447 }
1448#elif defined STM32F4
1449void dma1_stream4_isr(void) {
1450 if ((DMA1_HISR & DMA_HISR_TCIF4) != 0) {
1451 // clear int pending bit
1453 }
1454#endif
1456}
1457
1458#endif /* USE_SPI2_SLAVE */
1459
1460
1461#if USE_SPI3_SLAVE
1462#ifndef STM32F4
1463#warning "SPI3 slave only tested on STM32F4!"
1464#endif
1465
1466/****************** Slave 3 ******************/
1467#if USE_SPI3
1468#error "Using SPI3 as a slave and master at the same time is not possible."
1469#endif
1470
1471static struct spi_periph_dma spi3_dma;
1472
1473void spi3_slave_arch_init(void) {
1474 // set dma options
1476#if defined STM32F1
1477 spi3_dma.dma = DMA2;
1478 spi3_dma.rcc_dma = RCC_DMA2;
1479 spi3_dma.rx_chan = DMA_CHANNEL1;
1480 spi3_dma.tx_chan = DMA_CHANNEL2;
1481 spi3_dma.rx_nvic_irq = NVIC_DMA2_CHANNEL1_IRQ;
1482 spi3_dma.tx_nvic_irq = NVIC_DMA2_CHANNEL2_IRQ;
1483#elif defined STM32F4
1484 spi3_dma.dma = DMA1;
1485 spi3_dma.rcc_dma = RCC_DMA1;
1486 spi3_dma.rx_chan = DMA_STREAM0;
1487 spi3_dma.tx_chan = DMA_STREAM5;
1488 spi3_dma.rx_chan_sel = DMA_SxCR_CHSEL_0;
1489 spi3_dma.tx_chan_sel = DMA_SxCR_CHSEL_0;
1490 spi3_dma.rx_nvic_irq = NVIC_DMA1_STREAM0_IRQ;
1491 spi3_dma.tx_nvic_irq = NVIC_DMA1_STREAM5_IRQ;
1492#endif
1493 spi3_dma.tx_dummy_buf = 0;
1494 spi3_dma.tx_extra_dummy_dma = false;
1495 spi3_dma.rx_dummy_buf = 0;
1496 spi3_dma.rx_extra_dummy_dma = false;
1497
1498 // set the default configuration
1500 spi3_dma.comm_sig = get_comm_signature(&spi3_dma.comm);
1501
1502 // set init struct, indices and status
1503 spi3.reg_addr = (void *)SPI3;
1504 spi3.init_struct = &spi3_dma;
1505 spi3.trans_insert_idx = 0;
1506 spi3.trans_extract_idx = 0;
1507 spi3.status = SPIIdle;
1508
1509 // Enable SPI3 Periph and gpio clocks
1511
1512 // Configure GPIOs: SCK, MISO and MOSI
1513#if defined STM32F1
1517 // set NSS as input
1519#elif defined STM32F4
1524
1526#endif
1527
1528 // reset SPI
1529 spi_reset(SPI3);
1530
1531 // Disable SPI peripheral
1533
1534 // Force SPI mode over I2S
1535 SPI3_I2SCFGR = 0;
1536
1537 // configure default spi settings
1538 spi_init_master(SPI3, spi3_dma.comm.br, spi3_dma.comm.cpol, spi3_dma.comm.cpha,
1539 spi3_dma.comm.dff, spi3_dma.comm.lsbfirst);
1540
1541 // configure slave select management
1543
1544 // set slave mode
1546
1547 // Enable SPI_2 DMA clock
1549
1550 // Enable SPI3 periph
1552}
1553
1555#ifdef STM32F1
1556void dma2_channel1_isr(void) {
1557 if ((DMA2_ISR & DMA_ISR_TCIF1) != 0) {
1558 // clear int pending bit
1560 }
1561#elif defined STM32F4
1562void dma1_stream0_isr(void) {
1563 if ((DMA1_LISR & DMA_LISR_TCIF0) != 0) {
1564 // clear int pending bit
1566 }
1567#endif
1569}
1570
1572#ifdef STM32F1
1573void dma2_channel2_isr(void) {
1574 if ((DMA2_ISR & DMA_ISR_TCIF2) != 0) {
1575 // clear int pending bit
1577 }
1578#elif defined STM32F4
1579void dma1_stream5_isr(void) {
1580 if ((DMA1_HISR & DMA_HISR_TCIF5) != 0) {
1581 // clear int pending bit
1583 }
1584#endif
1586}
1587
1588#endif /* USE_SPI3_SLAVE */
1589
1590/****************** General SPI slave Functions ******************/
1591static void spi_slave_set_config(struct spi_periph * periph, struct spi_transaction * trans) {
1592 struct spi_periph_dma *dma;
1593
1594 dma = periph->init_struct;
1595
1596 /* set the new configuration */
1597 set_comm_from_transaction(&(dma->comm), trans);
1598
1599 /* remember the new conf signature */
1600 dma->comm_sig = get_transaction_signature(trans);
1601
1602 /* apply the new configuration */
1603 spi_disable((uint32_t)periph->reg_addr);
1604 spi_init_master((uint32_t)periph->reg_addr, dma->comm.br, dma->comm.cpol,
1605 dma->comm.cpha, dma->comm.dff, dma->comm.lsbfirst);
1606
1607 // configure slave select management
1609
1610 // set slave mode
1612
1613 // enable spi peripheral
1614 spi_enable((uint32_t)periph->reg_addr);
1615}
1616
1617//static void spi_start_slave_dma_transaction(struct spi_periph* periph, struct spi_transaction* trans)
1618
1619/*
1620 * Please note: Spi_slave_register will set-up the DMA which will automatically load the first byte of the transmit buffer
1621 * Therefore, to ensure that the first byte of your data will be set, you have to set the transmit buffer before you call
1622 * this function
1623 */
1624bool spi_slave_register(struct spi_periph * periph, struct spi_transaction * trans) {
1625 struct spi_periph_dma *dma = periph->init_struct;
1626
1627 /* Store local copy to notify of the results */
1628 trans->status = SPITransRunning;
1629 periph->status = SPIRunning;
1630
1631 periph->trans_insert_idx = 0;
1632 periph->trans[periph->trans_insert_idx] = trans;
1633
1634 /* update peripheral if changed */
1636 if (sig != dma->comm_sig) {
1637 spi_slave_set_config(periph, trans);
1638 }
1639
1640 /*
1641 * Transmit DMA channel configuration ---------------------------------------
1642 */
1643 spi_configure_dma(dma->dma, dma->rcc_dma, dma->tx_chan, (uint32_t)dma->spidr,
1644 (uint32_t)trans->output_buf, trans->output_length, trans->dss, TRUE);
1645
1646#ifdef STM32F1
1647 dma_set_read_from_memory(dma->dma, dma->tx_chan);
1648 dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
1649#elif defined STM32F4
1650 dma_channel_select(dma->dma, dma->tx_chan, dma->tx_chan_sel);
1652 dma_set_priority(dma->dma, dma->tx_chan, DMA_SxCR_PL_MEDIUM);
1653#endif
1654
1655 /*
1656 * Receive DMA channel configuration ----------------------------------------
1657 */
1658 spi_configure_dma(dma->dma, dma->rcc_dma, dma->rx_chan, (uint32_t)dma->spidr,
1659 (uint32_t)trans->input_buf, trans->input_length, trans->dss, TRUE);
1660
1661#ifdef STM32F1
1662 dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
1664#elif defined STM32F4
1665 dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
1668#endif
1669
1670 /* Enable DMA transfer complete interrupts. */
1673
1674 /* Enable DMA channels */
1675#ifdef STM32F1
1676 dma_enable_channel(dma->dma, dma->tx_chan);
1677 dma_enable_channel(dma->dma, dma->rx_chan);
1678#elif defined STM32F4
1679 dma_enable_stream(dma->dma, dma->tx_chan);
1680 dma_enable_stream(dma->dma, dma->rx_chan);
1681#endif
1682
1683 /* Enable SPI transfers via DMA */
1686
1687 /* enable dma interrupt */
1688 spi_arch_int_enable(periph);
1689
1690 return true;
1691}
1692
1694 struct spi_periph_dma *dma = periph->init_struct;
1695 struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
1696
1697 /* Disable DMA Channel */
1699
1700 /* disable dma interrupts */
1701 spi_arch_int_disable(periph);
1702
1703 /* Disable SPI rx request */
1705
1706 /* Disable DMA rx channel */
1707#ifdef STM32F1
1708 dma_disable_channel(dma->dma, dma->rx_chan);
1709#elif defined STM32F4
1710 dma_disable_stream(dma->dma, dma->rx_chan);
1711#endif
1712
1713 /* Run the callback */
1714 trans->status = SPITransSuccess;
1715
1716 if (trans->after_cb != 0) {
1717 trans->after_cb(trans);
1718 }
1719}
1720
1722 struct spi_periph_dma *dma = periph->init_struct;
1723
1724 /* Disable DMA Channel */
1726
1727 /* Disable SPI tx request */
1729
1730 /* Disable DMA tx channel */
1731#ifdef STM32F1
1732 dma_disable_channel(dma->dma, dma->tx_chan);
1733#elif defined STM32F4
1734 dma_disable_stream(dma->dma, dma->tx_chan);
1735#endif
1736}
1737
1738#endif /* SPI_SLAVE */
#define SPI1_GPIO_SCK
Definition board.h:478
#define SPI_SELECT_SLAVE3_PIN
Definition board.h:491
#define SPI1_GPIO_AF
SPI Config.
Definition board.h:472
#define SPI1_GPIO_PORT_SCK
Definition board.h:477
#define SPI_SELECT_SLAVE0_PORT
Definition board.h:481
#define SPI_SELECT_SLAVE1_PIN
Definition board.h:485
#define SPI_SELECT_SLAVE4_PORT
Definition board.h:493
#define SPI_SELECT_SLAVE0_PIN
Definition board.h:482
#define SPI1_GPIO_MOSI
Definition board.h:476
#define SPI1_GPIO_PORT_MISO
Definition board.h:473
#define SPI_SELECT_SLAVE4_PIN
Definition board.h:494
#define SPI_SELECT_SLAVE3_PORT
Definition board.h:490
#define SPI_SELECT_SLAVE1_PORT
Definition board.h:484
#define SPI_SELECT_SLAVE2_PORT
Definition board.h:487
#define SPI1_GPIO_MISO
Definition board.h:474
#define SPI_SELECT_SLAVE2_PIN
Definition board.h:488
#define SPI1_GPIO_PORT_MOSI
Definition board.h:475
void gpio_setup_pin_af(ioportid_t port, uint16_t pin, uint8_t af, bool is_output)
Setup a gpio for input or output with alternate function.
Definition gpio_arch.c:65
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
Definition gpio_arch.c:33
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
Definition gpio_arch.h:104
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
Definition gpio_arch.h:114
#define SPI_SELECT_SLAVE5_PIN
Definition chimera.h:541
#define SPI_SELECT_SLAVE5_PORT
Definition chimera.h:540
#define SPI3_GPIO_MOSI
#define SPI2_GPIO_SCK
#define SPI2_GPIO_PORT_SCK
#define SPI3_GPIO_SCK
#define SPI2_GPIO_MOSI
#define SPI3_GPIO_PORT_MISO
#define SPI3_GPIO_PORT_SCK
#define SPI3_GPIO_AF
#define SPI2_GPIO_MISO
#define SPI2_GPIO_AF
#define SPI2_GPIO_PORT_MOSI
#define SPI3_GPIO_PORT_MOSI
#define SPI3_GPIO_MISO
#define SPI2_GPIO_PORT_MISO
#define SPI1_GPIO_PORT_NSS
#define SPI2_GPIO_NSS
#define SPI1_GPIO_NSS
#define SPI2_GPIO_PORT_NSS
Some architecture independent helper functions for GPIOs.
enum SPISlaveSelect select
slave selection behavior
Definition spi.h:154
SPICallback before_cb
NULL or function called before the transaction.
Definition spi.h:160
enum SPIStatus status
internal state of the peripheral
Definition spi.h:180
SPICallback after_cb
NULL or function called after the transaction.
Definition spi.h:161
struct spi_transaction * trans[SPI_TRANSACTION_QUEUE_LEN]
circular buffer holding transactions
Definition spi.h:176
void * reg_addr
Definition spi.h:183
enum SPIDataSizeSelect dss
data transfer word size
Definition spi.h:157
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition spi.h:150
uint16_t input_length
number of data words to read
Definition spi.h:151
void * init_struct
Definition spi.h:184
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition spi.h:149
uint8_t trans_insert_idx
Definition spi.h:177
volatile uint8_t suspend
control for stop/resume of the fifo
Definition spi.h:187
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition spi.h:153
uint8_t trans_extract_idx
Definition spi.h:178
uint16_t output_length
number of data words to write
Definition spi.h:152
enum SPITransactionStatus status
Definition spi.h:162
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition spi_arch.c:533
bool spi_lock(struct spi_periph *p, uint8_t slave)
spi_lock() function
Definition spi_arch.c:681
#define SPI_TRANSACTION_QUEUE_LEN
SPI transaction queue length.
Definition spi.h:169
void spi_slave_unselect(uint8_t slave)
spi_slave_unselect() function
Definition spi_arch.c:623
void spi1_arch_init(void)
Architecture dependent SPI1 initialization.
Definition spi_arch.c:423
SPIDataSizeSelect
SPI data word size of transfer.
Definition spi.h:89
process_rx_dma_interrupt & spi2
receive transferred over DMA
Definition spi_arch.c:1004
bool spi_slave_register(struct spi_periph *periph, struct spi_transaction *trans)
Register a spi transaction in slave mode (only one transaction can be registered).
Definition spi_arch.c:1624
void spi_slave_select(uint8_t slave)
spi_slave_select() function
Definition spi_arch.c:566
void spi2_arch_init(void)
Architecture dependent SPI2 initialization.
Definition spi_arch.c:442
process_rx_dma_interrupt & spi1
receive transferred over DMA
Definition spi_arch.c:967
bool spi_resume(struct spi_periph *p, uint8_t slave)
spi_resume() function
Definition spi_arch.c:695
void spi_init_slaves(void)
spi_init_slaves() function
Definition spi_arch.c:709
@ SPICphaEdge2
CPHA = 1.
Definition spi.h:75
@ SPICphaEdge1
CPHA = 0.
Definition spi.h:74
@ SPIIdle
Definition spi.h:107
@ SPIRunning
Definition spi.h:108
@ SPITransFailed
Definition spi.h:100
@ SPITransSuccess
Definition spi.h:99
@ SPITransRunning
Definition spi.h:98
@ SPITransPending
Definition spi.h:97
@ SPICpolIdleLow
CPOL = 0.
Definition spi.h:83
@ SPICpolIdleHigh
CPOL = 1.
Definition spi.h:84
@ SPISelect
slave is selected before transaction but not unselected
Definition spi.h:64
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition spi.h:63
@ SPIUnselect
slave is not selected but unselected after transaction
Definition spi.h:65
@ SPILSBFirst
Definition spi.h:113
@ SPIMSBFirst
Definition spi.h:112
@ SPIDiv4
Definition spi.h:121
@ SPIDiv8
Definition spi.h:122
@ SPIDiv2
Definition spi.h:120
@ SPIDiv256
Definition spi.h:127
@ SPIDiv128
Definition spi.h:126
@ SPIDiv32
Definition spi.h:124
@ SPIDiv64
Definition spi.h:125
@ SPIDiv16
Definition spi.h:123
@ SPIDss8bit
Definition spi.h:90
@ SPIDss16bit
Definition spi.h:91
SPI peripheral structure.
Definition spi.h:174
SPI transaction structure.
Definition spi.h:148
static float p[2][2]
#define SPI3_GPIO_PORT_NSS
Definition board.h:473
#define SPI3_GPIO_NSS
uint16_t foo
Definition main_demo5.c:58
static uint32_t idx
Architecture independent SPI (Serial Peripheral Interface) API.
#define TRUE
Definition std.h:4
#define FALSE
Definition std.h:5
static uint8_t get_transaction_signature(struct spi_transaction *t)
Definition spi_arch.c:336
uint32_t dma
DMA controller base address (DMA1 or DMA2)
Definition spi_arch.c:91
uint8_t tx_nvic_irq
transmit interrupt
Definition spi_arch.c:98
static uint8_t get_comm_signature(struct locm3_spi_comm *c)
Definition spi_arch.c:342
static struct spi_periph_dma spi1_dma
Definition spi_arch.c:112
uint16_t rx_dummy_buf
dummy rx buffer for receive only cases
Definition spi_arch.c:101
uint8_t tx_chan
transmit DMA channel (or stream on F4) number
Definition spi_arch.c:94
struct locm3_spi_comm comm
current communication parameters
Definition spi_arch.c:103
static void process_slave_tx_dma_interrupt(struct spi_periph *periph)
SPI_MASTER.
Definition spi_arch.c:1721
uint32_t dff
data frame format 8/16 bits
Definition spi_arch.c:80
static struct spi_periph_dma spi2_dma
Definition spi_arch.c:115
static void spi_arch_int_disable(struct spi_periph *spi)
Disable DMA channel interrupts.
Definition spi_arch.c:510
static void process_slave_rx_dma_interrupt(struct spi_periph *periph)
Definition spi_arch.c:1693
static void process_tx_dma_interrupt(struct spi_periph *periph)
Processing done after tx completes.
Definition spi_arch.c:1139
uint32_t br
baudrate (clock divider)
Definition spi_arch.c:77
uint8_t rx_nvic_irq
receive interrupt
Definition spi_arch.c:97
uint32_t lsbfirst
frame format lsb/msb first
Definition spi_arch.c:81
uint32_t cpol
clock polarity
Definition spi_arch.c:78
static void spi_start_dma_transaction(struct spi_periph *periph, struct spi_transaction *_trans)
Start a new transaction with DMA.
Definition spi_arch.c:539
#define NVIC_SPI_IRQ_PRIO
Definition spi_arch.c:69
uint32_t rx_chan_sel
F4 only: actual receive DMA channel number.
Definition spi_arch.c:95
uint32_t spi
SPI peripheral identifier.
Definition spi_arch.c:89
static void spi_arch_int_enable(struct spi_periph *spi)
Enable DMA channel interrupts.
Definition spi_arch.c:498
static void spi_configure_dma(uint32_t dma, uint32_t rcc_dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr, uint16_t len, enum SPIDataSizeSelect dss, bool increment)
Definition spi_arch.c:458
uint16_t tx_dummy_buf
dummy tx buffer for receive only cases
Definition spi_arch.c:99
static void spi_next_transaction(struct spi_periph *periph)
start next transaction if there is one in the queue
Definition spi_arch.c:517
static void spi_slave_set_config(struct spi_periph *periph, struct spi_transaction *trans)
Definition spi_arch.c:1591
static void SpiSlaveSelect(uint8_t slave)
Definition spi_arch.c:175
bool tx_extra_dummy_dma
extra tx dummy dma flag for tx_len < rx_len
Definition spi_arch.c:100
static void set_default_comm_config(struct locm3_spi_comm *c)
Definition spi_arch.c:327
uint8_t rx_chan
receive DMA channel (or stream on F4) number
Definition spi_arch.c:93
uint8_t comm_sig
comm config signature used to check for changes
Definition spi_arch.c:104
uint32_t spidr
SPI DataRegister address for DMA.
Definition spi_arch.c:90
static void process_rx_dma_interrupt(struct spi_periph *periph)
Processing done after rx completes.
Definition spi_arch.c:1064
uint32_t tx_chan_sel
F4 only: actual transmit DMA channel number.
Definition spi_arch.c:96
uint32_t rcc_dma
RCC DMA enable clock pin (RCC_DMA1 or RCC_DMA2)
Definition spi_arch.c:92
uint32_t cpha
clock phase
Definition spi_arch.c:79
static void set_comm_from_transaction(struct locm3_spi_comm *c, struct spi_transaction *t)
Update SPI communication conf from generic paparazzi SPI transaction.
Definition spi_arch.c:399
static void SpiSlaveUnselect(uint8_t slave)
Definition spi_arch.c:137
bool rx_extra_dummy_dma
extra rx dummy dma flag for tx_len > rx_len
Definition spi_arch.c:102
Libopencm3 specifc communication parameters for a SPI peripheral in master mode.
Definition spi_arch.c:76
This structure keeps track of specific config for each SPI bus, which allows for more code reuse.
Definition spi_arch.c:88
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.