ДЕЙЛ 32 24 июля, 2014 Опубликовано 24 июля, 2014 (изменено) · Жалоба Начал изучать алгоритм чтения-записи данных на карту SD, для этого перевёл соответствующий раздел из LPC178x/7x User manual Rev. 2.1 — 6 March 2013. Пдфка прикреплена к сообщению. Нет уверенности, что перевод безошибочный, поэтому хотелось бы иметь критику со стороны, т.е. просьба к здешним читателям-писателям почитать мой перевод и указать на принципиальные ошибки, если таковые имеются. Существует ли какое-то упорядоченное и подробное описание команд работы с SD-картой? Желательно на русском языке. А ещё интересно посмотреть демонстрационный пример работы с картой памяти объёмом больше 4 ГГб. добавил более позднюю версию перевода, в предыдущей забыл две таблицы вставить ________SD_______.pdf Изменено 24 июля, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 25 июля, 2014 Опубликовано 25 июля, 2014 · Жалоба Вполне приличный перевод, на мой взгляд. Может вы так весь User Manual переведёте? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 32 25 июля, 2014 Опубликовано 25 июля, 2014 · Жалоба Вполне приличный перевод, на мой взгляд. Может вы так весь User Manual переведёте? Всётки есть сомнения насчёт возможных ошибок в переводе, поэтому и выложил для критики.Точный перевод потребует 2-3 итерации для согласованости написанного. На весь мануал энтузиазма пока не хватает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 32 26 июля, 2014 Опубликовано 26 июля, 2014 (изменено) · Жалоба Здесь был вопрос, но проблема была в настройках осциллографа, уж чуть было мозги не закипели :05: Изменено 26 июля, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 32 28 июля, 2014 Опубликовано 28 июля, 2014 (изменено) · Жалоба Читаю описание команд и пока непонятна разница между командами CMD и ACMD. К примеру, CMD10 означает, что в поле индекса команды записывается число 10 или 0xA, а в чём отличие команды ACMD10? http://habrahabr.ru/post/213803/ Важное пояснение по поводу ACMD: пространство их индексов пересекается с индексами CMD команд, поэтому, чтобы контроллер воспринял команду именно, как Application-Specific, ей должна предшествовать CMD55! Т.е. команда ACMD10 равносильна последовательной передаче CMD55 с пустым аргументом и команды CMD10? Если так, то нужно ли ждать окончания ответа на команду CMD55 или сразу отсылать CMD10? Изменено 28 июля, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 28 июля, 2014 Опубликовано 28 июля, 2014 · Жалоба На CMD55 нужно ждать ответа R1. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 32 29 июля, 2014 Опубликовано 29 июля, 2014 (изменено) · Жалоба Опять имеются непонятки. При отправке команды CMD0 в карту возвращается ответ с установленным битом In Idle State, т.е. говорит, что карта в нерабочем состоянии. Но карточка рабочая - телефон её видит. Этот ответ с установленным нулевым битом допустим? В одном из описаний процесса инициализации после команды CMD0 ожидается ответ 0x00, а у меня почему-то всегда 0x01. Что тут не так может быть? Для пробы отправлял заведомо левую команду - бит 2 устанавливался, т.е. карта сказала, что команда неправильная. Тут всё нормально, но и бит 0 тоже всё равно в единицу установлен. Карта 8 гигов. Надо полагать, что SDHC. Частота тактирования 300 кГц. UP1. Отправил CMD8 c аргументом 0x1AA, т.е. указал карте питание хоста 2.7-3.5В, ответ пришёл вроде нормальный, т.е. с 0x1АА в хвосте, но бит 0 в ответе всё равно остался установленным. Изменено 29 июля, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 29 июля, 2014 Опубликовано 29 июля, 2014 · Жалоба Ответы нужно искать на Figure 7-2: SPI Mode Initialization Flow документа Physical Layer Simplified Specification Version 3.01 - там CMD1 нет. Если память мне не изменяет то CMD1 актуальна для MMC. Я инициализирую карточки так (правда, uSD, т.е. >=ver2.00): //----------------------------------------------------------------------------- // 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 32 29 июля, 2014 Опубликовано 29 июля, 2014 (изменено) · Жалоба Днём покопаюсь в коде, а пока читаю вот тут 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. Изменено 29 июля, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 32 3 августа, 2014 Опубликовано 3 августа, 2014 · Жалоба Продолжаю ковыряться с SD-картой. С алгоритмом инициализации, чтения и записи самой карты в общих чертах разобрался. Теперь копаюсь с интерфейсом карты со стороны МК. В нём имеется буфер FIFO, с которым у меня появились непонятки. Насколько я понимаю, этот буфер проталкивает через себя 32битные слова от начала к хвосту по мере появления данных в начальной ячейке. Настроил срабатывание прерывания по каждому заполнению буфера, т.е. 16*4=64 байта. Тут всё нормально. Дальше в прерывании останавливаю SD_CLK, принятые данные копирую для передачи на ПК, сбрасываю флаг заполнения и опять включаю SD_CLK. Только почему-то получается такая ерунда, что во всех ячейках буфера одинаковые данные, причём такая картина и в режиме отладки, и в обычном режиме работы. Какая тут может быть причина? Можно было бы код приложить, но его от всего лишнего чистить нужно долго - там вся инициализация и команды чтения-записи выполняется с ПК через UART. Надеюсь, что кто-то из местных наблюдал у себя такую картину. Интересно было бы узнать, на что нужно обратить внимание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 32 5 августа, 2014 Опубликовано 5 августа, 2014 · Жалоба Попробовал записать в один из 16 регистров FIFO - записываю в один, меняется содержимое сразу во всех. У каждого регистра свой отдельный адрес. Как токое может быть? На скрине режим пошаговой отладки в железе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться