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

 
 
 
Reply to this topicStart new topic
> Работа с SD-картой, LPC1778
ДЕЙЛ
сообщение Jul 24 2014, 10:25
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Начал изучать алгоритм чтения-записи данных на карту SD, для этого перевёл соответствующий раздел из LPC178x/7x User manual Rev. 2.1 — 6 March 2013. Пдфка прикреплена к сообщению. Нет уверенности, что перевод безошибочный, поэтому хотелось бы иметь критику со стороны, т.е. просьба к здешним читателям-писателям почитать мой перевод и указать на принципиальные ошибки, если таковые имеются.

Существует ли какое-то упорядоченное и подробное описание команд работы с SD-картой? Желательно на русском языке. А ещё интересно посмотреть демонстрационный пример работы с картой памяти объёмом больше 4 ГГб.

добавил более позднюю версию перевода, в предыдущей забыл две таблицы вставить

Сообщение отредактировал ДЕЙЛ - Jul 24 2014, 20:57
Прикрепленные файлы
Прикрепленный файл  ________SD_______.pdf ( 1.43 мегабайт ) Кол-во скачиваний: 1096
 
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jul 25 2014, 07:39
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Вполне приличный перевод, на мой взгляд. Может вы так весь User Manual переведёте?
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Jul 25 2014, 10:59
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(andrewlekar @ Jul 25 2014, 11:39) *
Вполне приличный перевод, на мой взгляд. Может вы так весь User Manual переведёте?

Всётки есть сомнения насчёт возможных ошибок в переводе, поэтому и выложил для критики.Точный перевод потребует 2-3 итерации для согласованости написанного. На весь мануал энтузиазма пока не хватает.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Jul 26 2014, 17:53
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Здесь был вопрос, но проблема была в настройках осциллографа, уж чуть было мозги не закипели 05.gif

Сообщение отредактировал ДЕЙЛ - Jul 26 2014, 18:05
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Jul 28 2014, 10:44
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Читаю описание команд и пока непонятна разница между командами CMD и ACMD. К примеру, CMD10 означает, что в поле индекса команды записывается число 10 или 0xA, а в чём отличие команды ACMD10?

http://habrahabr.ru/post/213803/
Цитата
Важное пояснение по поводу ACMD: пространство их индексов пересекается с индексами CMD команд, поэтому, чтобы контроллер воспринял команду именно, как Application-Specific, ей должна предшествовать CMD55!


Т.е. команда ACMD10 равносильна последовательной передаче CMD55 с пустым аргументом и команды CMD10? Если так, то нужно ли ждать окончания ответа на команду CMD55 или сразу отсылать CMD10?

Сообщение отредактировал ДЕЙЛ - Jul 28 2014, 10:54
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 28 2014, 13:02
Сообщение #6


Гуру
******

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



На CMD55 нужно ждать ответа R1.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Jul 29 2014, 18:53
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Опять имеются непонятки. При отправке команды CMD0 в карту возвращается ответ с установленным битом In Idle State, т.е. говорит, что карта в нерабочем состоянии. Но карточка рабочая - телефон её видит. Этот ответ с установленным нулевым битом допустим? В одном из описаний процесса инициализации после команды CMD0 ожидается ответ 0x00, а у меня почему-то всегда 0x01. Что тут не так может быть? Для пробы отправлял заведомо левую команду - бит 2 устанавливался, т.е. карта сказала, что команда неправильная. Тут всё нормально, но и бит 0 тоже всё равно в единицу установлен. Карта 8 гигов. Надо полагать, что SDHC. Частота тактирования 300 кГц.

UP1. Отправил CMD8 c аргументом 0x1AA, т.е. указал карте питание хоста 2.7-3.5В, ответ пришёл вроде нормальный, т.е. с 0x1АА в хвосте, но бит 0 в ответе всё равно остался установленным.

Сообщение отредактировал ДЕЙЛ - Jul 29 2014, 19:21
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 29 2014, 19:34
Сообщение #8


Гуру
******

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



Ответы нужно искать на Figure 7-2: SPI Mode Initialization Flow документа Physical Layer Simplified Specification Version 3.01 - там CMD1 нет.
Если память мне не изменяет то CMD1 актуальна для MMC.
Я инициализирую карточки так (правда, uSD, т.е. >=ver2.00):
CODE

