Перейти к содержанию

    

USB MASS storage эмуляция большего размера

Добрый день!

Имеется печатная плата, на которой расположена ПЛИС как основное устройство и микроконтроллер STM32, как

вспомогательное устройство для загрузки конфигурационного файла в ПЛИС.

Замысел следующий - STM32 реализует USB Mass storage, в результате, пользоваттель, при подключении по USB

видит подключенную к компу флешку, загружает на эту флешку bit-файл, которым инициализируется ПЛИС.

Реализовал данное устройство с памятью во внутренней памяти микроконтроллера, но проблема в том, что

она меньше размеров загрузочного файла. Сам файл мне сохранять в памяти не нужно, - требуется лишь дергая

ножками STM32 загрузить его в ПЛИС, соответственно нужно эмулировать для компа память большего размера,

а для этого, необходимо парсить usb-запросы от компа на запись и считывание.

Сама реализация USB mass storage устройства в STM32 - проще некуда, достаточно реализовать лишь две

функции

STORAGE_Write_FS

и

STORAGE_Read_FS

См. файл по ссылке:

https://cloud.mail.ru/public/ALsV/UTQGUYgwo

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

файла, вычитать его данные, делая вид, что сохраняю его во флеш, а на самом деле передать его в ПЛИС, а в

ответ на запрос на считывание его просто вернуть набор нулей.

Кто-нибудь сталкивался с подобной задачей? Поделитесь мануалами, примерами кода, описанием протокола

usb-команд к usb mass storage.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Замысел следующий - STM32 реализует USB Mass storage, в результате, пользоваттель, при подключении по USB видит подключенную к компу флешку, загружает на эту флешку bit-файл, которым инициализируется ПЛИС.

Реализовал данное устройство с памятью во внутренней памяти микроконтроллера, но проблема в том, что она меньше размеров загрузочного файла...

Кто-нибудь сталкивался с подобной задачей?

Делали - двумя способами:

 

1. Запись файла с определённым именем: нужна поддержка файловой системы типа Х внутри МК и отслеживания появления файла.

Мы проверяли наличие файла при подаче питания на карте памяти. После прошивки его удаляли и перезагружались.

В вашем случае не подойдёт - памяти мало.

Можно конечно парсить на лету диск, чтоб понять, что запись сектора - это создание файла... это будет увлекательно, но примеры врятли есть - надо писать самому.

 

2. Запись в определённые сектора. Делается виртуальный диск любого размера. Записываете файл через любую утилиту типа HxD.

Можно и своё приложение написать, только для работы с секторами под виндой - потребуются права администратора...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Можно конечно парсить на лету диск, чтоб понять, что запись сектора - это создание файла... это будет увлекательно, но примеры врятли есть - надо писать самому.

Видимо, это единственный возможный вариант.

Попытался прикрутить библиотеку FatFS от Chan - не хватает памяти.

Пока удалось следующее:

Во флеш-память usb mass storage устройства загрузил файл с наименованием "00000.txt" и содержимым "77777", т.е. обычный текстовый файл размером 5 байт. После этого считал память МК. USB mass storage устройство имеет размер 43 блока по 512 байт. 20 КБ из них занято файловой системой FatFS, т.е. устройство после подключения к ПК по USB имеет размер 1.5 КБ:

43 * 512 = 0x5600 Глянул содержимое памяти HEX-редактором и действительно, флеш-память МК начиная с адреса 0x08010000 по которому хранится содержимое usb mass устройства по адрес 0x08015600 Содержит осмысленные данные. Вся остальная память после 0x08015600 заполнена FF.

Вырезал данный кусок памяти 0x08010000 - 0x08015600в отдельный файл (он в приложении).

Ищу кодовую последовательность 30 30 30 30 30 ( "00000" в ASCII кодах, т.е. наименование файла) - вижу ее по адресу 0x1060:

 

Captureeeee.png

 

 

Кодовая последовательность 37 37 37 37 37 ( "77777" в ASCII кодах, т.е. содержимое файла) расположена по адресу 0x5400:

 

Captureeeee.png

 

Адрес 0x5400 соответствует началу последнего сектора (размер сектора 512 байт = 0x200). Интуиция подсказывает, что рядом с названием файла должен располагаться указатель на адрес, по которому расположено содержимое файла и его размер. Видимо предстоит раскуривать какую-либо библиотеку, реализующую FatFS, например, того же самого Chan'а в поисках нужного куска кода, который откроет свет на взаимосвязь между названием файла и его расположением.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Реализовал данное устройство с памятью во внутренней памяти микроконтроллера, но проблема в том, что

