Цитата(Dog Pawlowa @ Nov 24 2008, 19:39)

Пробовать то можно, но существующие порт efsl (например) для SD интерфейса ARM7 NXP не использует DMA. В отличие от SPI, между прочим.
Что касается SPI AVR, то что толку разогнать сам SPI? нужно же еще флаг готовности анализировать, адрес инкрементировать, проверять адрес на соответствие диапазону. Без DMA+IRQ сделать это с высокой скоростью нереально.
Это так, но если данные идут непрерывно, без дефрагментации то можно просто установить размер блока данных, скажем 64 кБ и принимать их непрерывно, а потом уже делать проверки и прочая. мне лично больше 256кбит/с не было нужно, поэтому не пробовала.
вот например часть кода из рабочей программы с функциями установки длины блока, считывания блока а также инициализацией карты, чтением FAT и т.д:
Код
unsigned char sec_per_clust, data[512];
unsigned int j, j2;
unsigned long fat_base, cluster_base, addr;
flash unsigned char
cmd0[6] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95},
cmd1[6] = {0x41, 0x00, 0x00, 0x00, 0x00, 0x01},
blck_ln_200[6] = {0x50, 0x00, 0x00, 0x02, 0x00, 0x01}; //элементы 2-5 задают размер блока, в данном случае 512 байт
...
void set_block_len(void)
{
spi(0xff);
for(i=0; i<6; i++) spi(blck_ln_200[i]);
while(spi(0xff)==0xff);
spi(0xff);
}
...
void read_single_block(unsigned long daddr)
{
//k=255; //убрать комментарии если не хотите зависания при отсутствии карты
do
{
spi(0xff);
spi(0x51);
spi(daddr>>24);
spi(daddr>>16);
spi(daddr>>8);
spi(daddr);
spi(0x01);
while(spi(0xff)==0xff);
//--k;
}
while((SPDR!=0x00));//&&(k>0));
while(spi(0xff)!=0xfe);
for(j2=0; j2<512; j2++) data[j2]=spi(0xff); //разумеется, количество итераций зависит от размера считываемого блока
spi(0xff);
spi(0xff);
spi(0xff);
}
...
//далее функция преобразования четырех байтов в одно 32-битное число (ну не нашла я готовых функций)
void uchar_to_ulong(unsigned long *p, unsigned int offset, unsigned int count)
{
*p=0;
for(; count>0; count--)
{
*p|=*(data+offset+count-1);
if(count>1) *p<<=8;
}
}
...
//=======инициализация карты===========
for (i=0; i<10; i++) spi(0xff);
delay_ms(1);
//========сброс карты===============
card_cs=0;
do
{
spi(0xff);
for(i=0; i<6; i++) spi(cmd0[i]);
for(i=0; i<8; i++) if(spi(0xff)!=0xff) break;
}
while(SPDR!=0x01); //ждем ответа 0x01 - спящий режим
//spi(0xff);
//CS=1;
//=======инициализация режима spi карты=======
//CS=0;
do
{
spi(0xff);
for(i=0; i<6; i++) spi(cmd1[i]);
for(i=0; i<8; i++) if(spi(0xff)!=0xff) break;
}
while(SPDR!=0x00);
//spi(0xff);
set_block_len();//0x100);
read_single_block(0); //чтение master boot record
card_cs=1;
uchar_to_ulong(&addr, 0x1c6, 4); //позиция partition boot record в секторах
card_cs=0;
read_single_block(addr<<9); //чтение pbr
card_cs=1;
//================вычисление root base=======================
uchar_to_ulong(&root_base, 0x0e , 2); //зарезервированных секторов
root_base+=addr; //fat base в секторах
fat_base=root_base<<9; //fat base в байтах
uchar_to_ulong(&addr, 0x16, 2); //секторов на fat
addr<<=1; //удвоение из-за того что 2 таблицы fat
root_base+=addr; //root base в секторах
root_base<<=9; //в байтах
//================вычисление cluster base====================
sec_per_clust=data[0x0d]; //секторов на кластер
addr=data[0x0d];
addr<<=10; //байтов на 2 фиктивных кластера
cluster_base=root_base-addr;
uchar_to_ulong(&addr, 0x11, 2); //число записей в корневом каталоге
addr<<=5; //размер корневого каталога в байтах
cluster_base+=addr; //cluster base в байтах
card_cs=0;
read_single_block(root_base); //чтение корневого каталога
код читается плохо, согласна (написано полностью с нуля), но разобраться можно. спрашивайте, если что.