Драйвер SD-карт и файловая система

Материал из MIK32 микроконтроллер

По ссылке располагается репозиторий драйвера карт SD и файловой системы MIK32FAT, совместимой с файловой системой FAT32.

Репозиторий имеет форму проекта PlatformIO IDE, фреймворк -- framework-mik32v2-sdk.

Файлы main.c, sd-spi.c содержит пример записи и чтения файлов. Файлы mik32fat.h и mik32fat.c относятся к файловой системе. Файлы sd.h и sd.c -- это драйвер диска.

Драйвер карт SD

Драйвер SD-карт в настоящее время реализует общение с картами по шине SPI. Имеются функции инициализации карты SD (с попутным определением ее типа), функции отправки команды на карту, а также функции одиночного чтения, записи и стирания 512-байтных секторов.

Файловая система MIK32FAT

Позволяет читать, дозаписывать и перезаписывать файлы, создавать и удалять файлы и директории. Файловая система в настоящее время не поддерживает формат длинных имен файлов (LFN), имена открываемых и создаваемых файлов и директорий должны состоять из заглавных (!) латинских букв и цифр, длина имени не должна превышать 8 символов, а длина расширения - 3 символов.

Во время инициализации файловой системы (функция MIK32FAT_Init) выполняется чтение boot-сектора диска, открывается первый том диска из возможных. В ходе инициализации в дескриптор файловой системы загружаются значения номеров начальных секторов секции данных, записей таблицы аллокации файлов (FAT). После выполнения функции MIK32FAT_Init микроконтроллер готов к работе с файловой системой.

/* Инициализация */
static FAT_Descriptor_t fs;
FAT_Status_t res;
res = MIK32FAT_Init(&fs);
xprintf("FS initialization: %s", res==FAT_OK ? "ok\n" : "failed, ");

FAT_Status_t MIK32FAT_Init(FAT_Descriptor_t* fs);

  • Поле fs -- указатель на дескриптор файловой системы (структура типа FAT_Descriptor_t)

Работа с файлами

Открытие файлов

Работа с файлами начинается с вызова функции MIK32FileOpen.

FAT_Status_t MIK32FAT_FileOpen(FAT_File_t* file, FAT_Descriptor_t* fs, char* name, char modificator);

  • Поле file -- указатель на структуру-дескриптор файла
  • Поле fs -- указатель на структуру-дескриптор файловой системы
  • Поле name -- путь (имя) файла
  • Поле modificator определяет режим доступа к файлу

Всякая функция файловой системы требудет для работы информацию из структуры-дескриптора файловой системы, однако функции работы с файлами требуют также доступ к специфической информации о файле, что есть только в структуре-дескрипторе файла. Чтобы не подавать аргументом функции два указателя на структуры-дескрипторы, указатель на дескриптор файловой системы включается в дескриптор файла функцией MIK32FAT_FileOpen.

Функция MIK32FAT_FileOpen, помимо этого, выполняет поиск файла на диске по строке-пути. Строка путь (поле name)

  • Совпадает с именем файла, если файл находится в корневом каталоге диска
  • Содержит перед имененм файла названия субдиректорий, отделенные символом '/' ("слеш")

Так, например, если необходимо прочитать файл TEXT.TXT, который находится в папке FOLDER, строка-путь должна иметь вид "FOLDER/TEXT.TXT".

Поле modificator имеет 3 возможных значения

- 'R' (0x52) -- открыть файл для чтения

- 'W' (0x57) -- открыть файл для записи (дозаписи). Если открываемый файл не будет найден на диске, он будет автоматически создан

- 'A' (0x41) -- открыть файл для перезаписи. Если открываемый файл не будет найден на диске, он будет автоматически создан. Если файл будет найден, он будет удален, а затем автоматически создан.

Если файл был открыт для чтения ('R'), то к нему применим метод MIK32FAT_ReadFile. Если файл был открыт для дозаписи или для перезаписи ('W' или 'A'), то к нему применим метод MIK32FAT_WriteFile.

/* Пример открытия файла */
FAT_File_t write_file;
FAT_Status_t res = MIK32FAT_FileOpen(&write_file, &fs, "TESTS/WRITE1.TXT", 'W');
xprintf("TESTS/WRITE1.TXT file open status: %s\n", res==FAT_OK ? "ok" : "failed");

Чтение файлов

Чтение файлов выполняется функцией MIK32FAT_ReadFile.

uint32_t MIK32FAT_ReadFile(FAT_File_t* file, char* buf, uint32_t quan)