она меньше размеров загрузочного файла. Сам файл мне сохранять в памяти не нужно, - требуется лишь дергая

ножками STM32 загрузить его в ПЛИС, соответственно нужно эмулировать для компа память большего размера,

О каком размере файла хоть речь-то?

Вообще в любом STM32 есть довольно большой объём памяти - flash-памяти программ. Почему не использовать её раз уж так хочется mass storage?

Но я бы не заморачивался: раз USB, значит - реализовать DFU. DFU именно для того и предназначен (обновления прошивки). Вместо странного использования mass storage.

Ну или хоть сделать CDC и передать туда файл прошивки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Mass Storage - просто считывание/запись сектора и ФС вы уже сами должны изображать. По минимуму в флеше STM32 должно хранится содержимое 4 секторов по 512 байт: mbr, boot, fat, root с прописанными туда данными вашего файла. При этом отдавать в зависимости от номера запрошенного сектора или эти предопределенные сектора, или выкачанную по SPI вашу прошивку. Записывать можно примерно также, но желательно размер носителя сделать равным размеру прошивки+служебная область файловой системы. При этом новая прошивка будет перезаписывать старую.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
О каком размере файла хоть речь-то?

Вообще в любом STM32 есть довольно большой объём памяти - flash-памяти программ. Почему не использовать её раз уж так хочется mass storage?

Но я бы не заморачивался: раз USB, значит - реализовать DFU. DFU именно для того и предназначен (обновления прошивки). Вместо странного использования mass storage.

Ну или хоть сделать CDC и передать туда файл прошивки.

Размер файла от 1-го МБ/ USB Mass storage - требование заказчика. Ему хочется, чтобы обновление прошивки ПЛИС выглядело простой записью файла на флешку, подключенную к ПК по USB. И роль этой флешки должна играть STM32 с размером флеш-памяти 128 КБ.

 

Mass Storage - просто считывание/запись сектора и ФС вы уже сами должны изображать. По минимуму в флеше STM32 должно хранится содержимое 4 секторов по 512 байт: mbr, boot, fat, root с прописанными туда данными вашего файла. При этом отдавать в зависимости от номера запрошенного сектора или эти предопределенные сектора, или выкачанную по SPI вашу прошивку. Записывать можно примерно также, но желательно размер носителя сделать равным размеру прошивки+служебная область файловой системы. При этом новая прошивка будет перезаписывать старую.

Удалось впихнуть FatFS от Chan'а в 64 КБ флеш-памяти МК, оставив другие 64 КБ под память программы. Выяснилось, что при перезаписи файла с ПК файл остается в прежнем секторе, не меняя своего положения. На первый взгляд это очень упрощает задачу в том случае, если файл прошивки ПЛИС будет иметь одно и то же название - тогда достаточно будет отслеживать запись в один и тот же сектор памяти. Но прежде этого нужно научиться симулировать для ПК флешку размером несколько мегабайт имея всего лишь 64 КБ.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Выяснилось, что при перезаписи файла с ПК файл остается в прежнем секторе, не меняя своего положения. На первый взгляд это очень упрощает задачу в том случае, если файл прошивки ПЛИС будет иметь одно и то же название - тогда достаточно будет отслеживать запись в один и тот же сектор памяти. Но прежде этого нужно научиться симулировать для ПК флешку размером несколько мегабайт имея всего лишь 64 КБ.

Ну да - а теперь попробуйте туда записать ещё файлы, потом дописать предыдущий файл и т.п. - нет никакой гарантии по расположению файла по секторам, это всё на откупе драйвера ФС ПК. Будет очень ненадёжно. Что делать если ФС ПК обратится к тем секторам, которые вы уже вытеснили за пределы своих 64кБ? Вернуть мусор?

Впрочем - если есть доступ к прошивке ПЛИС не только по записи, но и по чтению, то можно эти сектора читать оттуда: если файл прошивки при записи в ПЛИС никак не преобразуется, пишется "как есть", байт-в-байт, то можно считать первые 512 байт прошивки - первым сектором файла, вторые - вторым и т.д. Хранить в памяти МК только таблицу FAT, по ней определять когда доступ (по чтению или записи) идёт к сектору относящемуся к файлу прошивки - читать или писать его из/в память ПЛИС по соответствующему смещению, равному номеру сектора в цепочке секторов файла.

