Paparazzi UAS  v5.2.2_stable-0-gd6b9f29
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures 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 
82 };
83 
104 };
105 
106 
107 #if USE_SPI0
108 #error "The STM32 doesn't have SPI0"
109 #endif
110 #if USE_SPI1
111 static struct spi_periph_dma spi1_dma;
112 #endif
113 #if USE_SPI2
114 static struct spi_periph_dma spi2_dma;
115 #endif
116 #if USE_SPI3
117 static struct spi_periph_dma spi3_dma;
118 #endif
119 
120 static void spi_start_dma_transaction(struct spi_periph* periph, struct spi_transaction* _trans);
121 static void spi_next_transaction(struct spi_periph* periph);
122 static void spi_configure_dma(uint32_t dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr,
123  uint16_t len, enum SPIDataSizeSelect dss, bool_t increment);
124 static void process_rx_dma_interrupt(struct spi_periph* periph);
125 static void process_tx_dma_interrupt(struct spi_periph* periph);
126 static void spi_arch_int_enable(struct spi_periph *spi);
127 static void spi_arch_int_disable(struct spi_periph *spi);
128 
129 
130 /******************************************************************************
131  *
132  * Handling of Slave Select outputs
133  *
134  *****************************************************************************/
135 
136 static inline void SpiSlaveUnselect(uint8_t slave) {
137  switch(slave) {
138 #if USE_SPI_SLAVE0
139  case 0:
141  break;
142 #endif // USE_SPI_SLAVE0
143 #if USE_SPI_SLAVE1
144  case 1:
146  break;
147 #endif //USE_SPI_SLAVE1
148 #if USE_SPI_SLAVE2
149  case 2:
151  break;
152 #endif //USE_SPI_SLAVE2
153 #if USE_SPI_SLAVE3
154  case 3:
156  break;
157 #endif //USE_SPI_SLAVE3
158 #if USE_SPI_SLAVE4
159  case 4:
161  break;
162 #endif //USE_SPI_SLAVE4
163 #if USE_SPI_SLAVE5
164  case 5:
166  break;
167 #endif //USE_SPI_SLAVE5
168  default:
169  break;
170  }
171 }
172 
173 static inline void SpiSlaveSelect(uint8_t slave) {
174  switch(slave) {
175 #if USE_SPI_SLAVE0
176  case 0:
178  break;
179 #endif // USE_SPI_SLAVE0
180 #if USE_SPI_SLAVE1
181  case 1:
183  break;
184 #endif //USE_SPI_SLAVE1
185 #if USE_SPI_SLAVE2
186  case 2:
188  break;
189 #endif //USE_SPI_SLAVE2
190 #if USE_SPI_SLAVE3
191  case 3:
193  break;
194 #endif //USE_SPI_SLAVE3
195 #if USE_SPI_SLAVE4
196  case 4:
198  break;
199 #endif //USE_SPI_SLAVE4
200 #if USE_SPI_SLAVE5
201  case 5:
203  break;
204 #endif //USE_SPI_SLAVE5
205  default:
206  break;
207  }
208 }
209 
211  SpiSlaveSelect(slave);
212 }
213 
215  SpiSlaveUnselect(slave);
216 }
217 
218 void spi_init_slaves(void) {
219 
220 #if USE_SPI_SLAVE0
222  SpiSlaveUnselect(0);
223 #endif
224 
225 #if USE_SPI_SLAVE1
227  SpiSlaveUnselect(1);
228 #endif
229 
230 #if USE_SPI_SLAVE2
232  SpiSlaveUnselect(2);
233 #endif
234 
235 #if USE_SPI_SLAVE3
237  SpiSlaveUnselect(3);
238 #endif
239 
240 #if USE_SPI_SLAVE4
242  SpiSlaveUnselect(4);
243 #endif
244 
245 #if USE_SPI_SLAVE5
247  SpiSlaveUnselect(5);
248 #endif
249 }
250 
251 
252 /******************************************************************************
253  *
254  * Implementation of the generic SPI functions
255  *
256  *****************************************************************************/
257 bool_t spi_submit(struct spi_periph* p, struct spi_transaction* t)
258 {
259  uint8_t idx;
260  idx = p->trans_insert_idx + 1;
261  if (idx >= SPI_TRANSACTION_QUEUE_LEN) idx = 0;
262  if ((idx == p->trans_extract_idx) || ((t->input_length == 0) && (t->output_length == 0))) {
263  t->status = SPITransFailed;
264  return FALSE; /* queue full or input_length and output_length both 0 */
265  // TODO can't tell why it failed here if it does
266  }
267 
268  t->status = SPITransPending;
269 
270  //Disable interrupts to avoid race conflict with end of DMA transfer interrupt
271  //FIXME
273 
274  // GT: no copy? There's a queue implying a copy here...
275  p->trans[p->trans_insert_idx] = t;
276  p->trans_insert_idx = idx;
277 
278  /* if peripheral is idle, start the transaction */
279  if (p->status == SPIIdle && !p->suspend) {
281  }
282  //FIXME
284  return TRUE;
285 }
286 
287 bool_t spi_lock(struct spi_periph* p, uint8_t slave) {
289  if (slave < 254 && p->suspend == 0) {
290  p->suspend = slave + 1; // 0 is reserved for unlock state
292  return TRUE;
293  }
295  return FALSE;
296 }
297 
298 bool_t spi_resume(struct spi_periph* p, uint8_t slave) {
300  if (p->suspend == slave + 1) {
301  // restart fifo
302  p->suspend = 0;
303  if (p->trans_extract_idx != p->trans_insert_idx && p->status == SPIIdle) {
305  }
307  return TRUE;
308  }
310  return FALSE;
311 }
312 
313 
314 /******************************************************************************
315  *
316  * Transaction configuration helper functions
317  *
318  *****************************************************************************/
319 static void set_default_comm_config(struct locm3_spi_comm* c) {
320  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_64;
321  c->cpol = SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE;
322  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_2;
323  c->dff = SPI_CR1_DFF_8BIT;
324  c->lsbfirst = SPI_CR1_MSBFIRST;
325 }
326 
328  return ((t->dss << 6) | (t->cdiv << 3) | (t->bitorder << 2) |
329  (t->cpha << 1) | (t->cpol));
330 }
331 
333  uint8_t sig = 0;
334  if (c->cpol == SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE) {
335  sig |= SPICpolIdleLow;
336  } else {
337  sig |= SPICpolIdleHigh;
338  }
339  if (c->cpha == SPI_CR1_CPHA_CLK_TRANSITION_1) {
340  sig |= (SPICphaEdge1 << 1);
341  } else {
342  sig |= (SPICphaEdge2 << 1);
343  }
344  if (c->lsbfirst == SPI_CR1_MSBFIRST) {
345  sig |= (SPIMSBFirst << 2);
346  } else {
347  sig |= (SPILSBFirst << 2);
348  }
349  uint8_t cdiv = SPIDiv256;
350  switch (c->br) {
351  case SPI_CR1_BAUDRATE_FPCLK_DIV_2:
352  cdiv = SPIDiv2;
353  break;
354  case SPI_CR1_BAUDRATE_FPCLK_DIV_4:
355  cdiv = SPIDiv4;
356  break;
357  case SPI_CR1_BAUDRATE_FPCLK_DIV_8:
358  cdiv = SPIDiv8;
359  break;
360  case SPI_CR1_BAUDRATE_FPCLK_DIV_16:
361  cdiv = SPIDiv16;
362  break;
363  case SPI_CR1_BAUDRATE_FPCLK_DIV_32:
364  cdiv = SPIDiv32;
365  break;
366  case SPI_CR1_BAUDRATE_FPCLK_DIV_64:
367  cdiv = SPIDiv64;
368  break;
369  case SPI_CR1_BAUDRATE_FPCLK_DIV_128:
370  cdiv = SPIDiv128;
371  break;
372  case SPI_CR1_BAUDRATE_FPCLK_DIV_256:
373  cdiv = SPIDiv256;
374  break;
375  default:
376  break;
377  }
378  sig |= (cdiv << 3);
379  if (c->dff == SPI_CR1_DFF_8BIT) {
380  sig |= (SPIDss8bit << 6);
381  } else {
382  sig |= (SPIDss16bit << 6);
383  }
384  return sig;
385 }
386 
388 static void set_comm_from_transaction(struct locm3_spi_comm* c, struct spi_transaction* t) {
389  if (t->dss == SPIDss8bit) {
390  c->dff = SPI_CR1_DFF_8BIT;
391  } else {
392  c->dff = SPI_CR1_DFF_16BIT;
393  }
394  if (t->bitorder == SPIMSBFirst) {
395  c->lsbfirst = SPI_CR1_MSBFIRST;
396  } else {
397  c->lsbfirst = SPI_CR1_LSBFIRST;
398  }
399  if (t->cpha == SPICphaEdge1) {
400  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_1;
401  } else {
402  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_2;
403  }
404  if (t->cpol == SPICpolIdleLow) {
405  c->cpol = SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE;
406  } else {
407  c->cpol = SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE;
408  }
409 
410  switch (t->cdiv) {
411  case SPIDiv2:
412  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_2;
413  break;
414  case SPIDiv4:
415  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_4;
416  break;
417  case SPIDiv8:
418  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_8;
419  break;
420  case SPIDiv16:
421  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_16;
422  break;
423  case SPIDiv32:
424  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_32;
425  break;
426  case SPIDiv64:
427  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_64;
428  break;
429  case SPIDiv128:
430  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_128;
431  break;
432  case SPIDiv256:
433  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_256;
434  break;
435  default:
436  break;
437  }
438 }
439 
440 
441 /******************************************************************************
442  *
443  * Helpers for SPI transactions with DMA
444  *
445  *****************************************************************************/
446 static void spi_configure_dma(uint32_t dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr,
447  uint16_t len, enum SPIDataSizeSelect dss, bool_t increment)
448 {
449 #ifdef STM32F1
450  dma_channel_reset(dma, chan);
451 #elif defined STM32F4
452  dma_stream_reset(dma, chan);
453 #endif
454  dma_set_peripheral_address(dma, chan, periph_addr);
455  dma_set_memory_address(dma, chan, buf_addr);
456  dma_set_number_of_data(dma, chan, len);
457 
458  /* Set the dma transfer size based on SPI transaction DSS */
459 #ifdef STM32F1
460  if (dss == SPIDss8bit) {
461  dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_8BIT);
462  dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_8BIT);
463  } else {
464  dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_16BIT);
465  dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_16BIT);
466  }
467 #elif defined STM32F4
468  if (dss == SPIDss8bit) {
469  dma_set_peripheral_size(dma, chan, DMA_SxCR_PSIZE_8BIT);
470  dma_set_memory_size(dma, chan, DMA_SxCR_MSIZE_8BIT);
471  } else {
472  dma_set_peripheral_size(dma, chan, DMA_SxCR_PSIZE_16BIT);
473  dma_set_memory_size(dma, chan, DMA_SxCR_MSIZE_16BIT);
474  }
475 #endif
476 
477  if (increment)
478  dma_enable_memory_increment_mode(dma, chan);
479  else
480  dma_disable_memory_increment_mode(dma, chan);
481 }
482 
484 static void spi_arch_int_enable(struct spi_periph *spi) {
486  // enable receive interrupt
487  nvic_set_priority( ((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq, NVIC_SPI_IRQ_PRIO);
488  nvic_enable_irq( ((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq );
489  // enable transmit interrupt
490  nvic_set_priority( ((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq, NVIC_SPI_IRQ_PRIO);
491  nvic_enable_irq( ((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq );
492 }
493 
495 static void spi_arch_int_disable(struct spi_periph *spi) {
496  nvic_disable_irq( ((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq );
497  nvic_disable_irq( ((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq );
498 }
499 
501 static void spi_next_transaction(struct spi_periph* periph) {
502  /* Increment the transaction to handle */
503  periph->trans_extract_idx++;
504 
505  /* wrap read index of circular buffer */
507  periph->trans_extract_idx = 0;
508 
509  /* Check if there is another pending SPI transaction */
510  if ((periph->trans_extract_idx == periph->trans_insert_idx) || periph->suspend)
511  periph->status = SPIIdle;
512  else
513  spi_start_dma_transaction(periph, periph->trans[periph->trans_extract_idx]);
514 }
515 
516 
520 static void spi_start_dma_transaction(struct spi_periph* periph, struct spi_transaction* trans)
521 {
522  struct spi_periph_dma *dma;
523  uint8_t sig = 0x00;
524 
525  /* Store local copy to notify of the results */
526  trans->status = SPITransRunning;
527  periph->status = SPIRunning;
528 
529  dma = periph->init_struct;
530 
531  /*
532  * Check if we need to reconfigure the spi peripheral for this transaction
533  */
534  sig = get_transaction_signature(trans);
535  if (sig != dma->comm_sig) {
536  /* A different config is required in this transaction... */
537  set_comm_from_transaction(&(dma->comm), trans);
538 
539  /* remember the new conf signature */
540  dma->comm_sig = sig;
541 
542  /* apply the new configuration */
543  spi_disable((uint32_t)periph->reg_addr);
544  spi_init_master((uint32_t)periph->reg_addr, dma->comm.br, dma->comm.cpol,
545  dma->comm.cpha, dma->comm.dff, dma->comm.lsbfirst);
546  spi_enable_software_slave_management((uint32_t)periph->reg_addr);
547  spi_set_nss_high((uint32_t)periph->reg_addr);
548  spi_enable((uint32_t)periph->reg_addr);
549  }
550 
551  /*
552  * Select the slave after reconfiguration of the peripheral
553  */
554  if (trans->select == SPISelectUnselect || trans->select == SPISelect) {
555  SpiSlaveSelect(trans->slave_idx);
556  }
557 
558  /* Run the callback AFTER selecting the slave */
559  if (trans->before_cb != 0) {
560  trans->before_cb(trans);
561  }
562 
563  /*
564  * Receive DMA channel configuration ----------------------------------------
565  *
566  * We always run the receive DMA until the very end!
567  * This is done so we can use the transfer complete interrupt
568  * of the RX DMA to signal the end of the transaction.
569  *
570  * If we want to receive less than we transmit, a dummy buffer
571  * for the rx DMA is used after for the remaining data.
572  *
573  * In the transmit only case (input_length == 0),
574  * the dummy is used right from the start.
575  */
576  if (trans->input_length == 0) {
577  /* run the dummy rx dma for the complete transaction length */
578  spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
579  (uint32_t)&(dma->rx_dummy_buf), trans->output_length, trans->dss, FALSE);
580  } else {
581  /* run the real rx dma for input_length */
582  spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
583  (uint32_t)trans->input_buf, trans->input_length, trans->dss, TRUE);
584  /* use dummy rx dma for the rest */
585  if (trans->output_length > trans->input_length) {
586  /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
587  dma->rx_extra_dummy_dma = TRUE;
588  }
589  }
590 #ifdef STM32F1
591  dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
592  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_VERY_HIGH);
593 #elif defined STM32F4
594  dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
595  dma_set_transfer_mode(dma->dma, dma->rx_chan, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
596  dma_set_priority(dma->dma, dma->rx_chan, DMA_SxCR_PL_VERY_HIGH);
597 #endif
598 
599 
600  /*
601  * Transmit DMA channel configuration ---------------------------------------
602  *
603  * We always run the transmit DMA!
604  * To receive data, the clock must run, so something has to be transmitted.
605  * If needed, use a dummy DMA transmitting zeros for the remaining length.
606  *
607  * In the reveive only case (output_length == 0),
608  * the dummy is used right from the start.
609  */
610  if (trans->output_length == 0) {
611  spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
612  (uint32_t)&(dma->tx_dummy_buf), trans->input_length, trans->dss, FALSE);
613  } else {
614  spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
615  (uint32_t)trans->output_buf, trans->output_length, trans->dss, TRUE);
616  if (trans->input_length > trans->output_length) {
617  /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
618  dma->tx_extra_dummy_dma = TRUE;
619  }
620  }
621 #ifdef STM32F1
622  dma_set_read_from_memory(dma->dma, dma->tx_chan);
623  dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
624 #elif defined STM32F4
625  dma_channel_select(dma->dma, dma->tx_chan, dma->tx_chan_sel);
626  dma_set_transfer_mode(dma->dma, dma->tx_chan, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
627  dma_set_priority(dma->dma, dma->tx_chan, DMA_SxCR_PL_MEDIUM);
628 #endif
629 
630  /* Enable DMA transfer complete interrupts. */
631  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
632  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
633 
634  /* Enable DMA channels */
635 #ifdef STM32F1
636  dma_enable_channel(dma->dma, dma->rx_chan);
637  dma_enable_channel(dma->dma, dma->tx_chan);
638 #elif defined STM32F4
639  dma_enable_stream(dma->dma, dma->rx_chan);
640  dma_enable_stream(dma->dma, dma->tx_chan);
641 #endif
642 
643  /* Enable SPI transfers via DMA */
644  spi_enable_rx_dma((uint32_t)periph->reg_addr);
645  spi_enable_tx_dma((uint32_t)periph->reg_addr);
646 }
647 
648 
649 
650 /******************************************************************************
651  *
652  * Initialization of each SPI peripheral
653  *
654  *****************************************************************************/
655 #if USE_SPI1
656 void spi1_arch_init(void) {
657 
658  // set dma options
659  spi1_dma.spidr = (uint32_t)&SPI1_DR;
660 #ifdef STM32F1
661  spi1_dma.dma = DMA1;
662  spi1_dma.rx_chan = DMA_CHANNEL2;
663  spi1_dma.tx_chan = DMA_CHANNEL3;
664  spi1_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL2_IRQ;
665  spi1_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL3_IRQ;
666 #elif defined STM32F4
667  spi1_dma.dma = DMA2;
668  // TODO make a macro to configure this from board/airframe file ?
669  spi1_dma.rx_chan = DMA_STREAM0;
670  spi1_dma.tx_chan = DMA_STREAM3;
671  spi1_dma.rx_chan_sel = DMA_SxCR_CHSEL_3;
672  spi1_dma.tx_chan_sel = DMA_SxCR_CHSEL_3;
675 #endif
680 
681  // set the default configuration
684 
685  // set init struct, indices and status
686  spi1.reg_addr = (void *)SPI1;
687  spi1.init_struct = &spi1_dma;
688  spi1.trans_insert_idx = 0;
689  spi1.trans_extract_idx = 0;
690  spi1.status = SPIIdle;
691 
692 
693  // Enable SPI1 Periph and gpio clocks
694  rcc_periph_clock_enable(RCC_SPI1);
695 
696  // Configure GPIOs: SCK, MISO and MOSI
697 #ifdef STM32F1
698  // TODO configure lisa board files to use gpio_setup_pin_af function
699  gpio_set_mode(GPIO_BANK_SPI1_SCK, GPIO_MODE_OUTPUT_50_MHZ,
700  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
701  GPIO_SPI1_SCK | GPIO_SPI1_MOSI);
702 
703  gpio_set_mode(GPIO_BANK_SPI1_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
704  GPIO_SPI1_MISO);
705 #elif defined STM32F4
709 
710  gpio_set_output_options(SPI1_GPIO_PORT_MOSI, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_GPIO_MOSI);
711  gpio_set_output_options(SPI1_GPIO_PORT_SCK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_GPIO_SCK);
712 #endif
713 
714  // reset SPI
715  spi_reset(SPI1);
716 
717  // Disable SPI peripheral
718  spi_disable(SPI1);
719 
720  // Force SPI mode over I2S.
721  SPI1_I2SCFGR = 0;
722 
723  // configure master SPI.
724  spi_init_master(SPI1, spi1_dma.comm.br, spi1_dma.comm.cpol, spi1_dma.comm.cpha,
726  /*
727  * Set NSS management to software.
728  *
729  * Note:
730  * Setting nss high is very important, even if we are controlling the GPIO
731  * ourselves this bit needs to be at least set to 1, otherwise the spi
732  * peripheral will not send any data out.
733  */
734  spi_enable_software_slave_management(SPI1);
735  spi_set_nss_high(SPI1);
736 
737  // Enable SPI_1 DMA clock
738 #ifdef STM32F1
739  rcc_periph_clock_enable(RCC_DMA1);
740 #elif defined STM32F4
741  rcc_periph_clock_enable(RCC_DMA2);
742 #endif
743 
744  // Enable SPI1 periph.
745  spi_enable(SPI1);
746 
748 }
749 #endif
750 
751 #if USE_SPI2
752 void spi2_arch_init(void) {
753 
754  // set dma options
755  spi2_dma.spidr = (uint32_t)&SPI2_DR;
756  spi2_dma.dma = DMA1;
757 #ifdef STM32F1
758  spi2_dma.rx_chan = DMA_CHANNEL4;
759  spi2_dma.tx_chan = DMA_CHANNEL5;
760  spi2_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL4_IRQ;
761  spi2_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL5_IRQ;
762 #elif defined STM32F4
763  spi2_dma.rx_chan = DMA_STREAM3;
764  spi2_dma.tx_chan = DMA_STREAM4;
765  spi2_dma.rx_chan_sel = DMA_SxCR_CHSEL_0;
766  spi2_dma.tx_chan_sel = DMA_SxCR_CHSEL_0;
769 #endif
774 
775  // set the default configuration
778 
779  // set init struct, indices and status
780  spi2.reg_addr = (void *)SPI2;
781  spi2.init_struct = &spi2_dma;
782  spi2.trans_insert_idx = 0;
783  spi2.trans_extract_idx = 0;
784  spi2.status = SPIIdle;
785 
786 
787  // Enable SPI2 Periph and gpio clocks
788  rcc_periph_clock_enable(RCC_SPI2);
789 
790  // Configure GPIOs: SCK, MISO and MOSI
791 #ifdef STM32F1
792  // TODO configure lisa board files to use gpio_setup_pin_af function
793  gpio_set_mode(GPIO_BANK_SPI2_SCK, GPIO_MODE_OUTPUT_50_MHZ,
794  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
795  GPIO_SPI2_SCK | GPIO_SPI2_MOSI);
796 
797  gpio_set_mode(GPIO_BANK_SPI2_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
798  GPIO_SPI2_MISO);
799 #elif defined STM32F4
803 
804  gpio_set_output_options(SPI2_GPIO_PORT_MOSI, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI2_GPIO_MOSI);
805  gpio_set_output_options(SPI2_GPIO_PORT_SCK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI2_GPIO_SCK);
806 #endif
807 
808  // reset SPI
809  spi_reset(SPI2);
810 
811  // Disable SPI peripheral
812  spi_disable(SPI2);
813 
814  // Force SPI mode over I2S.
815  SPI2_I2SCFGR = 0;
816 
817  // configure master SPI.
818  spi_init_master(SPI2, spi2_dma.comm.br, spi2_dma.comm.cpol, spi2_dma.comm.cpha,
820 
821  /*
822  * Set NSS management to software.
823  * Setting nss high is very important, even if we are controlling the GPIO
824  * ourselves this bit needs to be at least set to 1, otherwise the spi
825  * peripheral will not send any data out.
826  */
827  spi_enable_software_slave_management(SPI2);
828  spi_set_nss_high(SPI2);
829 
830  // Enable SPI_2 DMA clock
831  rcc_periph_clock_enable(RCC_DMA1);
832 
833  // Enable SPI2 periph.
834  spi_enable(SPI2);
835 
837 }
838 #endif
839 
840 #if USE_SPI3
841 void spi3_arch_init(void) {
842 
843  // set the default configuration
844  spi3_dma.spidr = (uint32_t)&SPI3_DR;
845 #ifdef STM32F1
846  spi3_dma.dma = DMA2;
847  spi3_dma.rx_chan = DMA_CHANNEL1;
848  spi3_dma.tx_chan = DMA_CHANNEL2;
849  spi3_dma.rx_nvic_irq = NVIC_DMA2_CHANNEL1_IRQ;
850  spi3_dma.tx_nvic_irq = NVIC_DMA2_CHANNEL2_IRQ;
851 #elif defined STM32F4
852  spi3_dma.dma = DMA1;
853  spi3_dma.rx_chan = DMA_STREAM0;
854  spi3_dma.tx_chan = DMA_STREAM5;
855  spi3_dma.rx_chan_sel = DMA_SxCR_CHSEL_0;
856  spi3_dma.tx_chan_sel = DMA_SxCR_CHSEL_0;
857  spi3_dma.rx_nvic_irq = NVIC_DMA1_STREAM0_IRQ;
858  spi3_dma.tx_nvic_irq = NVIC_DMA1_STREAM5_IRQ;
859 #endif
860  spi3_dma.tx_dummy_buf = 0;
861  spi3_dma.tx_extra_dummy_dma = FALSE;
862  spi3_dma.rx_dummy_buf = 0;
863  spi3_dma.rx_extra_dummy_dma = FALSE;
864 
865  // set the default configuration
866  set_default_comm_config(&spi3_dma.comm);
867  spi3_dma.comm_sig = get_comm_signature(&spi3_dma.comm);
868 
869  // set init struct, indices and status
870  spi3.reg_addr = (void *)SPI3;
871  spi3.init_struct = &spi3_dma;
872  spi3.trans_insert_idx = 0;
873  spi3.trans_extract_idx = 0;
874  spi3.status = SPIIdle;
875 
876 
877  // Enable SPI3 Periph and gpio clocks
878  rcc_periph_clock_enable(RCC_SPI3);
879 
880  // Configure GPIOs: SCK, MISO and MOSI
881 #ifdef STM32F1
882  // TODO configure lisa board files to use gpio_setup_pin_af function
883  gpio_set_mode(GPIO_BANK_SPI3_SCK, GPIO_MODE_OUTPUT_50_MHZ,
884  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
885  GPIO_SPI3_SCK | GPIO_SPI3_MOSI);
886 
887  gpio_set_mode(GPIO_BANK_SPI3_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
888  GPIO_SPI3_MISO);
889 #elif defined STM32F4
893 
894  gpio_set_output_options(SPI3_GPIO_PORT_MOSI, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI3_GPIO_MOSI);
895  gpio_set_output_options(SPI3_GPIO_PORT_SCK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI3_GPIO_SCK);
896 #endif
897 
899 
900  // reset SPI
901  spi_reset(SPI3);
902 
903  // Disable SPI peripheral
904  spi_disable(SPI3);
905 
906  // Force SPI mode over I2S.
907  SPI3_I2SCFGR = 0;
908 
909  // configure master SPI.
910  spi_init_master(SPI3, spi3_dma.comm.br, spi3_dma.comm.cpol, spi3_dma.comm.cpha,
911  spi3_dma.comm.dff, spi3_dma.comm.lsbfirst);
912 
913  /*
914  * Set NSS management to software.
915  * Setting nss high is very important, even if we are controlling the GPIO
916  * ourselves this bit needs to be at least set to 1, otherwise the spi
917  * peripheral will not send any data out.
918  */
919  spi_enable_software_slave_management(SPI3);
920  spi_set_nss_high(SPI3);
921 
922  // Enable SPI_3 DMA clock
923 #ifdef STM32F1
924  rcc_periph_clock_enable(RCC_DMA2);
925 #elif defined STM32F4
926  rcc_periph_clock_enable(RCC_DMA1);
927 #endif
928 
929  // Enable SPI3 periph.
930  spi_enable(SPI3);
931 
932  spi_arch_int_enable(&spi3);
933 }
934 #endif
935 
936 
937 
938 
939 /******************************************************************************
940  *
941  * DMA Interrupt service routines
942  *
943  *****************************************************************************/
944 #ifdef USE_SPI1
945 #ifdef STM32F1
947 void dma1_channel2_isr(void)
948 {
949  if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) {
950  // clear int pending bit
951  DMA1_IFCR |= DMA_IFCR_CTCIF2;
952  }
953 #elif defined STM32F4
954 void dma2_stream0_isr(void)
955 {
956  if ((DMA2_LISR & DMA_LISR_TCIF0) != 0) {
957  // clear int pending bit
958  DMA2_LIFCR |= DMA_LIFCR_CTCIF0;
959  }
960 #endif
962 }
963 
965 #ifdef STM32F1
966 void dma1_channel3_isr(void)
967 {
968  if ((DMA1_ISR & DMA_ISR_TCIF3) != 0) {
969  // clear int pending bit
970  DMA1_IFCR |= DMA_IFCR_CTCIF3;
971  }
972 #elif defined STM32F4
973 void dma2_stream3_isr(void)
974 {
975  if ((DMA2_LISR & DMA_LISR_TCIF3) != 0) {
976  // clear int pending bit
977  DMA2_LIFCR |= DMA_LIFCR_CTCIF3;
978  }
979 #endif
981 }
982 
983 #endif
984 
985 #ifdef USE_SPI2
986 #ifdef STM32F1
988 void dma1_channel4_isr(void)
989 {
990  if ((DMA1_ISR & DMA_ISR_TCIF4) != 0) {
991  // clear int pending bit
992  DMA1_IFCR |= DMA_IFCR_CTCIF4;
993  }
994 #elif defined STM32F4
995 void dma1_stream3_isr(void)
996 {
997  if ((DMA1_LISR & DMA_LISR_TCIF3) != 0) {
998  // clear int pending bit
999  DMA1_LIFCR |= DMA_LIFCR_CTCIF3;
1000  }
1001 #endif
1003 }
1004 
1006 #ifdef STM32F1
1007 void dma1_channel5_isr(void)
1008 {
1009  if ((DMA1_ISR & DMA_ISR_TCIF5) != 0) {
1010  // clear int pending bit
1011  DMA1_IFCR |= DMA_IFCR_CTCIF5;
1012  }
1013 #elif defined STM32F4
1014 void dma1_stream4_isr(void)
1015 {
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 {
1031  if ((DMA2_ISR & DMA_ISR_TCIF1) != 0) {
1032  // clear int pending bit
1033  DMA2_IFCR |= DMA_IFCR_CTCIF1;
1034  }
1035 #elif defined STM32F4
1036 void dma1_stream0_isr(void)
1037 {
1038  if ((DMA1_LISR & DMA_LISR_TCIF0) != 0) {
1039  // clear int pending bit
1040  DMA1_LIFCR |= DMA_LIFCR_CTCIF0;
1041  }
1042 #endif
1043  process_rx_dma_interrupt(&spi3);
1044 }
1045 
1047 #ifdef STM32F1
1048 void dma2_channel2_isr(void)
1049 {
1050  if ((DMA2_ISR & DMA_ISR_TCIF2) != 0) {
1051  // clear int pending bit
1052  DMA2_IFCR |= DMA_IFCR_CTCIF2;
1053  }
1054 #elif defined STM32F4
1055 void dma1_stream5_isr(void)
1056 {
1057  if ((DMA1_HISR & DMA_HISR_TCIF5) != 0) {
1058  // clear int pending bit
1059  DMA1_HIFCR |= DMA_HIFCR_CTCIF5;
1060  }
1061 #endif
1062  process_tx_dma_interrupt(&spi3);
1063 }
1064 
1065 #endif
1066 
1068 void process_rx_dma_interrupt(struct spi_periph *periph) {
1069  struct spi_periph_dma *dma = periph->init_struct;
1070  struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
1071 
1072  /* Disable DMA Channel */
1073  dma_disable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
1074 
1075  /* Disable SPI Rx request */
1076  spi_disable_rx_dma((uint32_t)periph->reg_addr);
1077 
1078  /* Disable DMA rx channel */
1079 #ifdef STM32F1
1080  dma_disable_channel(dma->dma, dma->rx_chan);
1081 #elif defined STM32F4
1082  dma_disable_stream(dma->dma, dma->rx_chan);
1083 #endif
1084 
1085 
1086  if (dma->rx_extra_dummy_dma) {
1087  /*
1088  * We are finished the first part of the receive with real data,
1089  * but still need to run the dummy to get a transfer complete interrupt
1090  * after the complete transaction is done.
1091  */
1092 
1093  /* Reset the flag so this only happens once in a transaction */
1094  dma->rx_extra_dummy_dma = FALSE;
1095 
1096  /* Use the difference in length between rx and tx */
1097  uint16_t len_remaining = trans->output_length - trans->input_length;
1098 
1099  spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
1100  (uint32_t)&(dma->rx_dummy_buf), len_remaining, trans->dss, FALSE);
1101 #ifdef STM32F1
1102  dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
1103  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_HIGH);
1104 #elif defined STM32F4
1105  dma_channel_select(dma->dma, dma->rx_chan, dma->rx_chan_sel);
1106  dma_set_transfer_mode(dma->dma, dma->rx_chan, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
1107  dma_set_priority(dma->dma, dma->rx_chan, DMA_SxCR_PL_HIGH);
1108 #endif
1109 
1110  /* Enable DMA transfer complete interrupts. */
1111  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
1112  /* Enable DMA channels */
1113 #ifdef STM32F1
1114  dma_enable_channel(dma->dma, dma->rx_chan);
1115 #elif defined STM32F4
1116  dma_enable_stream(dma->dma, dma->rx_chan);
1117 #endif
1118  /* Enable SPI transfers via DMA */
1119  spi_enable_rx_dma((uint32_t)periph->reg_addr);
1120  }
1121  else {
1122  /*
1123  * Since the receive DMA is always run until the very end
1124  * and this interrupt is triggered after the last data word was read,
1125  * we now know that this transaction is finished.
1126  */
1127 
1128  /* Run the callback */
1129  trans->status = SPITransSuccess;
1130  if (trans->after_cb != 0) {
1131  trans->after_cb(trans);
1132  }
1133 
1134  /* AFTER the callback, then unselect the slave if required */
1135  if (trans->select == SPISelectUnselect || trans->select == SPIUnselect) {
1136  SpiSlaveUnselect(trans->slave_idx);
1137  }
1138 
1139  spi_next_transaction(periph);
1140  }
1141 }
1142 
1144 void process_tx_dma_interrupt(struct spi_periph *periph) {
1145  struct spi_periph_dma *dma = periph->init_struct;
1146  struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
1147 
1148  /* Disable DMA Channel */
1149  dma_disable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
1150 
1151  /* Disable SPI TX request */
1152  spi_disable_tx_dma((uint32_t)periph->reg_addr);
1153 
1154  /* Disable DMA tx channel */
1155 #ifdef STM32F1
1156  dma_disable_channel(dma->dma, dma->tx_chan);
1157 #elif defined STM32F4
1158  dma_disable_stream(dma->dma, dma->tx_chan);
1159 #endif
1160 
1161  if (dma->tx_extra_dummy_dma) {
1162  /*
1163  * We are finished the first part of the transmit with real data,
1164  * but still need to clock in the rest of the receive data.
1165  * Set up a dummy dma transmit transfer to accomplish this.
1166  */
1167 
1168  /* Reset the flag so this only happens once in a transaction */
1169  dma->tx_extra_dummy_dma = FALSE;
1170 
1171  /* Use the difference in length between tx and rx */
1172  uint16_t len_remaining = trans->input_length - trans->output_length;
1173 
1174  spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
1175  (uint32_t)&(dma->tx_dummy_buf), len_remaining, trans->dss, FALSE);
1176 #ifdef STM32F1
1177  dma_set_read_from_memory(dma->dma, dma->tx_chan);
1178  dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
1179 #elif defined STM32F4
1180  dma_channel_select(dma->dma, dma->tx_chan, dma->tx_chan_sel);
1181  dma_set_transfer_mode(dma->dma, dma->tx_chan, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
1182  dma_set_priority(dma->dma, dma->tx_chan, DMA_SxCR_PL_MEDIUM);
1183 #endif
1184 
1185  /* Enable DMA transfer complete interrupts. */
1186  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
1187  /* Enable DMA channels */
1188 #ifdef STM32F1
1189  dma_enable_channel(dma->dma, dma->tx_chan);
1190 #elif defined STM32F4
1191  dma_enable_stream(dma->dma, dma->tx_chan);
1192 #endif
1193  /* Enable SPI transfers via DMA */
1194  spi_enable_tx_dma((uint32_t)periph->reg_addr);
1195 
1196  }
1197 }
1198 
1199 #endif
1202 /*
1203  *
1204  * SPI Slave code
1205  * Currently only for F1, SPI1
1206  *
1207  */
1208 #ifdef SPI_SLAVE
1209 
1210 static void process_slave_rx_dma_interrupt(struct spi_periph* periph);
1211 
1212 
1213 // SPI arch slave init
1214 #if USE_SPI1_SLAVE
1215 #warning "SPI1 slave: Untested code!"
1216 
1217 #ifndef STM32F1
1218 #error "SPI1 slave on STM32 only implemented for STM32F1"
1219 #endif
1220 
1221 #if USE_SPI1
1222 #error "Using SPI1 as a slave and master at the same time is not possible."
1223 #endif
1224 
1225 static struct spi_periph_dma spi1_dma;
1226 
1227 void spi1_slave_arch_init(void) {
1228  // set dma options
1229  spi1_dma.spidr = (uint32_t)&SPI1_DR;
1230  spi1_dma.dma = DMA1;
1231  spi1_dma.rx_chan = DMA_CHANNEL2;
1232  spi1_dma.tx_chan = DMA_CHANNEL3;
1233  spi1_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL2_IRQ;
1234  spi1_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL3_IRQ;
1235  spi1_dma.tx_dummy_buf = 0;
1237  spi1_dma.rx_dummy_buf = 0;
1239 
1240  // set the default configuration
1243 
1244  // set init struct, indices and status
1245  spi1.reg_addr = (void *)SPI1;
1246  spi1.init_struct = &spi1_dma;
1247  spi1.trans_insert_idx = 0;
1248  spi1.trans_extract_idx = 0;
1249  spi1.status = SPIIdle;
1250 
1251  // Enable SPI1 Periph and gpio clocks
1252  rcc_periph_clock_enable(RCC_SPI1);
1253 
1254  // Configure GPIOs: SCK, MISO and MOSI
1255  // TODO configure lisa board files to use gpio_setup_pin_af function
1256  gpio_set_mode(GPIO_BANK_SPI1_SCK, GPIO_MODE_INPUT,
1257  GPIO_CNF_INPUT_FLOAT,
1258  GPIO_SPI1_SCK | GPIO_SPI1_MOSI);
1259 
1260  gpio_set_mode(GPIO_BANK_SPI1_MISO, GPIO_MODE_OUTPUT_50_MHZ,
1261  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
1262  GPIO_SPI1_MISO);
1263 
1264  gpio_set_mode(GPIO_BANK_SPI1_NSS, GPIO_MODE_INPUT,
1265  GPIO_CNF_INPUT_FLOAT,
1266  GPIO_SPI1_NSS);
1267 
1268  // reset SPI
1269  spi_reset(SPI1);
1270 
1271  // Disable SPI peripheral
1272  spi_disable(SPI1);
1273 
1274  // Force SPI mode over I2S.
1275  SPI1_I2SCFGR = 0;
1276 
1277  // configure master SPI.
1278  spi_init_master(SPI1, spi1_dma.comm.br, spi1_dma.comm.cpol, spi1_dma.comm.cpha,
1280 
1281  spi_disable_software_slave_management(SPI1);
1282 
1283  spi_set_slave_mode(SPI1);
1284 
1285  // Enable SPI_1 DMA clock
1286 #ifdef STM32F1
1287  rcc_periph_clock_enable(RCC_DMA1);
1288 #elif defined STM32F4
1289  rcc_periph_clock_enable(RCC_DMA2);
1290 #endif
1291 
1292  // Enable SPI1 periph.
1293  spi_enable(SPI1);
1294 
1296 }
1297 
1299 void dma1_channel2_isr(void)
1300 {
1301  if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) {
1302  // clear int pending bit
1303  DMA1_IFCR |= DMA_IFCR_CTCIF2;
1304  }
1306 }
1307 
1308 
1309 #endif /* USE_SPI1_SLAVE */
1310 
1311 
1312 static void spi_slave_set_config(struct spi_periph* periph, struct spi_transaction* trans)
1313 {
1314  struct spi_periph_dma *dma;
1315 
1316  dma = periph->init_struct;
1317 
1318  set_comm_from_transaction(&(dma->comm), trans);
1319 
1320  /* remember the new conf signature */
1321  //dma->comm_sig = sig;
1322 
1323  /* apply the new configuration */
1324  spi_disable((uint32_t)periph->reg_addr);
1325  spi_init_master((uint32_t)periph->reg_addr, dma->comm.br, dma->comm.cpol,
1326  dma->comm.cpha, dma->comm.dff, dma->comm.lsbfirst);
1327  spi_disable_software_slave_management((uint32_t)periph->reg_addr);
1328  spi_set_slave_mode((uint32_t)periph->reg_addr);
1329  spi_enable((uint32_t)periph->reg_addr);
1330 }
1331 
1332 
1333 
1334 //static void spi_start_slave_dma_transaction(struct spi_periph* periph, struct spi_transaction* trans)
1335 bool_t spi_slave_register(struct spi_periph* periph, struct spi_transaction* trans)
1336 {
1337  spi_slave_set_config(periph, trans);
1338 
1339  struct spi_periph_dma *dma;
1340  uint8_t sig = 0x00;
1341 
1342  /* Store local copy to notify of the results */
1343  trans->status = SPITransRunning;
1344  periph->status = SPIRunning;
1345 
1346  periph->trans_insert_idx = 0;
1347  periph->trans[periph->trans_insert_idx] = trans;
1348 
1349  dma = periph->init_struct;
1350 
1351  /*
1352  * Receive DMA channel configuration ----------------------------------------
1353  */
1354  spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
1355  (uint32_t)trans->input_buf, trans->input_length, trans->dss, TRUE);
1356 
1357  dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
1358  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_VERY_HIGH);
1359 
1360 
1361  /*
1362  * Transmit DMA channel configuration ---------------------------------------
1363  */
1364  spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
1365  (uint32_t)trans->output_buf, trans->output_length, trans->dss, TRUE);
1366 
1367  dma_set_read_from_memory(dma->dma, dma->tx_chan);
1368  dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
1369 
1370  /* Enable DMA transfer complete interrupts. */
1371  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
1372 
1373  /* Enable DMA channels */
1374  dma_enable_channel(dma->dma, dma->rx_chan);
1375  dma_enable_channel(dma->dma, dma->tx_chan);
1376 
1377  /* Enable SPI transfers via DMA */
1378  spi_enable_rx_dma((uint32_t)periph->reg_addr);
1379  spi_enable_tx_dma((uint32_t)periph->reg_addr);
1380 
1381  return TRUE;
1382 }
1383 
1385  struct spi_periph_dma *dma = periph->init_struct;
1386  struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
1387 
1388  /* Disable DMA Channel */
1389  dma_disable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
1390 
1391  /* Disable SPI Rx request */
1392  spi_disable_rx_dma((uint32_t)periph->reg_addr);
1393 
1394  /* Disable DMA rx channel */
1395  dma_disable_channel(dma->dma, dma->rx_chan);
1396 
1397  /* Run the callback */
1398  trans->status = SPITransSuccess;
1399  //return;
1400  if (trans->after_cb != 0) {
1401  trans->after_cb(trans);
1402  }
1403 
1404  /*dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
1405  dma_enable_channel(dma->dma, dma->rx_chan);
1406  spi_enable_rx_dma((uint32_t)periph->reg_addr);*/
1407 }
1408 
1409 
1410 // Slave Select / NSS pin GPIO config
1411 
1412 
1413 // DMA config?
1414 
1415 
1416 // SPI transaction handling
1417 
1418 #endif /* SPI_SLAVE */
uint32_t br
baudrate (clock divider)
Definition: spi_arch.c:77
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:152
#define NVIC_DMA2_STREAM0_IRQ
unsigned short uint16_t
Definition: types.h:16
uint16_t tx_dummy_buf
dummy tx buffer for receive only cases
Definition: spi_arch.c:98
uint32_t spidr
SPI DataRegister address for DMA.
Definition: spi_arch.c:90
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:149
#define SPI2_GPIO_MOSI
Definition: krooz_sd.h:112
Definition: spi.h:118
#define SPI3_GPIO_MISO
Definition: px4fmu_1.7.h:73
uint8_t tx_nvic_irq
transmit interrupt
Definition: spi_arch.c:97
static struct spi_periph_dma spi2_dma
Definition: spi_arch.c:114
static void process_tx_dma_interrupt(struct spi_periph *periph)
Processing done after tx completes.
Definition: spi_arch.c:1144
bool_t spi_lock(struct spi_periph *p, uint8_t slave)
Lock the SPI fifo.
Definition: spi_arch.c:536
uint8_t input_length
number of data words to read
Definition: spi.h:145
SPIDataSizeSelect
SPI data word size of transfer.
Definition: spi.h:83
process_rx_dma_interrupt & spi2
receive transferred over DMA
Definition: spi_arch.c:1002
static void spi_arch_int_disable(struct spi_periph *spi)
Disable DMA channel interrupts.
Definition: spi_arch.c:495
slave is selected before transaction but not unselected
Definition: spi.h:58
void spi1_arch_init(void)
Architecture dependant SPI1 initialization.
Definition: spi_arch.c:445
slave is not selected but unselected after transaction
Definition: spi.h:59
#define SPI_SELECT_SLAVE5_PORT
Definition: lisa_m_common.h:21
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:150
CPHA = 1.
Definition: spi.h:69
#define NVIC_DMA1_STREAM3_IRQ
#define SPI3_GPIO_PORT_MOSI
Definition: px4fmu_1.7.h:74
#define SPI3_GPIO_PORT_SCK
Definition: px4fmu_1.7.h:76
Some architecture independent helper functions for GPIOs.
void gpio_set(uint32_t port, uint16_t pin)
Set a gpio output to high level.
#define SPI_SELECT_SLAVE0_PORT
Definition: apogee_0.99.h:70
Definition: spi.h:115
This structure keeps track of specific config for each SPI bus, which allows for more code reuse...
Definition: spi_arch.c:88
CM3_WEAK dma1_stream0_isr(void)
void * reg_addr
Definition: spi.h:177
uint8_t rx_nvic_irq
receive interrupt
Definition: spi_arch.c:96
uint16_t rx_dummy_buf
dummy rx buffer for receive only cases
Definition: spi_arch.c:100
#define SPI1_GPIO_AF
Definition: apogee_0.99.h:62
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:143
CPOL = 1.
Definition: spi.h:78
void * init_struct
Definition: spi.h:178
static void spi_configure_dma(uint32_t dma, uint8_t chan, uint32_t periph_addr, uint32_t buf_addr, uint16_t len, enum SPIDataSizeSelect dss, bool_t increment)
Definition: spi_arch.c:446
uint32_t cpha
clock phase
Definition: spi_arch.c:79
#define SPI_SELECT_SLAVE3_PORT
Definition: lisa_l_1.0.h:27
static struct spi_periph_dma spi1_dma
Definition: spi_arch.c:111
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
static void spi_start_dma_transaction(struct spi_periph *periph, struct spi_transaction *_trans)
Start a new transaction with DMA.
Definition: spi_arch.c:520
#define SPI_SELECT_SLAVE3_PIN
Definition: lisa_l_1.0.h:28
uint8_t tx_chan
transmit DMA channel (or stream on F4) number
Definition: spi_arch.c:93
#define FALSE
Definition: imu_chimu.h:141
enum SPITransactionStatus status
Definition: spi.h:156
Architecture independent SPI (Serial Peripheral Interface) API.
#define SPI_SELECT_SLAVE2_PIN
Definition: apogee_0.99.h:137
Definition: spi.h:114
enum SPIStatus status
internal state of the peripheral
Definition: spi.h:174
#define SPI3_GPIO_AF
Definition: px4fmu_1.7.h:71
static void SpiSlaveSelect(uint8_t slave)
Definition: spi_arch.c:173
#define SPI1_GPIO_PORT_MISO
Definition: apogee_0.99.h:63
Definition: spi.h:84
#define SPI2_GPIO_PORT_MOSI
Definition: krooz_sd.h:111
void spi_slave_unselect(uint8_t slave)
Unselect a slave.
Definition: spi_arch.c:532
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:153
bool_t spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit a spi transaction.
Definition: spi_arch.c:470
uint8_t comm_sig
comm config signature used to check for changes
Definition: spi_arch.c:103
#define SPI1_GPIO_PORT_SCK
Definition: apogee_0.99.h:67
uint32_t rx_chan_sel
F4 only: actual receive DMA channel number.
Definition: spi_arch.c:94
static uint8_t get_transaction_signature(struct spi_transaction *t)
Definition: spi_arch.c:327
#define SPI_SELECT_SLAVE0_PIN
Definition: apogee_0.99.h:71
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
unsigned long uint32_t
Definition: types.h:18
void spi2_arch_init(void)
Architecture dependant SPI2 initialization.
Definition: spi_arch.c:752
uint8_t output_length
number of data words to write
Definition: spi.h:146
#define SPI3_GPIO_SCK
Definition: px4fmu_1.7.h:77
struct spi_transaction * trans[SPI_TRANSACTION_QUEUE_LEN]
circular buffer holding transactions
Definition: spi.h:170
uint32_t dff
data frame format 8/16 bits
Definition: spi_arch.c:80
Libopencm3 specifc communication parameters for a SPI peripheral in master mode.
Definition: spi_arch.c:76
CM3_WEAK dma1_stream3_isr(void)
#define SPI2_GPIO_PORT_SCK
Definition: krooz_sd.h:113
uint32_t spi
SPI peripheral identifier.
Definition: spi_arch.c:89
struct locm3_spi_comm comm
current communication paramters
Definition: spi_arch.c:102
CM3_WEAK dma2_stream3_isr(void)
CPOL = 0.
Definition: spi.h:77
#define SPI1_GPIO_MOSI
Definition: apogee_0.99.h:66
uint8_t rx_chan
receive DMA channel (or stream on F4) number
Definition: spi_arch.c:92
#define SPI1_GPIO_SCK
Definition: apogee_0.99.h:68
void gpio_clear(uint32_t port, uint16_t pin)
Clear a gpio output to low level.
#define TRUE
Definition: imu_chimu.h:144
void gpio_setup_pin_af(uint32_t port, uint16_t pin, uint8_t af, bool_t is_output)
Setup a gpio for input or output with alternate function.
uint32_t cpol
clock polarity
Definition: spi_arch.c:78
#define SPI2_GPIO_MISO
Definition: krooz_sd.h:110
#define NVIC_DMA1_STREAM4_IRQ
SPI peripheral structure.
Definition: spi.h:168
volatile uint8_t suspend
control for stop/resume of the fifo
Definition: spi.h:181
static void SpiSlaveUnselect(uint8_t slave)
Definition: spi_arch.c:136
#define NVIC_SPI_IRQ_PRIO
Definition: spi_arch.c:69
uint32_t dma
DMA controller base address (DMA1 or DMA2)
Definition: spi_arch.c:91
#define SPI3_GPIO_MOSI
Definition: px4fmu_1.7.h:75
#define SPI_SELECT_SLAVE4_PIN
Definition: lisa_l_1.0.h:31
bool_t 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:648
#define SPI_SELECT_SLAVE5_PIN
Definition: lisa_m_common.h:22
uint32_t lsbfirst
frame format lsb/msb first
Definition: spi_arch.c:81
unsigned char uint8_t
Definition: types.h:14
static void spi_slave_set_config(struct spi_periph *periph, struct spi_transaction *trans)
Definition: spi_arch.c:1312
static void gpio_setup_output(uint32_t port, uint32_t gpios)
Setup one or more pins of the given GPIO port as outputs.
Definition: gpio_arch.h:76
#define SPI3_GPIO_PORT_MISO
Definition: px4fmu_1.7.h:72
Definition: spi.h:101
#define SPI_SELECT_SLAVE2_PORT
Definition: apogee_0.99.h:136
CPHA = 0.
Definition: spi.h:68
Definition: spi.h:117
Definition: spi.h:121
#define SPI_SELECT_SLAVE1_PIN
Definition: booz_1.0.h:126
slave is selected before transaction and unselected after
Definition: spi.h:57
#define SPI2_GPIO_SCK
Definition: krooz_sd.h:114
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:147
#define NVIC_DMA1_STREAM0_IRQ
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:388
CM3_WEAK dma2_stream0_isr(void)
#define NVIC_DMA1_STREAM5_IRQ
#define SPI2_GPIO_PORT_MISO
Definition: krooz_sd.h:109
Definition: spi.h:119
static float p[2][2]
bool_t spi_resume(struct spi_periph *p, uint8_t slave)
Resume the SPI fifo.
Definition: spi_arch.c:548
Definition: spi.h:116
uint8_t trans_extract_idx
Definition: spi.h:172
static void set_default_comm_config(struct locm3_spi_comm *c)
Definition: spi_arch.c:319
#define SPI1
Definition: LPC21xx.h:210
#define SPI_SELECT_SLAVE4_PORT
Definition: lisa_l_1.0.h:30
#define SPI1_GPIO_PORT_MOSI
Definition: apogee_0.99.h:65
CM3_WEAK dma1_stream4_isr(void)
static void process_slave_rx_dma_interrupt(struct spi_periph *periph)
SPI_MASTER.
Definition: spi_arch.c:1384
SPI transaction structure.
Definition: spi.h:142
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
#define SPI_TRANSACTION_QUEUE_LEN
SPI transaction queue length.
Definition: spi.h:163
static uint8_t get_comm_signature(struct locm3_spi_comm *c)
Definition: spi_arch.c:332
static void process_rx_dma_interrupt(struct spi_periph *periph)
Processing done after rx completes.
Definition: spi_arch.c:1068
SPICallback before_cb
NULL or function called before the transaction.
Definition: spi.h:154
#define SPI2_GPIO_AF
Definition: krooz_sd.h:108
void spi_init_slaves(void)
Initialize all used slaves and uselect them.
Definition: spi_arch.c:504
void spi_slave_select(uint8_t slave)
Select a slave.
Definition: spi_arch.c:528
bool_t tx_extra_dummy_dma
extra tx dummy dma flag for tx_len < rx_len
Definition: spi_arch.c:99
uint8_t trans_insert_idx
Definition: spi.h:171
uint32_t tx_chan_sel
F4 only: actual transmit DMA channel number.
Definition: spi_arch.c:95
process_rx_dma_interrupt & spi1
receive transferred over DMA
Definition: spi_arch.c:961
Definition: spi.h:120
#define NVIC_DMA2_STREAM3_IRQ
CM3_WEAK dma1_stream5_isr(void)
bool_t rx_extra_dummy_dma
extra rx dummy dma flag for tx_len > rx_len
Definition: spi_arch.c:101
static void spi_arch_int_enable(struct spi_periph *spi)
Enable DMA channel interrupts.
Definition: spi_arch.c:484
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:155
#define SPI1_GPIO_MISO
Definition: apogee_0.99.h:64
#define SPI_SELECT_SLAVE1_PORT
Definition: booz_1.0.h:125
static void spi_next_transaction(struct spi_periph *periph)
start next transaction if there is one in the queue
Definition: spi_arch.c:501