- Поле file -- указатель на структуру-дескриптор файла

- Поле buf -- указатель на массив, куда данные будут записываться

- Поле quan -- количество читаемых байт файла

Функция возвращает количество прочитанных байт. Если файл был открыт для записи или перезаписи, а его пытаются читать, функция выдадет 0.

/* Пример чтения файла */
/* (файловая система должна быть уже проинициализирована, а файл открыт) */

static char read_buffer[READ_BUFFER_LENGTH];

uint8_t i = read_file.len / (READ_BUFFER_LENGTH-1);
if (read_file.len % (READ_BUFFER_LENGTH-1) != 0) i += 1;
uint32_t bytes_read;
xprintf("Text:\n");
while (i > 0)
{
    /* Прочитать порцию байт длины READ_BUFFER_LENGTH-1 в буфер read_buffer */
    bytes_read = MIK32FAT_ReadFile(&read_file, read_buffer, READ_BUFFER_LENGTH-1);
    if (bytes_read == 0)
    {
        xprintf("Error occured while file reading, stop.\n");
        break;
    }
    else 
    {
        /* Вставить символ возврата каретки для корректной печати */
        read_buffer[bytes_read] = '\0';
        /* Напечатать содержимое буфера */
        xprintf("%s", read_buffer);
    }
    i -= 1;
}

Запись файлов

Запись файлов выполняется функцие MIK32FAT_WriteFile.

uint32_t MIK32FAT_WriteFile(FAT_File_t* file, const char* buf, uint32_t quan);

  • Поле file -- указатель на структуру-дескриптор файла
  • Поле buf -- указатель на массив, откуда данные будут браться для записи
  • Поле quan -- количество записываемых байт файла

Функция возвращает количество записанных байт. Если файл был открыт для чтения, а в него пытаются что-то записать, функция выдадет также 0.

/* Пример записи файлов */
/* (файловая система должна быть уже проинициализирована, а файл открыт) */

char str[] = "Writing string to file\n";
xprintf("Wrote bytes: %d\n", MIK32FAT_WriteFile(&write_file, str, strlen(str)-1));
xprintf("Close status: %d\n", MIK32FAT_FileClose(&write_file));

Закрытие файлов

Дескриптор файловой системы содержит 512-байтный буфер сектора диска. Функция MIK32FAT_WriteFile выполняет запись содержимого буфера на диск только когда буфер заполняется полностью. Если после вызова MIK32FAT_WriteFile количество байт в буфере меньше его длины, информация не будет перенесена на диск. Чтобы дозаписать остатки данных на диск, существует функция MIK32FAT_FileClose.

FAT_Status_t MIK32FAT_FileClose(FAT_File_t* file)

Прочие функции файловой системы

Создание файлов и директорий

Для создания файлов и директорий существует функция MIK32FAT_Create.

FAT_Status_t MIK32FAT_Create(FAT_Descriptor_t* fs, char* name, bool dir)

  • Поле fs -- указатель на дескриптор файловой системы
  • Поле name -- путь до файла или директории (смотри Открытие файлов)
  • Поле dir -- если true, то создаем директорию, если false, то создаем новый пустой файл
/* Пример создания файлов */
/* (файловая система должна быть уже проинициализирована) */
/* При вызове функции создается файл FILE.TXT в папке FOLDER. Если папка FOLDER
 * в корневой директории не найдена, функция создаст и ее */

MIK32FAT_Create(FAT_Descriptor_t* fs, "FOLDER/FILE.TXT", false);

Удаление файлов и директорий

Удаление файлов и директорий осуществляется функцией MIK32FAT_Delete.

FAT_Status_t MIK32FAT_Delete(FAT_Descriptor_t* fs, char* name)

  • Поле fs -- указатель на дескриптор файловой системы
  • Поле name -- путь до файла или директории (смотри Открытие файлов)

Важно отметить, что зачастую, когда при использовании персонального компьютера пользователь нажимает на кнопку удаления файла, файл не удаляется, а перемещается в скрытую директорию TRASH, которая расположена в корневом каталоге. Функция же MIK32FAT_Delete именно удаляет файл, стирая его с диска.

/* Пример удаления файлов */
/* (файловая система должна быть уже проинициализирована) */
/* При вызове функции удаляется файл FILE.TXT в папке FOLDER */

MIK32FAT_Delete(FAT_Descriptor_t* fs, "FOLDER/FILE.TXT", false);