Правда нужно будет пресекать все попытки выполнить операции записи каких-то ещё файлов кроме прошивки в такой mass storage.

 

Да и вообще - придётся ещё и в FatFS порыться: если вы даёте ей команду "запись данных в такой-то файл с такого то смещения", то как будете определять в какой именно сектор она данные этого смещения запишет? Она может их записать в каком угодно порядке, а не обязательно в цепочку возрастающих по номеру секторов.

Поэтому такой метод является крайне ненадёжным. И Вам бы лучше следовало объяснить заказчику какие потенциальные грабли он закладывает в свои будущие обновления прошивок, гонясь за кажущейся простотой, кажущейся ему, потому что он не понимает механизмов работы всего этого.

Ну или можно написать свой драйвер ФС (а не использовать FatFS) чтобы быть уверенным в соответствии секторов смещениям файла... B)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Удалось впихнуть FatFS от Chan'а в 64 КБ флеш-памяти МК, оставив другие 64 КБ под память программы. Выяснилось, что при перезаписи файла с ПК файл остается в прежнем секторе, не меняя своего положения. На первый взгляд это очень упрощает задачу в том случае, если файл прошивки ПЛИС будет иметь одно и то же название - тогда достаточно будет отслеживать запись в один и тот же сектор памяти. Но прежде этого нужно научиться симулировать для ПК флешку размером несколько мегабайт имея всего лишь 64 КБ.

Вам надо просто хранить во флеше 4 правильно сформированных сектора и фсе. Если идет запрос к ФС (запрашиваемый сектор меньше первого сектора файла прошивы) - отдаем эти сектора или нули, если к файлу прошивки - читаем. пишем из плис.

Если размер носителя в настройках массстораджа будет размер ФС+размер прошивки и правильно сформировать 4 служебных сектора, то запись файла размером с прошивку будет всегда идти одинаково.

Только надо учитывать, что если общее число кластеров ФС меньше 4096, то комп считает, что это FAT12, несмотря на то, что в буте прописана фат16. Возможно это можно побороть, но мне проще оказалось фат12 эмулировать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне пока удалось съэмулировать лишь 110КБ памяти. Для этого в запросах от ПК на считывание оказалось достаточно подменять:

 

1) значение байта по адресу 0x1D0 (сектор 0), который содержит размер раздела (partition):

 

Diff1.png

 

2) значение байта по адресу 0x7E13 (сектор 63), который содержит, видимо, размер раздела (пока не уверен):

 

Diff2.png

 

Если меняю значение байтов, выделенных на скриншотах синим цветом на 255 (0xff), то получаю размер флеш накопителя ( 255 + 63 ) * 512 = 159 КБ.

 

Как только пытаюсь задать количество секторов, превышающее 0xff, т.е. перезаписать больше одного байта, то все рушится. Видимо чего-то не учел. Нет ли у кого-нибудь бинарного "скана" (image) файловой системы на несколько мегабайт?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот содержимое MBR и BS секторов для 16 Мбайт "флешки". Скрины из WinHex.

Если что неясно спрашивайте.

 

Вот в текстовом виде

Для MBR. Фрагмент располагается с адреса 1BEh (на 1-й картинке - начало выделенной области).

0x00,0x03,0x02,0x00,0x06,0x07,0xE0,0xC9,0x61,0x00,0x00,0x00,0xff,0x7f,0x00,0x00

Для BootSector

0xEB,0x3C,0x90,0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30,0x00,0x02,0x04,0x04,0x00
0x02,0x00,0x02,0xff,0x7f,0xF8,0xF2,0x00,0x3F,0x00,0xFF,0x00,0x61,0x00,0x00,0x00
0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x0C,0x72,0xFA,0xB0,0x4E,0x4F,0x20,0x4E,0x41
0x4D,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x36,0x20,0x20,0x20

Для MBR и BS достаточно хранить в памяти контроллера только эти фрагменты, а остальное легко сформировать программно.

post-45309-1521317285_thumb.png

post-45309-1521317293_thumb.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Вот содержимое MBR и BS секторов для 16 Мбайт "флешки". Скрины из WinHex.

Если что неясно спрашивайте.

 

Вот в текстовом виде

Для MBR. Фрагмент располагается с адреса 1BEh (на 1-й картинке - начало выделенной области).

0x00,0x03,0x02,0x00,0x06,0x07,0xE0,0xC9,0x61,0x00,0x00,0x00,0xff,0x7f,0x00,0x00

