ARM CORTEX M7 SPI Problem

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

Hi, I am using an ARM Cortex M7 processor (ATSAME70Q21 with the SAME70 Xplained kit) and having some issue getting the SPI working as a master. The code is below.

 

When I run it, I get trap into  the Dummy_Handler that is for the unused interrupt. When the program run the spi_master_setup(), the spi_set_transfer_delay()  seems to generate that unused interrupt  when writing to the CSR register and force the program into a while loop in the Dummy_handler.

I am using the Atmel demo code for the SAME70 Xplained and just added the code to initialize the SPI as a master.

Any idea?

Thanks,

Charles

 

ioport_set_pin_level( PIO_PD25B_SPI0_NPCS1, 0 );

 

spi_disable(SPI0);

spi_master_init(SPI0);

spi_master_setup_device(SPI0, &SPI_ADC1, SPI_MODE_3, BAUDRATE, SAME70_XPLAINED);

spi_enable(SPI0);

 

//Read Data

spi_read_packet(SPI0, Rx_Data, Rx_Length);

 

//Turn off ADC chip select

ioport_set_pin_level( PIO_PD25B_SPI0_NPCS1, 1 );

 

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

I think I have an answer. When defining the PSI device ID structure, I did set the device ID to the chip select pin. The device iD need to be ether 0,1,2 or 3 corresponding to the SPI selected. When I change it to SPI0, it does not generate a unused interrupt anymore.

 

struct spi_device SPI_ADC1 = {

//! Board specific select id

.id = SPI0 //PIO_PD25B_SPI0_NPCS1

};

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

I am still having an issue with SPI chip select SPIO_NPCS1 using a SAME70Q21 ARM cortex 7. Accordingly to the datasheet SAM E70 page 942, it shows that chip select can be enabled when PCSDEC = 0 and setting the bit for PCS. My question is how do you deselect it? the datasheet shows 4 combinations to select the proper chip select and show 0x0f as "forbidden". After selecting the chip select, how does it come off?

Thanks,

Charles 

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

I'm using the ASF libraries for SPI communication, not sure if you're using atmel start or ASF. But here's an example from my code to receive data from a resistive touch screen controller - reads 5 bytes.

 

#define SPI_CS_TouchController 1
#define SPI_CS_TouchController_PCS	spi_get_pcs(1)

static void spi_master_init(void)
{
	spi_enable_clock(SPI0);
	spi_disable(SPI0);
	spi_reset(SPI0);
	
	spi_set_master_mode(SPI0);
	spi_disable_mode_fault_detect(SPI0);
	spi_set_variable_peripheral_select(SPI0);
	spi_set_delay_between_chip_select(SPI0,0x40);
	
	//touch screen
	spi_set_clock_polarity(SPI0, SPI_CS_TouchController, 0);
	spi_set_clock_phase(SPI0, SPI_CS_TouchController, 0);
	spi_set_bits_per_transfer(SPI0, SPI_CS_TouchController,	SPI_CSR_BITS_8_BIT);
	spi_set_baudrate_div(SPI0, SPI_CS_TouchController,	(sysclk_get_peripheral_hz()	/ 500000));//500kHz sclk
	spi_set_transfer_delay(SPI0, SPI_CS_TouchController, 0x78, 0xDD);//delay from cs to sclk ~ 1us, delay from byte sclk end to next byte sclk begin 60us
	spi_configure_cs_behavior(SPI0, SPI_CS_TouchController, SPI_CS_RISE_NO_TX);
}

void GetTouchScreenXY(void)
{
	uint8_t i;
	static uint16_t ReadData;
	uint8_t touchReportPacket[5];
	uint8_t lastXFER = 0;
		   	
	
	for (i = 0; i < 5; i++) {
		__ISB();
		__DSB();
		
		if(i == 4)
			lastXFER = 1;
			
		spi_write(SPI0, 0, SPI_CS_TouchController_PCS, lastXFER);
		
		/* Wait transfer done. */
		while ((spi_read_status(SPI0) & SPI_SR_RDRF) == 0);
		spi_read(SPI0, &ReadData, &uc_pcs);
		
		touchReportPacket[i] = ReadData;
		__ISB();
		__DSB();
	}
}

 

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

Are you talking about disabling the chip select or toggling it off after each transmission? The latter should be automatic. Writing data into the transmit data register (SPI_TDR) should toggle your chip select automatically if your peripheral is configured and enabled. You shouldn't have to do that in software. If you're talking about disabling the chip select, just disable the peripheral. 

 

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

There are options with how the chip select toggles though.

 

on this line:

spi_configure_cs_behavior(SPI0, SPI_CS_TouchController, SPI_CS_RISE_NO_TX);

the SPI_CS_RISE_NO_TX means that the chip select will not rise after each byte sent but instead wait for you to tell it which byte is the last one and then rise. lastXFER is set on the last byte of communication in the line here:

 

spi_write(SPI0, 0, SPI_CS_TouchController_PCS, lastXFER);