В этом примере я использовал отладочную плату Olimex SAM7-EX256 с микроконтроллером AT91SAM7X256. Карточка SD была на 512 мегабайт (хотя подходят и другие карточки MMC и SD). Использовался пример usb-device-massstorage-project от IAR и модули из библиотеки EFSL (для работы с карточкой SD/MMC по последовательному интерфейсу SPI), см. ссылки [2].
1. Берем за основу проект usb-device-massstorage-project из примеров IAR (находится в папке $TOOLKIT_DIR$\examples\Atmel\at91sam7x-ek\usb-device-massstorage-project\, или c:\Program Files\IAR Systems\Embedded Workbench 5.0 Evaluation\ARM\examples\Atmel\at91sam7x-ek\usb-device-massstorage-project\), копируем его в отдельную папку, добиваемся нормальной компиляции (правкой соответствующих опций и файлов, см. [6]). Предположим, это будет папка c:\asm\MSD-MMC\. Компилировать надо для конфигурации проекта at91sam7x256_sram (поскольку в качестве памяти у нас пока выступает flash микроконтроллера). Проверяем, что наше устройство USB Mass Storage Device (далее просто MSD) работает - пробуем его отформатировать, читать и писать (MSD должно получиться размером 34 килобайта).
2. Теперь займемся подключением карточки SD. К картам SD/MMC можно обращаться через последовательный интерфейс, который реализован в карточке. В микроконтроллере этому интерфейсу соответствует SPI (в моем примере используется SPI0). Карточка запитывается от напряжения 3.3 вольт. При подключении к микроконтроллеру карточка работает под управлением микроконтроллера, т. е. в терминах SPI карточка является slave, а микроконтроллер - master. Используются следующие сигналы и питание: 1. CD - выход микроконтроллера, выборка карточки, активный сигнал 0. В моем примере это ножка 21 AT91SAM7X256, порт PA13, аппаратная выборка slave-устройства SPI0_NPSC1. 2. CMD - выход микроконтроллера, сигнал данных, поступающих в карточку. Подключен к ножке 25 AT91SAM7X256, порт PA17, сигнал MOSI интерфейса SPI0. 3. GND 4. +3.3V 5. CLK - выход микроконтроллера, тактовый сигнал, поступающий на карточку. Подключен к ножке 26 AT91SAM7X256, порт PA18, сигнал SPCK интерфейса SPI0. 6. GND 7. DAT0 - вход микроконтроллера, поток данных, поступающий от карточки. Подключен к ножке 24 AT91SAM7X256, порт PA16, сигнал MISO интерфейса SPI0. 8. Не используется, подключен нагрузочный pullup-резистор 100 к на +3.3V. 9. Не используется, подключен нагрузочный pullup-резистор 100 к на +3.3V. На плате Olimex все уже подключено, остается только запрограммировать микроконтроллер.
|
|
№ конт.
|
сигнал |
описание |
Вариант подключения к SPI0, PIOA, периферия A |
1 |
~CS |
выборка карты (режим DAT3 не используется) |
PA13 |
2 |
MOSI |
данные, приходящие на вход карты |
PA17 |
3 |
GND |
минус питания карты, сигнальная земля |
|
4 |
VCC |
плюс питания карты, от 2.7 до 3.6 вольт, самый лучший вариант 3 вольта |
|
5 |
SCK |
такты данных, поступающие на вход карты |
PA18 |
6 |
GND |
минус питания карты, сигнальная земля |
|
7 |
MISO |
данные, уходящие с выхода карты (DAT0) |
PA16 |
8 |
|
не используется (DAT1) |
|
9 |
|
не используется (DAT2) |
|
3. Добавляем программную поддержку работы с карточкой. - добавляем в проект файлы MEDmmc.c и MEDmmc.h. Их надо записать в папку at91lib\memories, и файл MEDmmc.c добавить в группу проекта at91lib\memories. - добавляем в корень папки проекта папку efsl с её файлами, и настраиваем в опциях проекта пути до неё. - делаем в проекте группу efsl и туда помещаем файлы efsl\sd.c и efsl\at91_spi.c.
4. В опциях проекта удаляем макроопределение sram и добавляем макроопределения at91sam7x256 (если его нет), MMC_MEDIA, OlimexDBG и NOTRACE (Project -> Options... -> C/C++ Compiler -> Preprocessor -> Defined symbols: (one per line)). Макрос MMC_MEDIA понадобится, чтобы включить поддержку SD/MMC. Макрос OlimexDBG нужен, чтобы мигал индикационный светодиод, который можно подключить к ножке 66 AT91SAM7X256 (порт PB21). Макрос NOTRACE нужен, чтобы отключить вывод в DBGU сообщений протокола USB, иначе наше MSD будет работать очень медленно.
5. Включаем поддержку пользовательского сброса. Этот шаг необязателен - если его не сделать, то вызов RSTC_SetUserResetEnable делать не надо. Добавляем в проект группу at91lib\peripherials\rstc и туда помещаем файл rstc.c.
6. Добавляем/правим в main:
#include < rstc/rstc.h> #include < memories/MEDmmc.h> ... //Порт PB21, ножка 66 - используется для // тестирования программ как выход. #define PIN_PB21_TEST66 {1 << 21, \ AT91C_BASE_PIOB, \ AT91C_ID_PIOB, \ PIO_OUTPUT_0, \ PIO_DEFAULT}
const Pin outPB21_66 = PIN_PB21_TEST66;
void LED (unsigned char on) { on ? PIO_Set(&outPB21_66) : PIO_Clear(&outPB21_66); } volatile AT91PS_RSTC pRSTC = AT91C_BASE_RSTC; ... int main() { //разрешаем сброс от кнопки (если это Вам нужно) RSTC_SetUserResetEnable(pRSTC, 1); //запускаем вывод отладочных сообщений через DBGU #ifdef NOTRACE const Pin pinsDbgu[] = {PINS_DBGU}; PIO_Configure(pinsDbgu, PIO_LISTSIZE(pinsDbgu)); DBGU_Configure(DBGU_STANDARD, 115200, BOARD_MCK); #else trace_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK); #endif printf("-- USB Device Mass Storage Project 1.4 --\n\r"); // If they are present, configure Vbus & Wake-up pins PIO_InitializeInterrupts(0); //тестовая ножка, управляющая светодиодом LED PIO_Configure(&outPB21_66, 1); WAKEUP_CONFIGURE(); ... // Flash (only when NOT running in flash) #if defined(AT91C_BASE_EFC) && !defined(flash) && defined(FLASH_MEDIA) trace_LOG(trace_INFO, "LUN Flash\n\r"); if (numMedias == 0) { FLA_Initialize(&(medias[numMedias]), AT91C_BASE_EFC); LUN_Init(&(luns[numMedias]), &(medias[numMedias]), buffer, 30*1024, 34*1024, BLOCK_SIZE); numMedias++; // Install handler for flash interrupt AIC_ConfigureIT(AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, ISR_Media); AIC_EnableIT(AT91C_ID_SYS); } #endif #if defined(MMC_MEDIA) trace_LOG(trace_INFO, "LUN mmc\n\r"); if (numMedias == 0) { MMC_Initialize(&(medias[numMedias]), AT91C_BASE_SPI0); LUN_Init(&(luns[numMedias]), &(medias[numMedias]), buffer, 0, medias[numMedias].size, BLOCK_SIZE); numMedias++; } #endif ASSERT(numMedias > 0, "Error: No media defined.\n\r"); ... }
Это все! Теперь у Вас доступно USB Mass Storage Device на карточках SD/MMC, которое работает как обычная флешка. Правда, скорость у неё в разы меньше. Я пробовал разные карточки - MMC на 16 мегабайт и SD на 512 мегабайт, и получил скорость чтения 336 кбайт/сек, а скорость записи 180 кбайт/сек. Протокол приема-передачи на карточку через SPI сильно грузит AT91SAM7X256, поэтому для увеличения скорости желательно убрать все фоновые задачи из главного цикла main, а также все ненужные прерывания.
[Ссылки]
1. Готовый проект MSD-MMC можно скачать здесь. 2. Сайт EFSL. 3. IAR EW ARM: работа с файловой системой FAT на карточках SD/MMC. 4. Библиотека EFSL. 5. Другая популярная реализации файловой системы для микроконтроллеров - Petit FAT File System Module. См. также FatFs Generic FAT File System Module, как использовать SD/MMC. 6. IAR EW ARM: как перенести проект в другую папку. |