Для BootSector

0xEB,0x3C,0x90,0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30,0x00,0x02,0x04,0x04,0x00
0x02,0x00,0x02,0xff,0x7f,0xF8,0xF2,0x00,0x3F,0x00,0xFF,0x00,0x61,0x00,0x00,0x00
0x00,0x00,0x00,0x00,0x00,0x00,0x29,0x0C,0x72,0xFA,0xB0,0x4E,0x4F,0x20,0x4E,0x41
0x4D,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x31,0x36,0x20,0x20,0x20

Для MBR и BS достаточно хранить в памяти контроллера только эти фрагменты, а остальное легко сформировать программно.

Спасибо! Очень помогло!

Методом тыка добился эмуляции 678 КБ памяти:

uint8_t mbr[16] = {
        0x00,                     // not bootable
        0x01,                     // head number of partition start sector in CHS form. ??
        0x01,0x00,                // cylinder number ??
        0x01,                    // FAT12 (CHS/LBA, <65536 sectors)
        0x07,                    // header number of partition end sector in CHS form. ??
        0xE0,0xC9,                // cylinder number and sector number in the cylinder... ??
        0x3F,0x00,0x00,0x00,    // partition start sector in LBA (0x3F = 63)
        0xFF,0x7F,0x00,0x00        // partition size in unit of sector (0x7FFF = 32767)
};

 

uint8_t br[62] = {
        0xEB,0x3C,0x90,                            // Jump to bootstrap
        0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30,// "MSDOS5.0"
        0x00,0x02,                                // 512 bytes per sector
        0x04,                                     // 1 sector per cluster
        0x01, 0x00,                                // number of reserved sectors
        0x01,                                    // number of FAT copies
        0x00, 0x02,                                // number of root directory entries
        0xF0,0x07,                                // Total number of sectors in the filesystem
        0xF8,                                    // descriptor type - hard disk
        0x01,0x00,                                // Number of sectors per FAT
        0x3F,0x00,                                // Number of sector per track
        0xFF,0x00,                                // number of heads
        0x3F,0x00,                                // Number of hidden sectors
        0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x29,0x00,0x00,0x00,0x00,0x4E,0x4F,
0x20,0x4E,0x41,
        0x4D,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x20,0x20,0x20,0x20,0x20
};

 

Но изменение параметров совершенно рандомно влияет на объем памяти, которое "видит" Винда на ПК. Например, если в br поменяю поле "Total number of sectors in the filesystem" c 0x07F0 на 0x7FFF, т.е. увеличу значение поля, то Винда обнаружит меньше памяти - порядка 500 КБ.

Описание, которое нашел на просторах интернета - весьма скромное:

https://www.win.tue.nl/~aeb/linux/fs/fat/fat-1.html

http://elm-chan.org/docs/fat_e.html#partition

и не дает понимания на что влияет каждый параметр. Магическое "CHS form" гуглу вообще неизвестно)

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Магическое "CHS form" гуглу вообще неизвестно)

Это альтернативный способ адресации сектора, привязанный к физическим параметрам носителя.

Head - магнитная головка дисковода, которая в данный момент читает-пишет данные. Например у Floppy-диска доступно две стороны и соответственно используется две Head, у жестких дисков этих Head-ов ещё больше (4,6,8 и т.д.).

Cylinder - дорожка на выбранной стороне диска.

Sector - сектор на дорожке (на цилиндре).

Вместо неудобной CHS-адресации позже придумали более универсальную LBA - с линейным адресным пространством. Но для совместимости сохраняется и CHS.

 

Возможно параметры CHS и LBA должны как-то соотноситься между собой, но точно не знаю, т.к. с этим не экспериментировал.

Я брал готовые образцы: MicroSD карту на 128Мб (FAT16), и виртуальную флешку 32Мб (FAT16) с платы "STM32VLDiscovery". И по ним делал собственный вариант, который привёл выше.

На моей "флешке" реальный объём данных около 1Мб, а виртуальных 16Мб было объявлено для того, чтоб не сильно отклоняться от образца "STM32VLDiscovery", и не искать подводные камни.

 

Но изменение параметров совершенно рандомно влияет на объем памяти, которое "видит" Винда на ПК. Например, если в br поменяю поле "Total number of sectors in the filesystem" c 0x07F0 на 0x7FFF, т.е. увеличу значение поля, то Винда обнаружит меньше памяти - порядка 500 КБ.

