RA4M1 , SPI with DMA

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 !

Parents
  • 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 !?

Reply Children