//-----------------------------------------------------------------------------
// BYTE sd_init(void)
//-----------------------------------------------------------------------------
BYTE sd_init(void)
{
volatile int i;
BYTE response = 0xFF;
DWORD data;

sCSD_V1 *csd_v1;
sCSD_V2 *csd_v2;

sd_size_mb = 0;

// POWER OFF
SD_PWR_bit = 1;
delay_sd_tim(100);
SD_PWR_bit = 0;

delay_sd_tim(200);
SD_CS_bit = 1;

sd_set_mode(SD_MODE_INIT);

delay_sd_tim(10);
for(i = 0; i < 74; i++) sd_send_byte(0xFF);
delay_sd_tim(1);

SD_CS_bit = 0;
sd_send_cmd(CMD0_GO_IDLE_STATE, 0, 0x95);
response = sd_get_response();
SD_CS_bit = 1;
sd_send_byte(0xFF);

#ifdef SD_DEBUG_INIT
con_str("r_CMD0=");
con_byte(response);
con_str("\n\r");
con_start();
#endif

if(response == SD_RESP_IDLE)
{
i = 0;

#ifdef SD_DEBUG_INIT
con_str("Send CMD8\n\r");
con_start();
#endif // SD_DEBUG_INIT

SD_CS_bit = 0;
sd_send_cmd(CMD8_SEND_IF_COND, CARD_COND, 0x86);
response = sd_get_response();
data = sd_get_dword();
SD_CS_bit = 1;
sd_send_byte(0xFF);

#ifdef SD_DEBUG_INIT
con_str("r_CMD8=");
con_byte(response);
con_str(" - ");
con_dword(data);
con_str("\n\r");
con_start();
#endif // SD_DEBUG_INIT

if(response == SD_RESP_IDLE)
{
sd_type = SD_TYPE_V2;

#ifdef SD_DEBUG_INIT
con_str("SD ver2.00 or later.\n\r");
con_start();
#endif // SD_DEBUG_INIT

if(data != CARD_COND) return SD_INIT_ERROR;

#ifdef SD_DEBUG_INIT
con_str("Valid voltage range\n\r");
con_str("Send ACMD41\n\r");
con_start();
#endif // SD_DEBUG_INIT

do
{
SD_CS_bit = 0;
con_str("cmd55->");
con_start();
sd_send_cmd(CMD55_APP_CMD, 0, 0xFF);
response = sd_get_response();
SD_CS_bit = 1;
sd_send_byte(0xFF);
if(response == SD_RESP_IDLE)
{
SD_CS_bit = 0;
con_str("acmd41->");
con_start();
sd_send_cmd(CMD41_SEND_APP_OP_COND, SDIO_CARD_CCS | OCR_INDEX, 0xFF);
response = sd_get_response();
SD_CS_bit = 1;
sd_send_byte(0xFF);
}
else response = SD_RESP_IDLE;

while(con.tx_t != con.tx_b);

} while(response == SD_RESP_IDLE);

#ifdef SD_DEBUG_INIT
con_str("Card ready\n\r");
con_str("Send CMD58\n\r");
con_start();
#endif // SD_DEBUG_INIT

SD_CS_bit = 0;
sd_send_cmd(CMD58_READ_OCR, 0, 0xFF);
response = sd_get_response();
data = sd_get_dword();
SD_CS_bit = 1;
sd_send_byte(0xFF);

#ifdef SD_DEBUG_INIT
con_str("r_CMD58=");
con_byte(response);
con_str(" - ");
con_dword(data);
con_str("\n\r");
con_start();
#endif // SD_DEBUG_INIT

if(data & SDIO_CARD_CCS)
{
#ifdef SD_DEBUG_INIT
con_str("CCS = 1\n\r");
con_start();
#endif // SD_DEBUG_INIT
sd_type = SD_TYPE_SDHC;
}
else
{
#ifdef SD_DEBUG_INIT
con_str("CCS = 0\n\r");
con_start();
#endif // SD_DEBUG_INIT
sd_type = SD_TYPE_NORMAL;
}
}
else
{
sd_type = SD_TYPE_UNDEF;
return SD_INIT_ERROR;
}

while(response != SD_RESP_SUCCESS)
{
SD_CS_bit = 0;
sd_send_cmd(CMD1_SEND_OP_COND, 0, 0xFF);
response = sd_get_response();
SD_CS_bit = 1;
sd_send_byte(0xFF);
i++;
if(i == 0x100000)
{
#ifdef SD_DEBUG_INIT
con_str("r_CMD1=");
con_byte(response);
con_str(", i=");
con_dword(i);
con_str("\n\r");
con_start();
#endif
return SD_TIMEOUT_ERROR;
}
}
#ifdef SD_DEBUG_INIT
con_str("r_CMD1=");
con_byte(response);
con_str(", i=");
con_dword(i);
con_str("\n\r");
con_start();
#endif
}
else
{
#ifdef SD_DEBUG_INIT
con_str("INIT_ERROR\n\rr_CMD0=");
con_byte(response);
con_str("\n\r");
con_start();
#endif
return SD_INIT_ERROR;
}

// CMD9 Read CSD
con_str("CMD9\n\r");
con_start();

SD_CS_bit = 0;
sd_send_cmd(CMD9_SEND_CSD, 0, 0xFF);
response = sd_get_response();
if(response == SD_RESP_SUCCESS)
{
response = sd_get_xx_response(SD_START_DATA_BLOCK_TOKEN);
for(i = 0; i < 16; i++) sd_buf[15 - i] = sd_send_byte(0xFF);
SD_CS_bit = 1;
sd_send_byte(0xFF);

csd_v1 = (sCSD_V1 *)sd_buf;
con_str("[CSD SOURCE: ");
for(i = 0; i < 16; i++) con_byte(((BYTE *)sd_buf)[i]);
con_str("]\n\r");
con_start();

if(csd_v1->csd_structure == 0)
{
sd_size_mb = ((csd_v1->c_size + 1) * (1 << csd_v1->read_bl_len) * (1 << (csd_v1->c_size_mult + 2))) >> 20;
con_str("\n\n\rTotal Size: ");
con_dec(sd_size_mb);
con_str(" MB\n\n\r");
con_start();
}
else if(csd_v1->csd_structure == 1)
{
csd_v2 = (sCSD_V2 *)sd_buf;
sd_size_mb = (csd_v2->c_size + 1) >> 1;
con_str("\n\n\rTotal Size: ");
con_dec(sd_size_mb);
con_str(" MB\n\n\r");
con_start();
}
}
else
{
SD_CS_bit = 1;
sd_send_byte(0xFF);
}

sd_set_mode(SD_MODE_DATA);
sd_send_byte(0xff);
sd_send_byte(0xff);

return sd_set_block_length(512);
}

