USB флешка на ATmega8 и V-USB. От идеи к готовому устройству...

AVR
Прочитав пару статей других пользователей, захотелось самому начеркать чего-то полезного для остальных. Как все поняли из названия, речь пойдет о создании USB mass storage device класса на програмной реализации V-USB.



Знакомство мое с данной библиотекой произошло случайно и оч. давно. Как и большинство(наверное) на то время любителей я все работал на микрухах типа pl2303 и FT245(232), а они, как известно, не позволяют изменять класс устройства (тока то, что зашито на заводе и все). Купить контроллер с аппаратной частью USB возможности не было, вот, как говорится, и понеслось!) Бодяжил много чего полезного и бесполезного, но как говориться тока для себя зануды любимого. Как-то читал на одном известном форуме, что реализовать то или иное устройство на данной «псевдо» USB нереально, а передавать большие объемы данных и подавно. Так и задался целью замутить чегонить вроде USB флешки или микрофона. И то и другое сделал, но из-за того что я тяжелый на подъем, в массы так и не выкладывал. Вот и моя первая проба познакомить уважаемое сообщество со своим проектом.

Сразу оговорюсь, что все приведенные фотки моего девайса тока для ознакомления, потому как это платка мой программатор AVR по USB со своим бутом и прогой для апдейту. Схему я конечно выложу, но плату разводить, наверное, специально для этого проекта, не буду.


Проект выполнен на IAR'е, sPlan, SprintLayout, Device Monitoring Studio и утюге под пиво =) Ну, в путь!

Для начала, немного теории. MSD или Mass Storage Class это ничто иное, как один из стандартных классов USB для описания и взаимодействия с утройствами хранения информации. Реализаций и стандартов MSD довольно много и заморачиваться на каждом из них нет смысла. Опишу самый распространенный из них(он же самый простой на мой взгляд): Bulk-only или BBB.

В стандарте USB есть такое понятие, как конечная точка(end-point). Конечная точка — это часть USB-устройства, которая имеет уникальный идентификатор и является получателем или отправителем информации, передаваемой по шине USB. Проще говоря, это буфер, сохраняющий несколько байт. Обычно это блок данных в памяти или регистр микроконтроллера. Данные, хранящиеся в конечной точке, могут быть либо принятыми данными, либо данными, ожидающими передачу. Хост также имеет буфер для приема и передачи данных, но хост не имеет конечных точек.

Конечная точка имеет следующие основные параметры:
  • Частота доступа к шине
  • Допустимая величина задержки обслуживания
  • Требуемая ширина полосы пропускания канала
  • Номер конечной точки
  • Способ обработки ошибок
  • Максимальный размер пакета, который конечная точка может принимать или отправлять;
  • Используемый конечной точкой тип посылок
  • Направление передачи данных


Любое USB-устройство имеет конечную точку с нулевым номером (Endpoint Zero). Эта точка позволяет хосту опрашивать устройство с целью определения его типа и параметров, выполнять инициализацию и конфигурирование устройства.

Кроме нулевой точки, устройства, обычно, имеют дополнительные конечные точки, которые используются для обмена данными с хостом. Дополнительные точки могут работать либо только на прием данных от хоста (входные точки, IN), либо только на передачу данных хосту (выходные точки, OUT). Число дополнительных конечных точек устройств определяется режимом передачи.

Для низкоскоростных устройств допускается наличие одной или двух дополнительных конечных точек, а для высокоскоростных — до 15 входных и 15 выходных дополнительных точек.

Но это тока теория, которая выглядит довольно абстрактно. Будем считать, что конечная точка, это ничто иное как фунция в языке C, которая тока принимает параметры, или только возвращает значения.

Так вот, мы строим устьройство, отвечающее спецификации bulk-only. И тут самое приятное: все события делятся на три фазы:

  • Прием команды от хоста(копьютера)(CBW)
  • Прием/Передача запрашиваемых данных(DATA)
  • Передача хосту результата выполнения принятой комманды(STATUS)

Command\Data\Status

Здесь видно, что мы принимаем данные и отправляем данные, значит мы имеем 2 конечные точки (от хоста к устройству и наоборот), а, исходя из выбранной спецификации, эти точки используют bulk передачу данных.

Следовательно мы должны сконфигурировать библиотеку V-USB соответсвующим образом:
  • Описываем конечную точку-in
  • Конечную точку-out
  • Указываем v-USB, что мы используем 2 конечные точки помимо основной (control-endpoint)
  • Задаем класс устройсва USB — Mass Storage Class Bulk-only (Не пугайтесь, все это легко видно из файлов прошивки).

На этом весь процесс создания устройства MSD bulk-only закончен и мы приступаем к тому, что принимаем от хоста комманды и соответсвенно реагируем на них!

Теперь вкратце о тех самых коммандах от хоста. Их не так много и большинство из низ поступают только пару раз. Итак хост может попросить от нас следующее:

  • Inquiry — запрос основных характеристик устройства
  • Test unit ready — проверка готовности устройства, в т.ч. наличия диска в дисководе.
  • Request sense — возвращает код ошибки предыдущей команды.
  • Read capacity — возвращает ёмкость устройства.
  • Read (4 варианта) — чтение.
  • Write (4 варианта) — запись.
  • Mode select — установка параметров устройства.
  • Mode sense — возвращает текущие параметры устройства

Теперь далее. Пересмотрев массу устройств хранения информации (EEPROM, nand и т.д.) я выбрал, наверное, самое распространненое SD/MMC карту памяти. Подключение ее к AVRке давно известно, а протокол хорошо разжеван. Еще один плюс в том, что эти карты могут читать/писать по 512 байт данных, что очень подходит для данной задачи.

Так, основными коммандами MSD bulk-only устройстве являются чтение и запись блоков информации. Драйвер Windows (да простят меня пользователи Linux) обращается к нашему устройству по принципу LBA, то есть адрес логического блока (или его номер, что одно и тоже) и их количество.
В нашем случае один логический блок это сектор размером в 512 байт. Так если ОС запросит у нас данные из 20-го LBA, то мы просто умножим 20 на 512 и получим линейный адрес на устройстве носителя. Затем прочитем/запишем нужное число блоков и все! Знать что-то о данных на устройстве хранения информации и способе их размещения AVR не должна. Наша задача обеспечить возможность чтения и записи этих самых блоков из/на устроство хранения информации, а остальное сделает ОС.)

Теперь я представлю Вам мою схемку. Сразу оговорюсь, делал на быструю руку, так как печатку делал из головы (схема не сложная):

USB флешка - схема

Многие заметят, что практически стандартная схема для устройств на V-USB, и что я немного перемудрил с ней, на я повторюсь, что собрал флешку из моего программатора, поэтому здесь немного изврата присутствует. Перемычка JP2 предназначена для прошивки нашего устройства и должна быть установлена только во время обновления прошивки устройства(разъем Х2). Диоды D1 и D2 предназначены для задания рабочего напряжения питания ~3.6V. Можно обойтись и одним(проверено неоднократно), хотя при грамотном подходе лучше сделать не так как я=)

Ну а теперь немного по коду программы. Сначала опишем конфигурацию аппаратной части нашего устройства в файле «usbconfig.h»:

/* ---------------------------- Hardware Config ---------------------------- */

#define USB_CFG_IOPORTNAME      D
/* This is the port where the USB bus is connected. When you configure it to
 * "B", the registers PORTB, PINB and DDRB will be used.
 */
#define USB_CFG_DMINUS_BIT      2
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
 * This may be any bit in the port.
 */
#define USB_CFG_DPLUS_BIT       3
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
 * This may be any bit in the port. Please note that D+ must also be connected
 * to interrupt pin INT0! [You can also use other interrupts, see section
 * "Optional MCU Description" below, or you can connect D- to the interrupt, as
 * it is required if you use the USB_COUNT_SOF feature. If you use D- for the
 * interrupt, the USB interrupt will also be triggered at Start-Of-Frame
 * markers every millisecond.]
 */
 #define F_CPU 16000000


Здесь мы указали, что порт, к которому подключены дифференциальные сигналы D+ и D-, это порт PORTD, а выводы, к которым они подключены, соответсвенно 3 и 2. Частота кварцевого резонатора равна 16 Мгц. Затем мы описали, что мы сами управляем процессом подключения нашего устройства к шине USB. Для этого мы сделали следующее:

/* ----------------------- Optional Hardware Config ------------------------ */

#define USB_CFG_PULLUP_IOPORTNAME   D
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
 * V+, you can connect and disconnect the device from firmware by calling
 * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
 * This constant defines the port on which the pullup resistor is connected.
 */
#define USB_CFG_PULLUP_BIT          1
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
 * above) where the 1.5k pullup resistor is connected. See description
 * above for details.
 */


