ASF4 START - Out of the box spi dma example seems not to work

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can anyone replicate the issue?

My goal for now is to see anything on the SPI lines, there is no clock and no MOSI signal. (monitoring them with an oscilloscope).

I'm working with an SAMV71XPlained Ultra development board. I'm setting up the SPI Driver in START (see Image), with the code mentioned below. If I change the HAL dma driver to sync or async mode everything works fine.

 

 

This is the code of main.c

 

	/* Initializes MCU, drivers and middleware */
	atmel_start_init();

	ams_system32_setupGPIO(PIN_ABCC_SPI_SS, GPIO_DIRECTION_OUT, GPIO_PULL_OFF);
	ams_system32_setupGPIO(PIN_LED, GPIO_DIRECTION_OUT, GPIO_PULL_OFF);

	gpio_set_pin_level(PIN_ABCC_SPI_SS, 0);
	SPI_0_example();

	while(1){}
	

This is the relevant code of driver_examples.c (supplied by ATMEL START)

static uint8_t example_SPI_0[12] = "Hello World!";

struct io_descriptor *io;

	static void tx_complete_cb_SPI_0(struct _dma_resource *resource)
{
	/* Transfer completed */
}

void SPI_0_example(void)
{
	spi_m_dma_get_io_descriptor(&SPI_0, &io);

	spi_m_dma_register_callback(&SPI_0, SPI_M_DMA_CB_TX_DONE, (spi_m_dma_cb_t)tx_complete_cb_SPI_0);
	spi_m_dma_enable(&SPI_0);
	io_write(io, example_SPI_0, 12);

}

 

I surely did miss something, right?

This topic has a solution.

[insert smart signature here]

Last Edited: Mon. Nov 18, 2019 - 09:19 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Solved it a while ago.

The solution was, that ASF4's configuration of the DMA is plain wrong.

 

Since I didn't want to drop ASF4 completly I've just overwritten the XDMAC registers with a (self made) working configuration, after ASF4-Initialization.

 

Edit: My apologies for not including the solution.

 

So here it goes, it's for the SPI-0 instance:

 

#include <stdint-gcc.h>

#define XDMAC_GTYPE *((uint32_t*)(0x40078000 ))
#define XDMAC_GCFG	*((uint32_t*)(0x40078004 ))
#define XDMAC_GWAC	*((uint32_t*)(0x40078008 ))
#define XDMAC_GIE	*((uint32_t*)(0x4007800C ))
#define XDMAC_GID	*((uint32_t*)(0x40078010 ))
#define XDMAC_GIM	*((uint32_t*)(0x40078014 ))
#define XDMAC_GIS	*((uint32_t*)(0x40078018 ))
#define XDMAC_GE	*((uint32_t*)(0x4007801C ))
#define XDMAC_GD	*((uint32_t*)(0x40078020 ))
#define XDMAC_GS	*((uint32_t*)(0x40078024 ))
#define XDMAC_GRS	*((uint32_t*)(0x40078028 ))
#define XDMAC_GWS	*((uint32_t*)(0x4007802C ))
#define XDMAC_GRWS	*((uint32_t*)(0x40078030 ))
#define XDMAC_GRWR	*((uint32_t*)(0x40078034 ))
#define XDMAC_GSWR	*((uint32_t*)(0x40078038 ))
#define XDMAC_GSWS	*((uint32_t*)(0x4007803C ))
#define XDMAC_GSWF	*((uint32_t*)(0x40078040 ))
#define XDMAC_CIE(CHANNEL)	*((uint32_t*)(0x40078050 + (CHANNEL*0x40) ))		// +chid * 0x40
#define XDMAC_CID(CHANNEL)	*((uint32_t*)(0x40078054 + (CHANNEL*0x40) ))		// +chid * 0x40
#define XDMAC_CIM(CHANNEL)	*((uint32_t*)(0x40078058 + (CHANNEL*0x40) ))		// +chid * 0x40
#define XDMAC_CIS(CHANNEL)	*((uint32_t*)(0x4007805C + (CHANNEL*0x40) ))		// +chid * 0x40
#define XDMAC_CSA(CHANNEL)		*((uint32_t*)(0x40078060 + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CDA(CHANNEL)		*((uint32_t*)(0x40078064 + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CNDA(CHANNEL)		*((uint32_t*)(0x40078068 + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CNDC(CHANNEL)		*((uint32_t*)(0x4007806C + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CUBC(CHANNEL)		*((uint32_t*)(0x40078070 + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CBC(CHANNEL)		*((uint32_t*)(0x40078074 + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CC(CHANNEL)		*((uint32_t*)(0x40078078 + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CDS_MSP(CHANNEL)	*((uint32_t*)(0x4007807C + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CSUS(CHANNEL)		*((uint32_t*)(0x40078080 + (CHANNEL*0x40) ))	// +chid * 0x40
#define XDMAC_CDUS(CHANNEL)		*((uint32_t*)(0x40078084 + (CHANNEL*0x40) ))	// +chid * 0x40

