реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> SD card on SPI, как организовать общение c SD картой по SPI ?
zltigo
сообщение Sep 9 2009, 11:23
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Ndf @ Sep 9 2009, 13:15) *
Может какую команду еще пропустил?

Информация о SD читается из CSD. 9 команда. Соответственно все решения по частоте лично у меня принимаются после разборки ответа.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Ndf
сообщение Sep 9 2009, 12:36
Сообщение #17


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 22-08-07
Пользователь №: 29 977



Хм...в SPI-mode эта команда имеет параметры Argument-none, Resp.-R1, то есть 0 если все нормально...очень информативно. Возможно вы имеете ввиду что нужно при старте используя дефолтный ММС mode послать команду, разобрать и войти в SPI mode? Зачем тогда вообще переходить в SPI режим, ведь речь то идет именно о нем?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Sep 9 2009, 12:41
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Ndf @ Sep 9 2009, 14:36) *
Хм...в SPI-mode эта команда имеет параметры Argument-none, Resp.-R1, то есть 0 если все нормально...очень информативно.

Эта команда, в любом из режимов, уж поверьте на слово smile.gif позволяет считать после ее выполнения 16 байт информации. ВПОЛНЕ информативных smile.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Ndf
сообщение Sep 10 2009, 12:36
Сообщение #19


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 22-08-07
Пользователь №: 29 977



Прочитал еще раз spec... да, действительно, после ответа R1 на CMD9, клоки снимать не надо так как MMC/SD карта следом отправляет данные CSD регистра. Но дело в том, что в поле TRAN_SPEED находится 0x2a (20 Мгц) т.е. моя карта самая обычная, стало быть проблема не в этом. Укоротил шлейф карты до 10см, напаял блокир кондер 0,1 мкф, даже поставил резистор 100 Ом в цепь MISO - ничего не помогает... smile3046.gif
Go to the top of the page
 
+Quote Post
Ndf
сообщение Sep 11 2009, 13:04
Сообщение #20


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 22-08-07
Пользователь №: 29 977



Отвечу сам себе... причину нашел 1111493779.gif , и она кроется где то в недрах DMA режима. Дело в том что в исходнике от Analog Device почему то используется SPI в DMA chain mode with interrupts, т.е. модулю DMA нужно сообщить адрес первого байта команды, кол-во байт, назначить процедуру прерывания, куда попадаем после приема очередного байта. Такой код предназначен для работы в фоновом режиме и использует всю мощь проца,но с другой создает много проблем - например DMA работает только с внутренней памятью, и имеет свои заморочки которые часто заканчиваются зависанием проца (например когда несколько модулей его используют одновременно). На экране осциллографа все выглядит так как должно быть, но карта постоянно выдает ошибки. В общем отключил я все эти навороты, написал блокирующую процедуру вывода в SPI и все заработало вплоть до 20 Мгц CLK smile.gif

Сообщение отредактировал Ndf - Sep 11 2009, 13:05
Go to the top of the page
 
+Quote Post
MiklPolikov
сообщение Jan 19 2013, 12:09
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 2 015
Регистрация: 23-01-07
Из: Москва
Пользователь №: 24 702



Цитата(Ndf @ Sep 10 2009, 16:36) *
Прочитал еще раз spec... да, действительно, после ответа R1 на CMD9, клоки снимать не надо так как MMC/SD карта следом отправляет данные CSD регистра.


Скажите , в каком документе написано как читать CSD в режиме SPI ?

Уже третий день мучаюсь : Принимаю всё что карта ответила на CMD9 , 21 байт он начала и до того как пошли FF.
Пытаюсь увидеть последовательность байтов как в CSD Version 1.0 (карта 1Гб) :
1 байт 0,
2,3 байт хх
4 байт 32 или 5А
Но не вижу что бы 0 шёл на три байта раньше 0x32


--------------------
Если у Вас нет практического опыта в данной теме- не вступайте в дискуссию и не пишите никаких теоретических рассуждений! Заранее спасибо !
Go to the top of the page
 
+Quote Post
polyname
сообщение Jan 20 2013, 11:58
Сообщение #22


Частый гость
**

Группа: Участник
Сообщений: 147
Регистрация: 18-05-12
Пользователь №: 71 915