Это видно из схемы: резистор R7, подключенный к выводу 1 порта PORTD. Далее в программе нам это понадобиться для того, чтобы произвести подключение к хосту в момент времени, который нам более всего подходит. (напомню, что Хост определяет наличие подключения устройства к шине в случае подтягивания линии D- к Vdd. Это я для низкоскоростных устройств).

В рекомендации от V-USB сказано, что линия D+ должна быть подключена к INT0, но я внес некоторые изменения и подключил ее к INT1, что в принципе не запрещено (подключают к IN0 т.к. прерывание INT0 имеет наивысший приоритет в системе прерываний AVR. прим. DH), поэтому я указываю на соответствующие изменения в следующих строках:


#define USB_INTR_CFG            MCUCR
#define USB_INTR_CFG_SET        ((1 << ISC10) | (1 << ISC11))
#define USB_INTR_CFG_CLR        0
#define USB_INTR_ENABLE         GICR
#define USB_INTR_ENABLE_BIT     INT1
#define USB_INTR_PENDING        GIFR
#define USB_INTR_PENDING_BIT    INTF1
#define USB_INTR_VECTOR         INT1_vect


В принципе, в описании аппаратной части USB это все.

В этом же файле мы указываем, что класс и подкласс устройства определяется классом и подклассом интерфейса (это я про то, что мы используем стандартный интерфейс MSD bulk-only). Это делается следующим образом:


#define USB_CFG_DEVICE_CLASS        0x00    /* set to 0 if deferred to interface */
#define USB_CFG_DEVICE_SUBCLASS     0x00
/* See USB specification if you want to conform to an existing device class.
 * Class 0xff is "vendor specific".
 */
#define USB_CFG_INTERFACE_CLASS     0x08   // Именно в это месте мы указываем, что это
#define USB_CFG_INTERFACE_SUBCLASS  0x06   // Mass Storage Device bulk-only transport
#define USB_CFG_INTERFACE_PROTOCOL  0x50   //


Так же мы помним, что мы имеем 2 конечные точки (т.к. мы принимаем и отправляем данные от хоста), значит мы указываем на это библиотеке V-USB:


#define USB_CFG_HAVE_INTRIN_ENDPOINT    1  // конечная точка с номером 1 присудствует
/* Define this to 1 if you want to compile a version with two endpoints: The
 * default control endpoint 0 and an interrupt-in endpoint (any other endpoint
 * number).
 */
#define USB_CFG_HAVE_INTRIN_ENDPOINT3   1  // вторая конечная точка присудствует
/* Define this to 1 if you want to compile a version with three endpoints: The
 * default control endpoint 0, an interrupt-in endpoint 3 (or the number
 * configured below) and a catch-all default interrupt-in endpoint as above.
 * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
 */
#define USB_CFG_EP3_NUMBER              2  // Номер второй конечной точки


Теперь пару слов о следующих определениях:


#define USB_CFG_DESCR_PROPS_DEVICE                  USB_PROP_LENGTH(18)
#define USB_CFG_DESCR_PROPS_CONFIGURATION           USB_PROP_LENGTH(32)
#define USB_CFG_DESCR_PROPS_STRINGS                 0
#define USB_CFG_DESCR_PROPS_STRING_0                0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR           (2*(USB_CFG_VENDOR_NAME_LEN)+2)
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT          (2*(USB_CFG_DEVICE_NAME_LEN)+2)
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER    (2*(USB_CFG_SERIAL_NUMBER_LEN)+2)
#define USB_CFG_DESCR_PROPS_HID                     0
#define USB_CFG_DESCR_PROPS_HID_REPORT              0
#define USB_CFG_DESCR_PROPS_UNKNOWN                 0


Поскольку мы использовали стандартный класс USB MSD, то и описать устройство это класса обязаны мы. Позже я вернусь к этим строкам, а пока мы оставим их в покое.

В принципе в этом файле вроде как и все, но я оговорюсь для наиболее дотошных (как я=): я не пират и не пытался нарушить чьета права? использовав VID/PID, которые в моем файле usbconfig.h. Мало того, я даже не знаю чье они, просто первые попавшиеся под руку==)

Пожалуй, распишу немного процесс инициализации устройства на V-USB.

Немного выше я определил небольшой макрос USB_CFG_PULLUP_IOPORTNAME в соответствии со схемой, что в свою очередь дало мне возможность производить подключение и отключение от шины USB в произвольные моменты времени. Так вот, для подключения к шине используется макрос
usbDeviceConnect();

при вызове которого происходит подтяжка линии D- к напряжению питания устройства. Хост определяет это событие и начинает процедуру конфигурации устройства USB: Сброс девайса, присвоение адреса и т.д.
Во всей этой рутинной суете главное для нас это этап запроса дескриптора устройства, который в свою очередь содержит поддерживаемую версию USB, максимальный размер пакета для control конечной точки, идентификаторы устройства и производителя VID/PID, версию устройсва, строковые номера индексов(если таковые присутсвуют) и количество конфигураций нас родимых.

Поскольку мы проектируем свое собственное ни на что не похожее устройства, то давайте опишем этот дескриптор (Здесь и далее я рассматриваю файлы «MassStorage.h» и «MassStorage.cpp»)


//==============================================================================================
__flash char usbDescriptorDevice[] = {    	            /* USB дескриптор устройства */
    0x12,         /* sizeof(usbDescriptorDevice): длина устройства в байтах */
    USBDESCR_DEVICE,        				    /* тип дескриптора */
    0x10, 0x01,             				    /* поддерживаемая версия USB */
    0x00,
    0x00,
    0x00,                      				    /* протокол */
    0x08,                      				    /* max размер пакета */
    /* следующие два преобразования типа (cast) влияют только на первый байт константы, но
     * это важно для того, чтобы избежать предупреждения (warning) с величинами по умолчанию.
     */
    (unsigned char)USB_CFG_VENDOR_ID,			    /* 2 байта */
    (unsigned char)USB_CFG_DEVICE_ID,			    /* 2 байта */
    USB_CFG_DEVICE_VERSION, 				    /* 2 байта */
    USB_CFG_DESCR_PROPS_STRING_VENDOR != 0 ? 1 : 0,         /* индекс строки производителя */
    USB_CFG_DESCR_PROPS_STRING_PRODUCT != 0 ? 2 : 0,        /* индекс строки продукта */
    USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER != 0 ? 3 : 0,  /* индекс строки серийного номера */
    1,          					/* количество конфигураций */
};


Помните, выше мы описали #define USB_CFG_DESCR_PROPS_DEVICE. Так вот, определив это, мы сообщили библиотеке V-USB, что используется пользовательский «описатель устройства», и при запросе хостом данной информации V-USB передаст то, что мы с вами только что описали. Мы видим, что я описал в usbDescriptorDevice количество конфигураций устройтва равным 1. Что это значит? Это значит что наше устройство может работать только в одном режиме, который мы определим чуть ниже. Так вот наш режим(или конфигурация, если правильнее):


//==================================================================================
__flash char usbDescriptorConfiguration[] = {    /* USB дескриптор конфигурации */
    0x09,             /* sizeof(usbDescriptorConfiguration): длина устройства в байтах    */
    USBDESCR_CONFIG,  /* тип дескриптора                                      */
    0x20, 0x00,       /* общая длина возвращаемых данных (включая встроенные дескрипторы) */
    0x01,             /* количество интерфейсов в этой конфигурации                       */
    0x01,             /* индекс этой конфигурации                                         */
    0x00,             /* индекс строки имени конфигурации                                 */
    0x80,             /* self/bus powered and remote wakeup attribute                     */
    USB_CFG_MAX_BUS_POWER/2,      /* max ток USB в единицах 2mA                           */
/* дескриптор интерфейса следует встроенным (inline): */
    0x09,                         /* sizeof(usbDescrInterface): длина дескриптора в байтах*/
    USBDESCR_INTERFACE,           /* тип дескриптора                                      */
    0x00,                         /* индекс этого интерфейса                              */
    0x00,                         /* альтернативная установка этого интерфейса            */
    0x02,                         /* конечные точки за исключением 0: 2                    */
    USB_CFG_INTERFACE_CLASS,
    USB_CFG_INTERFACE_SUBCLASS,
    USB_CFG_INTERFACE_PROTOCOL,
    0x00,                         /* индекс строки для интерфейса                        */
/* дескриптор конечной точки для конечной точки 1 */
    0x07,                         /* sizeof(usbDescrEndpoint)                             */
    USBDESCR_ENDPOINT,            /* тип дескриптора = конечная точка                     */
    0x81,                         /* IN endpoint номер 1                                  */
    0x02,                         /* атрибут: конечная точка bulk                         */
    0x08, 0x00,                   /* max размер пакета                                    */
    0x00,                         /* в ms                                                 */
/* дескриптор конечной точки для конечной точки 3 */
    0x07,                         /* sizeof(usbDescrEndpoint)                             */
    USBDESCR_ENDPOINT,            /* тип дескриптора = конечная точка                     */
    0x02,                         /* IN endpoint номер 3                                  */
    0x02,                         /* атрибут: конечная точка bulk                         */
    0x08, 0x00,                   /* max размер пакета                                    */
    0x00,                         /* в ms                                                 */
};


