| Author |
Message |
|
|
Posted: Jul 17, 2008 - 04:32 PM |
|

Joined: Jan 22, 2008
Posts: 41
|
|
| Writing 10mb file 1GB SD-card take 1m20s. Is this OK? |
|
|
| |
|
|
|
|
|
Posted: Jul 17, 2008 - 04:33 PM |
|


Joined: Jan 07, 2003
Posts: 4580
Location: Oslo, Norway
|
|
Depends on your system and what it is doing at the same time.
So, short answer, sure it is fine... |
|
|
| |
|
|
|
|
|
Posted: Jul 17, 2008 - 04:54 PM |
|

Joined: Jan 22, 2008
Posts: 41
|
|
AVR32UC3A 48MHZ clock. FreeRTOS and FAT from Atmel SDK.
Only one task working. |
|
|
| |
|
|
|
|
|
Posted: Oct 08, 2008 - 11:51 AM |
|

Joined: Jun 15, 2005
Posts: 91
Location: -
|
|
with PBA at 12Mhz I would expect 12 Mbit/Sec = 1,5 MByte/Sec.
So 10 MBytes should be written in 7 Seconds ... |
|
|
| |
|
|
|
|
|
Posted: Oct 08, 2008 - 12:24 PM |
|


Joined: Aug 22, 2002
Posts: 1586
Location: Arendal Norway
|
|
| That is a theoretical speed with no prototocoles handling the data transfer. You will never get that speed in real use. |
|
|
| |
|
|
|
|
|
Posted: Oct 08, 2008 - 12:33 PM |
|

Joined: Jun 15, 2005
Posts: 91
Location: -
|
|
sure you're right, but the overhead seems too big. Its more than a factor of ten too slow ! I think that cannot be the overhead alone.
So what do think, how fast it should be in real world including protocol overhead ? |
|
|
| |
|
|
|
|
|
Posted: Mar 21, 2009 - 01:59 PM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
| i tried with my UC3B design with SPI running at 24MHz to 1GB SD card, and I got about 1MB write in 3.4 seconds. |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2009 - 07:39 AM |
|

Joined: Jun 15, 2005
Posts: 91
Location: -
|
|
with 12MHz I got 250 KB/sec.
not very fast at all ... |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2009 - 08:56 AM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
250KB/s with 12MHz SPI???
wow, that's faster than mine.
mine is about 300KB/s with 24MHz SPI |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2009 - 09:33 AM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
| and i just found out that the file_write_buf() function I used to write a 1GB microSD card has a variable execution time, sometime it could take several times more to finish. This is really bad... |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2009 - 11:11 AM |
|


Joined: Aug 22, 2002
Posts: 1586
Location: Arendal Norway
|
|
| Well an SD card buffers incoming data and then flushes its internal memory so yes you will see great variations on timing when writing to an SD card... |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2009 - 01:22 PM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
but how can I know the size of SD card's internal buffer, so that I can just have the same execution time when I use file_write_buf()
I tried to write 512 bytes every time I use file_write_buf(), but I still got variable time.
Isn't SD card internal block size 512 bytes? |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2009 - 08:21 PM |
|

Joined: Jun 04, 2007
Posts: 490
Location: Norway
|
|
| SD cards may have "sectors" of 4kB, and when you write 512 byte, worst case (every time?) would be the card must read 4kB, modify 512 byte and then write back 4 kB. I don't know if the UC3 framework supports writing multiple sectors, but if you do that there might be a much less difference between theoretical and practical writing speed. |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2009 - 04:11 PM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
| i just tried writing with 4KB everytime, and i sometimes still get about twice the normal execution time. |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2009 - 07:13 PM |
|

Joined: Jun 04, 2007
Posts: 490
Location: Norway
|
|
|
|
|
|
|
Posted: Mar 24, 2009 - 09:40 PM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
| at the moment I don't need to check for reading speed, but just want to have a good writing speed. I could check this in future. |
|
|
| |
|
|
|
|
|
Posted: Mar 25, 2009 - 07:02 AM |
|


Joined: Aug 22, 2002
Posts: 1586
Location: Arendal Norway
|
|
|
Code:
Performance
Timing Typical Maximum
Block Read Access Time 0.5 ms to 100 ms
Block Write Access Time 0.5 ms to 240 ms
CMD1 to Ready after Power-up 50 ms to 500 ms
Sleep to Ready 1 ms to 2 ms
The SD card has an internal controller that accesses the nand flash.
MCI/SPI interface -> Signel chip controller -> NAND media
Read - The read access time is defined as the sum of the two times given by the CSD
parameters TAAC and NSAC. These card parameters define the typical delay
between the end bit of the read command and the start bit of the data block.
Write - The R2W_FACTOR field in the CSD is used to calculate the typical block
program time obtained by multiplying the read access time by this factor. It
applies to all write/erase commands (e.g., SET(CLEAR)_WRITE_PROTECT,
PROGRAM_CSD(CID) and the block write commands). |
|
|
| |
|
|
|
|
|
Posted: Mar 26, 2009 - 08:13 AM |
|