может поможет - вот рабочий код:
Код
enum sd_type {SD_NONE, SD_V1, SD_V2, MMC_V3};
enum {CSD_V1=0, CSD_V2=1};
enum {
    CMD0=0,CMD1=1,CMD2=2,CMD8=8,CMD9=9,CMD10=10,CMD13=13,CMD16=16,CMD17=17,
    CMD55=55,CMD58=58,CMD59=59,ACMD41=41
};
enum {
    R1_READY=0x00, R1_IDLE=0x01, R1_ERASE_RESET=0x02, R1_CMD_ILLEGAL=0x04,
    R1_CMD_CRC=0x08, R1_ERASE_SEQ=0x10, R1_ADDR=0x20, R1_PARAM=0x40
};
U8 sd_get_CSD(void) {
    sd_cs(0);
    sd_cmd_NoCRC(CMD9, 0x00000000, 0x57);
    sd.r1 = (sd_get_R1() == R1_READY);
    if (sd.r1) {
        sd.r1 = sd_get_buf(&sd.csd[0], 16, 0xFE);
        sd_update_csd();
    }
    return sd.r1;
}
void sd_cmd_NoCRC(U8 cmd, U32 data, U8 crc) {
    spi_tx_U8_MSB(0xFF);
    spi_tx_U8_MSB(0x40 | cmd);
    spi_tx_U8_MSB(data >> 24);
    spi_tx_U8_MSB(data >> 16);
    spi_tx_U8_MSB(data >> 8);
    spi_tx_U8_MSB(data);
    spi_tx_U8_MSB((crc << 1) | 1);
}
U8 sd_get_R1(void) {
    U8 r1 = 0;
    U16 to = SD_CMD_TIMEOUT;
    do { r1 = spi_tx_U8_MSB(0xFF);
    } while (--to && (r1 == 0xFF));
    sd.r1 = r1;
    return r1;
}
U8 sd_get_buf(U8 *buf, U16 len, U8 token) {
    U8 r1 = 0;
    U16 to = SD_CMD_TIMEOUT;
    do {
        r1 = (spi_tx_U8_MSB(0xFF) == token);
    } while (--to && !r1);
    if (r1) {
        spi_rx_buf_MSB(buf, len);

        //skip CRC
        spi_tx_U8_MSB(0xFF);
        spi_tx_U8_MSB(0xFF);
    }
    return r1;
}
void sd_update_csd(void) {
    sd.sectors = 0;
    if (sd_ok()) {
        sd.ver = sd.csd[0] >> 6;
        if (sd.ver == CSD_V1) {
            U32 size = 1UL << (sd.csd[5] & 0xF);
            size *= 1UL << (((sd.csd[9] & 0x3) << 1) + (sd.csd[10] >> 7) + 2);
            size *= (U32)((((U16)(sd.csd[6] & 3)) << 10) + ((U16)sd.csd[7] << 2) + ((U16)(sd.csd[8] & 0xC0) >> 6) + 1);
            sd.sectors = size >> 9;
        } else if (sd.ver == CSD_V2) {
            sd.sectors = ((((U32)(sd.csd[7] & 0x3F)) << 16) + (((U32)sd.csd[8]) << 8) + (U32)sd.csd[9]) << 10;
        }
    }
}


Сообщение отредактировал polyname - Jan 20 2013, 12:00
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Jul 23 2014, 11:19
Сообщение #23


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Пишу на SDHC блок и после этого читаю его.
После записи сначала жду токена Data response со значением Data accepted - все ОК, получаю его сразу после второго байта CRC16. Затем, как я понял, карта шлёт busy байты в виде нулей, типа происходит запись из буфера в саму flash. Но эти busy заканчиваются только через 6-10 мс! Неужели, так и должно быть? Если так ждать после записи каждого байта, то получится максимальная скорость не более 100кБ/сек - бред.

Сейчас ещё раз глянул анализатором сразу после подачи питания - так busy длится вообще 20мс...

Сообщение отредактировал ohmjke - Jul 23 2014, 11:25
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 23 2014, 19:46
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(ohmjke @ Jul 23 2014, 15:19) *
Пишу на SDHC блок и после этого читаю его.
После записи сначала жду токена Data response со значением Data accepted - все ОК, получаю его сразу после второго байта CRC16. Затем, как я понял, карта шлёт busy байты в виде нулей, типа происходит запись из буфера в саму flash. Но эти busy заканчиваются только через 6-10 мс! Неужели, так и должно быть? Если так ждать после записи каждого байта, то получится максимальная скорость не более 100кБ/сек - бред.

Сейчас ещё раз глянул анализатором сразу после подачи питания - так busy длится вообще 20мс...


Ага. И при чтении может быть весело:
Цитата
SP uSD 16GB
<0.5ms – 4562197;
<1.0ms - 52698;
<2.0ms - 4683;
<5.0ms - 2;
<10 ms - 1;
<20 ms - 18;
<50 ms - 1971;
>50 ms - 4;
max - 59.9 ms

Карта непрерывно читается. Измеряется время ожидания начала данных. После тире указано число случаев для данного диапазона.
Для этой карты было 4 случая, когда данные были не готовы дольше 50 мс. Максимальное время ожидания почти 60 мс.
Самая беда в том, что чтение начинает тормозить в среднем по 46 мс но на протяжении секунды:
Цитата
<51254590:43.9ms-12075>
<+40:44.3ms-12147>
<+50:44.1ms-12123>
<+40:44.2ms-12139>
<+50:44.1ms-12113>
<+50:44.1ms-12091>
<+40:44.1ms-12111>
<+50:43.9ms-12057>
<+50:47.4ms-13023>
<+50:43.8ms-12001>
<+40:45.8ms-12577>
<+50:45.8ms-12573>
<+70:45.5ms-12501>
<+50:45.7ms-12541>
<+40:45.7ms-12551>
<+50:45.4ms-12467>
<+70:46.0ms-12649>
<+40:45.8ms-12573>
<+50:46.3ms-12711>
<+30:26.5ms-7271>
<+40:27.5ms-7541>