Хочу отметить, что в дескрипторе кофигурации мы встраиваем дескриптор интерфейса и дескрипторы конечных точек. Этот (или эти, если хотите) дескриптор передается V-USB благодаря ранее описанному определению

#define USB_CFG_DESCR_PROPS_CONFIGURATION           USB_PROP_LENGTH(32)

В этом же десрипторе (usbDescriptorConfiguration) мы указали, пожалуй, самую важную информацию для нашего устройства, а именно:

  • устройство класса MSD
  • тип передачи — bulk-only
  • размеры конецчных точек и их направление

После того, как хост получил дескрипторы устройства, конфигурации, интерфейса и конечных точек, он (хост) начинает «общаться» с нашим устройством как MSD bulk-only. Поскольку мы работаем со стандартным интерфейсом MSD, то никакие control передачи для control конечной точки нас не интересуют. Вместо этого мы определим функцию

USB_PUBLIC void usbFunctionWriteOut(unsigned char* ucData, unsigned char ucLen)


которая будет принимать все interrupt/bulk передачи данных от хоста к нашему устройству для всех конечных точек, кроме 0 (это control точка). Напомню, что максимальное количество байт, которое может быть принято через usbFunctionWriteOut за один вызов равно 8 байтам (это ограничение V-USB). Ну вот, теперь мы готовы принимать поступающие от хоста байты =))) И на этом этапе мы перейдем к следующему этапу — разделение потока байт от хоста на вменяемые пакеты, которые несут нам полезную информацию. Как мы узнали ранее, хост может направлять в MSD устройство толька комманды и данные. Теперь мы сделаем следующее:

  • разделим входной поток данных на комманды и данные
  • обработаем комманды в соответсвие с их предназначением или примем данные от хоста
  • ответим хосту на обработанную комманду (предварительно отправив запрошенные данные, если необходимо)

Для того, чтобы воплотить в жизнь написанное чуть выше, давайте разберемся с несколькими положениями, которые касаются Mass Storage Class в целом и bulk-only в частности. Как я уже оговаривал, Mass Storage Class(MSC) не подразумевает того, что устройство, которое работает согласно этой спецификации, занет что-либо о фойловой системе на своем насителе. Оснойвной задачей такого устройсва является предостваление запрашиваемой информации с носителя в нужном объеме и с нужного адреса. Это, с одной стороны, облегчает работу нам с вами, с другой стороны позволяет строить устройства, не привязанные к конкретным накопителям. Все, что мы должны уметь, это выполнить требуемое хостом действие. А действия эти не так уж и сложны(если не вдаваться во все мелочи данного протокола) — выполнять команды из набора SCSI. Я описал все необходимые из них ранее.
Далее. Раскажу немного о том, как согласно MSC bulk-only происходит обмен информацией между нашим устройством и хостом. Опознав нас свами на шине, сбросив, инициализировав и настроив наше устройство, хост посылает нам комманды в так называемом Command Block Wrapper(CBW). Содержимое этого блока разнится от комманды к команде, но самое главное, размер этого CBW остается неизменным. Это положение позволяет нам принять весь CBW при помощи V-USB не смотря на ограничение в 8 байт. Итак, приняв при помощи функции usbFunctionWriteOut CBW, мы можем выделить из него нужные нам данные, а именно — комманды, отсылаемые на исполнение хостом и параметры, которые зависят от принятой комманды. Наверняка у некоторых появится вопрос: А что же будет, если хост будет часто посылать комманды в наш адрес или мы долго будем на них отвечать??? Вот тут проявляется еще один аспект выбранного нами варианта MSD. Хост не будет посылать в наш адрес следующую комманду до тех пор, пока мы не сообщим о результате выполнения предыдущей(есть нюанс с таймаутом, но в программе для нашего устройства мы это обойдем)!!! Также хост присваевает каждому отсылаемому нам CBW уникальный тэг(или номер), так что мы можем обработать одну комманду и ответить на нее даже в случае если хост не дождался нас и отослал еще чтото в наш адрес. Вы скажете, а если мы зависли? Не беда, попытавшись пару раз и не получив никакого КПД с нашей стороны, хост просто будет нас игнарировать. С другой стороны bulk передача согласно спецификации USB не гарантирует доставку данных конечной точки, так что это дает нам дополнительное время на «ногодрыгание».
Но что-то меня опять понесло в теорию=) Давайте все-таки опишем этот самы загадочный CBW:


typedef struct
{
  unsigned long dCBWSignature;
  unsigned long dCBWTag;
  unsigned long dCBWDataTransferLength;
  unsigned char bCBWFlags;
  unsigned char bCBWLUN;
  unsigned char bCBWCBLength;
  unsigned char CBWCB[16];
} USB_MSD_CBW;


Вроде, на первый взгляд, ничего сложного. Теперь давайте пройдемся по его основным элементам (распишу только самые необходимые, если кому интересно, могу лично и подробнее). dCBWSignature — сигнатура блока CBW. Ничего интересного для нас, просто константа(чтото вроде USBD если смотреть в char. dCBWTag — вот это один из камней приткновения в CBW. Значение этого поля и есть тот самы номер пакета. Позже мы будем использовать это занчение для сообщения хосту орезультате выполнения операции с таким тегом. dCBWDataTransferLength — вроде понятно из названия и указывает на размер передаваемых за данную транзакцию, байт. Никогда и никого не интересовало и врядли будет. bCBWFlags — всевозможные флаги. значений много и интерпритаций еще больше. Просто не обращаем внимания. bCBWLUN — номер логического устройства, которому адресован CBW. У нас вроде одно такое устройство, но если кто будет делать картридер, то может и пригодится =) bCBWCBLength — размер переданного CBW. CBWCB[16] — вот она, полезная информация. Этот массив содержит и номер комманды, и параметры для нее, и многое другое. С этим блоком мы познакомимся позже, когда будем знакомиться с коммандами SCSI.
Мы помним, что в MSD bulk-only все транзакции делятся максинум на три этапа. Так вот, приняли мы CBW и выделили из него нужную нам информацию. Это и есть первый этап: так называемый command transport. Из приведенной блок-схемы выше мы видим, что следующим этапом в нашишем диалоге могжут быть передача данных хосту (либо прием их от него) или передача статуса обработки принятого CBW. Так вот, передача того самого статуса являестя обязательным этапом для любой комманды. Этот этап как бы подтвердает тот факт, что мы приняли от хоста CBW с номером dCBWTag и выполнили ее(вне зависимости от результата ее выполненя). Этот этап называется status transport, а данные передаются определенным блоком, имя которому CSW. Давайте опишем и его:


typedef struct
{
  unsigned long dCSWSignature;
  unsigned long dCSWTag;
  unsigned long dCSWDataResidue;
  unsigned char bCSWStatus;
} USB_MSD_CSW;


Эта небольшая структурка как бы является завершением транзакции MSD вида коммандв->данные->статус. Поля этой структуры означают следующее: dCSWSignature — сигнатура блока CSW (это константа, в char это USBS), dCSWTag — номер блока(должен совпадать с номером CBW, для которого высылается статус), dCSWDataResidue — разности между ожидаемым чилом байт от хоста dCBWDataTransferLength в блоке CBW и реально принятыми(при OUT передаче) и наобоот, между запрошенным чилов байт в dCBWDataTransferLength и переданным хосту. Ну и наконец bCSWStatus — результат выполнения комманды с тегом dCSWTag. Нуль — значит все впорядке, другие значения — смотрим в спецификации =))).
Ну и на последок в этапах транзакций осталась стадия передачи данных(data transport). Напомню, что этот этап не всегда присутствует в процессе общения MSD с хостом. Есть энное количество комманд, которые не требуют передачи данных. Но все же этот этап присутствует и мы его сейчас рассмотрим. Мы знаем, что данные могут передаваться как от хоста к MSD, так и наоборот(мы же помним, что мы описали 2 конечные токи in и out). Так вот, в данной реализации MSD от хоста к MSD могут передаваться только данные для записи на носитель информации, а от MSD к хосту как данные прочитанные с носителя, так и запрашиваемые хостом параметры нашего устройства.

