ATSAMD21 SPI is doing my head in...

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

Ok I have done this numerous times with other Atmel chips...UC3, AVR, ATSAME70 and so on...but only this time with ATSAMD21...and its not working. I am connecting a flash AT45DB161E chip using SPI with ucontroller. And I am not reading in the correct bytes. I have a feeling its something to do with the "double buffering" of receive.

//Send a single byte via SPI.
unsigned char SPI_WriteByte(SPI_Int *spi, unsigned char data)
{
	//Make sure there is no byte waiting already.
	while(!(spi->SerComPort->SPI.INTFLAG.reg & SERCOM_SPI_INTFLAG_DRE));
	spi->SerComPort->SPI.DATA.reg = data & SERCOM_SPI_DATA_MASK;
	return OK;
}


//Receive a single byte via SPI.
unsigned char SPI_ReadByte(SPI_Int *spi, unsigned char *data)
{
	//Write dummy byte to read in.
	if(SPI_WriteByte(spi, spi->TxfrByte) != OK)
	{
		*data = spi->TxfrByte;
		return KO;
	}

	if (spi->SerComPort->SPI.STATUS.reg & SERCOM_SPI_STATUS_BUFOVF)
	{
		spi->SerComPort->SPI.STATUS.reg = SERCOM_SPI_STATUS_BUFOVF;
	}

	//Make sure we have fully received a byte.
	while(!(spi->SerComPort->SPI.INTFLAG.reg & SERCOM_SPI_INTFLAG_RXC));
	*data = spi->SerComPort->SPI.DATA.reg;
	return OK;	
}

//Get manufacturer id and device details.
static void AT45_PrintDeviceInfo(void)
{
	unsigned short i, j;
	unsigned char data[16];
	
	spi_MEM.ChipSelect(SPI_MEM_FL_CS_PIN);				//Select the flash mem.
	SPI_WriteByte(&spi_MEM, 0x9F);

	SPI_ReadByte(&spi_MEM, &data[0]);					//Manufacture ID: 0x1F (Adesto).
	SPI_ReadByte(&spi_MEM, &data[1]);					//Device ID: 0x26 (Byte 1).
	SPI_ReadByte(&spi_MEM, &data[2]);					//Device ID: 0x00 (Byte 2).
	SPI_ReadByte(&spi_MEM, &data[3]);					//Extended Device Info: 0x00 or 0x01 (String Length).

	if (data[3] > 0)
	{
		for (i = 4, j = 0; i < 16 && j < data[3]; i++, j++)
		{
			SPI_ReadByte(&spi_MEM, &data[i]);
		}
	}

	spi_MEM.ChipUnselect(SPI_MEM_FL_CS_PIN);			//Deselect the flash mem.
	DebugPrintHex("FlashID: ", data, 4);
}

 

On the oscilloscope I am seeing correct byte responses from the MISO pin (slave). But uController is not reading them correctly. It is reading bytes that seem out of order....Also I try to detect OVER for overflow and this bit is being set as well. Which tells me it is something to do with double buffering....

Ok here is another question...when we first time call SPI_WriteByte() it sends a byte...but we do need to flush its DATA reg (as it also received dummy) before we start to read in byte responses? Like using SPI_readByte() that follow immediately after?

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

Ok here is a clue...

https://community.atmel.com/foru...

It seems the WriteByte() function must flush the read in byte (in the process of writing). Otherwise when we go to call ReadByte() the FIFO gets messed up.

So the ReadByte() should not call WriteByte() internally but implement whats inside ofWriteByte().

Hope this helps someone.