Устойчиво работают карты разных производителей, объемом 2Gb, 4GB, 8Gb, 16GB и 32GB.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Jul 29 2014, 20:02
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Днём покопаюсь в коде, а пока читаю вот тут habrahabr.ru/post/213803/ Насколько правильно там всё описано? Я пока застрял на ожидании ответа на ACMD41 с установленными в аргументе битами 30 и 20(3.2 - 3.3В). Предполагаемого ответа в виде содержимого регистра OCR с установленной единицей в 31 бите пока не вижу. Только изменился бит 0 в ответе R1 на нулевой.

UP1: Проблема в описании по ссылке - автор по памяти наверно писал и упустил один момент. Делал как тут http://we.easyelectronics.ru/AVR/mmcsd-i-a...tifikaciya.html и вроде дальше продвинулся, читаю дальше http://we.easyelectronics.ru/AVR/mmcsd-i-a...a-s-kartoy.html и вроде пока получилось считать регистр CSD.

Сообщение отредактировал ДЕЙЛ - Jul 29 2014, 20:44
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Aug 3 2014, 17:33
Сообщение #10


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Продолжаю ковыряться с SD-картой. С алгоритмом инициализации, чтения и записи самой карты в общих чертах разобрался. Теперь копаюсь с интерфейсом карты со стороны МК. В нём имеется буфер FIFO, с которым у меня появились непонятки. Насколько я понимаю, этот буфер проталкивает через себя 32битные слова от начала к хвосту по мере появления данных в начальной ячейке. Настроил срабатывание прерывания по каждому заполнению буфера, т.е. 16*4=64 байта. Тут всё нормально. Дальше в прерывании останавливаю SD_CLK, принятые данные копирую для передачи на ПК, сбрасываю флаг заполнения и опять включаю SD_CLK. Только почему-то получается такая ерунда, что во всех ячейках буфера одинаковые данные, причём такая картина и в режиме отладки, и в обычном режиме работы. Какая тут может быть причина? Можно было бы код приложить, но его от всего лишнего чистить нужно долго - там вся инициализация и команды чтения-записи выполняется с ПК через UART. Надеюсь, что кто-то из местных наблюдал у себя такую картину. Интересно было бы узнать, на что нужно обратить внимание.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Aug 5 2014, 19:29
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Попробовал записать в один из 16 регистров FIFO - записываю в один, меняется содержимое сразу во всех. У каждого регистра свой отдельный адрес. Как токое может быть? На скрине режим пошаговой отладки в железе.
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd August 2025 - 06:39
Рейтинг@Mail.ru


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