В принципе про этапы передачи информации MSD наверное и все. Теперь я коснусь реализации всего написанного выше. Примем исходное сосояние(назовем его RxCBW)=) Хост нам не передал не байта и мы ожидаем от него CBW. Размер этого блока мы занем, а следовательно первые sizeof(CBW) приятых байт и будут CBW. Как только мы приняли CBW мы начинаем его анализировать. Анализ блока CBW начинается с того, что мы распознаем комманду, которая находиться в USB_MSD_CBW.CBWCB[0]. Значение этого байта и есть комманда, которую хост просит нас выполнить. На этом этапе, в зависимости от предложенной нам комманды, устройство может перейти в одно из нескольких состояний: прием данных от хоста(RxData), передача данных хосту(TxData) или передача статуса(TxStatus). При переходе в состояние RxData мы принимаем от хоста n байт информации, записываем ее на носитель и переходим в состояние TxStatus. При переходе в состояние TxData мы передаем хосту запрошенную информацию n байт и переходим в состояние TxStatus. Из состояния TxStatus, передав блок CSW хосту, переходим в состояние RxCBW и ожидаем новые байты от хоста. Сейчас попробую предстваить это во временной диаграмме.

Внеменные диаграммы транзакций MSD

Ну как-то так (я понимаю, что не все, наверное, понятно, так что готов ответить на вопросы).

Выложу немного скринов, для разнообразия
Скрин1
фото 1
фото 1

Я так пологаю, что расписывать работу с картой SD(MMC) не имеет смысла, т.к. про это написано очень много. Пожалуй опишу основные грабли, на которые я наступал в этом процессе (так думаю будет логичнее). Так вот, первое(и наверное основное), я не вседа использую внешнюю подтяжку на линии _CS карты памяти, из-за чего иногда возникают довольно большие неприятности. потому (хотя это и не очень красиво) в таких случаях я всегда первым делом настраиваю должным образом вывод _CS. Второе, не все карты, с которыми я работал(а их было не мало, поверьте), подразумевают размер блока для чтения/записи равным 512 байт. Потому при инициализации карты я страхуюсь и устанавливаю размер этого блока 512. Видел пару карт, которые поддерживали размер блока для чтения/записи в 1 байт, а есть, которые тока 2048 и ни грамом больше(тока 1 раз встречал). В данном проекте я использовал карту kingston на 1гб, хотя можно и другие, думаю проблем не возникнет. Третье, не всегда карта памяти инициализируется на максимальной скорости SPI(возможно это зависит и от разводки, использование проводов и много от чего еще), поэтому можно производить инициализацию на меньших скоростях, хотя у меня на 16Мгц все прекрасно работает на максимуме. Четвертое, линия MISO avr'ки. Я раньше не использовал внешнюю подтяжку на этом выводе, от чего поимел много головной боли. Теперь использую всегда, чего и советую начинающим. Наверное это основное, поэтому поедем дальше.

Мы разобрали процесс(или логики) работы нашего MSD. Научились принимать пакеты CBW, отправлять CSW и данные.

Файлы с исходным кодом.

Вроде как все. Если у общественности возникнут вопросы, замечания, пожелания более подробного описания или чегото еще, то буду рад помочь!

Жду откликов, предложений и т.п. Мот у кого возникнет идея создания устройства на V-USB, то готов поучавствовать в коммандном проекте. Сейчас займусь работой с v-usb и сенсорной панелью вместо мышки=) Всем удачи!
  • +10
  • 16 марта 2011, 03:08
  • lleeloo
  • 2
Файлы в топике: mmc_test.zip, MassStorage.Mega8.libusb.zip

Комментарии (222)

RSS свернуть / развернуть
орфографию не мешало бы подправить
0
  • avatar
  • Bass
  • 16 марта 2011, 06:36
и еще поставьте тэг после первого абзаца. А вообще статья интересная
0
тэг cut. сожрал зараза…
0
Оформление я чуток вечером подрихтую. Т.к. товарищ пока не в теме как это сделать. Ну и статью вроде как хотел дописать.
0
Подскажите, а исходники, схемы, другие файлики куда заливать? Я просто не в курсе, чак что залил на deposit. К моменту окончания статьи хотелбы выложить ссылки, ну тут на форуме не знаю как. Если можете, помогите!
0
С файлами я пока не решил вопрос. Можешь кинуть их мне на dihalt@dihalt.ru а я сохраню их на хостинге. Либо положить их в систему dropbox. Если не знаешь что это пиши мне на мыло я тебе обьясню. Рулезная вещь вообщет :)
0
Штучка интересная. Жаль конечно что low-speed только 1.5 мбит/с, но вообще для спортивного интереса отличная статья.
0
Да у low-speed скорость маловата для mass storage. Максимальная практическая скорость, которую мне удалось получить на V-USB 18-19 КБайт/с, при теоритическом лимите 24 КБайт/с. Ну а если учесть, что еще с флешки читать/писать время нужно, практическма скорость обмена будет около 10 КБайт/с — меньше чем у старых дискет :)
0
Кстати, о дискетах. Никто не пробовал USB-Floppy адаптер запилить? Это было забавно, да и полезно иногда.
0
Я года 3 назад, делал USB to GPIB адаптер, но не доделал, по причине смены места работы.
0
А между флопиками и GPIB есть какая-то связь? А то про GPIB знаю только что это интерфейс для соединения измерительного оборудования.
0
Нет никакой, я просто к слову сказал. На счет USB-Floppy — задача вполне выполнимая, не сложней чем с SD карточки читать.
0
Хм, а вполне интересное предложение)))Надо найти рабочий флопик и попробывть собрать такой девайсик))
0
А с другой стороны — лучше не надо, а то если найду готовый — лень будет самому поковыряццо)))
0
А мне идея понравилась. У друзей, да и в школе полно в компах флопиков. Как контроллеры приедут, попробую что нибудь намутить
0
В том-то и дело, что мне тоже понравилась) И флопик есть. Может, скооперироваться?)
0
я за)) Флопик приволоку завтра. Впринципе от неудачного usb asp'a мега восьмая есть без ноги одной правда, на ней попробывать сделать можно. Правда я оба своих програматора уничтожил, так что всёравно надо посылки дождаться, ну пока можно порыскать по поводу алгоритмов)
0
ТАм правда надо что-то с +12V придумать.Делать повышающий DC-DC и 2 штекера usb как портативных HD…
0
Это довольно просто, если USB обеспечит необходимую мощность.
0
Флопики 12V не юзают. Достаточно только 5V
0
Действительно, щас прошёлся по дорожкам, на +12 нету.
0
Не совсем, у меня получалось достигнуть 17-19 КБайт/с
0
Немножко подрихтовал оформление

Это окончательная версия статьи или еще будет продолжение?
0
У меня почему то картинка не полностью показывается. Обрезана под шаблон. Может сделать уменьшенную копию?
0
Хм, а у меня полностью. ПОди в Опере какую-нибудь боковую панель открыл?
0
у меня ГуглХром=)
0
У меня в хроме все нормально. Но эт если развернуть его на весь экран. Разрешение экрана у тебя какое?
0
Ну хотя бы «Сдесь видно» после блоксхемы поправил за одно. Ну стыдно же…
0
А не заметил просто.
0
еще оч много будет. готовлю фотки видео текст
0
ХОрошо, тогда ждем :)
0
А чем обычно уважаемое сообщество снимает видео? Я пытался мобилкой с моника и с телека, но качество говно редкостное. Ничего не видно=( А я так хотел показать наработки…
0
Я видео снимаю своим фотиком (Sony H50) вообще любой фотик умеет снимать более менее вменяемое видео. Можешь кого нибудь из знакомых попросить снять, наверняка у кого то есть.

Видео заливается на ютуб какой нибудь и вставляется. Напиши мне на мыло я тебе еще прогу дам для ужимки видео в адекватный формат.
0
Ди, а можешь ссылку на эту програмку дать, а то я упарился видео на ютуб заливать и еще потом смотрится оно тормозно…
0
freemaker video converter
Интерфейса не пугайся :)

жми видео в формат H264 разрешением 640х480 или около того. Оно, как я понял, на ютубе не пережимается.
0
А какой там профиль H264? Их же несколько, под декодеры с разными возможностями и производительностью.
0
Я обычно делают to Mp4 внутри профиль Smartphones H.264, AAC 640x480 и его уже лью на ютуб
0
пасиб, ща качнем и проверим
0
Ааа тебе видео с экрана снять надо… Тут есть куча прог. Например UVScreenCamera 4.7 beta
0
Либо CamStudio
0
Доступно написано про endpoints (конечные точки). Теория это как раз то, чего не хватает мне… :) У меня основной упор на практику, разбираю на запчасти другие (в основном буржуйские) проекты на V-USB для того чтобы научиться. Постараюсь грамотно дописать свои статьи :) Спасибо lleeloo за статью, ждем продолжения :)
0
И ещё: для принудительного отключения/подключения к хосту совсем не обязательно подтягивающий резистор на линии D- заводить на ногу микроконтроллера. Вот как это реализовано в usbdrv.h:
#ifdef USB_CFG_PULLUP_IOPORTNAME
#define usbDeviceConnect()      ((USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT)), \
                                  (USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT)))
#define usbDeviceDisconnect()   ((USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT)), \
                                  (USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT)))
