Forum: Mikrocontroller und Digitale Elektronik SAMC21 SPI Slave mit DMA


von zimmerpflanze (Gast)


Lesenswert?

Hallo zusammen,

ich möchte für ein Projekt einen SAMC21 mikrocontroller als SPI Slave 
verwenden. Um die Daten schnell genug, und ohne den Prozessor dabei zu 
stark auszulasten, möchte ich die Daten per DMA an das SPI Modul geben.

Meine Setup Funktion sieht aus wie folgt:
1
static DmacDescriptor dma_descriptor_array[2] __attribute__ ((aligned (16)));
2
static DmacDescriptor dma_writeback_array[2] __attribute__ ((aligned (16)));
3
4
uint8_t dma_rx_buffer[8];
5
6
void hal_init_dma(void) {
7
  
8
  MCLK->AHBMASK.bit.DMAC_ = 1;
9
  
10
  /* perform a software reset before enable DMA controller */
11
  DMAC->CTRL.reg &= ~DMAC_CTRL_DMAENABLE;
12
  DMAC->CTRL.reg = DMAC_CTRL_SWRST;
13
  
14
  /* setup descriptopr base address and write back section base address */
15
  DMAC->BASEADDR.reg =  (uint32_t) &dma_descriptor_array;
16
  DMAC->WRBADDR.reg = (uint32_t) &dma_writeback_array;
17
  
18
  /* enable all priority level at the same time */
19
  DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xf);
20
  
21
  /* perform a reset for channel 0 */
22
  DMAC->CHID.reg = DMAC_CHID_ID(0);
23
  DMAC->CHCTRLA.reg &= ~DMAC_CHCTRLA_ENABLE;
24
  DMAC->CHCTRLA.reg = DMAC_CHCTRLA_SWRST;  
25
  
26
  DMAC->CHCTRLB.reg = DMAC_CHCTRLB_TRIGACT_BEAT;
27
  DMAC->CTRL.reg =  DMAC_CTRL_LVLEN0 | DMAC_CTRL_DMAENABLE;
28
  
29
  dma_descriptor_array[0].BTCTRL.reg = DMAC_BTCTRL_DSTINC| DMAC_BTCTRL_VALID;
30
  dma_descriptor_array[0].BTCNT.reg = 8;
31
  dma_descriptor_array[0].SRCADDR.reg = (uint32_t) &SERCOM5->SPI.DATA;
32
  dma_descriptor_array[0].DSTADDR.reg = (uint32_t) &dma_rx_buffer[8];
33
  dma_descriptor_array[0].DESCADDR.reg = 0;
34
35
  DMAC->PRICTRL0.reg = 0;  
36
}

Ich würde gerne 8 Byte Daten nach dem Empfangen direkt in den 
dma_rx_buffer schreiben.
Mein aktueller Ansatz wäre es bei einem Chip Select Low Interrupt per 
software-flag einen DMA Transfer zu starten.
Ich habe das SERCOM5 Modul als SPI Slave konfiguriert. Das funktioniert 
auch, konnte ich bereits ohne DMA testen.
1
void SERCOM5_Handler() {
2
  
3
  /* flag is set when nCS pin is going low */
4
  if (SERCOM5->SPI.INTFLAG.bit.SSL && SERCOM5->SPI.INTENSET.bit.SSL) {
5
    SERCOM5->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_SSL;
6
    DMAC->CHID.reg = DMAC_CHID_ID(0);
7
DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
8
  }
9
}

Leider scheint mein Ansatz so nicht zu funktionieren. Kann mir jemand 
mit dem Problem weiterhelfen und ist das überhaupt der richtige Ansatz 
für den Empfang der Daten mit DMA? Habe ich vielleicht einen Fehler in 
der Konfig des DMA Controllers? Danke für eure Hilfe.

von Moritz (Gast)


Lesenswert?

Hallo zimmerpflanze,
hast du dem Interrupt für SERCOM5 eine Priorität gegeben und aktiviert?
Dies geht per
NVIC_SetPriority(SERCOM5_IRQn, 1);
NVIC_EnableIRQ(SERCOM5_IRQn);

Gruß Moritz

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.