"SPI bug" in at91 linux 4.9.xxx

This forum is for users of Microchip MPUs and who are interested in using Linux OS.

Moderator: nferre

Stefan J
Posts: 12
Joined: Thu Sep 15, 2016 10:07 am

"SPI bug" in at91 linux 4.9.xxx

Tue Jul 04, 2017 6:35 pm

There is a problem reading large amount of data form flash which is connected to a SAMA3D35 via SPI.

dmesg-print:

Code: Select all

[    1.420000] atmel_spi f8008000.spi: version: 0x213
[    1.420000] atmel_spi f8008000.spi: Using dma1chan0 (tx) and dma1chan1 (rx) for DMA transfers
[    1.430000] m25p80 spi32766.0: s25fl164k (8192 Kbytes)
[    1.440000] atmel_spi f8008000.spi: Atmel SPI Controller at 0xf8008000 (irq 22)
...
[   44.240000] ------------[ cut here ]------------
[   44.240000] WARNING: CPU: 0 PID: 629 at /home/user/myTC/poky/sek4/tmp/work-shared/sama5d3xek/kernel-source/drivers/spi/spi-atmel.c:1280 atmel_spi_transfer_one_message+0x444/0x9b8
[   44.240000] Modules linked in: sek4bsp(O)
[   44.240000] CPU: 0 PID: 629 Comm: RTSLoader Tainted: G           O    4.9.30-linux4sam_5.6-rc6 #1
[   44.240000] Hardware name: Atmel SAMA5
[   44.240000] [<c010cbfc>] (unwind_backtrace) from [<c010a71c>] (show_stack+0x10/0x14)
[   44.240000] [<c010a71c>] (show_stack) from [<c0115920>] (__warn+0xe4/0xfc)
[   44.240000] [<c0115920>] (__warn) from [<c01159e8>] (warn_slowpath_null+0x20/0x28)
[   44.240000] [<c01159e8>] (warn_slowpath_null) from [<c03eb3c8>] (atmel_spi_transfer_one_message+0x444/0x9b8)
[   44.240000] [<c03eb3c8>] (atmel_spi_transfer_one_message) from [<c03ea124>] (__spi_pump_messages+0x304/0x454)
[   44.240000] [<c03ea124>] (__spi_pump_messages) from [<c03ea3dc>] (__spi_sync+0x15c/0x16c)
[   44.240000] [<c03ea3dc>] (__spi_sync) from [<c03ea410>] (spi_sync+0x24/0x3c)
[   44.240000] [<c03ea410>] (spi_sync) from [<c03c3c4c>] (m25p80_read+0x2e4/0x370)
[   44.240000] [<c03c3c4c>] (m25p80_read) from [<c03cff80>] (spi_nor_read+0x80/0xf4)
[   44.240000] [<c03cff80>] (spi_nor_read) from [<c03ba974>] (mtd_read+0x78/0xa8)
[   44.240000] [<c03ba974>] (mtd_read) from [<c03bfc70>] (mtdchar_read+0xf8/0x230)
[   44.240000] [<c03bfc70>] (mtdchar_read) from [<c01a4af4>] (__vfs_read+0x1c/0x10c)
[   44.240000] [<c01a4af4>] (__vfs_read) from [<c01a5858>] (vfs_read+0x8c/0x118)
[   44.240000] [<c01a5858>] (vfs_read) from [<c01a6644>] (SyS_read+0x3c/0x90)
[   44.240000] [<c01a6644>] (SyS_read) from [<c01073e0>] (ret_fast_syscall+0x0/0x1c)
[   44.240000] ---[ end trace 028eaee5cd77d987 ]---
[   44.240000] m25p80 spi32766.0: spi transfer timeout
A hopefully amost working c code snipet for that:

Code: Select all

/* open source file */
fd = open("/dev/mtd8", O_NOCTTY);
if (-1 == fd)
{
	printf("open failed", errno);
	fd = 0;
	goto JL_FAILED;
}