#else /* USB_CFG_PULLUP_IOPORTNAME */
#define usbDeviceConnect()      (USBDDR &= ~(1<<USBMINUS))
#define usbDeviceDisconnect()   (USBDDR |= (1<<USBMINUS))
#endif /* USB_CFG_PULLUP_IOPORTNAME */

Получается если не задан USB_CFG_PULLUP_IOPORTNAME тогда линия просто прижимается к земле переключая направление порта (disconnect is done by brute-force pulling D- to GND. This does not conform to the spec, but it works):
#define usbDeviceConnect()      (USBDDR &= ~(1<<USBMINUS))
#define usbDeviceDisconnect()   (USBDDR |= (1<<USBMINUS))

Хорошая штука такой аля «електрохабр» :) С миру по нитке…
0
Можно и так, но на некоторых материнках отот метод не ахти как работает =( Такойже гвоздь и со стабилитронами на D+ D- при питании от 5 вольт. На некоторых мамках все в огне, а некоторые «Устройство USB не опознано». То же косается и хабов, так что я предпочитаю с нормальной подтяжкой.
0
Обычная подтяжка 1.5К коректно работает на большинстве материнок только на 3.3V, а чтобы отлично определялось на 5 вольтах со стабилитронами, нужен правильный делитель напряжения :)
0
со стабилитронами ана и так налюбой мамке работает с 1.5к подтяжкой=)
0
А как там с usbDeviceConnect/usbDeviceDisconnect при таком раскладе?
0
Еще боюсь тебе не хватит длины поста чтобы все описать. Тут ограничение в 30 чтоль тысяч знаков. Так что когда будешь писать продолжение заверши какую нибудь мысль в этом посте, а дальше создай новый пост, часть 2 и продолжай там
0
А нет, вру. Лимит стоит на 50 тыщь, в этом посте уже около 27тысяч знаков. Так что еще есть куда развернуться, но если тебе напишет, что длина поста слишком большая не удивляйся.

З.Ы. Статья просто супер! Все подробно и по делу! Отлично!
0
Я так пологаю, что расписывать работу с картой SD(MMC) не имеет смысла

Еще как имеет! Вы очень подробно и четко все расписываете, поэтому если найдете время на развернутую статью про работу с картами памяти (можно даже в контексте создания USB флешки), то будет просто отлично. Можно ее сделать вторым постом — я потом подредактирую и сделаю ссылки с одного на другой.

Эту же статью я из вашего личного блога перебрасываю в блог AVR. Негоже столь обширный и хороший материал прятать по личным блогам.
0
Спасибо. Раз Вы говорите, что смысл в описании работы с вышеуказанными катамими есть, то, пожалуй попробую. Но только в личном блоге. Потом, после обзора Вами и коллективом, если понравиться, что с ней делать решать Вам.
0
Еще как имеет! Вы очень подробно и четко все расписываете, поэтому если найдете время на развернутую статью про работу с картами памяти (можно даже в контексте создания USB флешки), то будет просто отлично. Можно ее сделать вторым постом — я потом подредактирую и сделаю ссылки с одного на другой.
не могу не поддержать, тема изобилует подводными камнями для новичков
0
А ничего, что статья (и даже две) давно написана?
0
Немного про SD|MMC есть тут: mp3vkarmane.narod.ru/mmc.html
0
Всем привет. Вот интересно, хватит ли на программную реализацию USB-HOST
0
Боюсь что нет, по крайне мере V-USB работает только как клиент. Да и не хватит ресурсов самой AVR'ки=( Хотя гдето проскакивала тема по поводу такой реализации на atmega32, но там вроде какаяято поделка на тему USB host, да и то поддержка не всего. Короче врядли что получиться…
0
Есть специальная микрушка от FTDI и парнишка сделал шилд для ардуина на ней — читать ТУТ
0
Ну скажем не FTDI а MAXIM. Там аппаратно реализован USB host, а вопрос задан чуть выше!
0
Да… и Правда там МАХ :) Я видел ещё похожий проэкт на FTDI VINCULUM… На софт УСБ это сделать нельзя… просто нехватает мощи у АВР чипов.
0
была поделка на меге (какой именно не помню) там USB мышку подключали для управления захватом. на hackaday глянуть можно.
0
Дабы подвести итог по диспутом на тему software usb-host на atmeg'е, приведу ссылку на проект!!! SIAM32 USB HC
0
А про USB — микрофон будет?
+1
Осталось только накрапать статью. Вот только со временем туговато… У меня теперь сын (недавно родился), поэтому особоне не поработаешь дома =)
0
Грац. Сын уже паяльник в руки взял? или пока только проводки скручивать умеет? :)
0
Наверное в мое отсутствие=) Как приду домой с работы, так чегот на столе из моих причендалков не хватает=)))
0
Вот еще по хосту. только в переводчик загоните.
0
0
Через GoogleTranslate читать невозможно — легко можно живот порвать.
С самого начала страницы практически ссылка:
«Непосредственно удовлетворить фантазии микроконтроллеров AVR» ))
0
Не совсем понял, там что, про создание USB хоста средствами AVR?
0
Попытка=( Хотя было бы здорово!
0
Т.е. фиг чего у них получилось? АВР-ка даже LS-мышку не подняла?
0
Вродь подняла, а вродь и нет… Если подняла мышку, то в чем проблема с поднятием других усб устройств?
0
ооо USB host на attiny2313 это просто круто
Там в конце исходники
можно повторять.

А на счёт работоспособности там же есть видео.

Очень жду USB микрофон :)

А ещё у меня вопрос, как вместо SD карты поставить какую-нибудь SPI eeprom
0
Разницы что используется в качестве накопителя никакой. Хоть жесткий диск цепляй=)
0
Статья просто супер. Попробую собрать данный девайс и отпишусь сюда о результатах. Спасибо Автору!
0
собрал на меге16 и ммс на 32Мб — определяется как запоминающее устройство, но его нет в дисковых устройствах, в св-вах пишет: Запуск этого устройства невозможен. (Код 10). В чем может быть косяк? ММС флеха определилась (по светодиоду) при скорости spi f/4, при f/2 не определялась.
0
  • avatar
  • Racer
  • 11 февраля 2012, 18:20
Нужно правильно указать в прошивке размер флешки(32мб).
0
А где именно? Весь код просматриваю уже не раз…
0
кажется нашел: usb_read_capacity[] ,- оно? Если да, то какой формат записи в массиве чтоб я знал какие байты править?
0
автор, никола тесла чипостроя :)
0
Чегот не понял…
0
Чего-то пляски с usb_read_capacity не дают рез-та, по лит. нашел, что первые 4 байта — адресс последнего LBA, след. 4 байта — размер блока. Мб еще где косяк?
0
  • avatar
  • Racer
  • 12 февраля 2012, 18:31
Нашел правильно. Попробуй прочитай какойнить спец регистр. Смотри его занчение правильно ли читается. В моей статье есть програмка для чтения этих регистров и прошивка для контроллера. Будут вопросы, пиши.
0


Вот что выдает прога по моей флешке.
0
  • avatar
  • Racer
  • 13 февраля 2012, 12:26
Ну вроде карта инициализировалась нормально, хотя несколько полей меня смущают(наверное мой недочет в программе). В каком формате карта (фат16?)? Вечером допилю прогу для чтения секторов с флешки и тогда, думаю, все станет на свои места. Короче вечером раскурим и, возможно, допилим статью с учетом твоего случая. Время минское. Часам к 22.00 постараюсь отписаться.
0
По поводу FAT не знаю. Стояла в нокиа6230.
0
Ну чего там может быть с моей ммс картой?
0
Завтра выложу новую версию программы. Разберемся=)
0
Выложил бинарник в топик. Содержимое вкладок прошу прикрепить к кометам. Покопаюсь, разберусь сам и выложу исходники.
0



Скрины проги при чтении флешки
0
С картой все в порядке (по крайней мере на первый взгляд). Для проверки чтения с карты можем заценить лог проги Device monitoring studio. Завтра выложу версию для чтения секторов и работе с файловой системой. Посмотрим лог чтения и узнаем косяк.
0
Обновил програмку и прошивку в топике. Протестируй на 3-й вкладке и отпишись.
0
А в мк обновлять прошивку?
0
Обязательно!
0
Я уже понял)
0
В секторах значения отличные от 0x00 и 0xFF, значит записано что-то. Что здесь надо посмотреть?
0

0
Сектор именно 0. Переключи на сектор 1 а потом на сектор 0. Затем посмотри. Особенно второй скрин!
0
Все поля отличаются от твоих! Скрин дать?
0
Дай лучше мыло. Счас скину версию с возможностью
сохранять сектор. Скинешь файлик с содержимым, попробую раскурить.
0
mail_vladimir_94@mail.ru
0
Скрин можешь выложить. попробую прикинуть.
0

