Grzegorz
It is possible to do a channel burst transfer to an SPI but it means that the writes are very fast and if the SPI doesn't have adequate FIFO depth (SPI0 has 4 but others have only 1) it will overrun the transmitter and only the first 4 or 1 will be sent.
When you sent to SPI via DMA you therefore need to use the SPIs DMA trigger to control transmission and not the trigger from a pin. You can use the trigger for the pin to set up the transfer (via interrupt) or via DMA.
Below I can show you how a pin DMA trigger can be used to control the start of an SPI DMA transmission burst (as included in the uTasker project). In fact it is used to automate both transmission and reception, transmitting a predefined sequence of bytes, controlling the CS line, reading returned data and finally clearing SPI flags via DMA when the transmission has completed (otherwise it won't work a second time!).
It is useful for external high speed ADCs that indicated data is ready via sync line (triggering the operation to write and read a number of bytes purely using DMA).
POWER_UP_ATOMIC(6, SPI0);
_CONFIG_PERIPHERAL(D, 0, (PD_0_SPI0_PCS0 | PORT_SRE_FAST | PORT_DSE_HIGH));
_CONFIG_PERIPHERAL(D, 1, (PD_1_SPI0_SCK | PORT_SRE_FAST | PORT_DSE_HIGH));
_CONFIG_PERIPHERAL(D, 2, (PD_2_SPI0_SOUT | PORT_SRE_FAST | PORT_DSE_HIGH));
_CONFIG_PERIPHERAL(D, 3, (PD_3_SPI0_SIN));
SPI0_MCR = (SPI_MCR_MSTR | SPI_MCR_DCONF_SPI | SPI_MCR_CLR_RXF | SPI_MCR_CLR_TXF | SPI_MCR_PCSIS_CS0 | SPI_MCR_PCSIS_CS1 | SPI_MCR_PCSIS_CS2 | SPI_MCR_PCSIS_CS3 | SPI_MCR_PCSIS_CS4 | SPI_MCR_PCSIS_CS5);
SPI0_RSER = (SPI_SRER_TFFF_DIRS | SPI_SRER_TFFF_RE | SPI_SRER_RFDF_DIRS | SPI_SRER_RFDF_RE);
SPI0_CTAR0 = (SPI_CTAR_DBR | SPI_CTAR_FMSZ_8 | SPI_CTAR_PDT_7 | SPI_CTAR_BR_4 | SPI_CTAR_CPHA | SPI_CTAR_CPOL);
interrupt_setup.int_port = PORTE;
interrupt_setup.int_port_bits = PORTE_BIT4;
interrupt_setup.int_port_sense = (IRQ_FALLING_EDGE | PULLUP_ON | PORT_DMA_MODE);
interrupt_setup.int_handler = 0;
{
#define DMA_CHANNEL_FOR_CS_END 6
#define DMA_CHANNEL_FOR_PORT_EDGE 7
#define DMA_CHANNEL_FOR_SPI_TX 8
#define DMA_CHANNEL_FOR_SPI_RX 9
static const unsigned long ulSPI_TX[8] = {
(0x01 | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
(0x02 | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
(0x03 | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
(0x04 | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
(0x05 | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
(0x06 | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
(0x07 | SPI_PUSHR_CONT | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
(0x08 | SPI_PUSHR_EOQ | SPI_PUSHR_PCS0 | SPI_PUSHR_CTAS_CTAR0),
};
static volatile unsigned char ucRxData[128] = {0};
static const unsigned char ucDMA_start = ((DMA_ERQ_ERQ0 << (DMA_CHANNEL_FOR_SPI_TX - 8)) | (DMA_ERQ_ERQ0 << (DMA_CHANNEL_FOR_SPI_RX - 8)));
static const unsigned long ulSPI_clear = (SPI_SR_RFDF | SPI_SR_RFOF | SPI_SR_TFUF | SPI_SR_EOQF | SPI_SR_TCF);
fnConfigDMA_buffer(DMA_CHANNEL_FOR_SPI_TX, DMAMUX0_CHCFG_SOURCE_SPI0_TX, sizeof(ulSPI_TX), (void *)ulSPI_TX, (void *)SPI0_PUSHR_ADDR, (DMA_DIRECTION_OUTPUT | DMA_LONG_WORDS | DMA_SINGLE_CYCLE), 0, 0);
fnConfigDMA_buffer(DMA_CHANNEL_FOR_SPI_RX, DMAMUX0_CHCFG_SOURCE_SPI0_RX, sizeof(ucRxData), (void *)SPI0_POPR_ADDR, (void *)ucRxData, (DMA_DIRECTION_INPUT | DMA_BYTES | DMA_HALF_BUFFER_INTERRUPT), spi_half_buffer, PRIORITY_DMA9);
fnConfigDMA_buffer(DMA_CHANNEL_FOR_PORT_EDGE, DMAMUX0_CHCFG_SOURCE_PORTE, sizeof(ucDMA_start), (void *)&ucDMA_start, (void *)(((unsigned char *)DMA_ERQ_ADDR) + 1), (DMA_FIXED_ADDRESSES | DMA_BYTES), 0, 0);
fnDMA_BufferReset(DMA_CHANNEL_FOR_PORT_EDGE, DMA_BUFFER_START);
fnConfigureInterrupt((void *)&interrupt_setup);
interrupt_setup.int_port = PORTD;
interrupt_setup.int_port_bits = PORTD_BIT0;
interrupt_setup.int_port_sense = (IRQ_RISING_EDGE | PULLUP_ON | PORT_DMA_MODE | PORT_KEEP_PERIPHERAL);
fnConfigDMA_buffer(DMA_CHANNEL_FOR_CS_END, DMAMUX0_CHCFG_SOURCE_PORTD, sizeof(ulSPI_clear), (void *)&ulSPI_clear, (void *)SPI0_SR_ADDR, (DMA_FIXED_ADDRESSES | DMA_LONG_WORDS), 0, 0);
fnDMA_BufferReset(DMA_CHANNEL_FOR_CS_END, DMA_BUFFER_START);
fnConfigureInterrupt((void *)&interrupt_setup);
}
This uses 4 DMA channels and represents just one of probably numerous possibilities to do more or less the same thing. There may be more efficient ones but this was simple to set up using the uTasker DMA and port interrupt/DMA APIs.
Regards
Mark