Hi,
I search a small example for SPI Master and DMA transfer.
So that I can receive e.g. 15 bytes with DMA and get a transfer end interrupt/callback when it is finished.
Thanks in advanced !
now I tested it at low level programming without FSP .
void hal_entry(void) { unsigned char txByte[] = {0,1,2,3,4,5,6,7,8,9}; unsigned char rxByte[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; // Init SPI Master Mode R_SPI0->SPCR_b.SPE = 0x00; // Disable SPI function R_SPI0->SSLP_b.SSL0P = 0; R_SPI0->SSLP_b.SSL1P = 0; R_SPI0->SSLP_b.SSL2P = 0; R_SPI0->SSLP_b.SSL3P = 0; R_SPI0->SSLP_b.SSL4P = 0; R_SPI0->SSLP_b.SSL5P = 0; R_SPI0->SSLP_b.SSL6P = 0; R_SPI0->SSLP_b.SSL7P = 0; R_SPI0->SPPCR = 0; R_SPI0->SPBR = 0x17; R_SPI0->SPDCR = 0x00; // Read SPDR from receive buffer + Halfword R_SPI0->SPCKD = 0x00; // RSPCK Delay = 1 RSPCK -> 1 SPI Clock Pause nachdem CS auf low gezogen wurde R_SPI0->SSLND = 0x00; // SLNDL Delay = 1 RSPCK -> 1 SPI Clock Pause bevor CS wieder auf high gezogen wird R_SPI0->SPND = 0x00; // Next-Access Delay -> 1 RSPCK + 2 PCLKA R_SPI0->SPCR2_b.SPPE = 0x00; // No Parity R_SPI0->SPCR2_b.SPOE = 0x00; // Select even parity for use in transmission and reception R_SPI0->SPCR2_b.SPIIE = 0x00; // Idle interrupt requests disabled R_SPI0->SPCR2_b.PTE = 0x00; // Self-diagnosis function of the parity circuit disabled R_SPI0->SPCR2_b.SCKASE = 0x00; // RSPCK auto-stop function disabled R_SPI0->SPCR2_b.SPTDDL = 0x00; // R_SPI0->SPCMD_b->CPHA = 0x01; // Select data change on leading edge, data sampling on trailing edge. R_SPI0->SPCMD_b->CPOL = 0x00; // Set RSPCK low when idle R_SPI0->SPCMD_b->BRDV = 0x00; // Base bit rate R_SPI0->SPCMD_b->SSLA = 0x00; // Set SSL0 als CS R_SPI0->SPCMD_b->SPB = 0x0f; // 16 Bits Data length R_SPI0->SPCMD_b->LSBF = 0x00; // MSB first R_SPI0->SPCMD_b->SPNDEN = 0x01; // A next-access delay equal to the setting of the SPI Next-Access Delay Register (SPND). R_SPI0->SPCMD_b->SLNDEN = 0x01; // An SSL negation delay equal to the setting of the SPI Slave Select Negation Delay Register (SSLND). R_SPI0->SPCMD_b->SCKDEN = 0x01; // An RSPCK delay equal to the setting of the SPI Clock Delay Register (SPCKD) // Set TX DMAC R_DMAC0->DMSAR = (uint32_t)&txByte; // Source address R_DMAC0->DMDAR = (uint32_t)&R_SPI0->SPDR_HA; // destination address R_DMAC0->DMCRA_b.DMCRAL = 10; // Transfer count R_DMAC0->DMCRA_b.DMCRAH = 10; // Transfer count R_DMAC0->DMCRB = 0; // DMA Block Transfer Count R_DMAC0->DMTMD_b.DCTG = 0; // Transfer Request : Software R_DMAC0->DMTMD_b.SZ = 1; // Transfer Data Size : 16 Bits R_DMAC0->DMTMD_b.DTS = 1; // Repeat Area : Source R_DMAC0->DMTMD_b.MD = 1; // Transfer Mode : Repeat R_DMAC0->DMINT_b.DARIE = 0; // Destination Address Extended Repeat Area Overflow Interrupt disable R_DMAC0->DMINT_b.SARIE = 0; // Source Address Extended Repeat Area Overflow Interrupt disable R_DMAC0->DMINT_b.RPTIE = 0; // Repeat Size End Interrupt disable R_DMAC0->DMINT_b.ESIE = 0; // Transfer Escape End Interrupt disable R_DMAC0->DMINT_b.DTIE = 0; // Transfer End Interrupt disable R_DMAC0->DMAMD_b.DARA = 0; // Destination Address Extended Repeat Area : not specified R_DMAC0->DMAMD_b.DM = 0; // Destination address fixed R_DMAC0->DMAMD_b.SARA = 0; // Source Address Extended Repeat Area : not specified R_DMAC0->DMAMD_b.SM = 2; // Source address is incremented R_DMAC0->DMAMD_b.DADR = 0; R_DMAC0->DMAMD_b.SADR = 0; R_DMAC0->DMOFR = 0; // DMA Offset Register R_DMAC0->DMCNT_b.DTE = 1; // DMA transfer enable // Set RX DMAC R_DMAC1->DMDAR = (uint32_t)&rxByte; // Source address R_DMAC1->DMSAR = (uint32_t)&R_SPI0->SPDR_HA; // destination address R_DMAC1->DMCRA_b.DMCRAL = 1; // Transfer count R_DMAC1->DMCRA_b.DMCRAH = 1; // Transfer count R_DMAC1->DMCRB = 0; // DMA Block Transfer Count R_DMAC1->DMTMD_b.DCTG = 0; // Transfer Request : Software R_DMAC1->DMTMD_b.SZ = 1; // Transfer Data Size : 16 Bits R_DMAC1->DMTMD_b.DTS = 0; // Repeat Area : Destination R_DMAC1->DMTMD_b.MD = 1; // Transfer Mode : Repeat R_DMAC1->DMINT_b.DARIE = 0; // Destination Address Extended Repeat Area Overflow Interrupt disable R_DMAC1->DMINT_b.SARIE = 0; // Source Address Extended Repeat Area Overflow Interrupt disable R_DMAC1->DMINT_b.RPTIE = 0; // Repeat Size End Interrupt disable R_DMAC1->DMINT_b.ESIE = 0; // Transfer Escape End Interrupt disable R_DMAC1->DMINT_b.DTIE = 0; // Transfer End Interrupt disable R_DMAC1->DMAMD_b.DARA = 0; // Destination Address Extended Repeat Area : not specified R_DMAC1->DMAMD_b.DM = 2; // Destination address is incremented R_DMAC1->DMAMD_b.SARA = 0; // Source Address Extended Repeat Area : not specified R_DMAC1->DMAMD_b.SM = 0; // Source address fixed R_DMAC1->DMAMD_b.DADR = 0; R_DMAC1->DMAMD_b.SADR = 0; R_DMAC1->DMOFR = 0; // DMA Offset Register R_DMAC1->DMCNT_b.DTE = 1; // DMA transfer enable // Set SPI R_SPI0->SPCR_b.MSTR = 0x01; // Select Master mode R_SPI0->SPCR_b.SPMS = 0x00; // Select SPI operation (4-wire method) R_SPI0->SPCR_b.TXMD = 0x00; // Select full-duplex synchronous serial communications R_SPI0->SPCR_b.MODFEN = 0x00; // Disable the detection of mode fault error R_SPI0->SPCR_b.SPEIE = 0x00; // Disable SPI error interrupt requests R_SPI0->SPCR_b.SPTIE = 0x00; // Disable transmit buffer empty interrupt requests R_SPI0->SPCR_b.SPRIE = 0x00; // Disable SPI receive buffer full interrupt requests R_SPI0->SPCR_b.SPE = 0x01; // Enable SPI function // Start DMA R_DMA->DMAST_b.DMST = 1; // DMAC start enabled R_DMAC0->DMREQ_b.CLRS = 0; // SWREQ bit is cleared after DMA transfer is started by software R_DMAC0->DMREQ_b.SWREQ = 1; // DMA transfer is requested while(1) { }
The Pin configuration is maked with FSP.
On my Oszi I see a transmission from 16 bits and the CS (SSLP0) pin is handshaked.
But why only 16 Bits ? I will transfer 10 bytes ...
You need to link DMA transfer to an activation source.
R_ICU->DELSR[0] = ELC_EVENT_SPI0_TXI; // SPI0_SPTI
R_ICU->DELSR[1] = ELC_EVENT_SPI0_RXI; // SPI0_SPRI
I inserted this lines, but nothing is changed. Only 16 bits are transferred when I start the DMA.
You set software start.
R_DMAC1->DMTMD_b.DCTG = 0; // Transfer Request : Software
Please change to
R_DMAC1->DMTMD_b.DCTG = 1;
I want to use Software start. But when I make your changes , nothing is changed.In Software start mode , if I set of the SWREQ again in DMREQ register , transfer the SPI the next value.But it must send automaticly the 10 values ...If I use the blockmode the SPI send 2 values !?
Hi royw,
Could you try ra-fsp-examples/example_projects/ek_ra4m1/spi/spi_ek_ra4m1_ep/e2studio at master · renesas/ra-fsp-examples (github.com)
You can change transfer from dtc to dma for the master spi and test the R_SPI_WriteRead() api. The master and slave spi are on same RA4M1. You should see the activation source for dma transfer are the spi tx and rx interrupts. You can send/receive upto 64 bytes in that example.