0
Похоже на старый формат карточки. Через минутку проверь мыло. Сохрани сектор 0 и 1 вышли мне обратно=)
0
Традиционная проблема флешек из нокий — случайно поставленный пароль, после чего флешку никто не видит. Лечится через телефон, если пароль известен (с части телефонов его можно выдернуть) либо ресеттером (есть на DX, либо покурить спецификации SD/MMC и сделать самому, все, что нужно — это послать карте команду полного стирания).
0
Попробую прикрутить эту фишку, кэп! Осталось только залочить флешку=)
0
в описании второй ENDPOINT, судя по исходникам usbdrv.c нужно поставить 0x82
__flash char usbDescriptorConfiguration[] = { /* USB дескриптор конфигурации */

/* дескриптор конечной точки для конечной точки 3 */
0x07, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* тип дескриптора = конечная точка */
0x82, /* IN endpoint номер 3 */
0x02, /* атрибут: конечная точка bulk */

Честно говоря, не знаю насколько это сказывается на функционировании конечного устройства. Но в usbdrv.c используется (char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
0
  • avatar
  • rhs7
  • 20 февраля 2012, 13:19
Ошибся, первый бит в номере ENDPOINT определяет аправление 0x80 — IN 0x0 — OUT. Все правильно с описание usbDescriptorConfiguration.
0
  • avatar
  • rhs7
  • 20 февраля 2012, 13:39
В исходниках при запросе ёмкости носителя хосту отправляется массив-константа, где уже заложен размер карты в 484Мб. Я так понимаю, что правильно было бы спрашивать объём у карты и соответствующие данные отправлять в ответе?
0
Ну тык да. Только лень же не отменена=) Правильно просчитать объем карты и отослать хосту, но, как говориться, нет ничего постоянней, чем временное…
0
Я с кодом разбираюсь, теперь про емкость стало понятно =) А почему именно 484Мб, а не вся емкость карты?
И сколько времени позволено потратить на запись блока в MMC? Предположим, я хочу повесить на I2C внешнюю EEPROM и писать/читать «сектора» из неё, а она куда медленнее карты. Возможно?
0
Да. Единственное что тупить при этом не надо — МК должен обслуживать дрыги шины. Но пакета с данными хост подождет.
0
Т.е. пока я вычитываю по шине блок, периодически должен вызывать usbPoll()?
0
Да. И нельзя прерывание блокировать, на котором USB висит.
0
Я так понимаю, что из-за прерываний во внутреннюю Flash писать не получится?
0
Вот хз. Этот вопрос я уже обдумывал, два варианта:
1) Использовать МК с поддержкой бутлоадера и ту часть кода, что работает с USB и флешем, а также все прерывания убрать в RWW секцию.
2) Если запись странички укладывается в 500-600мкс, то можно синхронизировать запись с USB — начинать ее сразу после того, как закончится обмен данными по USB (он занимает достаточно немного времени и производится с периодичностью 1мс). Такой метод используется, например, здесь для того, чтобы обмен по USB не сбивал тайминги софтового 1-wire-подобного протокола.
0
Я специально в тело функции MMC_WriteBlock ввёл большую задержку, сама функция пока никуда не пишет (закомментировано). Так вот задержку даже в несколько секунд хост ждёт и флешка не отваливается. Потом добавил в MMC_WriteBlock запись во внутреннюю память EEPROM — тоже всё нормально. А когда сделал в MMC_WriteBlock просто стирание одной страницы во Flash, то флешка зависает, хотя стирание действительно происходит независимо от того отключены прерывания или нет.
0
На задержки параллельно — прерывание их прервет и свое дело сделает. А вот при записи в флэш и исполнении кода из NRWW секции ядро на время записи уходит в halt, при этом обламываются и прерывания.
0
В загрузчик размером 2кБ наверное софтовый USB не влезет, надо МК с загрузчиком 4кБ.
0
все влезает
0
Влезет, вполне. Если порыться в ссылках на проекты на сайте V-USB, то можно найти 2-3 готовых бута.
0
А как думаете, если MSD к загрузчику прикрутить и разгребатель hex-формата, влезет?
0
А зачем разгребать HEX? Проще бинарник лить =)
0
Естественно проще, но с разгребателем прошить даже нуб сможет.
0
с разгребателем прошить даже нуб сможет
не понял, ты про что сейчас?
0
Человек включает плату в порт, стартует загрузчик, прикидывается флешкой, на которой лежит hex-файл. Человек берёт свой hex-файл и в проводнике бросает его на «флешку», заменяя оригинальный.
0
Человек включает плату в порт, стартует загрузчик, прикидывается флешкой, на которой лежит bin-файл. Человек берёт свой bin-файл и в проводнике бросает его на «флешку», заменяя оригинальный.
В тако случае никаких разгребателей не нужно…
0
Собственно вопрос не в этом был, да бинарник удобнее, разве что конвертнуть в него надо предварительно, вопрос: влезет ли в 2кБ загрузчика V-USB + MSD?
0
Любой компилятор соберет тебе бинарник. Про влезет это можно проверить…
0
Да соберет, я это прекрасно знаю. Если есть просто сторонний hex-файл, то его придётся конвертировать. Но это не суть, главное, чтобы влезла часть V-USB + MSD без функций работы с картой MMC/SD и осталось немножко места, чтобы всунуть запись во Flash.
0
вопрос скорее такой: влезет ли вусб + мсд + эмуляция диска(фат)
0
Эмуляция диска (Boot+FAT+Root) лежит не в загрузчике, а в основной области в самой нижней части перед самым загрузчиком. Новая прошивка не должна налезать на эту область, за чем и проследит загрузчик.
0
Массив с описанием емкости в прошивке: 1-е 4 байта — номер последнего логического блока, 2-е 4 байта — размер логического блока(обычно 512байт), величины идут 1-й байт — старший разряд
0
Спасибо, уже разобрался с форматом ответа по спецификации SCSI. Планирую использовать EEPROM на 64кБ, соответственным образом поменяю первую 4-х байтную запись.
0
484 это и есть полный размер=) если сам не разберешься почему, тогда отвечу…
0
В статье указано, что использовалась карточка на 1Гб. Если бы было 512Мб, то цифра 484Мб вопросов вызывала меньше бы. :)
0
Гм, почему? Флешка не тот девайс, где есть смысл указывать емкость в десятичных мегабайтах. Недостача места, AFAIK, объясняется местом, занятым ФС, но ридеру же параллельно на это.
0
Полная ёмкость вроде как при форматировании учитывается, а в свойствах диска уже показана ёмкость с учётом занятого файловой системой места. Но опять-таки, с 1Гб не может остаться всего 484Мб.
0
Я говорю о том, что ридеру параллельно на ФС, так что с его точки зрения флешка должна иметь объем 512МиБ (если говорить о полгиговой, а не гиговой). Разве что часть флешки расходуется под WL-инфу. Но опять-таки, у моей полугиговой флешки винда показывает объем 498МБ, и это без учета места, занимаемого ФС. Так что 484МБ цифра таки странноватая.
0
В общем, мне пока не понятно, почему именно 484Мб. Тем более на картинках видно, что на карте доступно 472Мб.
0
Можно заюзать и 2гб как 512мб. Реальный объем носителя в этом случае не меняется. Я сам намеренно указал такой объем. Для 1гб флешки можно расчитать из CSD ее полный объем и указать его хосту. Но чем больше объем, тем дольше происходит определение флешки(чтение фат и др.). Меня это не устраивало и я указал объем на вскидку, боближе к 512мб. Это, надеюсь, не уголовно наказуемо=)
0
Можно заюзать и 2гб как 512мб
Это понятно, я например WinHex-ом заливал образ 3.5" дискеты на SD-карту и система думала, что карточка действительно 1.44Мб.
Я сам намеренно указал такой объем
Вот именно это я и хотел понять, спасибо. В том, чтобы понимать, а не просто знать как использовать и есть смысл моих вопросов.
0
ГОСПОДА ХОРОШИЕ. Вчера подвернулась под руку карта SDHC. В следствие чего было откопано пары ОШИБОК, которые были исправлены. Библиотеку для работы с картами памяти выложу чуть позже, а также зделаю пометку в статье UPDATE=)
0
#С#делаю
0
Помогите переделать исходник MassStorage.cpp, что бы можно было использовать с микроконтроллерами, у которых память данных SRAM меньше 512 Байт. Например микроконтроллеры AVR семейства Tiny. В исходнике используется буфер ucDataPBP размером, равным сектру 512 Байт для чтения/записи на карту памяти, который надо уменьшить и записывать сектор по частям, а не весь целиком. Есть какое-нибудь описание исходника MassStorage.cpp на РУССКОМ языке? Схему я собрал, переписал проект для своего микроконтроллера ATMege8515 c 512 Байт SRAM, уменьшил размер буфера до 32 байт, устройство определяется как Съёмный диск.
0
Если карта памяти поддерживает чтение и запись данных блоками, меньше чем 512 байт, то это можно сделать. Если нужно только чтение, то можно сделать с любой картой(по идее). Но если карта поддерживает запись только блоками по 512 байт, то гемороя выше крыши=( В принципе реализовать это можно и с меньшим количеством SRAM, было бы желание. Объявите ucDataPBP размером в 32 байта, и производите чтение(запись) с(на) карту по 8 байт не убирая сигнала _CS. Т.е. делаем так. Пришла команда прочитать 2 сектора (по 512 байт) с адреса 4(4*512=2048). Выбираем карту, отправляем команду чтения с указанного адреса, вычитываем 8 байт и отправляем хосту. Читаем по 8 байт до тех пор, пока не прочитаем полностью 2 сектора и только после этого снимаем сигнал _CS. Аналогично для записи. Попробуй, если не получиться, пиши, попробуем вместе. Просто, честно говоря, неохота переделывать это по несколько раз.
0
Лучше уже не жлобиться и купить другой МК. Выйдет на порядок дешевле, и нервишки целыми будут.
+1
+100500
0
Работает на Mega8515, 20МГц с буфером 64 Байта. Изменения минимальны. Код для Меги 8.
0
Спасибо
0
Скорость чтения — 23,5 кБ/с.
Скорость записи — 23 кБ/с.
Немного не дотягивает до 24 кБ/с для нормального воспроизведения музыки 192 кб/с MP3.
Код для Mega8515.
0
Конфигурационные ячейки: CKOPT, EESAVE.
Частота: 20 МГц.
Подключение: тоже.
0
Добавил извлечение card-reader.
0
Увеличил скорость чуток — исходник.
0
Ещё для mega8 Код.
0
Люди добрые, помогите! Подскажите пожалуйста, я могу использовать с этим кодом МК ATmega88?
Вроде они не сильно отличаются… То есть, например, я перечерчиваю схему для ATMega88 с сохранением всех ног(они одинаковые вроде у обоих МК), делаю печатку, напаиваю и заливаю .hex в ATMega88. Так будет работать? И если не будет, но исправить недолго, может кто поможет мне? Спасибо!
0
Собрал на ATMega8, из схемы выкинул один стабилитрон, выкинул все конденсаторы. В остальном схема полностью идентичная. Перевел .bin в .hex и залил в кристалл. Верификация прошла успешно. При подключении девайса — USB устройство не опознано. ЧТО Я ДЕЛАЮ НЕ ТАК?((
0
www.engbedded.com/fusecalc/ вот здесь пытаюсь понять какие фьюзы нужны
перепробовал все, наинающееся с Ext osclilograh
если выбирать medium то при подключении диоды помигивают, но все равно USB устройство не опознано((
на раных компах одно и то же

отзвоитесь хоть кто нибудь(
0
С чего вдруг убрал стабилитрон? Конденсаторы из цепи кварца надеюсь не убирал? Какую прошивку заливал? На какой кварц прошивка собрана? Уточняй, поможем!
0
И да, скачай последнюю версию из конца статьи (ту, которую выложил именно я) там маленькая незаметная ссылка после основного текста. Собрана под 20 МГц, должна запуститься с одним стабилитроном! Удачи=)
0
уже вернул стабилитрон, кондеры у кварца конечно не убирал
прошивка та, что по ссылке. только вот там в папке relese иbin файл, я его в hex перегнал, это нормально?

вернул фильтр даже 47 µF и все равно та же фигня. устройство не опознано, но с кондером даже не моргает ничем о_О

фьюзы перепробовал все, которые там были в списке с «Ext osc. medium»
без кондера что то помигивает диодами, но устройство не опознано. флэшка microSD 512 Мб

кристалл ATMega8A
0
фьюзы перепробовал все, которые там были в списке с «Ext osc. medium»
Нужен Ext Crystal HF, ЕМНИП.
0
их тоже пробовал, ну нивкакую. без 47µF помигиавает диоами, потом устройство не опознано

с ним — вообще ноль реакции, но устройство опять не опоазнано
0
Надпись «MassStorage.Mega8.libusb.zip»
0
Прошивка здесь
Да и покажи схему! Еще, укажи для какого кристалла и частоты собрать тебе прошивку (а лучше сам собери). Счас там на 20МГц и один стабилитрон=)
0
спасибо, сейчас тогда прошью этой и сменю кварц на 20

схему могу выложить, но она отличается от конечной разводки. если в виде файлов proteus(ISIS, ARES) выложу — нормально? всяко лучше чем картинкой. а еще думал что может где с выводами карточки ошибся, но вроде нет… наверно из-за стабилитронов все же. еще мне неясно, почему при наличии конденсатора меж землей и питанием вообще не моргает диодами о_О никак. как сделаю — отпишусь, спасибо большое за отзыв) думал уже никто и не заметит
0
И еще, мои фьюзы для меги8
avreal32.exe +MEGA8 -o1.0MHZ -p1 -fblev=0,cksel=F,sut=1,eesave=on,bootrst=on -w -%%
Только в твоем случае bootrst=off, т.к. у меня еще бут есть.
0
не понимаю, как это будет выглядеть в avrdude =( вообще я много чего не понимаю, во всем просто хотел разобраться уже после того как заработает. пока прошью со стандартными фьюзами плюс ext osc high freq

младший будет 0xEC и старший 0xD9 вроде
0
нашел версию от 18 марта 2011, а не второго. это ее надо юзать с 20 МГц?
То есть в принципе я могу попробовать поставить вместо 16 на 20(вроде кондеры так и оставить на 22pF?) и залить новую прошивку, я правильно понял?
0
Да и внимательно с выводами D- D+. В прошивке D- это PD2, D+ это PD3.
0
Первое, что пришло в голову) Проверил, все верно здесь. Даже печатку на всяк случай прозвонил все, что только можно.
0
Итак, в схеме один стабилитрон, кварц на 20 МГц, ни одного конденсатора. Теперь обнаруживает съемное устройство но не может его запустить(код 10)

Хрееень((
попробую сейчас поставить кондер на 47 µF или второй стабилитрон или и то и другое
0
Попробуй USB сниффер, узнаешь на каком этапе затыкается устройство!) Потом после логов поговорим! (Я использовал Device Monitoring studio)
0
Не факт, что мега на 20МГц при двух стабилитронах запуститься=( Кондер на запуск устройства влияет больше чем никак=) Затык в софте, я думаю… Проверь сниффером!
0
сейчас наблюдал старнные штуки

1) с карточкой на 512 мб, двумя стабилитронами и кондере мигает но не работает, эта же карточка стояла при коде 10. но карта мертва, как случайно выяснилось

2)с картой 2 гб и той же схеме карта грелась нереально и даже задымила(но выжила, что странно) при этом девайс мигал

вообще жесть какая то)
0
Все дело в том, что карта не должна работать при напряжениях питания > 3.6В. Идеальный вариант, использовать питание меги 5В, карта 3.3В, согласование уровней с картой и по стабилитрону 3.6В на каждую линию D+(-). Запускать для проверки без карты памяти и смотреть на содержимое USB пакетов на ПК. Для этого установи Device Monitoring Studio и приведи содержимое лога.
0
При работе с 1 стабилитроном (диодом) питание системы ~4.3V, что не есть хорошо для карты и USB порта PC 0-)
0
Твою мать, что с комментариями… Нажимаешь добавить, а оно блин крутить круг пока не обновишь страницу. А млять!!!
0
Не у тебя одного. Последний месяц такая шняга появляется.
0
Это я понимаю, но оказывается закономерность другая: поставил новую стопроцентно работающую флэшку и опять код десять

