Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
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 
72  u32 br;
73  u32 cpol;
74  u32 cpha;
75  u32 dff;
76  u32 lsbfirst;
77 };
78 
84  u32 spi;
85  u32 spidr;
86  u32 dma;
87  u8 rx_chan;
88  u8 tx_chan;
96  u8 comm_sig;
97 };
98 
99 
100 #if USE_SPI0
101 #error "The STM32 doesn't have SPI0"
102 #endif
103 #if USE_SPI1
104 static struct spi_periph_dma spi1_dma;
105 #endif
106 #if USE_SPI2
107 static struct spi_periph_dma spi2_dma;
108 #endif
109 #if USE_SPI3
110 static struct spi_periph_dma spi3_dma;
111 #endif
112 
113 static void spi_start_dma_transaction(struct spi_periph* periph, struct spi_transaction* _trans);
114 static void spi_next_transaction(struct spi_periph* periph);
115 static void spi_configure_dma(u32 dma, u8 chan, u32 periph_addr, u32 buf_addr,
116  u16 len, enum SPIDataSizeSelect dss, bool_t increment);
117 static void process_rx_dma_interrupt(struct spi_periph* periph);
118 static void process_tx_dma_interrupt(struct spi_periph* periph);
119 static void spi_arch_int_enable(struct spi_periph *spi);
120 static void spi_arch_int_disable(struct spi_periph *spi);
121 
122 
123 /******************************************************************************
124  *
125  * Handling of Slave Select outputs
126  *
127  *****************************************************************************/
128 
129 static inline void SpiSlaveUnselect(uint8_t slave) {
130  switch(slave) {
131 #if USE_SPI_SLAVE0
132  case 0:
134  break;
135 #endif // USE_SPI_SLAVE0
136 #if USE_SPI_SLAVE1
137  case 1:
139  break;
140 #endif //USE_SPI_SLAVE1
141 #if USE_SPI_SLAVE2
142  case 2:
144  break;
145 #endif //USE_SPI_SLAVE2
146 #if USE_SPI_SLAVE3
147  case 3:
149  break;
150 #endif //USE_SPI_SLAVE3
151 #if USE_SPI_SLAVE4
152  case 4:
154  break;
155 #endif //USE_SPI_SLAVE4
156 #if USE_SPI_SLAVE5
157  case 5:
159  break;
160 #endif //USE_SPI_SLAVE5
161  default:
162  break;
163  }
164 }
165 
166 static inline void SpiSlaveSelect(uint8_t slave) {
167  switch(slave) {
168 #if USE_SPI_SLAVE0
169  case 0:
171  break;
172 #endif // USE_SPI_SLAVE0
173 #if USE_SPI_SLAVE1
174  case 1:
176  break;
177 #endif //USE_SPI_SLAVE1
178 #if USE_SPI_SLAVE2
179  case 2:
181  break;
182 #endif //USE_SPI_SLAVE2
183 #if USE_SPI_SLAVE3
184  case 3:
186  break;
187 #endif //USE_SPI_SLAVE3
188 #if USE_SPI_SLAVE4
189  case 4:
191  break;
192 #endif //USE_SPI_SLAVE4
193 #if USE_SPI_SLAVE5
194  case 5:
196  break;
197 #endif //USE_SPI_SLAVE5
198  default:
199  break;
200  }
201 }
202 
204  SpiSlaveSelect(slave);
205 }
206 
208  SpiSlaveUnselect(slave);
209 }
210 
211 void spi_init_slaves(void) {
212 
213 #if USE_SPI_SLAVE0
215  SpiSlaveUnselect(0);
216 #endif
217 
218 #if USE_SPI_SLAVE1
220  SpiSlaveUnselect(1);
221 #endif
222 
223 #if USE_SPI_SLAVE2
225  SpiSlaveUnselect(2);
226 #endif
227 
228 #if USE_SPI_SLAVE3
230  SpiSlaveUnselect(3);
231 #endif
232 
233 #if USE_SPI_SLAVE4
235  SpiSlaveUnselect(4);
236 #endif
237 
238 #if USE_SPI_SLAVE5
240  SpiSlaveUnselect(5);
241 #endif
242 }
243 
244 
245 /******************************************************************************
246  *
247  * Implementation of the generic SPI functions
248  *
249  *****************************************************************************/
250 bool_t spi_submit(struct spi_periph* p, struct spi_transaction* t)
251 {
252  uint8_t idx;
253  idx = p->trans_insert_idx + 1;
254  if (idx >= SPI_TRANSACTION_QUEUE_LEN) idx = 0;
255  if ((idx == p->trans_extract_idx) || ((t->input_length == 0) && (t->output_length == 0))) {
256  t->status = SPITransFailed;
257  return FALSE; /* queue full or input_length and output_length both 0 */
258  // TODO can't tell why it failed here if it does
259  }
260 
261  t->status = SPITransPending;
262 
263  //Disable interrupts to avoid race conflict with end of DMA transfer interrupt
264  //FIXME
266 
267  // GT: no copy? There's a queue implying a copy here...
268  p->trans[p->trans_insert_idx] = t;
269  p->trans_insert_idx = idx;
270 
271  /* if peripheral is idle, start the transaction */
272  if (p->status == SPIIdle && !p->suspend) {
274  }
275  //FIXME
277  return TRUE;
278 }
279 
280 bool_t spi_lock(struct spi_periph* p, uint8_t slave) {
282  if (slave < 254 && p->suspend == 0) {
283  p->suspend = slave + 1; // 0 is reserved for unlock state
285  return TRUE;
286  }
288  return FALSE;
289 }
290 
291 bool_t spi_resume(struct spi_periph* p, uint8_t slave) {
293  if (p->suspend == slave + 1) {
294  // restart fifo
295  p->suspend = 0;
296  if (p->trans_extract_idx != p->trans_insert_idx && p->status == SPIIdle) {
298  }
300  return TRUE;
301  }
303  return FALSE;
304 }
305 
306 
307 /******************************************************************************
308  *
309  * Transaction configuration helper functions
310  *
311  *****************************************************************************/
313  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_64;
314  c->cpol = SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE;
315  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_2;
316  c->dff = SPI_CR1_DFF_8BIT;
317  c->lsbfirst = SPI_CR1_MSBFIRST;
318 }
319 
321  return ((t->dss << 6) | (t->cdiv << 3) | (t->bitorder << 2) |
322  (t->cpha << 1) | (t->cpol));
323 }
324 
326  uint8_t sig = 0;
327  if (c->cpol == SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE) {
328  sig |= SPICpolIdleLow;
329  } else {
330  sig |= SPICpolIdleHigh;
331  }
332  if (c->cpha == SPI_CR1_CPHA_CLK_TRANSITION_1) {
333  sig |= (SPICphaEdge1 << 1);
334  } else {
335  sig |= (SPICphaEdge2 << 1);
336  }
337  if (c->lsbfirst == SPI_CR1_MSBFIRST) {
338  sig |= (SPIMSBFirst << 2);
339  } else {
340  sig |= (SPILSBFirst << 2);
341  }
342  uint8_t cdiv = SPIDiv256;
343  switch (c->br) {
344  case SPI_CR1_BAUDRATE_FPCLK_DIV_2:
345  cdiv = SPIDiv2;
346  break;
347  case SPI_CR1_BAUDRATE_FPCLK_DIV_4:
348  cdiv = SPIDiv4;
349  break;
350  case SPI_CR1_BAUDRATE_FPCLK_DIV_8:
351  cdiv = SPIDiv8;
352  break;
353  case SPI_CR1_BAUDRATE_FPCLK_DIV_16:
354  cdiv = SPIDiv16;
355  break;
356  case SPI_CR1_BAUDRATE_FPCLK_DIV_32:
357  cdiv = SPIDiv32;
358  break;
359  case SPI_CR1_BAUDRATE_FPCLK_DIV_64:
360  cdiv = SPIDiv64;
361  break;
362  case SPI_CR1_BAUDRATE_FPCLK_DIV_128:
363  cdiv = SPIDiv128;
364  break;
365  case SPI_CR1_BAUDRATE_FPCLK_DIV_256:
366  cdiv = SPIDiv256;
367  break;
368  default:
369  break;
370  }
371  sig |= (cdiv << 3);
372  if (c->dff == SPI_CR1_DFF_8BIT) {
373  sig |= (SPIDss8bit << 6);
374  } else {
375  sig |= (SPIDss16bit << 6);
376  }
377  return sig;
378 }
379 
382  if (t->dss == SPIDss8bit) {
383  c->dff = SPI_CR1_DFF_8BIT;
384  } else {
385  c->dff = SPI_CR1_DFF_16BIT;
386  }
387  if (t->bitorder == SPIMSBFirst) {
388  c->lsbfirst = SPI_CR1_MSBFIRST;
389  } else {
390  c->lsbfirst = SPI_CR1_LSBFIRST;
391  }
392  if (t->cpha == SPICphaEdge1) {
393  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_1;
394  } else {
395  c->cpha = SPI_CR1_CPHA_CLK_TRANSITION_2;
396  }
397  if (t->cpol == SPICpolIdleLow) {
398  c->cpol = SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE;
399  } else {
400  c->cpol = SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE;
401  }
402 
403  switch (t->cdiv) {
404  case SPIDiv2:
405  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_2;
406  break;
407  case SPIDiv4:
408  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_4;
409  break;
410  case SPIDiv8:
411  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_8;
412  break;
413  case SPIDiv16:
414  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_16;
415  break;
416  case SPIDiv32:
417  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_32;
418  break;
419  case SPIDiv64:
420  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_64;
421  break;
422  case SPIDiv128:
423  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_128;
424  break;
425  case SPIDiv256:
426  c->br = SPI_CR1_BAUDRATE_FPCLK_DIV_256;
427  break;
428  default:
429  break;
430  }
431 }
432 
433 
434 /******************************************************************************
435  *
436  * Helpers for SPI transactions with DMA
437  *
438  *****************************************************************************/
439 static void spi_configure_dma(u32 dma, u8 chan, u32 periph_addr, u32 buf_addr,
440  u16 len, enum SPIDataSizeSelect dss, bool_t increment)
441 {
442  dma_channel_reset(dma, chan);
443  dma_set_peripheral_address(dma, chan, periph_addr);
444  dma_set_memory_address(dma, chan, buf_addr);
445  dma_set_number_of_data(dma, chan, len);
446 
447  /* Set the dma transfer size based on SPI transaction DSS */
448  if (dss == SPIDss8bit) {
449  dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_8BIT);
450  dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_8BIT);
451  } else {
452  dma_set_peripheral_size(dma, chan, DMA_CCR_PSIZE_16BIT);
453  dma_set_memory_size(dma, chan, DMA_CCR_MSIZE_16BIT);
454  }
455 
456  if (increment)
457  dma_enable_memory_increment_mode(dma, chan);
458  else
459  dma_disable_memory_increment_mode(dma, chan);
460 }
461 
463 static void spi_arch_int_enable(struct spi_periph *spi) {
465  // enable receive interrupt
466  nvic_set_priority( ((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq, 0);
467  nvic_enable_irq( ((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq );
468  // enable transmit interrupt
469  nvic_set_priority( ((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq, 0);
470  nvic_enable_irq( ((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq );
471 }
472 
474 static void spi_arch_int_disable(struct spi_periph *spi) {
475  nvic_disable_irq( ((struct spi_periph_dma *)spi->init_struct)->rx_nvic_irq );
476  nvic_disable_irq( ((struct spi_periph_dma *)spi->init_struct)->tx_nvic_irq );
477 }
478 
480 static void spi_next_transaction(struct spi_periph* periph) {
481  /* Increment the transaction to handle */
482  periph->trans_extract_idx++;
483 
484  /* wrap read index of circular buffer */
486  periph->trans_extract_idx = 0;
487 
488  /* Check if there is another pending SPI transaction */
489  if ((periph->trans_extract_idx == periph->trans_insert_idx) || periph->suspend)
490  periph->status = SPIIdle;
491  else
492  spi_start_dma_transaction(periph, periph->trans[periph->trans_extract_idx]);
493 }
494 
495 
499 static void spi_start_dma_transaction(struct spi_periph* periph, struct spi_transaction* trans)
500 {
501  struct spi_periph_dma *dma;
502  uint8_t sig = 0x00;
503 
504  /* Store local copy to notify of the results */
505  trans->status = SPITransRunning;
506  periph->status = SPIRunning;
507 
508  dma = periph->init_struct;
509 
510  /*
511  * Check if we need to reconfigure the spi peripheral for this transaction
512  */
513  sig = get_transaction_signature(trans);
514  if (sig != dma->comm_sig) {
515  /* A different config is required in this transaction... */
516  set_comm_from_transaction(&(dma->comm), trans);
517 
518  /* remember the new conf signature */
519  dma->comm_sig = sig;
520 
521  /* apply the new configuration */
522  spi_disable((u32)periph->reg_addr);
523  spi_init_master((u32)periph->reg_addr, dma->comm.br, dma->comm.cpol,
524  dma->comm.cpha, dma->comm.dff, dma->comm.lsbfirst);
525  spi_enable_software_slave_management((u32)periph->reg_addr);
526  spi_set_nss_high((u32)periph->reg_addr);
527  spi_enable((u32)periph->reg_addr);
528  }
529 
530  /*
531  * Select the slave after reconfiguration of the peripheral
532  */
533  if (trans->select == SPISelectUnselect || trans->select == SPISelect) {
534  SpiSlaveSelect(trans->slave_idx);
535  }
536 
537  /* Run the callback AFTER selecting the slave */
538  if (trans->before_cb != 0) {
539  trans->before_cb(trans);
540  }
541 
542  /*
543  * Receive DMA channel configuration ----------------------------------------
544  *
545  * We always run the receive DMA until the very end!
546  * This is done so we can use the transfer complete interrupt
547  * of the RX DMA to signal the end of the transaction.
548  *
549  * If we want to receive less than we transmit, a dummy buffer
550  * for the rx DMA is used after for the remaining data.
551  *
552  * In the transmit only case (input_length == 0),
553  * the dummy is used right from the start.
554  */
555  if (trans->input_length == 0) {
556  /* run the dummy rx dma for the complete transaction length */
557  spi_configure_dma(dma->dma, dma->rx_chan, (u32)dma->spidr,
558  (u32)&(dma->rx_dummy_buf), trans->output_length, trans->dss, FALSE);
559  } else {
560  /* run the real rx dma for input_length */
561  spi_configure_dma(dma->dma, dma->rx_chan, (u32)dma->spidr,
562  (u32)trans->input_buf, trans->input_length, trans->dss, TRUE);
563  /* use dummy rx dma for the rest */
564  if (trans->output_length > trans->input_length) {
565  /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
566  dma->rx_extra_dummy_dma = TRUE;
567  }
568  }
569  dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
570  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_VERY_HIGH);
571 
572 
573  /*
574  * Transmit DMA channel configuration ---------------------------------------
575  *
576  * We always run the transmit DMA!
577  * To receive data, the clock must run, so something has to be transmitted.
578  * If needed, use a dummy DMA transmitting zeros for the remaining length.
579  *
580  * In the reveive only case (output_length == 0),
581  * the dummy is used right from the start.
582  */
583  if (trans->output_length == 0) {
584  spi_configure_dma(dma->dma, dma->tx_chan, (u32)dma->spidr,
585  (u32)&(dma->tx_dummy_buf), trans->input_length, trans->dss, FALSE);
586  } else {
587  spi_configure_dma(dma->dma, dma->tx_chan, (u32)dma->spidr,
588  (u32)trans->output_buf, trans->output_length, trans->dss, TRUE);
589  if (trans->input_length > trans->output_length) {
590  /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
591  dma->tx_extra_dummy_dma = TRUE;
592  }
593  }
594  dma_set_read_from_memory(dma->dma, dma->tx_chan);
595  dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
596 
597 
598  /* Enable DMA transfer complete interrupts. */
599  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
600  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
601 
602  /* Enable DMA channels */
603  dma_enable_channel(dma->dma, dma->rx_chan);
604  dma_enable_channel(dma->dma, dma->tx_chan);
605 
606  /* Enable SPI transfers via DMA */
607  spi_enable_rx_dma((u32)periph->reg_addr);
608  spi_enable_tx_dma((u32)periph->reg_addr);
609 }
610 
611 
612 
613 /******************************************************************************
614  *
615  * Initialization of each SPI peripheral
616  *
617  *****************************************************************************/
618 #if USE_SPI1
619 void spi1_arch_init(void) {
620 
621  // set dma options
622  spi1_dma.spidr = (u32)&SPI1_DR;
623  spi1_dma.dma = DMA1;
624  spi1_dma.rx_chan = DMA_CHANNEL2;
625  spi1_dma.tx_chan = DMA_CHANNEL3;
626  spi1_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL2_IRQ;
627  spi1_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL3_IRQ;
632 
633  // set the default configuration
636 
637  // set init struct, indices and status
638  spi1.reg_addr = (void *)SPI1;
642  spi1.status = SPIIdle;
643 
644 
645  // Enable SPI1 Periph and gpio clocks
646  rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SPI1EN);
647 
648  // Configure GPIOs: SCK, MISO and MOSI
649  gpio_set_mode(GPIO_BANK_SPI1_SCK, GPIO_MODE_OUTPUT_50_MHZ,
650  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
651  GPIO_SPI1_SCK | GPIO_SPI1_MOSI);
652 
653  gpio_set_mode(GPIO_BANK_SPI1_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
654  GPIO_SPI1_MISO);
655 
656  // reset SPI
657  spi_reset(SPI1);
658 
659  // Disable SPI peripheral
660  spi_disable(SPI1);
661 
662  // Force SPI mode over I2S.
663  SPI1_I2SCFGR = 0;
664 
665  // configure master SPI.
666  spi_init_master(SPI1, spi1_dma.comm.br, spi1_dma.comm.cpol, spi1_dma.comm.cpha,
668  /*
669  * Set NSS management to software.
670  *
671  * Note:
672  * Setting nss high is very important, even if we are controlling the GPIO
673  * ourselves this bit needs to be at least set to 1, otherwise the spi
674  * peripheral will not send any data out.
675  */
676  spi_enable_software_slave_management(SPI1);
677  spi_set_nss_high(SPI1);
678 
679  // Enable SPI_1 DMA clock
680  rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);
681 
682  // Enable SPI1 periph.
683  spi_enable(SPI1);
684 
686 }
687 #endif
688 
689 #if USE_SPI2
690 void spi2_arch_init(void) {
691 
692  // set dma options
693  spi2_dma.spidr = (u32)&SPI2_DR;
694  spi2_dma.dma = DMA1;
695  spi2_dma.rx_chan = DMA_CHANNEL4;
696  spi2_dma.tx_chan = DMA_CHANNEL5;
697  spi2_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL4_IRQ;
698  spi2_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL5_IRQ;
703 
704  // set the default configuration
707 
708  // set init struct, indices and status
709  spi2.reg_addr = (void *)SPI2;
713  spi2.status = SPIIdle;
714 
715 
716  // Enable SPI2 Periph and gpio clocks
717  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_SPI2EN);
718 
719  // Configure GPIOs: SCK, MISO and MOSI
720  gpio_set_mode(GPIO_BANK_SPI2_SCK, GPIO_MODE_OUTPUT_50_MHZ,
721  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
722  GPIO_SPI2_SCK | GPIO_SPI2_MOSI);
723 
724  gpio_set_mode(GPIO_BANK_SPI2_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
725  GPIO_SPI2_MISO);
726 
727  // reset SPI
728  spi_reset(SPI2);
729 
730  // Disable SPI peripheral
731  spi_disable(SPI2);
732 
733  // Force SPI mode over I2S.
734  SPI2_I2SCFGR = 0;
735 
736  // configure master SPI.
737  spi_init_master(SPI2, spi2_dma.comm.br, spi2_dma.comm.cpol, spi2_dma.comm.cpha,
739 
740  /*
741  * Set NSS management to software.
742  * Setting nss high is very important, even if we are controlling the GPIO
743  * ourselves this bit needs to be at least set to 1, otherwise the spi
744  * peripheral will not send any data out.
745  */
746  spi_enable_software_slave_management(SPI2);
747  spi_set_nss_high(SPI2);
748 
749  // Enable SPI_2 DMA clock
750  rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);
751 
752  // Enable SPI2 periph.
753  spi_enable(SPI2);
754 
756 }
757 #endif
758 
759 #if USE_SPI3
760 void spi3_arch_init(void) {
761 
762  // set the default configuration
763  spi3_dma.spidr = (u32)&SPI3_DR;
764  spi3_dma.dma = DMA2;
765  spi3_dma.rx_chan = DMA_CHANNEL1;
766  spi3_dma.tx_chan = DMA_CHANNEL2;
767  spi3_dma.rx_nvic_irq = NVIC_DMA2_CHANNEL1_IRQ;
768  spi3_dma.tx_nvic_irq = NVIC_DMA2_CHANNEL2_IRQ;
769  spi3_dma.tx_dummy_buf = 0;
770  spi3_dma.tx_extra_dummy_dma = FALSE;
771  spi3_dma.rx_dummy_buf = 0;
772  spi3_dma.rx_extra_dummy_dma = FALSE;
773 
774  // set the default configuration
775  set_default_comm_config(&spi3_dma.comm);
776  spi3_dma.comm_sig = get_comm_signature(&spi3_dma.comm);
777 
778  // set init struct, indices and status
779  spi3.reg_addr = (void *)SPI3;
780  spi3.init_struct = &spi3_dma;
781  spi3.trans_insert_idx = 0;
782  spi3.trans_extract_idx = 0;
783  spi3.status = SPIIdle;
784 
785 
786  // Enable SPI3 Periph and gpio clocks
787  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_SPI3EN);
788 
789  // Configure GPIOs: SCK, MISO and MOSI
790  gpio_set_mode(GPIO_BANK_SPI3_SCK, GPIO_MODE_OUTPUT_50_MHZ,
791  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
792  GPIO_SPI3_SCK | GPIO_SPI3_MOSI);
793 
794  gpio_set_mode(GPIO_BANK_SPI3_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
795  GPIO_SPI3_MISO);
796 
798 
799  // reset SPI
800  spi_reset(SPI3);
801 
802  // Disable SPI peripheral
803  spi_disable(SPI3);
804 
805  // Force SPI mode over I2S.
806  SPI3_I2SCFGR = 0;
807 
808  // configure master SPI.
809  spi_init_master(SPI3, spi3_dma.comm.br, spi3_dma.comm.cpol, spi3_dma.comm.cpha,
810  spi3_dma.comm.dff, spi3_dma.comm.lsbfirst);
811 
812  /*
813  * Set NSS management to software.
814  * Setting nss high is very important, even if we are controlling the GPIO
815  * ourselves this bit needs to be at least set to 1, otherwise the spi
816  * peripheral will not send any data out.
817  */
818  spi_enable_software_slave_management(SPI3);
819  spi_set_nss_high(SPI3);
820 
821  // Enable SPI_3 DMA clock
822  rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA2EN);
823 
824  // Enable SPI3 periph.
825  spi_enable(SPI3);
826 
827  spi_arch_int_enable(&spi3);
828 }
829 #endif
830 
831 
832 
833 
834 /******************************************************************************
835  *
836  * DMA Interrupt service routines
837  *
838  *****************************************************************************/
839 #ifdef USE_SPI1
840 void dma1_channel2_isr(void)
842 {
843  if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) {
844  // clear int pending bit
845  DMA1_IFCR |= DMA_IFCR_CTCIF2;
846  }
848 }
849 
852 {
853  if ((DMA1_ISR & DMA_ISR_TCIF3) != 0) {
854  // clear int pending bit
855  DMA1_IFCR |= DMA_IFCR_CTCIF3;
856  }
858 }
859 
860 #endif
861 
862 #ifdef USE_SPI2
863 void dma1_channel4_isr(void)
865 {
866  if ((DMA1_ISR & DMA_ISR_TCIF4) != 0) {
867  // clear int pending bit
868  DMA1_IFCR |= DMA_IFCR_CTCIF4;
869  }
871 }
872 
875 {
876  if ((DMA1_ISR & DMA_ISR_TCIF5) != 0) {
877  // clear int pending bit
878  DMA1_IFCR |= DMA_IFCR_CTCIF5;
879  }
881 }
882 
883 #endif
884 
885 #if USE_SPI3
886 void dma2_channel1_isr(void)
888 {
889  if ((DMA2_ISR & DMA_ISR_TCIF1) != 0) {
890  // clear int pending bit
891  DMA2_IFCR |= DMA_IFCR_CTCIF1;
892  }
894 }
895 
897 void dma2_channel2_isr(void)
898 {
899  if ((DMA2_ISR & DMA_ISR_TCIF2) != 0) {
900  // clear int pending bit
901  DMA2_IFCR |= DMA_IFCR_CTCIF2;
902  }
904 }
905 
906 #endif
907 
909 void process_rx_dma_interrupt(struct spi_periph *periph) {
910  struct spi_periph_dma *dma = periph->init_struct;
911  struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
912 
913  /* Disable DMA Channel */
914  dma_disable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
915 
916  /* Disable SPI Rx request */
917  spi_disable_rx_dma((u32)periph->reg_addr);
918 
919  /* Disable DMA rx channel */
920  dma_disable_channel(dma->dma, dma->rx_chan);
921 
922 
923  if (dma->rx_extra_dummy_dma) {
924  /*
925  * We are finished the first part of the receive with real data,
926  * but still need to run the dummy to get a transfer complete interrupt
927  * after the complete transaction is done.
928  */
929 
930  /* Reset the flag so this only happens once in a transaction */
931  dma->rx_extra_dummy_dma = FALSE;
932 
933  /* Use the difference in length between rx and tx */
934  u16 len_remaining = trans->output_length - trans->input_length;
935 
936  spi_configure_dma(dma->dma, dma->rx_chan, (u32)dma->spidr,
937  (u32)&(dma->rx_dummy_buf), len_remaining, trans->dss, FALSE);
938  dma_set_read_from_peripheral(dma->dma, dma->rx_chan);
939  dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_HIGH);
940 
941  /* Enable DMA transfer complete interrupts. */
942  dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan);
943  /* Enable DMA channels */
944  dma_enable_channel(dma->dma, dma->rx_chan);
945  /* Enable SPI transfers via DMA */
946  spi_enable_rx_dma((u32)periph->reg_addr);
947  }
948  else {
949  /*
950  * Since the receive DMA is always run until the very end
951  * and this interrupt is triggered after the last data word was read,
952  * we now know that this transaction is finished.
953  */
954 
955  /* Run the callback */
956  trans->status = SPITransSuccess;
957  if (trans->after_cb != 0) {
958  trans->after_cb(trans);
959  }
960 
961  /* AFTER the callback, then unselect the slave if required */
962  if (trans->select == SPISelectUnselect || trans->select == SPIUnselect) {
963  SpiSlaveUnselect(trans->slave_idx);
964  }
965 
966  spi_next_transaction(periph);
967  }
968 }
969 
971 void process_tx_dma_interrupt(struct spi_periph *periph) {
972  struct spi_periph_dma *dma = periph->init_struct;
973  struct spi_transaction *trans = periph->trans[periph->trans_extract_idx];
974 
975  /* Disable DMA Channel */
976  dma_disable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
977 
978  /* Disable SPI TX request */
979  spi_disable_tx_dma((u32)periph->reg_addr);
980 
981  /* Disable DMA tx channel */
982  dma_disable_channel(dma->dma, dma->tx_chan);
983 
984  if (dma->tx_extra_dummy_dma) {
985  /*
986  * We are finished the first part of the transmit with real data,
987  * but still need to clock in the rest of the receive data.
988  * Set up a dummy dma transmit transfer to accomplish this.
989  */
990 
991  /* Reset the flag so this only happens once in a transaction */
992  dma->tx_extra_dummy_dma = FALSE;
993 
994  /* Use the difference in length between tx and rx */
995  u16 len_remaining = trans->input_length - trans->output_length;
996 
997  spi_configure_dma(dma->dma, dma->tx_chan, (u32)dma->spidr,
998  (u32)&(dma->tx_dummy_buf), len_remaining, trans->dss, FALSE);
999  dma_set_read_from_memory(dma->dma, dma->tx_chan);
1000  dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM);
1001 
1002  /* Enable DMA transfer complete interrupts. */
1003  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_chan);
1004  /* Enable DMA channels */
1005  dma_enable_channel(dma->dma, dma->tx_chan);
1006  /* Enable SPI transfers via DMA */
1007  spi_enable_tx_dma((u32)periph->reg_addr);
1008 
1009  }
1010 }
1011 
1012 #endif
1015 /*
1016  *
1017  * SPI Slave code
1018  *
1019  * FIXME implement it
1020  *
1021  */
1022 #ifdef SPI_SLAVE
1023 
1024 #warning SPI_SLAVE mode currently not implemented for STM32.
1025 
1026 #endif /* SPI_SLAVE */
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:152
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:149
void dma1_channel3_isr(void)
transmit transferred over DMA
Definition: spi_arch.c:851
Definition: spi.h:118
static struct spi_periph_dma spi2_dma
Definition: spi_arch.c:107
static void process_tx_dma_interrupt(struct spi_periph *periph)
Processing done after tx completes.
Definition: spi_arch.c:971
bool_t spi_lock(struct spi_periph *p, uint8_t slave)
Lock the SPI fifo.
Definition: spi_arch.c:535
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
struct spi_periph spi2
Definition: spi.c:55
static void spi_arch_int_disable(struct spi_periph *spi)
Disable DMA channel interrupts.
Definition: spi_arch.c:474
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:444
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
u32 spidr
SPI DataRegister address for DMA.
Definition: spi_arch.c:85
Some architecture independent helper functions for GPIOs.
u8 rx_nvic_irq
receive interrupt
Definition: spi_arch.c:89
u32 cpha
clock phase
Definition: spi_arch.c:74
u32 br
baudrate (clock divider)
Definition: spi_arch.c:72
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:83
void * reg_addr
Definition: spi.h:172
static void spi_configure_dma(u32 dma, u8 chan, u32 periph_addr, u32 buf_addr, u16 len, enum SPIDataSizeSelect dss, bool_t increment)
Definition: spi_arch.c:439
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:173
void gpio_setup_output(uint32_t port, uint16_t pin)
Setup gpio pin as generic output.
#define SPI_SELECT_SLAVE3_PORT
Definition: lisa_l_1.0.h:34
u8 tx_chan
transmit DMA channel number
Definition: spi_arch.c:88
static struct spi_periph_dma spi1_dma
Definition: spi_arch.c:104
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
void dma1_channel4_isr(void)
receive transferred over DMA
Definition: spi_arch.c:864
static void spi_start_dma_transaction(struct spi_periph *periph, struct spi_transaction *_trans)
Start a new transaction with DMA.
Definition: spi_arch.c:499
#define SPI_SELECT_SLAVE3_PIN
Definition: lisa_l_1.0.h:35
u32 spi
SPI peripheral identifier.
Definition: spi_arch.c:84
#define SPI_SELECT_SLAVE0_PIN
Definition: booz_1.0.h:133
#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:163
Definition: spi.h:114
enum SPIStatus status
internal state of the peripheral
Definition: spi.h:169
static void SpiSlaveSelect(uint8_t slave)
Definition: spi_arch.c:166
void dma1_channel2_isr(void)
receive transferred over DMA
Definition: spi_arch.c:841
Definition: spi.h:84
void spi_slave_unselect(uint8_t slave)
Unselect a slave.
Definition: spi_arch.c:531
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:153
#define SPI_SELECT_SLAVE0_PORT
Definition: booz_1.0.h:132
u16 rx_dummy_buf
dummy rx buffer for receive only cases
Definition: spi_arch.c:93
bool_t spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit a spi transaction.
Definition: spi_arch.c:469
static uint8_t get_transaction_signature(struct spi_transaction *t)
Definition: spi_arch.c:320
u8 tx_nvic_irq
transmit interrupt
Definition: spi_arch.c:90
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
void spi2_arch_init(void)
Architecture dependant SPI2 initialization.
Definition: spi_arch.c:690
uint8_t output_length
number of data words to write
Definition: spi.h:146
struct spi_transaction * trans[SPI_TRANSACTION_QUEUE_LEN]
circular buffer holding transactions
Definition: spi.h:165
Libopencm3 specifc communication parameters for a SPI peripheral in master mode.
Definition: spi_arch.c:71
struct locm3_spi_comm comm
current communication paramters
Definition: spi_arch.c:95
CPOL = 0.
Definition: spi.h:77
int gpio_set(int nr, int val)
Definition: gpio_ardrone.c:32
void dma1_channel5_isr(void)
transmit transferred over DMA
Definition: spi_arch.c:874
u32 lsbfirst
frame format lsb/msb first
Definition: spi_arch.c:76
#define TRUE
Definition: imu_chimu.h:144
u16 tx_dummy_buf
dummy tx buffer for receive only cases
Definition: spi_arch.c:91
volatile uint8_t suspend
control for stop/resume of the fifo
Definition: spi.h:176
static void SpiSlaveUnselect(uint8_t slave)
Definition: spi_arch.c:129
#define SPI_SELECT_SLAVE4_PIN
Definition: lisa_l_1.0.h:39
#define SPI_SELECT_SLAVE5_PIN
Definition: lisa_m_common.h:22
unsigned char uint8_t
Definition: types.h:14
Definition: spi.h:101
#define SPI_SELECT_SLAVE2_PORT
Definition: apogee_0.99.h:162
CPHA = 0.
Definition: spi.h:68
Definition: spi.h:117
Definition: spi.h:121
#define SPI_SELECT_SLAVE1_PIN
Definition: booz_1.0.h:139
slave is selected before transaction and unselected after
Definition: spi.h:57
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:147
u32 cpol
clock polarity
Definition: spi_arch.c:73
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:381
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:547
Definition: spi.h:116
uint8_t trans_extract_idx
Definition: spi.h:167
static void set_default_comm_config(struct locm3_spi_comm *c)
Definition: spi_arch.c:312
u8 rx_chan
receive DMA channel number
Definition: spi_arch.c:87
#define SPI1
Definition: LPC21xx.h:210
#define SPI_SELECT_SLAVE4_PORT
Definition: lisa_l_1.0.h:38
SPI transaction structure.
Definition: spi.h:142
u32 dma
DMA controller base address (DMA1 or DMA2)
Definition: spi_arch.c:86
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
#define SPI_TRANSACTION_QUEUE_LEN
Definition: spi.h:160
static uint8_t get_comm_signature(struct locm3_spi_comm *c)
Definition: spi_arch.c:325
static void process_rx_dma_interrupt(struct spi_periph *periph)
Processing done after rx completes.
Definition: spi_arch.c:909
SPICallback before_cb
NULL or function called before the transaction.
Definition: spi.h:154
static struct point c
Definition: discsurvey.c:39
void spi_init_slaves(void)
Initialize all used slaves and uselect them.
Definition: spi_arch.c:503
void spi_slave_select(uint8_t slave)
Select a slave.
Definition: spi_arch.c:527
bool_t tx_extra_dummy_dma
extra tx dummy dma flag for tx_len < rx_len
Definition: spi_arch.c:92
uint8_t trans_insert_idx
Definition: spi.h:166
u32 dff
data frame format 8/16 bits
Definition: spi_arch.c:75
u8 comm_sig
comm config signature used to check for changes
Definition: spi_arch.c:96
struct spi_periph spi1
Definition: spi.c:45
Definition: spi.h:120
bool_t rx_extra_dummy_dma
extra rx dummy dma flag for tx_len > rx_len
Definition: spi_arch.c:94
static void spi_arch_int_enable(struct spi_periph *spi)
Enable DMA channel interrupts.
Definition: spi_arch.c:463
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:155
#define SPI_SELECT_SLAVE1_PORT
Definition: booz_1.0.h:138
static void spi_next_transaction(struct spi_periph *periph)
start next transaction if there is one in the queue
Definition: spi_arch.c:480