FreeRTOS+FAT on Altera (Intel) Cyclone V SoC

hdkn wrote on Tuesday, May 14, 2019:

Hi,

I am evaluating FreeRTOS (v10.1.1) and +FAT (160919) on the Altera (Intel) Cyclone V SoC kit. I created a project based on the “blinky” sample, added +FAT from 160919_FreeRTOS_Labs, and created a rudimentary (e.g. no DMA) ff_sddisk.c based on the examples from the other boards.

The problem is, I can only get about 49KB/s file write/read speeds. My wish is to get 5MB/s or above. But 49 kilobytes seems just too slow, even with my basic driver. The card is Kingston 16GB SDHC w/ UFS-I logo, so I believe it should at least be capable of 10MB/s.

I was wondering if anyone has tried it on the Cyclone V. Any help would be appreciated.

When I switched to RAM disk, I can get 94MB/s on writes and 142MB/s on reads. So, I believe the FreeRTOS core and +FAT are decently configured and running OK.

For the low-level drivers, I’m using Altera HWLib (13.1?) that came with the Cyclone V blinky sample. But since the included alt_sdmmc wasn’t quite useable, I had to swap it with EDS version 18.0’s.

Thanks

heinbali01 wrote on Wednesday, May 15, 2019:

Hi Hideki, great that you’re working on FreeRTOS+FAT on the Altera/Intel Cyclone V SoC. There already is a driver for FreeRTOS+TCP, but not a driver for +FAT.

I don’t know much about the SD/MMC interface that you’re using. But what I do know is that if you pass large “aligned” blocks of data to the +FAT driver, they will be passed directly to the low-level driver.
The larger the blocks, the higher the transmission speeds will be.

With “aligned” I mean that you should write/read with multiples of 512 bytes (sector size).

How is your card reader connected? Is it using 1, 4 of 8 bits?
Did you check the clocks that are related to the interface?

Are you using a module called alt_sdmmc.c ?
Are you using functions like alt_sdmmc_write() and alt_sdmmc_read()?
What’s the value of the size parameter?
Hein

hdkn wrote on Wednesday, May 15, 2019:

Hello Hein,

Thanks for replying.

Regarding alignment. The file write/read test functions simply pass the whole data buffer directly to the ff_stdio functions. The buffer address is aligned and I use byte sizes of N x 1024. The calling code looks something like:

	/* Allocate the file buffer at a high-enough address. */
	pcFileBuffer = ( void * ) 0x10000000; // 256M
            ...
	xWritten = ff_fwrite( pcFileBuffer, 1, xSize, xFp );

According to the dev board’s manual: “This 4-bit data interface can sustain burst read operations at up to 50 MHz for a throughput of 25 MBps.”

I will check the clock and other settings today.

I am using alt_sdmmc.c, but the one from HWLib 18.0 because the one under the CORTEX_A9_Cyclone_V_SoC_DK demo lacked basic features like getting the max sectors, which is needed for initializing FF_Disk.

I do use alt_sdmmc_read() and alt_sdmmc_write(). I think that’s all they have for general read/write. I pass ulSectorCount x 512 for the size. Here’s what I use in prvFFWrite():

	void *pvDest = ( void * ) ( ulSectorNumber * 512UL );

		xResult = alt_sdmmc_write( &xCardInfo,	// card_info
			pvDest,								// dest
			( void * ) pucBuffer,				// src
			ulSectorCount * 512UL );			// size

Forgot to mention that the card was formatted with FF_SDDiskFormat() just to be complete.

I am attaching the relevant source files for your reference.

Hideki

heinbali01 wrote on Thursday, May 16, 2019:

FF_SDDiskFormat() : what cluster size did it get?

49KB/s : that is extremely slow. I saw higher speeds on much simpler CPU’s. Wouldn’t it make a big difference to use DMA at full speed?

Does the driver really use the multi-sector read/write and not the single-sector commands?

The code that you’re attaching looks goot to me

hdkn wrote on Thursday, May 16, 2019:

Hello Hein,

Good news, I got it working! I was able to achieve 6.9MB/s and 7.9MB/s on writes and reads, respectively. I am happy with these numbers.

As you mentioned checking the clock values, I dumped all card related values and saw these:

  • SD/MMC clock freq = 200MHz.
  • clock divider = 62.
  • card speed = 403225 (speed = 200^6 / 4 x 2 x clk_div).
  • card bus width = 1 (bit).

Apparently, the above settings are necessary for the card discovery during POR. But now the 49 kilobytes/s can be explained. Dividing the above speed by 8 bits gives you ~50KB/s.

I revisted the API document to see if I overlooked anything and found these functions, alt_sdmmc_card_speed_set() and alt_sdmmc_card_bus_width_set(). Calling them with 25Mbps and 4-bit width enabled the 6.9 & 7.9MB/s speeds. I also tried a value above 25Mbps, which, according to the code, switches to the high-speed (50MHz ) mode. But it didn’t make it any faster. I wonder if that is limited by the SD card itself.

To answer your questions, FF_SDDiskFormat() got 64 sectors/cluster. alt_sdmmc uses multiple block read/write.

Bad news is, alt_sdmmc only supports SD storage devices:( It was on the top page of the HWLib SD/MMC document… What I will eventually need for the production is eMMC interface. So, now I have a new, bigger problem. Not sure what to do now.

heinbali01 wrote on Friday, May 17, 2019:

Hi Hideki, that is good news.

How strange that a SD/MMC driver doesn’t support MMC cards. It does have a define for ALT_SDMMC_CARD_TYPE_MMC, which is never used in the code.

Hello,

Is there any way I can see these source files that were attached to this original chain?

thank you

Attached to this post.ff_sddisk.c (14.1 KB) main_fstest.c (15.5 KB)