Тут формат такое <реальное время или смещение в мс от последнего события : время ожидания данных - число байт переданных в карту до момента ответа>
Go to the top of the page
 
+Quote Post
ohmjke
сообщение Jul 24 2014, 15:33
Сообщение #25


Частый гость
**

Группа: Участник
Сообщений: 116
Регистрация: 27-01-10
Из: СПб
Пользователь №: 55 094



Пришлось городить кольцевой буфер в RAM. Пока всё работает норм...

Сообщение отредактировал ohmjke - Jul 24 2014, 15:33
Go to the top of the page
 
+Quote Post
Ndf
сообщение Jul 25 2014, 06:41
Сообщение #26


Частый гость
**

Группа: Свой
Сообщений: 101
Регистрация: 22-08-07
Пользователь №: 29 977



Цитата(ohmjke @ Jul 23 2014, 15:19) *
Пишу на SDHC блок и после этого читаю его.
После записи сначала жду токена Data response со значением Data accepted - все ОК, получаю его сразу после второго байта CRC16. Затем, как я понял, карта шлёт busy байты в виде нулей, типа происходит запись из буфера в саму flash. Но эти busy заканчиваются только через 6-10 мс! Неужели, так и должно быть? Если так ждать после записи каждого байта, то получится максимальная скорость не более 100кБ/сек - бред.
Сейчас ещё раз глянул анализатором сразу после подачи питания - так busy длится вообще 20мс...
Так и должно быть (у меня размер сектора 512 байт). Причем я не заметил чтобы SPI mode работал медленнее SD mode в режиме записи.
Go to the top of the page
 
+Quote Post
Ruslan-maniak
сообщение Feb 19 2016, 09:21
Сообщение #27


Частый гость
**

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



Помогите, товарищи. Третий день не могу запустить нормально SD карту. Работаю по SPI. Инициализация проходит нормально. Также OCR считывается вполне адекватным {0x80, 0xFF, 0x80, 0x00}. Но абсолютно на все остальные команды карта отвечает 0x05: и чтение CSD, и CID, и просто блоков памяти. Ничего не получается. Карта в картридере работает адекаватно.
Go to the top of the page
 
+Quote Post
doom13
сообщение Feb 19 2016, 10:24
Сообщение #28


Профессионал
*****

Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539



Цитата(Ruslan-maniak @ Feb 19 2016, 12:21) *
Помогите, товарищи. Третий день не могу запустить нормально SD карту. Работаю по SPI. Инициализация проходит нормально. Также OCR считывается вполне адекватным {0x80, 0xFF, 0x80, 0x00}. Но абсолютно на все остальные команды карта отвечает 0x05: и чтение CSD, и CID, и просто блоков памяти. Ничего не получается. Карта в картридере работает адекаватно.

Если не ошибаюсь, то для некоторых команд ответ идёт не сразу, а надо вычитать несколько пустых (0xFF) байт. Может в этом проблема?
Go to the top of the page
 
+Quote Post
Ruslan-maniak
сообщение Feb 19 2016, 10:42
Сообщение #29


Частый гость
**

Группа: Участник
Сообщений: 92
Регистрация: 27-12-12
Из: Томск
Пользователь №: 74 999



Так в том то и дело, что это именно ответ. До него я принимаю один раз 0xFF.
Go to the top of the page
 
+Quote Post
doom13
сообщение Feb 19 2016, 11:00
Сообщение #30


Профессионал
*****

Группа: Свой
Сообщений: 1 404
Регистрация: 11-03-11
Из: Минск, Беларусь
Пользователь №: 63 539



У меня так работало:
CODE

void SDCard::SendCmd(SDCardCmd *command)
{
unsigned char *byte = (unsigned char *)command;

// Send 6 bytes of command
for(int i = 0; i < 6; i++)
{
McBSPA_WriteByte(byte[i]);
}

// Send 1 byte of pause
//McBSPA_WriteByte(0xFF);
}

void SDCard::RecvRsp(unsigned char *response, unsigned short len)
{
McbspaRegs.SPCR1.bit.RRST = 1;

// wait for 1-st byte of response
do
{
McBSPA_WriteByte(0xFF);
response[0] = McBSPA_ReadByte();
}
while(response[0] == 0xFF);

// receive len-1 bytes of response
for(int i = 1; i < len; i++)
{
McBSPA_WriteByte(0xFF);
response[i] = McBSPA_ReadByte();
}

McbspaRegs.SPCR1.bit.RRST = 0;

// Send 1 byte of pause
McBSPA_WriteByte(0xFF);
}

Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 12:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.01498 секунд с 7
ELECTRONIX ©2004-2016