uint32_t channel_tx;
uint32_t channel_rx;

void dma_init_channel(const uint32_t channel, const uint8_t is_tx)
{

	// dummy for correct 'clear by read' operations
	volatile uint32_t read_dummy = 0;

	// TX CHANNEL SETUP as single block with single microblock transfer

	// read XDMAC_GS to select a free channel
	while( XDMAC_GS & (1 << channel) )
	{
		// error! Channel is already enabled!

		// disable the channel for reconfiguration!
		XDMAC_GD = (1 << channel);

	}

	// clear pending interrupts for 'channel'
	read_dummy = XDMAC_CIS(channel);

		// check if a tx or rx channel should be initialized
	if(is_tx)
	{
		channel_tx = channel;
		// configure the xdmac configuration register
		XDMAC_CC(channel) = ( 1 )	|	// type (peripheral <-> Memory)
							( 0 << 1 )	|	// Memory Burst size (0 = 1 Byte)
							( 1 << 4 )	|	// Direction: Memory -> Peripheral  ( = TX) // ( 0 << 4 )	|	// Direction: Memory -> Peripheral  ( = RX)
							( 0 << 6 )	|	// Trigger config (hardware)	// should be OK
							( 0 << 7 )	|	// Deactivate Memset
							( 0 << 8 )	|	// chunk size: 0 (= 1 data transfered)
							( 0 << 11 )	|	// Datenbreite: 0 (=  1BYTE)
							( 1 << 13 )	|	// SIF Source Interface Identifier		// only id 1 is connected to SPI as seen in the datasheet
							( 1 << 14 )	|	// DIF Destination (Target) identifier
							( 1 << 16 )	|	// SAM Source addressing mode: 1 (=increment to datalenght)
							( 0 << 18 )	|	// DAM Destination addressing mode: 0 (=fixed address)
							( 0 )		|	// READ ONLY: INITD: Channel init done
							( 0 )		|	// READ ONLY: RDIP:  Read in Progress
							( 0 )		|	// READ ONLY: WRIP:  Write in Progress
							( 1 << 24 );	// PERID: Peripheral hardware request line identifier: 1 (= SPI0 Tx req line)
	}else
	{
		channel_rx = channel;
		XDMAC_CC(channel) = ( 1 )	|	// type (peripheral <-> Memory)
		( 0 << 1 )	|	// Memory Burst size (0 = 1 Byte)
		( 0 << 4 )	|	// Direction: Memory <- Peripheral  ( = RX)
		( 0 << 6 )	|	// Trigger config (hardware)	// should be OK
		( 0 << 7 )	|	// Deactivate Memset
		( 0 << 8 )	|	// chunk size: 0 (= 1 data transfered)
		( 0 << 11 )	|	// data width: 0 (= 1 BYTE)
		( 1 << 13 )	|	// SIF Source Interface Identifier
		( 1 << 14 )	|	// DIF Destination (Target) identifier
		( 0 << 16 )	|	// SAM Source addressing mode: 0 (=fixed address)
		( 1 << 18 )	|	// DAM Destination addressing mode: 1 (=increment to datalenght)
		( 0 )		|	// READ ONLY: INITD: Channel init done
		( 0 )		|	// READ ONLY: RDIP:  Read in Progress
		( 0 )		|	// READ ONLY: WRIP:  Write in Progress
		( 2 << 24 );	// PERID: Peripheral hardware request line identifier: 2 (= SPI0 Rx req line)
	}

	XDMAC_CNDC(channel) = 0;
	XDMAC_CBC(channel) = 0;
	XDMAC_CDS_MSP(channel) = 0;
	XDMAC_CSUS(channel) = 0;
	XDMAC_CDUS(channel) = 0;

	XDMAC_CIE(channel) = 1;
	XDMAC_GIE = (1 << channel);

}

 

[insert smart signature here]

Last Edited: Thu. Feb 20, 2020 - 04:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any chance you can post what you did or where it is wrong? I've struggled with that for a while and I have to come back to it in a few days. Thanks in advance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The post marked as a solution does not contain anything which could be used as a solution. Working DMA code or configuration steps showing how to add DMA to the SPI registers in START could be possible solutions but nothing is provided. Apparently a_random_Martin marked his announcement that he found a solution as a "solution".

This forum would be more helpful if the members were coming here not only to ask questions but also to share the answers they found.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I added the full channel init code. Note that ASF4 must initialize the SPI-0 with the normal init.

[insert smart signature here]