/* detect size of source file */
mtd_info_t fd_info;
if (-1 == ioctl(fd, MEMGETINFO, &fd_info))
{
	printf("ioctrl[MEMGETINFO] failed", errno);
	goto JL_FAILED;
}
size_t flashSize = (size_t) fd_info.size;
if (0 == flashSize)
{
	printf("Database is empty!");
	goto JL_FAILED;
}
printf("EsaSystemInfo: Database is %d bytes in size. Reading from flash in %d Bytes chunks.", fd_info.size, fd_info.erasesize);

/* create buffer */
uint8_t * InternalMemPtr__ = calloc(flashSize, sizeof(uint8_t));

/* read data form device */
size_t bytesRemaining = flashSize;
uint8_t *pWritePtr = (uint8_t *)pBuffer;
while(bytesRemaining)
{

	const ssize_t bytesRead = read(fd, pWritePtr, bytesRemaining > fd_info.erasesize ? fd_info.erasesize : bytesRemaining);
	if (-1 == bytesRead)
	{
		printf("Failed to read from device '%s'! %u Bytes remaining. Error: %s", "/dev/mtd8", (unsigned int)bytesRemaining, strerror(errno));
		goto JL_FAILED;
	}
	else if (0 == bytesRead)
	{
		printf("Encountered EoF while trying to read %lu bytes. This may lead to errors.", bytesRemaining);
		break;
	}
	else
	{
		bytesRemaining -= bytesRead;
		pWritePtr += bytesRead;
	}
}
When trying to read the memory in one flush with:

Code: Select all

const ssize_t bytesRead = read(fd, pWritePtr, bytesRemaining);
I can produce the timeout warning.
In the older 4.4.xxx kernel it worked without the timeout.
I checked it for the 4.9.30,4.9.33, 4.9.34 and 4.9.35 kernels. Same error.

Hope that helps if someone has a similar problem.
CortexAlex
Posts: 8
Joined: Thu Jan 26, 2017 12:48 pm

Re: "SPI bug" in at91 linux 4.9.xxx

Wed Jul 12, 2017 1:26 pm

hi,

interesting topic as I'm having the same issue when reading a large buffer on a peripheral connected via spi2 on sama5d4 using kernel 4.4.26-linux4sam_5.5.
jay214128
Posts: 9
Joined: Fri Jan 23, 2015 3:29 am

Re: "SPI bug" in at91 linux 4.9.xxx

Wed Nov 29, 2017 8:38 pm

I think I may be experiencing the same issue with the at91sam9x5 (9G25,9G45) devices. My issue is that MTD flash reads of SPI attached devices are really slow with 4.9 compared to 4.4 and 3.2 kernels. Example:

Code: Select all

time dd if=/dev/mtdblock5 of=/tmp/uboot-env1.bin 
264+0 records in
264+0 records out
real    0m 3.20s
user    0m 0.01s
sys     0m 0.01s
This command only takes about 0.39 seconds with the 4.4 kernel. It is about 100 times slower with the 4.9 kernel.
I have an application that also reads an MTD dataflash partition (via SPI) and it now times out. It does read in smaller blocks, though, not in one go.

Anyone figure this one out?
jay214128
Posts: 9
Joined: Fri Jan 23, 2015 3:29 am

Re: "SPI bug" in at91 linux 4.9.xxx

Thu Nov 30, 2017 7:50 pm

Using a logic analyzer, I have observed the following:

With the previous kernels, the SPI clock is fairly symmetrical. With the 4.9.52 kernel, it is highly asymmetrical. With the 4.9.x kernel, the high portion of the clock pulse is about the same as that in the previous kernels, but the low portion of the clock pulse is much longer (~ 100 times longer). Something has gotten buggered with the SPI clock. With some luck, I might track this down.

Return to “Linux”

Who is online

Users browsing this forum: No registered users and 2 guests