Joined: Dec 31, 2008
Posts: 521
Location: Langgoens, Germany
|
|
Hi,
yesterday we got 1MB/s on a 2GB SD-Card on an EVK1101. The UC3B is running 48MHz, the SPI-SClk 24MHz but block write is done by µC, still without PDCA. |
|
|
| |
|
|
|
|
|
Posted: Mar 26, 2009 - 09:02 PM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
1MB/s????!!!!
What buffer size did you use in your file_write_buf()?
or did you use file_write()? |
|
|
| |
|
|
|
|
|
Posted: Mar 28, 2009 - 03:35 PM |
|

Joined: Dec 31, 2008
Posts: 521
Location: Langgoens, Germany
|
|
Hi,
we didn't use any of these given functions of the framework. We did it ourselves but it's not very universal and not optimized. What we have done is reading the documentation of the S-D-card as for as we got it, made a lot of different tries and got a final fine working solution.
The main reason for the speed should be the write multi blocks command and we write blocks of 512 bytes each 500µs. To write one of the blocks takes 180µs only but to you have to wait until the block is excepted before you start with the next one. |
|
|
| |
|
|
|
|
|
Posted: Mar 28, 2009 - 07:32 PM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
| ok, so you use your own driver for your own card, not a general driver for every SD card, right? |
|
|
| |
|
|
|
|
|
Posted: Mar 28, 2009 - 08:44 PM |
|

Joined: Dec 31, 2008
Posts: 521
Location: Langgoens, Germany
|
|
| Yes it's our own driver but it should work with all kind of cards. We have five different tested from 16MB up to 2GB. |
|
|
| |
|
|
|
|
|
Posted: Mar 29, 2009 - 09:23 AM |
|

Joined: Jul 18, 2005
Posts: 803
|
|
aha!
hehe, do you want to share your driver with us??? |
|
|
| |
|
|
|
|
|
Posted: May 24, 2010 - 05:58 AM |
|

