Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
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 
82 };
83 
105 };
106 
107 
108 #if USE_SPI0
109 #error "The STM32 doesn't have SPI0"
110 #endif
111 #if USE_SPI1
112 static struct spi_periph_dma spi1_dma;
113 #endif
114 #if USE_SPI2
115 static struct spi_periph_dma spi2_dma;
116 #endif
117 #if USE_SPI3
118 static struct spi_periph_dma spi3_dma;
119 #endif
120 
121 static void spi_start_dma_transaction(struct spi_periph *periph, struct spi_transaction *_trans);
122 static void spi_next_transaction(struct spi_periph *periph);
123 static void spi_configure_dma(uint32_t dma, uint32_t rcc_dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr,
124  uint16_t len, enum SPIDataSizeSelect dss, bool increment);
125 static void __attribute__((unused)) process_rx_dma_interrupt(struct spi_periph *periph);
126 static void __attribute__((unused)) process_tx_dma_interrupt(struct spi_periph *periph);
127 static void spi_arch_int_enable(struct spi_periph *spi);
128 static void spi_arch_int_disable(struct spi_periph *spi);
129 
130 
131 /******************************************************************************
132  *
133  * Handling of Slave Select outputs
134  *
135  *****************************************************************************/
136 
137 static 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 
175 static 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 
214 {
215  SpiSlaveSelect(slave);
216 }
217 
219 {
220  SpiSlaveUnselect(slave);
221 }
222 
223 void spi_init_slaves(void)
224 {
225 
226 #if USE_SPI_SLAVE0
228  SpiSlaveUnselect(0);
229 #endif
230 
231 #if USE_SPI_SLAVE1
233  SpiSlaveUnselect(1);
234 #endif
235 
236 #if USE_SPI_SLAVE2
238  SpiSlaveUnselect(2);
239 #endif
240 
241 #if USE_SPI_SLAVE3
243  SpiSlaveUnselect(3);
244 #endif
245 
246 #if USE_SPI_SLAVE4
248  SpiSlaveUnselect(4);
249 #endif
250 
251 #if USE_SPI_SLAVE5
253  SpiSlaveUnselect(5);
254 #endif
255 }
256 
257 
258 /******************************************************************************
259  *
260  * Implementation of the generic SPI functions
261  *
262  *****************************************************************************/
263 bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
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 
293 bool spi_lock(struct spi_periph *p, uint8_t slave)
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 
305 bool spi_resume(struct spi_periph *p, uint8_t slave)
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  *****************************************************************************/
327 static void __attribute__((unused)) set_default_comm_config(struct locm3_spi_comm *c)
328 {
329  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_64;
330  c->cpol = SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE;
331  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_2;
332  c->dff = SPI_CR1_DFF_8BIT;
333  c->lsbfirst = SPI_CR1_MSBFIRST;
334 }
335 
337 {
338  return ((t->dss << 6) | (t->cdiv << 3) | (t->bitorder << 2) |
339  (t->cpha << 1) | (t->cpol));
340 }
341 
342 static uint8_t __attribute__((unused)) get_comm_signature(struct locm3_spi_comm *c)
343 {
344  uint8_t sig = 0;
345  if (c->cpol == SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE) {
346  sig |= SPICpolIdleLow;
347  } else {
348  sig |= SPICpolIdleHigh;
349  }
350  if (c->cpha == SPI_CR1_CPHA_CLK_TRANSITION_1) {
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) {
362  case SPI_CR1_BAUDRATE_FPCLK_DIV_2:
363  cdiv = SPIDiv2;
364  break;
365  case SPI_CR1_BAUDRATE_FPCLK_DIV_4:
366  cdiv = SPIDiv4;
367  break;
368  case SPI_CR1_BAUDRATE_FPCLK_DIV_8:
369  cdiv = SPIDiv8;
370  break;
371  case SPI_CR1_BAUDRATE_FPCLK_DIV_16:
372  cdiv = SPIDiv16;
373  break;
374  case SPI_CR1_BAUDRATE_FPCLK_DIV_32:
375  cdiv = SPIDiv32;
376  break;
377  case SPI_CR1_BAUDRATE_FPCLK_DIV_64:
378  cdiv = SPIDiv64;
379  break;
380  case SPI_CR1_BAUDRATE_FPCLK_DIV_128:
381  cdiv = SPIDiv128;
382  break;
383  case SPI_CR1_BAUDRATE_FPCLK_DIV_256:
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) {
402  c->dff = SPI_CR1_DFF_8BIT;
403  } else {
404  c->dff = SPI_CR1_DFF_16BIT;
405  }
406  if (t->bitorder == SPIMSBFirst) {
407  c->lsbfirst = SPI_CR1_MSBFIRST;
408  } else {
409  c->lsbfirst = SPI_CR1_LSBFIRST;
410  }
411  if (t->cpha == SPICphaEdge1) {
412  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_1;
413  } else {
414  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_2;
415  }
416  if (t->cpol == SPICpolIdleLow) {
417  c->cpol = SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE;
418  } else {
419  c->cpol = SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE;
420  }
421 
422  switch (t->cdiv) {
423  case SPIDiv2:
424  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_2;
425  break;
426  case SPIDiv4:
427  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_4;
428  break;
429  case SPIDiv8:
430  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_8;
431  break;
432  case SPIDiv16:
433  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_16;
434  break;
435  case SPIDiv32:
436  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_32;
437  break;
438  case SPIDiv64:
439  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_64;
440  break;
441  case SPIDiv128:
442  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_128;
443  break;
444  case SPIDiv256:
445  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_256;
446  break;
447  default:
448  break;
449  }
450 }
451 
452 
453 /******************************************************************************
454  *
455  * Helpers for SPI transactions with DMA
456  *
457  *****************************************************************************/
458 static void spi_configure_dma(uint32_t dma, uint32_t rcc_dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr,
459  uint16_t len, enum SPIDataSizeSelect dss, bool increment)
460 {
461  rcc_periph_clock_enable(rcc_dma);
462 #ifdef STM32F1
463  dma_channel_reset(dma, chan);
464 #elif defined STM32F4
465  dma_stream_reset(dma, chan);
466 #endif
467  dma_set_peripheral_address(dma, chan, periph_addr);
468  dma_set_memory_address(dma, chan, buf_addr);
469  dma_set_number_of_data(dma, chan, len);
470 
471  /* Set the dma transfer size based on SPI transaction DSS */
472 #ifdef STM32F1
473  if (dss == SPIDss8bit) {
474  dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_8BIT);
475  dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_8BIT);
476  } else {
477  dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_16BIT);
478  dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_16BIT);
479  }
480 #elif defined STM32F4
481  if (dss == SPIDss8bit) {
482  dma_set_peripheral_size(dma, chan, DMA_SxCR_PSIZE_8BIT);
483  dma_set_memory_size(dma, chan, DMA_SxCR_MSIZE_8BIT);
484  } else {
485  dma_set_peripheral_size(dma, chan, DMA_SxCR_PSIZE_16BIT);
486  dma_set_memory_size(dma, chan, DMA_SxCR_MSIZE_16BIT);
487  }
488 #endif
489 
490  if (increment) {
491  dma_enable_memory_increment_mode(dma, chan);
492  } else {
493  dma_disable_memory_increment_mode(dma, chan);
494  }
495 }
496 
498 static void spi_arch_int_enable(struct spi_periph *spi)
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 
510 static void spi_arch_int_disable(struct spi_periph *spi)
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 
517 static 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 
539 static 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  */
553  sig = get_transaction_signature(trans);
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);
565  spi_enable_software_slave_management((uint32_t)periph->reg_addr);
566  spi_set_nss_high((uint32_t)periph->reg_addr);
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) {
574  SpiSlaveSelect(trans->slave_idx);
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);
611  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_VERY_HIGH);
612 #elif defined STM32F4
613  dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
614  dma_set_transfer_mode(dma->dma, dma->rx_chan, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
615  dma_set_priority(dma->dma, dma->rx_chan, DMA_SxCR_PL_VERY_HIGH);
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);
645  dma_set_transfer_mode(dma->dma, dma->tx_chan, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
646  dma_set_priority(dma->dma, dma->tx_chan, DMA_SxCR_PL_MEDIUM);
647 #endif
648 
649  /* Enable DMA transfer complete interrupts. */
650  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
651  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
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 */
663  spi_enable_rx_dma((uint32_t)periph->reg_addr);
664  spi_enable_tx_dma((uint32_t)periph->reg_addr);
665 }
666 
667 
668 
669 /******************************************************************************
670  *
671  * Initialization of each SPI peripheral
672  *
673  *****************************************************************************/
674 #if USE_SPI1
675 void spi1_arch_init(void)
676 {
677 
678  // set dma options
679  spi1_dma.spidr = (uint32_t)&SPI1_DR;
680 #ifdef STM32F1
681  spi1_dma.dma = DMA1;
682  spi1_dma.rcc_dma = RCC_DMA1;
683  spi1_dma.rx_chan = DMA_CHANNEL2;
684  spi1_dma.tx_chan = DMA_CHANNEL3;
685  spi1_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL2_IRQ;
686  spi1_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL3_IRQ;
687 #elif defined STM32F4
688  spi1_dma.dma = DMA2;
689  spi1_dma.rcc_dma = RCC_DMA2;
690  // TODO make a macro to configure this from board/airframe file ?
691  spi1_dma.rx_chan = DMA_STREAM0;
692  spi1_dma.tx_chan = DMA_STREAM5;
693  spi1_dma.rx_chan_sel = DMA_SxCR_CHSEL_3;
694  spi1_dma.tx_chan_sel = DMA_SxCR_CHSEL_3;
695  spi1_dma.rx_nvic_irq = NVIC_DMA2_STREAM0_IRQ;
696  spi1_dma.tx_nvic_irq = NVIC_DMA2_STREAM5_IRQ;
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
716  rcc_periph_clock_enable(RCC_SPI1);
717 
718  // Configure GPIOs: SCK, MISO and MOSI
719 #ifdef STM32F1
720  gpio_setup_pin_af(GPIO_BANK_SPI1_MISO, GPIO_SPI1_MISO, 0, FALSE);
721  gpio_setup_pin_af(GPIO_BANK_SPI1_MOSI, GPIO_SPI1_MOSI, 0, TRUE);
722  gpio_setup_pin_af(GPIO_BANK_SPI1_SCK, GPIO_SPI1_SCK, 0, TRUE);
723 #elif defined STM32F4
727 
728  gpio_set_output_options(SPI1_GPIO_PORT_MOSI, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_GPIO_MOSI);
729  gpio_set_output_options(SPI1_GPIO_PORT_SCK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_GPIO_SCK);
730 #endif
731 
732  // reset SPI
733  spi_reset(SPI1);
734 
735  // Disable SPI peripheral
736  spi_disable(SPI1);
737 
738  // Force SPI mode over I2S.
739  SPI1_I2SCFGR = 0;
740 
741  // configure master SPI.
742  spi_init_master(SPI1, spi1_dma.comm.br, spi1_dma.comm.cpol, spi1_dma.comm.cpha,
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  */
752  spi_enable_software_slave_management(SPI1);
753  spi_set_nss_high(SPI1);
754 
755  // Enable SPI_1 DMA clock
756  rcc_periph_clock_enable(spi1_dma.rcc_dma);
757 
758  // Enable SPI1 periph.
759  spi_enable(SPI1);
760 
762 }
763 #endif
764 
765 #if USE_SPI2
766 void spi2_arch_init(void)
767 {
768 
769  // set dma options
770  spi2_dma.spidr = (uint32_t)&SPI2_DR;
771  spi2_dma.dma = DMA1;
772  spi2_dma.rcc_dma = RCC_DMA1;
773 #ifdef STM32F1
774  spi2_dma.rx_chan = DMA_CHANNEL4;
775  spi2_dma.tx_chan = DMA_CHANNEL5;
776  spi2_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL4_IRQ;
777  spi2_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL5_IRQ;
778 #elif defined STM32F4
779  spi2_dma.rx_chan = DMA_STREAM3;
780  spi2_dma.tx_chan = DMA_STREAM4;
781  spi2_dma.rx_chan_sel = DMA_SxCR_CHSEL_0;
782  spi2_dma.tx_chan_sel = DMA_SxCR_CHSEL_0;
783  spi2_dma.rx_nvic_irq = NVIC_DMA1_STREAM3_IRQ;
784  spi2_dma.tx_nvic_irq = NVIC_DMA1_STREAM4_IRQ;
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
804  rcc_periph_clock_enable(RCC_SPI2);
805 
806  // Configure GPIOs: SCK, MISO and MOSI
807 #ifdef STM32F1
808  gpio_setup_pin_af(GPIO_BANK_SPI2_MISO, GPIO_SPI2_MISO, 0, FALSE);
809  gpio_setup_pin_af(GPIO_BANK_SPI2_MOSI, GPIO_SPI2_MOSI, 0, TRUE);
810  gpio_setup_pin_af(GPIO_BANK_SPI2_SCK, GPIO_SPI2_SCK, 0, TRUE);
811 #elif defined STM32F4
815 
816  gpio_set_output_options(SPI2_GPIO_PORT_MOSI, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI2_GPIO_MOSI);
817  gpio_set_output_options(SPI2_GPIO_PORT_SCK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI2_GPIO_SCK);
818 #endif
819 
820  // reset SPI
821  spi_reset(SPI2);
822 
823  // Disable SPI peripheral
824  spi_disable(SPI2);
825 
826  // Force SPI mode over I2S.
827  SPI2_I2SCFGR = 0;
828 
829  // configure master SPI.
830  spi_init_master(SPI2, spi2_dma.comm.br, spi2_dma.comm.cpol, spi2_dma.comm.cpha,
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  */
839  spi_enable_software_slave_management(SPI2);
840  spi_set_nss_high(SPI2);
841 
842  // Enable SPI_2 DMA clock
843  rcc_periph_clock_enable(spi2_dma.rcc_dma);
844 
845  // Enable SPI2 periph.
846  spi_enable(SPI2);
847 
849 }
850 #endif
851 
852 #if USE_SPI3
853 void 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
881  set_default_comm_config(&spi3_dma.comm);
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
893  rcc_periph_clock_enable(RCC_SPI3);
894 
895  // Configure GPIOs: SCK, MISO and MOSI
896 #ifdef STM32F1
897  gpio_setup_pin_af(GPIO_BANK_SPI3_MISO, GPIO_SPI3_MISO, 0, FALSE);
898  gpio_setup_pin_af(GPIO_BANK_SPI3_MOSI, GPIO_SPI3_MOSI, 0, TRUE);
899  gpio_setup_pin_af(GPIO_BANK_SPI3_SCK, GPIO_SPI3_SCK, 0, TRUE);
900 #elif defined STM32F4
904 
905  gpio_set_output_options(SPI3_GPIO_PORT_MOSI, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI3_GPIO_MOSI);
906  gpio_set_output_options(SPI3_GPIO_PORT_SCK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI3_GPIO_SCK);
907 #endif
908 
910 
911  // reset SPI
912  spi_reset(SPI3);
913 
914  // Disable SPI peripheral
915  spi_disable(SPI3);
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  */
930  spi_enable_software_slave_management(SPI3);
931  spi_set_nss_high(SPI3);
932 
933  // Enable SPI_3 DMA clock
934  rcc_periph_clock_enable(spi3_dma.rcc_dma);
935 
936  // Enable SPI3 periph.
937  spi_enable(SPI3);
938 
939  spi_arch_int_enable(&spi3);
940 }
941 #endif
942 
943 
944 
945 
946 /******************************************************************************
947  *
948  * DMA Interrupt service routines
949  *
950  *****************************************************************************/
951 #ifdef USE_SPI1
952 #ifdef STM32F1
954 void dma1_channel2_isr(void)
955 {
956  if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) {
957  // clear int pending bit
958  DMA1_IFCR |= DMA_IFCR_CTCIF2;
959  }
960 #elif defined STM32F4
961 void dma2_stream0_isr(void) {
962  if ((DMA2_LISR & DMA_LISR_TCIF0) != 0) {
963  // clear int pending bit
964  DMA2_LIFCR |= DMA_LIFCR_CTCIF0;
965  }
966 #endif
968 }
969 
971 #ifdef STM32F1
972 void dma1_channel3_isr(void) {
973  if ((DMA1_ISR & DMA_ISR_TCIF3) != 0) {
974  // clear int pending bit
975  DMA1_IFCR |= DMA_IFCR_CTCIF3;
976  }
977 #elif defined STM32F4
978 void dma2_stream5_isr(void) {
979  if ((DMA2_HISR & DMA_HISR_TCIF5) != 0) {
980  // clear int pending bit
981  DMA2_HIFCR |= DMA_HIFCR_CTCIF5;
982  }
983 #endif
985 }
986 
987 #endif
988 
989 #ifdef USE_SPI2
990 #ifdef STM32F1
992 void dma1_channel4_isr(void) {
993  if ((DMA1_ISR & DMA_ISR_TCIF4) != 0) {
994  // clear int pending bit
995  DMA1_IFCR |= DMA_IFCR_CTCIF4;
996  }
997 #elif defined STM32F4
998 void dma1_stream3_isr(void) {
999  if ((DMA1_LISR & DMA_LISR_TCIF3) != 0) {
1000  // clear int pending bit
1001  DMA1_LIFCR |= DMA_LIFCR_CTCIF3;
1002  }
1003 #endif
1005 }
1006 
1008 #ifdef STM32F1
1009 void dma1_channel5_isr(void) {
1010  if ((DMA1_ISR & DMA_ISR_TCIF5) != 0) {
1011  // clear int pending bit
1012  DMA1_IFCR |= DMA_IFCR_CTCIF5;
1013  }
1014 #elif defined STM32F4
1015 void dma1_stream4_isr(void) {
1016  if ((DMA1_HISR & DMA_HISR_TCIF4) != 0) {
1017  // clear int pending bit
1018  DMA1_HIFCR |= DMA_HIFCR_CTCIF4;
1019  }
1020 #endif
1022 }
1023 
1024 #endif
1025 
1026 #if USE_SPI3
1027 #ifdef STM32F1
1029 void dma2_channel1_isr(void) {
1030  if ((DMA2_ISR & DMA_ISR_TCIF1) != 0) {
1031  // clear int pending bit
1032  DMA2_IFCR |= DMA_IFCR_CTCIF1;
1033  }
1034 #elif defined STM32F4
1035 void dma1_stream0_isr(void) {
1036  if ((DMA1_LISR & DMA_LISR_TCIF0) != 0) {
1037  // clear int pending bit
1038  DMA1_LIFCR |= DMA_LIFCR_CTCIF0;
1039  }
1040 #endif
1041  process_rx_dma_interrupt(&spi3);
1042 }
1043 
1045 #ifdef STM32F1
1046 void dma2_channel2_isr(void) {
1047  if ((DMA2_ISR & DMA_ISR_TCIF2) != 0) {
1048  // clear int pending bit
1049  DMA2_IFCR |= DMA_IFCR_CTCIF2;
1050  }
1051 #elif defined STM32F4
1052 void dma1_stream5_isr(void) {
1053  if ((DMA1_HISR & DMA_HISR_TCIF5) != 0) {
1054  // clear int pending bit
1055  DMA1_HIFCR |= DMA_HIFCR_CTCIF5;
1056  }
1057 #endif
1058  process_tx_dma_interrupt(&spi3);
1059 }
1060 
1061 #endif
1062 
1064 void process_rx_dma_interrupt(struct spi_periph * periph) {
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 */
1069  dma_disable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
1070 
1071  /* Disable SPI Rx request */
1072  spi_disable_rx_dma((uint32_t)periph->reg_addr);
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 */
1093  uint16_t len_remaining = trans->output_length - trans->input_length;
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
1098  dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
1099  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_HIGH);
1100 #elif defined STM32F4
1101  dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
1102  dma_set_transfer_mode(dma->dma, dma->rx_chan, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
1103  dma_set_priority(dma->dma, dma->rx_chan, DMA_SxCR_PL_HIGH);
1104 #endif
1105 
1106  /* Enable DMA transfer complete interrupts. */
1107  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
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 */
1115  spi_enable_rx_dma((uint32_t)periph->reg_addr);
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) {
1131  SpiSlaveUnselect(trans->slave_idx);
1132  }
1133 
1134  spi_next_transaction(periph);
1135  }
1136 }
1137 
1139 void process_tx_dma_interrupt(struct spi_periph * periph) {
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 */
1144  dma_disable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
1145 
1146  /* Disable SPI TX request */
1147  spi_disable_tx_dma((uint32_t)periph->reg_addr);
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 */
1167  uint16_t len_remaining = trans->input_length - trans->output_length;
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
1172  dma_set_read_from_memory(dma->dma, dma->tx_chan);
1173  dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
1174 #elif defined STM32F4
1175  dma_channel_select(dma->dma, dma->tx_chan, dma->tx_chan_sel);
1176  dma_set_transfer_mode(dma->dma, dma->tx_chan, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
1177  dma_set_priority(dma->dma, dma->tx_chan, DMA_SxCR_PL_MEDIUM);
1178 #endif
1179 
1180  /* Enable DMA transfer complete interrupts. */
1181  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
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 */
1189  spi_enable_tx_dma((uint32_t)periph->reg_addr);
1190 
1191  }
1192 }
1193 
1194 #endif
1197 /*
1198  *
1199  * SPI Slave code
1200  * Currently only for F1
1201  *
1202  */
1203 #ifdef SPI_SLAVE
1204 
1205 static void process_slave_tx_dma_interrupt(struct spi_periph * periph);
1206 static 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 
1216 static struct spi_periph_dma spi1_dma;
1217 
1218 void spi1_slave_arch_init(void) {
1219  // set dma options
1220  spi1_dma.spidr = (uint32_t)&SPI1_DR;
1221 #ifdef STM32F1
1222  spi1_dma.dma = DMA1;
1223  spi1_dma.rcc_dma = RCC_DMA1;
1224  spi1_dma.rx_chan = DMA_CHANNEL2;
1225  spi1_dma.tx_chan = DMA_CHANNEL3;
1226  spi1_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL2_IRQ;
1227  spi1_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL3_IRQ;
1228 #elif defined STM32F4
1229  spi1_dma.dma = DMA2;
1230  spi1_dma.rcc_dma = RCC_DMA2;
1231  spi1_dma.rx_chan = DMA_STREAM0;
1232  spi1_dma.tx_chan = DMA_STREAM5;
1233  spi1_dma.rx_chan_sel = DMA_SxCR_CHSEL_3;
1234  spi1_dma.tx_chan_sel = DMA_SxCR_CHSEL_3;
1235  spi1_dma.rx_nvic_irq = NVIC_DMA2_STREAM0_IRQ;
1236  spi1_dma.tx_nvic_irq = NVIC_DMA2_STREAM5_IRQ;
1237 #endif
1238  spi1_dma.tx_dummy_buf = 0;
1239  spi1_dma.tx_extra_dummy_dma = false;
1240  spi1_dma.rx_dummy_buf = 0;
1241  spi1_dma.rx_extra_dummy_dma = false;
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
1255  rcc_periph_clock_enable(RCC_SPI1);
1256 
1257  // Configure GPIOs: SCK, MISO and MOSI
1258 #if defined STM32F1
1259  gpio_setup_pin_af(GPIO_BANK_SPI1_MISO, GPIO_SPI1_MISO, 0, TRUE);
1260  gpio_setup_pin_af(GPIO_BANK_SPI1_MOSI, GPIO_SPI1_MOSI, 0, FALSE);
1261  gpio_setup_pin_af(GPIO_BANK_SPI1_SCK, GPIO_SPI1_SCK, 0, FALSE);
1262  gpio_setup_pin_af(GPIO_BANK_SPI1_NSS, GPIO_SPI1_NSS, 0, FALSE);
1263 #elif defined STM32F4
1268 
1269  gpio_set_output_options(SPI1_GPIO_PORT_MISO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_GPIO_MISO);
1270 #endif
1271 
1272  // reset SPI
1273  spi_reset(SPI1);
1274 
1275  // Disable SPI peripheral
1276  spi_disable(SPI1);
1277 
1278  // Force SPI mode over I2S
1279  SPI1_I2SCFGR = 0;
1280 
1281  // configure default spi settings
1282  spi_init_master(SPI1, spi1_dma.comm.br, spi1_dma.comm.cpol, spi1_dma.comm.cpha,
1284 
1285  // configure slave select management
1286  spi_disable_software_slave_management(SPI1);
1287 
1288  // set slave mode
1289  spi_set_slave_mode(SPI1);
1290 
1291  // Enable SPI_1 DMA clock
1292  rcc_periph_clock_enable(spi1_dma.rcc_dma);
1293 
1294  // Enable SPI1 periph.
1295  spi_enable(SPI1);
1296 }
1297 
1299 #ifdef STM32F1
1300 void dma1_channel2_isr(void) {
1301  if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) {
1302  // clear int pending bit
1303  DMA1_IFCR |= DMA_IFCR_CTCIF2;
1304  }
1305 #elif defined STM32F4
1306 void dma2_stream0_isr(void) {
1307  if ((DMA2_LISR & DMA_LISR_TCIF0) != 0) {
1308  // clear int pending bit
1309  DMA2_LIFCR |= DMA_LIFCR_CTCIF0;
1310  }
1311 #endif
1313 }
1314 
1316 #ifdef STM32F1
1317 void dma1_channel3_isr(void) {
1318  if ((DMA1_ISR & DMA_ISR_TCIF3) != 0) {
1319  // clear int pending bit
1320  DMA1_IFCR |= DMA_IFCR_CTCIF3;
1321  }
1322 #elif defined STM32F4
1323 void dma2_stream5_isr(void) {
1324  if ((DMA2_HISR & DMA_HISR_TCIF5) != 0) {
1325  // clear int pending bit
1326  DMA2_HIFCR |= DMA_HIFCR_CTCIF5;
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 
1344 static struct spi_periph_dma spi2_dma;
1345 
1346 void spi2_slave_arch_init(void) {
1347  // set dma options
1348  spi2_dma.spidr = (uint32_t)&SPI2_DR;
1349  spi2_dma.dma = DMA1;
1350  spi2_dma.rcc_dma = RCC_DMA1;
1351 #ifdef STM32F1
1352  spi2_dma.rx_chan = DMA_CHANNEL4;
1353  spi2_dma.tx_chan = DMA_CHANNEL5;
1354  spi2_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL4_IRQ;
1355  spi2_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL5_IRQ;
1356 #elif defined STM32F4
1357  spi2_dma.rx_chan = DMA_STREAM3;
1358  spi2_dma.tx_chan = DMA_STREAM4;
1359  spi2_dma.rx_chan_sel = DMA_SxCR_CHSEL_0;
1360  spi2_dma.tx_chan_sel = DMA_SxCR_CHSEL_0;
1361  spi2_dma.rx_nvic_irq = NVIC_DMA1_STREAM3_IRQ;
1362  spi2_dma.tx_nvic_irq = NVIC_DMA1_STREAM4_IRQ;
1363 #endif
1364  spi2_dma.tx_dummy_buf = 0;
1365  spi2_dma.tx_extra_dummy_dma = false;
1366  spi2_dma.rx_dummy_buf = 0;
1367  spi2_dma.rx_extra_dummy_dma = false;
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
1381  rcc_periph_clock_enable(RCC_SPI2);
1382 
1383  // Configure GPIOs: SCK, MISO and MOSI
1384 #ifdef STM32F1
1385  gpio_setup_pin_af(GPIO_BANK_SPI2_MISO, GPIO_SPI2_MISO, 0, TRUE);
1386  gpio_setup_pin_af(GPIO_BANK_SPI2_MOSI, GPIO_SPI2_MOSI, 0, FALSE);
1387  gpio_setup_pin_af(GPIO_BANK_SPI2_SCK, GPIO_SPI2_SCK, 0, FALSE);
1388  gpio_setup_pin_af(GPIO_BANK_SPI2_NSS, GPIO_SPI2_NSS, 0, FALSE);
1389 #elif defined STM32F4
1394 
1395  gpio_set_output_options(SPI2_GPIO_PORT_MISO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI2_GPIO_MISO);
1396 #endif
1397 
1398  // reset SPI
1399  spi_reset(SPI2);
1400 
1401  // Disable SPI peripheral
1402  spi_disable(SPI2);
1403 
1404  // Force SPI mode over I2S
1405  SPI2_I2SCFGR = 0;
1406 
1407  // configure default spi settings
1408  spi_init_master(SPI2, spi2_dma.comm.br, spi2_dma.comm.cpol, spi2_dma.comm.cpha,
1410 
1411  // configure slave select management
1412  spi_disable_software_slave_management(SPI2);
1413 
1414  // set slave mode
1415  spi_set_slave_mode(SPI2);
1416 
1417  // Enable SPI_2 DMA clock
1418  rcc_periph_clock_enable(spi2_dma.rcc_dma);
1419 
1420  // Enable SPI2 periph
1421  spi_enable(SPI2);
1422 }
1423 
1425 #ifdef STM32F1
1426 void dma1_channel4_isr(void) {
1427  if ((DMA1_ISR & DMA_ISR_TCIF4) != 0) {
1428  // clear int pending bit
1429  DMA1_IFCR |= DMA_IFCR_CTCIF4;
1430  }
1431 #elif defined STM32F4
1432 void dma1_stream3_isr(void) {
1433  if ((DMA1_LISR & DMA_LISR_TCIF3) != 0) {
1434  // clear int pending bit
1435  DMA1_LIFCR |= DMA_LIFCR_CTCIF3;
1436  }
1437 #endif
1439 }
1440 
1442 #ifdef STM32F1
1443 void dma1_channel5_isr(void) {
1444  if ((DMA1_ISR & DMA_ISR_TCIF5) != 0) {
1445  // clear int pending bit
1446  DMA1_IFCR |= DMA_IFCR_CTCIF5;
1447  }
1448 #elif defined STM32F4
1449 void dma1_stream4_isr(void) {
1450  if ((DMA1_HISR & DMA_HISR_TCIF4) != 0) {
1451  // clear int pending bit
1452  DMA1_HIFCR |= DMA_HIFCR_CTCIF4;
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 
1471 static struct spi_periph_dma spi3_dma;
1472 
1473 void spi3_slave_arch_init(void) {
1474  // set dma options
1475  spi3_dma.spidr = (uint32_t)&SPI3_DR;
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
1499  set_default_comm_config(&spi3_dma.comm);
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
1510  rcc_periph_clock_enable(RCC_SPI3);
1511 
1512  // Configure GPIOs: SCK, MISO and MOSI
1513 #if defined STM32F1
1514  gpio_setup_pin_af(GPIO_BANK_SPI3_MISO, GPIO_SPI3_MISO, 0, TRUE);
1515  gpio_setup_pin_af(GPIO_BANK_SPI3_MOSI, GPIO_SPI3_MOSI, 0, FALSE);
1516  gpio_setup_pin_af(GPIO_BANK_SPI3_SCK, GPIO_SPI3_SCK, 0, FALSE);
1517  // set NSS as input
1518  gpio_setup_pin_af(GPIO_BANK_SPI3_NSS, GPIO_SPI3_NSS, 0, FALSE);
1519 #elif defined STM32F4
1524 
1525  gpio_set_output_options(SPI3_GPIO_PORT_MISO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI3_GPIO_MISO);
1526 #endif
1527 
1528  // reset SPI
1529  spi_reset(SPI3);
1530 
1531  // Disable SPI peripheral
1532  spi_disable(SPI3);
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
1542  spi_disable_software_slave_management(SPI3);
1543 
1544  // set slave mode
1545  spi_set_slave_mode(SPI3);
1546 
1547  // Enable SPI_2 DMA clock
1548  rcc_periph_clock_enable(spi3_dma.rcc_dma);
1549 
1550  // Enable SPI3 periph
1551  spi_enable(SPI3);
1552 }
1553 
1555 #ifdef STM32F1
1556 void dma2_channel1_isr(void) {
1557  if ((DMA2_ISR & DMA_ISR_TCIF1) != 0) {
1558  // clear int pending bit
1559  DMA2_IFCR |= DMA_IFCR_CTCIF1;
1560  }
1561 #elif defined STM32F4
1562 void dma1_stream0_isr(void) {
1563  if ((DMA1_LISR & DMA_LISR_TCIF0) != 0) {
1564  // clear int pending bit
1565  DMA1_LIFCR |= DMA_LIFCR_CTCIF0;
1566  }
1567 #endif
1569 }
1570 
1572 #ifdef STM32F1
1573 void dma2_channel2_isr(void) {
1574  if ((DMA2_ISR & DMA_ISR_TCIF2) != 0) {
1575  // clear int pending bit
1576  DMA2_IFCR |= DMA_IFCR_CTCIF2;
1577  }
1578 #elif defined STM32F4
1579 void dma1_stream5_isr(void) {
1580  if ((DMA1_HISR & DMA_HISR_TCIF5) != 0) {
1581  // clear int pending bit
1582  DMA1_HIFCR |= DMA_HIFCR_CTCIF5;
1583  }
1584 #endif
1586 }
1587 
1588 #endif /* USE_SPI3_SLAVE */
1589 
1590 /****************** General SPI slave Functions ******************/
1591 static 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
1608  spi_disable_software_slave_management((uint32_t)periph->reg_addr);
1609 
1610  // set slave mode
1611  spi_set_slave_mode((uint32_t)periph->reg_addr);
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  */
1624 bool 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 */
1635  uint8_t sig = get_transaction_signature(trans);
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);
1651  dma_set_transfer_mode(dma->dma, dma->tx_chan, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
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);
1663  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_VERY_HIGH);
1664 #elif defined STM32F4
1665  dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
1666  dma_set_transfer_mode(dma->dma, dma->rx_chan, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
1667  dma_set_priority(dma->dma, dma->rx_chan, DMA_SxCR_PL_VERY_HIGH);
1668 #endif
1669 
1670  /* Enable DMA transfer complete interrupts. */
1671  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
1672  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
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 */
1684  spi_enable_tx_dma((uint32_t)periph->reg_addr);
1685  spi_enable_rx_dma((uint32_t)periph->reg_addr);
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 */
1698  dma_disable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
1699 
1700  /* disable dma interrupts */
1701  spi_arch_int_disable(periph);
1702 
1703  /* Disable SPI rx request */
1704  spi_disable_rx_dma((uint32_t)periph->reg_addr);
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 */
1725  dma_disable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
1726 
1727  /* Disable SPI tx request */
1728  spi_disable_tx_dma((uint32_t)periph->reg_addr);
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 */
SPI_SELECT_SLAVE3_PIN
#define SPI_SELECT_SLAVE3_PIN
Definition: board.h:550
SpiSlaveSelect
static void SpiSlaveSelect(uint8_t slave)
Definition: spi_arch.c:175
c
VIC slots used for the LPC2148 define name e g gps UART1_VIC_SLOT e g modem SPI1_VIC_SLOT SPI1 in mcu_periph spi_arch c or spi_slave_hs_arch c(and some others not using the SPI peripheral yet..) I2C0_VIC_SLOT 8 mcu_periph/i2c_arch.c I2C1_VIC_SLOT 9 mcu_periph/i2c_arch.c USB_VIC_SLOT 10 usb
SPIRunning
@ SPIRunning
Definition: spi.h:108
spi_periph_dma::rx_nvic_irq
uint8_t rx_nvic_irq
receive interrupt
Definition: spi_arch.c:97
uint16_t
unsigned short uint16_t
Definition: types.h:16
spi_periph::trans_insert_idx
uint8_t trans_insert_idx
Definition: spi.h:177
spi_transaction::cdiv
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:159
SPI3_GPIO_SCK
#define SPI3_GPIO_SCK
Definition: crazybee_f4_1.0.h:170
spi2_dma
static struct spi_periph_dma spi2_dma
Definition: spi_arch.c:115
spi_periph_dma::tx_extra_dummy_dma
bool tx_extra_dummy_dma
extra tx dummy dma flag for tx_len < rx_len
Definition: spi_arch.c:100
locm3_spi_comm::dff
uint32_t dff
data frame format 8/16 bits
Definition: spi_arch.c:80
SPI3_GPIO_PORT_MISO
#define SPI3_GPIO_PORT_MISO
Definition: crazybee_f4_1.0.h:171
spi_transaction::cpol
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:155
SPITransPending
@ SPITransPending
Definition: spi.h:97
SPI1_GPIO_SCK
#define SPI1_GPIO_SCK
Definition: board.h:537
SPI2_GPIO_AF
#define SPI2_GPIO_AF
Definition: crazybee_f4_1.0.h:154
SPI2_GPIO_PORT_MISO
#define SPI2_GPIO_PORT_MISO
Definition: crazybee_f4_1.0.h:157
SPI1_GPIO_MISO
#define SPI1_GPIO_MISO
Definition: board.h:533
spi_periph_dma::rx_chan_sel
uint32_t rx_chan_sel
F4 only: actual receive DMA channel number.
Definition: spi_arch.c:95
spi_periph_dma::comm
struct locm3_spi_comm comm
current communication parameters
Definition: spi_arch.c:103
process_tx_dma_interrupt
static void process_tx_dma_interrupt(struct spi_periph *periph)
Processing done after tx completes.
Definition: spi_arch.c:1139
spi_transaction::output_length
uint16_t output_length
number of data words to write
Definition: spi.h:152
locm3_spi_comm::lsbfirst
uint32_t lsbfirst
frame format lsb/msb first
Definition: spi_arch.c:81
spi_periph::reg_addr
void * reg_addr
Definition: spi.h:183
locm3_spi_comm
Libopencm3 specifc communication parameters for a SPI peripheral in master mode.
Definition: spi_arch.c:76
spi.h
SPI3_GPIO_MOSI
#define SPI3_GPIO_MOSI
Definition: crazybee_f4_1.0.h:174
spi_transaction
SPI transaction structure.
Definition: spi.h:148
set_comm_from_transaction
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
SPI_SELECT_SLAVE4_PORT
#define SPI_SELECT_SLAVE4_PORT
Definition: board.h:552
gpio_setup_output
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
spi_periph_dma::rx_chan
uint8_t rx_chan
receive DMA channel (or stream on F4) number
Definition: spi_arch.c:93
process_slave_tx_dma_interrupt
static void process_slave_tx_dma_interrupt(struct spi_periph *periph)
SPI_MASTER.
Definition: spi_arch.c:1721
uint32_t
unsigned long uint32_t
Definition: types.h:18
set_default_comm_config
static void set_default_comm_config(struct locm3_spi_comm *c)
Definition: spi_arch.c:327
spi_slave_register
bool spi_slave_register(struct spi_periph *p, struct spi_transaction *t)
Register one (and only one) transaction to use spi as slave.
Definition: spi_arch.c:679
process_slave_rx_dma_interrupt
static void process_slave_rx_dma_interrupt(struct spi_periph *periph)
Definition: spi_arch.c:1693
spi_periph::init_struct
void * init_struct
Definition: spi.h:184
SPI_SELECT_SLAVE3_PORT
#define SPI_SELECT_SLAVE3_PORT
Definition: board.h:549
spi_periph::suspend
volatile uint8_t suspend
control for stop/resume of the fifo
Definition: spi.h:187
process_rx_dma_interrupt
static void process_rx_dma_interrupt(struct spi_periph *periph)
Processing done after rx completes.
Definition: spi_arch.c:1064
SPI3_GPIO_NSS
#define SPI3_GPIO_NSS
Definition: lisa_mx_common.h:307
SPISelectUnselect
@ SPISelectUnselect
slave is selected before transaction and unselected after
Definition: spi.h:63
spi_periph_dma
This structure keeps track of specific config for each SPI bus, which allows for more code reuse.
Definition: spi_arch.c:88
SPITransSuccess
@ SPITransSuccess
Definition: spi.h:99
spi2
process_rx_dma_interrupt & spi2
receive transferred over DMA
Definition: spi_arch.c:1004
SPI2_GPIO_MISO
#define SPI2_GPIO_MISO
Definition: crazybee_f4_1.0.h:158
spi_transaction::bitorder
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:158
SPI_SELECT_SLAVE0_PIN
#define SPI_SELECT_SLAVE0_PIN
Definition: board.h:541
idx
static uint32_t idx
Definition: nps_radio_control_spektrum.c:105
SPI1_GPIO_PORT_MOSI
#define SPI1_GPIO_PORT_MOSI
Definition: board.h:534
spi_periph_dma::tx_chan_sel
uint32_t tx_chan_sel
F4 only: actual transmit DMA channel number.
Definition: spi_arch.c:96
spi_start_dma_transaction
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
SPI3_GPIO_AF
#define SPI3_GPIO_AF
Definition: crazybee_f4_1.0.h:168
spi_transaction::output_buf
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:150
SPI3_GPIO_MISO
#define SPI3_GPIO_MISO
Definition: crazybee_f4_1.0.h:172
spi_periph
SPI peripheral structure.
Definition: spi.h:174
spi_transaction::select
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:154
spi2_arch_init
void spi2_arch_init(void)
Architecture dependent SPI2 initialization.
Definition: spi_arch.c:405
spi_next_transaction
static void spi_next_transaction(struct spi_periph *periph)
start next transaction if there is one in the queue
Definition: spi_arch.c:517
SPICphaEdge1
@ SPICphaEdge1
CPHA = 0.
Definition: spi.h:74
SPIUnselect
@ SPIUnselect
slave is not selected but unselected after transaction
Definition: spi.h:65
gpio_clear
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
Definition: gpio_arch.h:108
SPIDiv4
@ SPIDiv4
Definition: spi.h:121
spi_periph_dma::tx_chan
uint8_t tx_chan
transmit DMA channel (or stream on F4) number
Definition: spi_arch.c:94
SPI_SELECT_SLAVE0_PORT
#define SPI_SELECT_SLAVE0_PORT
Definition: board.h:540
SPIMSBFirst
@ SPIMSBFirst
Definition: spi.h:112
SPICpolIdleLow
@ SPICpolIdleLow
CPOL = 0.
Definition: spi.h:83
SPI_SELECT_SLAVE1_PIN
#define SPI_SELECT_SLAVE1_PIN
Definition: board.h:544
SPI2_GPIO_SCK
#define SPI2_GPIO_SCK
Definition: crazybee_f4_1.0.h:156
get_transaction_signature
static uint8_t get_transaction_signature(struct spi_transaction *t)
Definition: spi_arch.c:336
locm3_spi_comm::cpol
uint32_t cpol
clock polarity
Definition: spi_arch.c:78
spi_transaction::cpha
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:156
spi_transaction::after_cb
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:161
spi_submit
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:511
get_comm_signature
static uint8_t get_comm_signature(struct locm3_spi_comm *c)
Definition: spi_arch.c:342
spi_periph_dma::tx_dummy_buf
uint16_t tx_dummy_buf
dummy tx buffer for receive only cases
Definition: spi_arch.c:99
SPI1_GPIO_PORT_SCK
#define SPI1_GPIO_PORT_SCK
Definition: board.h:536
locm3_spi_comm::br
uint32_t br
baudrate (clock divider)
Definition: spi_arch.c:77
SPI1_GPIO_AF
#define SPI1_GPIO_AF
SPI Config.
Definition: board.h:531
SPITransFailed
@ SPITransFailed
Definition: spi.h:100
spi_resume
bool spi_resume(struct spi_periph *p, uint8_t slave)
spi_resume() function
Definition: spi_arch.c:643
SPI3_GPIO_PORT_NSS
#define SPI3_GPIO_PORT_NSS
Definition: board.h:545
SPIDiv128
@ SPIDiv128
Definition: spi.h:126
SPI_SELECT_SLAVE1_PORT
#define SPI_SELECT_SLAVE1_PORT
Definition: board.h:543
spi_periph_dma::tx_nvic_irq
uint8_t tx_nvic_irq
transmit interrupt
Definition: spi_arch.c:98
spi_slave_unselect
void spi_slave_unselect(uint8_t slave)
spi_slave_unselect() function
Definition: spi_arch.c:586
spi_periph_dma::comm_sig
uint8_t comm_sig
comm config signature used to check for changes
Definition: spi_arch.c:104
spi_periph_dma::spi
uint32_t spi
SPI peripheral identifier.
Definition: spi_arch.c:89
SPICpolIdleHigh
@ SPICpolIdleHigh
CPOL = 1.
Definition: spi.h:84
uint8_t
unsigned char uint8_t
Definition: types.h:14
spi_periph_dma::spidr
uint32_t spidr
SPI DataRegister address for DMA.
Definition: spi_arch.c:90
spi_periph_dma::rcc_dma
uint32_t rcc_dma
RCC DMA enable clock pin (RCC_DMA1 or RCC_DMA2)
Definition: spi_arch.c:92
spi_periph::status
enum SPIStatus status
internal state of the peripheral
Definition: spi.h:180
SPIDss8bit
@ SPIDss8bit
Definition: spi.h:90
spi_periph_dma::rx_extra_dummy_dma
bool rx_extra_dummy_dma
extra rx dummy dma flag for tx_len > rx_len
Definition: spi_arch.c:102
SPI3_GPIO_PORT_SCK
#define SPI3_GPIO_PORT_SCK
Definition: crazybee_f4_1.0.h:169
spi_periph_dma::rx_dummy_buf
uint16_t rx_dummy_buf
dummy rx buffer for receive only cases
Definition: spi_arch.c:101
SPI_SELECT_SLAVE2_PORT
#define SPI_SELECT_SLAVE2_PORT
Definition: board.h:546
SPIDiv32
@ SPIDiv32
Definition: spi.h:124
SPI2_GPIO_PORT_SCK
#define SPI2_GPIO_PORT_SCK
Definition: crazybee_f4_1.0.h:155
SPI1_GPIO_PORT_MISO
#define SPI1_GPIO_PORT_MISO
Definition: board.h:532
gpio_setup_pin_af
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:61
SPIDiv64
@ SPIDiv64
Definition: spi.h:125
NVIC_SPI_IRQ_PRIO
#define NVIC_SPI_IRQ_PRIO
Definition: spi_arch.c:69
spi_slave_select
void spi_slave_select(uint8_t slave)
spi_slave_select() function
Definition: spi_arch.c:544
spi_lock
bool spi_lock(struct spi_periph *p, uint8_t slave)
spi_lock() function
Definition: spi_arch.c:629
SPI2_GPIO_PORT_NSS
#define SPI2_GPIO_PORT_NSS
Definition: elle0_common.h:225
spi_arch_int_disable
static void spi_arch_int_disable(struct spi_periph *spi)
Disable DMA channel interrupts.
Definition: spi_arch.c:510
spi_transaction::input_length
uint16_t input_length
number of data words to read
Definition: spi.h:151
SPI_SELECT_SLAVE2_PIN
#define SPI_SELECT_SLAVE2_PIN
Definition: board.h:547
spi_transaction::dss
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:157
gpio.h
spi_transaction::slave_idx
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:153
SPISelect
@ SPISelect
slave is selected before transaction but not unselected
Definition: spi.h:64
SPITransRunning
@ SPITransRunning
Definition: spi.h:98
spi_transaction::input_buf
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:149
SPILSBFirst
@ SPILSBFirst
Definition: spi.h:113
SPI2_GPIO_MOSI
#define SPI2_GPIO_MOSI
Definition: crazybee_f4_1.0.h:160
SPICphaEdge2
@ SPICphaEdge2
CPHA = 1.
Definition: spi.h:75
SPI_SELECT_SLAVE5_PIN
#define SPI_SELECT_SLAVE5_PIN
Definition: chimera.h:554
spi_arch_int_enable
static void spi_arch_int_enable(struct spi_periph *spi)
Enable DMA channel interrupts.
Definition: spi_arch.c:498
spi_periph::trans_extract_idx
uint8_t trans_extract_idx
Definition: spi.h:178
SPI1_GPIO_NSS
#define SPI1_GPIO_NSS
Definition: elle0_common.h:223
SPI2_GPIO_PORT_MOSI
#define SPI2_GPIO_PORT_MOSI
Definition: crazybee_f4_1.0.h:159
SPI2_GPIO_NSS
#define SPI2_GPIO_NSS
Definition: elle0_common.h:226
SpiSlaveUnselect
static void SpiSlaveUnselect(uint8_t slave)
Definition: spi_arch.c:137
spi_configure_dma
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
SPI_SELECT_SLAVE5_PORT
#define SPI_SELECT_SLAVE5_PORT
Definition: chimera.h:553
spi1
process_rx_dma_interrupt & spi1
receive transferred over DMA
Definition: spi_arch.c:967
SPI_SELECT_SLAVE4_PIN
#define SPI_SELECT_SLAVE4_PIN
Definition: board.h:553
spi_slave_set_config
static void spi_slave_set_config(struct spi_periph *periph, struct spi_transaction *trans)
Definition: spi_arch.c:1591
spi1_arch_init
void spi1_arch_init(void)
Architecture dependent SPI1 initialization.
Definition: spi_arch.c:366
spi_transaction::before_cb
SPICallback before_cb
NULL or function called before the transaction.
Definition: spi.h:160
FALSE
#define FALSE
Definition: std.h:5
SPI1_GPIO_PORT_NSS
#define SPI1_GPIO_PORT_NSS
Definition: elle0_common.h:222
SPIIdle
@ SPIIdle
Definition: spi.h:107
TRUE
#define TRUE
Definition: std.h:4
SPI1_GPIO_MOSI
#define SPI1_GPIO_MOSI
Definition: board.h:535
spi1_dma
static struct spi_periph_dma spi1_dma
Definition: spi_arch.c:112
gpio_set
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
Definition: gpio_arch.h:98
SPIDiv16
@ SPIDiv16
Definition: spi.h:123
SPIDiv256
@ SPIDiv256
Definition: spi.h:127
spi_init_slaves
void spi_init_slaves(void)
spi_init_slaves() function
Definition: spi_arch.c:657
SPI_TRANSACTION_QUEUE_LEN
#define SPI_TRANSACTION_QUEUE_LEN
SPI transaction queue length.
Definition: spi.h:169
spi_transaction::status
enum SPITransactionStatus status
Definition: spi.h:162
SPIDiv2
@ SPIDiv2
Definition: spi.h:120
SPIDss16bit
@ SPIDss16bit
Definition: spi.h:91
p
static float p[2][2]
Definition: ins_alt_float.c:268
spi_periph_dma::dma
uint32_t dma
DMA controller base address (DMA1 or DMA2)
Definition: spi_arch.c:91
SPI3_GPIO_PORT_MOSI
#define SPI3_GPIO_PORT_MOSI
Definition: crazybee_f4_1.0.h:173
SPI1
#define SPI1
Definition: LPC21xx.h:210
locm3_spi_comm::cpha
uint32_t cpha
clock phase
Definition: spi_arch.c:79
SPIDiv8
@ SPIDiv8
Definition: spi.h:122
spi_periph::trans
struct spi_transaction * trans[SPI_TRANSACTION_QUEUE_LEN]
circular buffer holding transactions
Definition: spi.h:176
SPIDataSizeSelect
SPIDataSizeSelect
SPI data word size of transfer.
Definition: spi.h:89