После этого сама карточка тоже не работает — тоже код 10
Охренеть вообще) сейчас поставлю сниффер и покажу логи
0
00000000 26.04.2012 13:55:10.944 UP PnP: Device Connected
00000001 26.04.2012 13:55:10.944 +0.0 DOWN 0x00000000 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
00000002 26.04.2012 13:55:10.945 +0.001 UP 0x00000000 URB_FUNCTION_CONTROL_TRANSFER
00000003 26.04.2012 13:55:10.945 +0.0 DOWN 0x00000000 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
00000004 26.04.2012 13:55:10.946 +0.001 UP 0x00000000 URB_FUNCTION_CONTROL_TRANSFER
00000005 26.04.2012 13:55:10.946 +0.0 DOWN 0x00000000 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
00000006 26.04.2012 13:55:10.948 +0.002 UP 0x00000000 URB_FUNCTION_CONTROL_TRANSFER
00000007 26.04.2012 13:55:10.948 +0.0 DOWN 0x00000000 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
00000008 26.04.2012 13:55:10.949 +0.001 UP 0x00000000 URB_FUNCTION_CONTROL_TRANSFER
00000009 26.04.2012 13:55:10.949 +0.0 DOWN 0x00000000 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
00000010 26.04.2012 13:55:10.950 +0.001 UP 0x00000000 URB_FUNCTION_CONTROL_TRANSFER
00000011 26.04.2012 13:55:10.950 +0.0 DOWN 0x00000000 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
00000012 26.04.2012 13:55:10.951 +0.001 UP 0x00000000 URB_FUNCTION_CONTROL_TRANSFER
00000013 26.04.2012 13:55:10.951 +0.0 DOWN 0x00000000 URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE
00000014 26.04.2012 13:55:10.953 +0.002 UP 0x00000000 URB_FUNCTION_CONTROL_TRANSFER
00000015 26.04.2012 13:55:10.954 +0.001 DOWN 0x00000000 URB_FUNCTION_SELECT_CONFIGURATION
00000016 26.04.2012 13:55:10.954 +0.0 UP Internal: Pipe Info Transfer
00000017 26.04.2012 13:55:10.954 +0.0 UP 0x80000300 URB_FUNCTION_SELECT_CONFIGURATION
00000018 26.04.2012 13:55:10.977 +0.023 UP PnP: Device Disconnected
0
Configuration Descriptor
Number of interfaces: 1
Configuration value: 0x1
Attributes: Bus powered
Max power: 100 mA

Interface Descriptor: 0, Alternate setting: 0
Number of endpoints: 2
Interface class: 0x8 — Mass Storage
Interface subclass: 0x6 — SCSI
Interface protocol: 0x50 — Bulk (Zip)
Endpoint address 0x1, Input, Bulk, max packet size: 8 bytes
Endpoint address 0x2, Output, Bulk, max packet size: 8 bytes

Connection Information
Port: 2
Speed: Low Speed
Device address: 1
Open pipes: 0
Connection status: Device connected

Device Descriptor
USB version: 1.10
Device class: 0x0 — (Defined at Interface level)
Device subclass: 0x0 — Unknown
Device protocol: 0x0 — Unknown
Control pipe max size: 8 bytes
Vendor ID: 0x16cc (silex technology, Inc.)
Product ID: 0x15ef (Unknown)
Product version: 1.0
Manufacturer: Saimon
Product: AVRData
Serial Number: 20090822
Configurations: 1
0
Не тот лог. Там есть расписанный по командам и параметрам листинг. По-моему это в USB Mass Storage закладочке.
0
а там вобще пусто
0
я не понимаю, почему происходит это:
Это я понимаю, но оказывается закономерность другая: поставил новую стопроцентно работающую флэшку и опять код десять

После этого сама карточка тоже не работает — тоже код 10
0
и еще не опнимаю, почему рядом лежит точно такой же девайс, но на 2 стабилитрона и 16 МГц, но он Не опознается компом о_О
0
Вы хоть покажите как это выглядит! Может там монтажка на картонке с распайкой проводами ВВГнг 2х1,5.
0
Ну USB 1.1 LS по идее к этому не особо требователен.
0
На 20 cs10673.userapi.com/v10673295/22b/nXnPA-TSMIA.jpg
На 16 cs10673.userapi.com/v10673295/234/tb4syRNbnLk.jpg

Обе платы прозвонены, где надо — контачит, где не надо — нет. Это было вторым, что пришло в голову(
0
Под кварц изоляцию положить не забыл?
И неплохо бы схему и трассировку. Хотя и врядли причина там.
0
нет, там все ок. да я это сто раз проверил, к сожалению
0
Потому, что прошивка под другой кварц.
0
Да и не факт что мега на 16МГц будет работать стабильно при Uпит ~3.6В!!!
0
я же старую заливал, там в коде задефайнено 16 — как у тебя в статье
0
сделал еще одну печатку, с самого начала покрыл лаком(прикрыв контактные площадки, конечно же), затем собрал.
теперь работает на 20 МГц, разбираюсь со схемой и софтом

всем огромное спасибо, сам я, в общем-то, программист, а не железячник
0
Я тоже подаю на микроконтроллер 5 Вольт, а питаю карточку от стабилизатора напряжения 3,3 В. Диоды поставлены как дешевый вариант, но стабилизатор сам стоит копейки. Для этого соединяю карточку с микроконтроллером не на прямую, а через делитель напряжения в виде сопротивлений. Резисторы могут быть такими, как у тебя. Как ты питаешь карточку с шины данных, мне не известно. В прошивке увеличил быстродействие кода до предела, заменил одноблочное чтение на многоблочное. Размер карточки — смотри мой код.
Для заливки программы у меня самостоятельно сделанный программатор из журнала радио с COM портом. Для программирования я вынимаю контроллер из схемы, вставляю в программатор, там 4 МГц кварц, программирую и возвращаю в схему. Ибо девайс у меня совершенно другой: аудио-плеер с R-2R цепочкой, демультиплексором, ФНЧ на счетверенном ОУ, УНЧ или переносное устройство для станков с ЧПУ. Вообще то я инженер-электроник, а не программист.
0
еще бы неплохо заточить его под usb-флоппи эмулятор, например для загрузки старых мат. плат или при установке winxp, драйверы SATA подсовывать. особенно для ноутов без флоппи.
0
lleeloo, помнишь ты мне давал прогу для чтения секторов с карты. У меня тогда ммс 32Мб стояла и ошибка 10 была. Сейчас поставил SD 1Гб — ошибка таже,10. Та прога по чтению секторов показывает такое же содержимое для SD, как и для MMC, в конце 0х45,0х00. В чем может быть причина ошибки?
0
так и должно быть?

в файле board.h

#define LED_RED_PIN PC3
#define LED_BLUE_PIN PC2
0
А что собственно смущает?
0
Видимо, слегка несоответствующие цвета диодов)
0
Под WinXP работает, а под Win7 — код 10. В какую сторону копать?
0
скорее всего дрова=)
0
А может сам стек обновить надобно...?
0
В сторону WinXP. Bulk-девайсы на Low Speed запрещены спецификацией. WinXP это игнорирует, а вот семерка уже проверяет. CDC на V-USB тоже не стартуют под семеркой. Только девайсы с interrupt передачей — т.е. HID.
0
Ну вот, сорвали завесу тайны=))
Ну а если честно, то спасибо за развернутый ответ! Хотя думаю на тему vendor под семеркой можно поиграться=)
0
А толку-то? Тут только свой драйвер писать, потому что стартовать отказывается на уровне дров.
А вообще, булк-девайсы для семерки лучше строить на чем-то с аппаратным USB. PIC18F14K50 например няшный, вполне приличен фаршем и имеет аппаратный USB при цене в 2.5 бакса.
0
Думаете, если VendorID поменять, то может прокатить?
0
Vendor specific(defined) class =0 Тут имелось ввиду, что менять не VID нужно.
0
Очень жаль, спасибо.
0
Какие фьюза надо ставить?
Их надо выдирать самому в зависимости от моих параметров, я правельно понял?
0
  • avatar
  • lzrs
  • 15 марта 2013, 13:43
Ребята, помогите. Я не могу запустить данный девайс. Я изменил значение usb_read_capacity (....0хFA 0x00) для eeprom 64k. прошил с фюзами atmega8: eesave sut1 ckopt. Устройство висит как накопитель для usb в диспетчере устройств, а в Мой Компьютер не появляется.
Когда заливаю прошивку не с сайта она отображается, и требует от форматироваться, т.к. у меня не 484мб, а 64кбт она не работает. Подскажите как быть
0
  • avatar
  • lzrs
  • 19 марта 2013, 05:56
Страница на накопителе 0х200 байт, размер еепром 0х10000 байт, значит размер, который нужно указать в usb_read_capacity должен быть 0х10000 / 0х200 = 0х80. Как-то так=) Удачи
0
С прошикой после компиляции, диск не отображаться как накопитель «в мой компьютер», даже если eeprom отпаять
0
  • avatar
  • lzrs
  • 19 марта 2013, 12:18
А в «управлении дисками» отображается? Попробуй его сперва отформатировать оттуда, а затем выдели букву. Ну и в семерке и старше оно не запустится, выдаст «код 10» в диспетчере устройств, насчет висты хз.
0
С прошивкой*
0
  • avatar
  • lzrs
  • 19 марта 2013, 12:18
Прошей то, что в прошивке из поста и проверь. Да и если Win7 то можешь наверное и пытаться=)
0
В Windows 8 функция usbFunctionWriteOut не вызывается.
Больше этот бульк работать не будет?
0
Bulk на USB LS запрещен спецификацией. WinXP это игнорирует, а вот семерка такие устройства уже не принимает.
0
Можно драйвер WinXP выковырять и установить в Win7/8?
0
Понятия не имею. Вроде какие-то костыли были. Но лучше просто не делать их. Хотя, конечно, наиболее привлекательный для радиолюбителей CDC при этом отпадает, да и MSD тоже.
0
Я только сделал на EEPROM микроконтроллера 512 байт проигрывание однотональных мелодий из журнала радио в виде файлов. Минимальный сектор 128 байт.
0
Загрузочная запись во FLASH.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.