Joined: Jul 13, 2009
Posts: 3
|
|
I finally improved the SD card speed from 250 KB/s to
2.5MB/s. What I did is to change the sd_mmc_mci_mem.c for the sd_mmc_mci_ram_2_mem_0 as following:
Ctrl_status sd_mmc_mci_ram_2_mem_0(U32 addr, const void *ram)
{
// return sd_mmc_mci_dma_ram_2_mem(0, addr, ram);
return sd_mmc_mci_dma_multiple_ram_2_mem(0, addr,ram, ;
}
and change ram_2_mem section in file.c as following:
// Directly data tranfert from buffer to memory
while( 0 != fs_g_seg.u32_size_or_pos )
{
if( CTRL_GOOD != ram_2_memory( fs_g_nav.u8_lun , fs_g_seg.u32_addr, buffer))
{
fs_g_status = FS_ERR_HW;
return u16_nb_write;
}
fs_g_seg.u32_size_or_pos -= 8;// 8;
fs_g_seg.u32_addr++;
buffer += FS_512B * 8;// * 8;
}
// Translate from sector unit to byte unit
u16_nb_write_tmp *= FS_512B;
Basically, the idea is to use DMA write for SD card with 8 sectors each write. With this change, the speed is 10 times higher. |
|
|
| |
|
|
|
|
|
Posted: May 25, 2010 - 05:44 AM |
|

Joined: Jul 13, 2009
Posts: 3
|
|
| I tried more to improve the SD write speed. In theory, you can use write_file() to pre-allocate the file so that the buffer can be transfered to SD using DMA without accessing FAT. But it is not always working especially when you have a large size fiel (eg. 20M byte) or these are already many sectors used in SD card. One way to do it is to use file_write_buf() to pre-allocate all the cluster for the file WITHOUT writing to SD by remove ram_2_mem() line. After the cluster list is established, the file can be writing to SD card at high speed. I tried use 16 sector size DMA to SD card, it takes 4 seconds to write a 20MB file which is 5MByte/s. |
|
|
| |
|
|
|
|
|
Posted: Jun 15, 2010 - 05:48 PM |
|

Joined: Jul 13, 2009
Posts: 3
|
|
One important point to remember that the buffer in the memory which will be written to the SD card needs to be aligned with /4 address which meaning it can be divided by 4 so that it starts at a new 32-bit memory address of MCU. Otherwise, it won't be written in page mode.
I created a function in file.c based on file_write_buf() standard function which is alway in the same file. This function will do multi-sector DMA transfer. Use it to write to SD card. I can get nearly 5MByte/second with SCandisk Ultra III.
//! This function transfer a buffer to a file at the current file position
//!
//! @param buffer data buffer
//! @param u16_buf_size data size
//!
//! @return number of byte write
//! @return 0, in case of error
//!
U16 file_write_buf_multi_dma( U8 _MEM_TYPE_SLOW_ *buffer , U16 u16_buf_size )
{
_MEM_TYPE_FAST_ U16 u16_nb_write_tmp;
_MEM_TYPE_FAST_ U16 u16_nb_write;
_MEM_TYPE_FAST_ U16 u16_pos_in_sector;
if( !fat_check_mount_select_open())
return FALSE;
if(!(FOPEN_WRITE_ACCESS & fs_g_nav_entry.u8_open_mode))
{
fs_g_status = FS_ERR_READ_ONLY;
return FALSE;
}
u16_nb_write = 0;
while( 0 != u16_buf_size )
{
// The file data sector can been directly transfer from buffer to memory (don't use internal cache)
u16_pos_in_sector = fs_g_nav_entry.u32_pos_in_file % FS_512B;
if( (0== u16_pos_in_sector)
&& (FS_512B <= u16_buf_size)
#if (defined __GNUC__) && (defined __AVR32__) || (defined __ICCAVR32__)
&& (Test_align((U32)buffer, sizeof(U32)))
#endif
)
{
u16_nb_write_tmp = u16_buf_size / FS_512B; // read a modulo sector size
// Get and eventually alloc the following sector segment of file
if( !fat_write_file( FS_CLUST_ACT_SEG , u16_nb_write_tmp ))
return FALSE;
// Truncate the segment found if more larger than asked size
if( u16_nb_write_tmp < fs_g_seg.u32_size_or_pos)
{
fs_g_seg.u32_size_or_pos = u16_nb_write_tmp;
}else{
u16_nb_write_tmp = fs_g_seg.u32_size_or_pos;
}
// Directly data tranfert from buffer to memory
if( CTRL_GOOD != sd_mmc_mci_dma_multiple_ram_2_mem(fs_g_nav.u8_lun , fs_g_seg.u32_addr, buffer, fs_g_seg.u32_size_or_pos))
{
fs_g_status = FS_ERR_HW;
return u16_nb_write;
}
fs_g_seg.u32_addr += fs_g_seg.u32_size_or_pos;
buffer += FS_512B * fs_g_seg.u32_size_or_pos;
fs_g_seg.u32_size_or_pos = 0;
// Translate from sector unit to byte unit
u16_nb_write_tmp *= FS_512B;
}
else
{
// The file data can't been directly transfer from buffer to memory, the internal cache must be used
// Tranfer and eventually alloc a data sector from internal cache to memory
if((fs_g_nav_entry.u32_pos_in_file == fs_g_nav_entry.u32_size)
&& (0==u16_pos_in_sector) )
{
// Eventually alloc one new sector for the file
if( !fat_write_file( FS_CLUST_ACT_SEG , 1 ))
return FALSE;
// Update the cache
fs_gu32_addrsector = fs_g_seg.u32_addr;
if( !fat_cache_read_sector( FALSE )) // The memory is not readed because it is a new sector
return FALSE;
}else{
// The sector must existed then alloc no necessary
if( !fat_write_file( FS_CLUST_ACT_ONE , 1 ))
return FALSE;
}
// Flag internal cache modified
fat_cache_mark_sector_as_dirty();
// Compute the number of data to transfer
u16_nb_write_tmp = FS_512B - u16_pos_in_sector; // The number is limited at sector size
if( u16_nb_write_tmp > u16_buf_size )
u16_nb_write_tmp = u16_buf_size;
// Tranfer data from buffer to internal cache
memcpy_ram2ram( &fs_g_sector[ u16_pos_in_sector ], buffer , u16_nb_write_tmp );
buffer += u16_nb_write_tmp;
}
// Update positions
fs_g_nav_entry.u32_pos_in_file+= u16_nb_write_tmp;
u16_nb_write += u16_nb_write_tmp;
u16_buf_size -= u16_nb_write_tmp;
// Update file size
if( fs_g_nav_entry.u32_pos_in_file > fs_g_nav_entry.u32_size )
{
fs_g_nav_entry.u32_size = fs_g_nav_entry.u32_pos_in_file;
}
}
return u16_nb_write; // All buffer is writed
} |
|
|
| |
|
|
|
|
|