Здесь приведен перевод популярной статьи [1] от Martin THOMAS, в которой раскрывается полезная тема использования карт памяти вместе с микроконтроллерами.
[Общие замечания по подключению карт памяти к микроконтроллерам]
Карты памяти SD (SDHC) или старые MMC (далее под картами SD подразумеваются карты MMC, SD, microSD) предоставляют объемное и относительно недорогое хранилище данных.
К картам SD можно получить доступ в режиме SPI, при этом для подключения к микроконтроллеру нужно только 4 сигнала (chip-select, MOSI, MISO, SCK, это режим с 1-разрядной шиной данных. Подробнее см. [2]). Для чтения и записи данных карт файлами на них должна быть создана "стандартная" файловая система, использующаяся на компьютерах PC.
Некоторые основные замечания: если Вы ищете библиотеку FAT, и у Вас есть код для низкоуровневого доступа к интерфейсу SPI (позволяющий писать/читать данные блоками сырые данные), то присмотритесь к библиотеке Chan FAT File System Module (FatFS, Petit FatFS, см. [3] или оригинальный сайт elm-chan.org). Это компактная, легко портируемая, бесплатная и быстрая библиотека, написанная на языке C. Она поддерживает FAT16 и FAT32, и начиная с версии R0.07 даже поддерживает длинные имена файлов. Другая библиотека, поддерживающая длинные имена, это libfat из пакета DevkitPro [4]. Лицензия у неё в стиле BSD, и никаких проблем быть не должно. Код предоставляет базовый набор функций - среди них поддержка длинных имен (LFN) и также некоторое кэширование, однако при этом потребуется дополнительная память. Автор не проводил обширных экспериментов с libfat, однако проекты на основе AT91SAM7S и LPC2000 (ядро ARM7TDMI(-S)) на ней успешно работали.
Все варианты реализации файловых систем FAT требуют наличия некоторого минимального набора интерфейсных функций, чтобы получить доступ к аппаратуре. В зависимости от используемого микроконтроллера с картой SD можно работать через 4-разрядную шину (так называемый режим MCI) или 1-разрядную шину (1-разрядную шину называют режимом SPI; некоторые современные карты micro-SD не могут работать в режиме SPI).
Для физического доступа к картам памяти Вам понадобятся как минимум 3 функции: одна для инициализации аппаратуры микроконтроллера и самой карты SD, другая для чтения блока данных (обычно размер блока 512 байт) из карты SD в RAM, и третья для записи блока данных из RAM на карту. Здесь также могут пригодится готовые шаблоны таких функций, которые можно найти в составе примеров из библиотеки на сайте Chan FatFs. Некоторые поставщики аппаратных средств (микроконтроллеров) или компиляторов также предоставляют коды функций драйвера для карт SD как минимум для режима SPI. Например, есть отличные примеры от компании Atmel для её микроконтроллеров ARM составе дистрибутива среды разработки IAR, см. также пакет SDK для микроконтроллеров STM. Примеры кода для реализации устройств USB MSD (USB mass-storage device, т. е. флешка), могут иметь программный интерфейс доступа к карте памяти и её содержимому, так что можно позаимствовать оттуда соответствующий низкоуровневый код (в соответствии с требованиями лицензии). Если Вы с нуля начинаете работать с картами через SPI, то просмотрите код для AVR примеров от Chan, измените соответствующие специфичные для AVR куски низкоуровневого кода (который использует аппаратуру SPI), и в результате получите работоспособный код для доступа к файловой системе. Для начала разберите простые готовые примеры, которые распечатывают содержимое каталога, читают несколько байт из файла, который уже есть на карте, создают файл. После того, как протестируете примеры и убедитесь в их исправной работе в нужной Вам аппаратной среде, можно приступать к пошаговой оптимизации кода и адаптации его к Вашим требованиям (или даже провести эксперименты с другой библиотекой FAT).
Прим. переводчика: для некоторых файловых систем (например, для FatFS) требуется также таймер для отсчета реального времени (таймауты обращения к диску). Для полной поддержки меток времени файлов также желательно предоставить функции для получения текущего времени (применимо к системам, которые имеют на борту энергонезависимые часы реального времени).
По поводу аппаратуры: нужно как минимум добавить pull-up резистор на сигнал MISO микроконтроллера (сигнал DO карты); если в микроконтроллере есть такая возможность (например, AVR и ARM от Atmel позволяют программно подключить pull-up резистор), то вместо внешнего нагрузочного резистора можно использовать встроенный в микроконтроллер. Убедитесь, что напряжение питания находится в допустимом для карты диапазоне - номинальное напряжение 3.3V, подробнее см. [2]. Для получения стабильного напряжения используйте специальный регулятор (прогуглите low drop out voltage regulator), во избежание проблем не применяйте хаки наподобие гасящих напряжение резисторов или цепочек на диодах. Подключите конденсатор емкостью как минимум 100 нФ между шинами VCC и GND рядом со слотом карты, и также должен быть добавлен конденсатор на 10 мкФ.
Также рекомендуется добавить схему для полного выключения питания карты, например на полевом P-канальном транзисторе FET, что позволит при необходимости программно сбросить карту в случае ошибок (карты MMC/SD/SDHC не имеют специального сигнала сброса).
Помните о том, что при выключении питания нужно также отключить pull-up резисторы микроконтроллера, поскольку они могут подавать на карту паразитное питание. Когда начинаете экспериментировать, установите меньше частоты шины (это делается при инициализации карты, подробности см. даташиты на карты памяти); далее в процессе оптимизации нужно подобрать частоту шины, чтобы добиться устойчивой работы интерфейса во всех условиях с разными типами карт. Избегайте использования согласования уровня сигналов с помощью делителей на резисторах. Ознакомьтесь со статьей "How to Use MMC/SDC" на сайте Chan (перевод приведен по ссылке [2]), где обсуждаются тонкости работы с интерфейсом, в частности освобождение сигнала DO/MISO.
• http://elm-chan.org/fsw/ff/00index_e.html - файловая система Chan FAT(12,16,32), где в одном пакете с библиотекой файловой системы есть несколько примеров для разных микроконтроллеров (например AVR SPI и LPC23xx/24xx MCI).
• http://sourceforge.net/projects/devkitpro/ devkitpro libfat FAT16/32, поддержка длинных имен файлов (LFN) реализована для GBA и DS, но код легко портируется как минимум на ARM7 и ARM9.
• http://www.zws.com/products/dosfs/index.html DOSFS Free FAT12/FAT16/FAT32 Filesystem. Описана как "бесплатная, FAT-совместимая, предназначенная относительно маломощных встраиваемых систем. Минимальные требования к целевой системе 1K RAM, 4K ROM".
• Implementing FAT32 File Systems on ADSP-BF533 Blackfin Processors site:analog.com апноут и код от компании Analog Devices.
• FAT Atmel AVR32 UC3 Software-Library site:atmel.com код системы FAT в составе библиотеки подпрограмм для микроконтроллеров AVR32 UC3 компании Atmel.
• AVR916: Upgrading the Flash using a U-Disk site:atmel.com апноут Atmel, где описывается обновление firmware микроконтроллера с помощью диска на карте памяти.
Примечание: site-ссылки предназначены для вставки в поисковую строку Google.
В этой статье сейчас есть ссылки на реализации интерфейсов для Embedded Filesystem Library (EFSL) с микроконтроллерами LPC2000 и AT91SAM7S и для ChaN Fat-Filesystem-module с микроконтроллерами STM32, AT91SAM7, LPC17xx при использовании SPI и LPC23xx/24xx при использовании MCI.
[ARM-интерфейс для Chan FatFS]
ChaN опубликовал очень хороший код библиотеки файловой системы, который назвал FatFs, и описал как "модуль стандартной файловой системы с реализацией FAT для малых встраиваемых систем". Для получения подробной информации пожалуйста посетите оригинальный сайт (или см. перевод документации по функциям FatFS [3]). Далее описаны некоторые примеры использования этой библиотеки. Имейте в виду, что на библиотека ChaN поддерживается и обновляется, поэтому проверьте релиз на предмет исправления багов (наличия патчей) или просто замените файлы библиотеки на новые и версии последнего релиза.
AT91SAM7 на SPI. Martin THOMAS добавил SPI-интерфейс к коду ChaN FatFS для карт MMC/SD/SDHC с опциональной поддержкой PDC/DMA (прямой доступ к памяти), и создал демо-приложение на основе примеров Chan (monitor). Вот что есть в пакете:
• Код библиотеки ChaN FatFS. • Модули библиотек AT91 (AT91lib, код поддержки периферийных устройств микроконтроллера от Atmel). • Исходный код демо-приложения. • Файл makefile, скрипты линковщика, код запуска startup (основанный на файлах AT91lib). • Рабочее окружение Eclipse с некоторыми конфигурациями для плагина аппаратной отладки (CDT hardware-debugging plugin).
Некоторые концепции для реализации драйвера diskio навеяны кодом плеером MP3/AAC [5], автор Andreas Schwarz.
Загрузка: at91sam_chanfat_mthomas_20090915c.zip - это исходный код проекта (метка времени 20090915, код тестировался с AT91SAM7S256 на плате разработчика Olimex SAM7-Pxxx, и компилировался под управлением Codesourcery G++ lite 2009Q1 [6], в makefile имеется опция сборки для AT91SAM7S64.
Дополнительная информация от Andy Kunz: [...] я использовал часть Вашего пакета at91sam_chanfat_mthomas_20090915c.zip package и обнаружил расхождение, которое возможно Вы захотите добавить. См. файл sd_spi_at91.c, строка 455:
Этот код нормально работает с новыми и большими по объему картами. Мы тестировали маленькие по размеру карты Canon 16M, и этот код работал только для одного или дух секторов, после чего происходит отказ. Однако на картах большего размера (2G .. 8G) все работало нормально. Если поменять код инициализации:
то код нормально работает со всеми картами, как старыми, так и новыми.[...]
NXP LPC2000 на SPI (SSP). Martin THOMAS добавил LPC2000 SSP-интерфейс для карт MMC/SD/SDHC к коду ChaN FatFS, и создал демо-приложение на основе примеров Chan (monitor). Карты памяти подключаются в режиме SPI (не 4-битный режим MCI/SD), так что этот код может использоваться для микроконтроллеров наподобие LPC214x/LPC213x с интерфейсом SSP, который работает как интерфейс SPI с маленьким буфером FIFO. Интерфейс SSP доступен для большинства микроконтроллеров LPC2000. Вот что есть в пакете:
• Код библиотеки ChaN FatFS. • Исходный код демо-приложения. • Файл makefile, скрипты линковщика, код запуска startup. • Из пакета исключены двоичные коды Win32 OpenOCD, используемые для тестов. Теперь для тестирования не нужно применять двоичный код Win32 arm-*-gdb. • Рабочее окружение Eclipse с некоторыми конфигурациями для плагина аппаратной отладки GDB (gdb-hardware-debugging).
Идеи для реализации драйвера diskio были взяты из аппаратного интерфейса EFSL LPC2k, автор Mike Anton и Martin THOMAS, и ничего не было копировано напрямую из кода EFSL, чтобы избежать проблем с лицензией.
Загрузка: lpc214x_chanfat_mthomas_20100704.zip - это исходный код проекта (метка времени 20100704, тестировалось на LPC2148 с платой разработчика Olimex LPC-P2148, компилятор Codesourcery G++ lite [6]).
LPC23xx/24xx на MCI.
18 апреля 2009: обратите внимание, что ChaN теперь предоставляет свою собственную реализацию драйвера MCI для LPC2k. Загрузите пакет из раздела "Sample projects" на его сайте.
Здесь также есть предварительная, не полностью обкатанная версия интерфейса MCI (этот аппаратный узел для подключения к картам SD/MMC есть на "новых" и "больших" NXP LPC2000 наподобие LPC2368 и LPC2378). Код использует драйвер MCI из собрания примеров NXP (доступны на сайте nxp.com) и модуль ChaN FatFs. Martin THOMAS сделал некоторые модификации и расширения для кода MCI и адаптировал "стандартный" пример для LPC23xx/24xx. В пакете архива есть 3 конфигурации:
• Для тулчейна GNU с использованием make и makefile (версия 20070917, которая тестировалась с WinARM 5/07; версия 20080914, которая тестировалась с CS G++ lite Q1/2008). • Для тулчейна GNU, который вызывается из uVision с использованием инструментария arm-glue (тестировалось с WinARM 5/06 и arm-glue 9/07). • Для тулчейна RealView и uVision (тестировалось только частично, см. readme).
Загрузка: lpc23xx_chan_mci_20090823.zip (метка времени 20090823, тестировалось с LPC2378 на Olimex/IAR LPC-2378-STK, дополнительную информацию см. в файле readme.txt).
STM32 на SPI. Это маленькое демо-приложение показывает интерфейс карт MMC/SD/SDHC с микроконтроллером STM32 (ядро ARM Ltd. Cortex-M3).
Код использует интерфейс SPI, не интерфейс хоста SDIO, поскольку плата разработчика имела слот карт, подключенный к SPI1, и микроконтроллер на плате (STM32F103VB) не предоставлял SDIO host interface. Если используется STM32 с SDIO, и слот подключен к SDIO, то можно использовать код примера из STM fwlib в качестве драйвера низкого уровня для diskio. Поскольку используется модуль ChaN FatFS, то поддерживаются длинные имена файлов. Имейте в виду, что возможно понадобится купить лицензию у Microsoft, когда Вы используете длинные имена файлов (LFN) в коммерческих устройствах. Поддержка LFN может быть запрещена опциями define. Также опциями define можно разрешить DMA для SPI.
В этом пакете рядом с драйверами diskio для STM32 SPI можно найти полезный код, который пригодится в разработке firmware с применением тулчейна GNU (например: размещение векторов прерывания, код startup, скрипты линкера, программирование flash с помощью OpenOCD, отладка под управлением Eclipse/gdb).
Включено рабочее пространство Eclipse с конфигурацией OpenOCD, файл Makefile для отдельной сборки в Eclipse и также рабочее пространство Keil/ARM uVision. Код подготовлен только для кросс-тулчейна GNU arm cross. Можно в качестве IDE использовать uVision, но RealView Tools в настоящий момент не поддерживаются (не тестировалось). Код наверняка будет легко портируется на другие тулчейны. Тестирование выполнялось с Codesourcery's G++ lite для "цельнометаллического" ARM (arm-none-eabi). Тестировалось на железе Manley EK-STM32F с микроконтроллером STM32F103VB Rev.Z. Также включены примеры программирования flash с использованием OpenOCD ("make program").
В пакете имеется полный исходный код для демо-приложения, модуль Chan FatFS (с таблицами Unicode), стандартная библиотека ST для поддержки периферийных устройств микроконтроллера STM32 (ST Microelectronics standard peripheral library) и бинарный код OpenOCD Win32 (нужно только для тестирования).
11 октября 2011: удостоверьтесь, что разрешено тактирование GPIO порта выводов MOSI, MISO и SCK, подключенных к карте памяти SD. В примере автора это делается в main.c/Periph_Configuration(), лучше разрешить тактирование периферии в sd_spi_stm32.c/poweron(), возможно после тестирования - если тактирование еще не разрешено.
LPC17xx для SPI (SSP) и USB-MSD. Это маленькое демо-приложение показывает, как можно использовать модуль ChaN FatFs с картами MMC/SD/SDHC и устройствами USB mass-storage devices на микроконтроллерах LPC17xx компании NXP (ядро ARM Ltd. Cortex-M3) для чтения и записи файлов на дисках, отформатированных FAT (FAT16, FAT32).
В этом пакете рядом с драйверами diskio для LPC SSP и LPC USB host можно найти полезный код, который пригодится в разработке firmware с применением тулчейна GNU. Включен также воркспейс Eclipse с конфигурацией OpenOCD, файл Makefile для сборки как отдельно, так и совместно с Eclipse, и воркспейс Keil/ARM uVision. Есть также примеры программирования flash с использованием OpenOCD ("make program"). Код подготовлен только для GNU кросс-тулчейна. Можно в качестве IDE использовать ARM/Keil µVision, но компилятор RealView и его сопутствующий инструментарий не тестировались. Код легко портируется на другие тулчейны.
Тесты выполняются под управлением Codesourcery's G++ lite для аппаратного ARM (arm-none-eabi). Тестировалось на аппаратуре Olimex LPC1766-STK с NXP LPC1766 Rev '-', Amontec JTAGkey2, OpenOCD0.5.0-pre/GIT.
В пакете имеется полный исходный код для демо-приложения, модуль ChaN FatFs, библиотека драйвера NXP и NXP/OnChip USB-Host 'lite' для LPC17xx.
В Embedded Filesystem Library [7] (EFSL, разработчики Lennart Yseboodt и Michael De Nil) были добавлены автором статьи интерфейсы для NPX/Philips LPC2000 ARM7TDMI-S и Atmel AT91SAM7S ARM7TDMI. Эта библиотека поддерживает файловые системы FAT, благодаря чему данные, записанные на карту компьютером PC могут быть прочитаны из firmware микроконтроллера, и данные, которые записал микроконтроллер, могут быть прочитаны на PC.
Интерфейс LPC2000 поддерживает SPI и SSP (последний доступен только на новых микроконтроллерах семейства NXP/Philips ARM7). Тестировалось на LPC2138 (плата разработчика от Keil) и LPC2148. Интерфейс AT91SAM7 в настоящий момент поддерживает SPI без использования DMA (PDC). Тестировалось на AT91SAM7S64 и AT91SAM7S256 (плата разработчика от ATMEL и плата Olimex SAM7-P). Оба интерфейса подтверждены разработчиками EFSL. Интерфейс LPC2000 изначально был доступен в официальном дистрибутиве. До сих пор интерфейс AT91SAM7 не был объединен с официальной кодовой базой (см. [7], возможно там появятся обновления).
Архив с исходным кодом содержит полный код EFSL (базирующийся на версии 0.2.x) и интерфейсы LPC2000 и AT91SAM7. Добавлен пример приложения для LPC2138 (также тестировалось на LPC2148) и AT91SAM7S64 (см. каталог examples). Другие микроконтроллеры из тех же семейств (например, LPC2129, LPC2106, AT91SAM7S256) должны работать с минимальными правками кода. Библиотека может использоваться как двоичная библиотека (efsl.a) или в виде модулей исходного кода, примеры демонстрируют оба метода. Дополнительную информацию см. в файле readme_arm7.txt (подкаталог docs), там описаны интерфейсы ARM. Подробная информация по EFSL API есть в файле pdf (он также находится в архиве).
Код подготовлен для компиляции под управлением arm-elf-gcc и newlib в качестве библиотек libc (как это было сделано для WinARM или gnuarm). Также добавлены файлы Makefile и скрипты линкера для WinARM.
В настоящее время лицензия заменена с LGPL на ecos (см. архив почтовой рассылки EFSL на сайте sourceforge). Таким образом, код можно использовать даже в проектах с закрытыми исходниками, но все модификации и расширения в коде библиотеки efsl должны быть опубликованы в виде исходного кода (лучший метод для предоставления исправлений и расширений разработчикам efsl).
Загрузка: arm7_efsl_0_2_8_mt_20060910c.zip (метка времени 20060910, код базируется на efsl Ver. 0.2.8 с некоторыми дополнительными исправлениями от sf.net не включены в официальный исходный код. В архиве есть примеры для LPC2138/LPC2148 и AT91SAM7S64/AT91SAM7S256, а также документация efsl).
[Словарик]
diskio в контексте данной статьи имеется в виду набор подпрограмм для низкоуровневого обмена данными с картой памяти. Этот набор подпрограмм является мостом между аппаратурой микроконтроллера с одной стороны, и с другой стороны с интерфейсом данных карты памяти.
DMA Direct Memory Access - прямой доступ к памяти. Технология, освобождающая ядро процессора от пересылок данных между периферийным устройством (например, последовательный порт) и оперативной памятью. Т. е. данные пересылаются автоматически, при этом процессор может параллельно выполнять код программы, не связанный с пересылкой данных.
EFSL Embedded Filesystem Library - библиотека для организации файловой системы на встраиваемых системах. Подробнее см. [12].
FAT файловая система, разработанная Microsoft. Впервые появилась на MS-DOS в версии FAT12, затем вышли версии FAT16 и FAT32. Цифра в названии версии означает разрядность номеров кластеров файловой системы (чем больше разрядов, тем больше данных может хранить диск).
FatFS библиотека для организации файловой системы на встраиваемых системах. Подробнее см. [3].
LFN Long File Names - длинные имена файлов. Технология, появившаяся (не сразу) на файловой системе FAT, которая позволяет помимо имен MS-DOS формата 8.3 хранить длинные имена файлов, и применять для имен файлов национальные кодировки символов (русские имена файлов).
MCI MultiMedia Card Interface - аппаратный интерфейс, поддерживающий 4-битный режим доступа к картам SD.
PetitFS облегченная библиотека файловой системы для микроконтроллеров наподобие AVR. Подробнее см. [3].
SD Secure Digital - название стандарта интеллектуальных карт памяти, которые используются в переносных устройствах для хранения данных (фотоаппараты, смартфоны и т. п.).
SDHC SD High Capacity - развитие стандарта SD, позволяющее использовать карты памяти повышенной емкости (больше 4 гигабайт).
SPI популярный дуплексный последовательный интерфейс (подробнее см. [11]).
SSP аппаратное периферийное устройство микроконтроллеров LPC (NXP), которое поддерживает множество протоколов, в том числе и SPI.
[Ссылки]
1. Interfacing ARM controllers with Memory-Cards site:siwawi.bauing.uni-kl.de. 2. Как использовать карты памяти MMC/SDC. 3. Файловые системы. 4. libfat devkitPro site:sourceforge.net. 5. ARM MP3/AAC Player site:embdev.net. 6. Sourcery CodeBench Lite Edition site:mentor.com. 7. Embedded Filesystems Library site:sourceforge.net. 8. Microsoft EFI FAT32 File System Specification site:msdn.microsoft.com. 9. ARM-Projects by Martin THOMAS site:siwawi.bauing.uni-kl.de. 10. AVR-Projects by Martin THOMAS site:siwawi.bauing.uni-kl.de. 11. Интерфейс SPI. 12. Библиотека EFSL.