В таблице данных BS, как мне кажется, есть ошибка: размер таблицы FAT = 1 сектор. Может этот размер должен быть равным количеству объявленных секторов (или хотя бы не менее)? Попробуйте его изменить.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Mass Storage - просто считывание/запись сектора и ФС вы уже сами должны изображать. По минимуму в флеше STM32 должно хранится содержимое 4 секторов по 512 байт: mbr, boot, fat, root с прописанными туда данными вашего файла. При этом отдавать в зависимости от номера запрошенного сектора или эти предопределенные сектора, или выкачанную по SPI вашу прошивку. Записывать можно примерно также, но желательно размер носителя сделать равным размеру прошивки+служебная область файловой системы. При этом новая прошивка будет перезаписывать старую.

 

Чет непонятно, там что, куча файлов должна быть и в разных каталогах??? По моему, достаточно файла прошивки в корневом каталоге, нафига тут "толстая" ФС?? Ну и под буфер для размещения прошивки целиком можно использовать какую-нить внешнюю флешку, FRAM, например...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добрый день.

Приключения не закончились. Методом перебора подобрал следующие параметры для эмуляции накопителя объемом 6МБ:

uint8_t mbr[16] = {
        0x00,                     // not bootable
        0x01,                     // head number of partition start sector in CHS form. ??
        0x01,0x00,                // cylinder number ??
        0x01,                    // FAT12 (CHS/LBA, <65536 sectors)
        0x07,                    // header number of partition end sector in CHS form. ??
        0xE0,0xC9,                // cylinder number and sector number in the cylinder... ??
        0x3F,0x00,0x00,0x00,    // partition start sector in LBA (0x3F = 63)
        0xFF,0x7F,0x00,0x00        // partition size in unit of sector (0x7FFF = 32767)
};

uint8_t br[62] = {
        0xEB,0xFE,0x90,                            // Jump to bootstrap
        0x4D,0x53,0x44,0x4F,0x53,0x35,0x2E,0x30,// "MSDOS5.0"
        0x00,0x02,                                // 512 bytes per sector
        0x20,                                     // 1 sector per cluster
        0x01, 0x00,                                // number of reserved sectors
        0x01,                                    // number of FAT copies
        0x00, 0x02,                                // number of root directory entries
        0xF0,0x40,                                // Total number of sectors in the filesystem
        0xF8,                                    // descriptor type - hard disk
        0x01,0x00,                                // Number of sectors per FAT
        0x3F,0x00,                                // Number of sector per track
        0xFF,0x00,                                // number of heads
        0x3F,0x00,                                // Number of hidden sectors
        0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x29,0x00,0x00,0x00,0x00,0x4E,0x4F,
0x20,0x4E,0x41,
        0x4D,0x45,0x20,0x20,0x20,0x20,0x46,0x41,0x54,0x20,0x20,0x20,0x20,0x20
};

 

Теперь накопитель отображается в ОС windows следующим образом:

 

 

Capture.png

 

Для того, чтобы переваривать файлы размером Мегабайты функцию STORAGE_Write_FS модифицировал следующим образом:

/**
  * @brief  .
  * @param  lun: .
  * @retval USBD_OK if all operations are OK else USBD_FAIL
  */
int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
    if(blk_addr <= 97) {
        flash_write(lun, buf, blk_addr, blk_len);
    } else {
        printf("!W blk %d, cnt %d\r\n", blk_addr, blk_len);
    }
    if(blk_addr == 97) {
        printf("W blk %d, cnt %d\r\n", blk_addr, blk_len);
        printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\r\n", *(buf+0x00), *(buf+0x01), *(buf+0x02), *(buf+0x03), *(buf+0x04), *(buf+0x05), *(buf+0x06), *(buf+0x07), *(buf+0x08), *(buf+0x09), *(buf+0x0A), *(buf+0x0B), *(buf+0x0C), *(buf+0x0D), *(buf+0x0E), *(buf+0x0F) );
    }
    return USBD_OK;
  /* USER CODE END 7 */
}

Где блок 97 - это область памяти, в котором FatFs создает реально существующий файл объемом 5 байт - этот блок записывается во флеш память МК по-настоящему, а все последующие нет.

При попытке записать файл размером 16КБ и выше получаю следующую ошибку:

 

 

Capture.png

 

В чем может быть проблема?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И в окне форматирования отображается 32.5 КБ вместо 6 МБ:

 

Capture.png

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация