Общее описание
Данные между ПК и микроконтроллером передаются через специальный USB буфер памяти доступные через USB периферию микроконтроллера. Размер этого буфера должен быть в соответствии с размером максимального пакета конечной точки и их количеством. Общий размер всех буферов должен не превышать 512 байт.
Каждая конечная точка связанна с USB буфером через регистр, в котором хранится адрес по которому конечная точка расположена в этом буфере и как много байт она может передать.
Когда маркер обнаружен периферией, происходит передача/прием данных (если конечная точка настроена) и данные пишутся/читаются в/из usb буфера. Когда все данные переданы, если необходимо передается/ожидается пакет подтверждения.
В конце передачи генерируется определенное прерывание. Чтение регистра позволяет определить причину и назначить функции реагирования.
USB блоки
- Serial Interface Engine (SIE). Функции данного блока: synchronization pattern recognition, bit-stuffing, CRC generation and checking, PID verification/generation, работа с подтверждением.
- Timer. Данный блок генерирует start-frame locked clock pulse и определяет suspend, если 3мс нет кадров на прием.
- Packet Buffer Interface. Этот блок управляет памятью usb буфера.Он может выбирать буфер в соответствии запросу SIE и определяет место расположения их в памяти usb буфера (для определенной конечной точки). Он инкрементирует адрес после каждого переданного/принятого слова, следит за номером переданных/принятых байт и предотвращает переполнения буфера.
- Endpoint-Related Registers. Каждая конечная точка описывается регистром.
- Control Register. Содержит информацию о статусе usb периферии и используется для обнаружения событий, например отключения или возвращения питания.
- Interrupt Registers. Содержит маски прерываний и событий. Используется для определения причины прерывания по USB (1 вектор на все прерывания) и для очистки флага.
USB периферия подключенная к шине APB1 имеет следующие блоки:
- Packet Memory. Это физическая память, для usb буфера, (связана/управляется Packet Buffer Interface). Размер 512 байт, разбитых на 256 слов по 2 байта.
- Arbiter. Используется для разрешения конфликтов между запросами от usb и от APB1.
- Register Mapper. Формирует 16-битное слово.
- APB1 Wrapper.
- Interrupt Mapper. Для указания вектора приоритета при возникновении прерывания от USB.
Программирование USB
System and power-on reset
Внутренний pull-up резистор контролируется регистром SYSCFG_PMC битом USB_PU. Когда USB_PU = 0, нет подтяжки к DP и USB не может обнаружится. Когда USB_PU бит установлен, подтяжка есть и USB определяется.
Первый шаг — необходимо активировать register macrocell clock и de-assert(установка в неактивный уровень macrocell specific reset signal using related control bits provided by device clock management logic.
После этого, аналоговая часть устройства, связанная с usb периферией, должна включиться используя PDWN bit in CNTR register. Этот бит включает внутренний voltage references, который питает usb передатчик. Эта схема имеет время включения tSTARTUP в течение которого поведение usb передатчика не определенно. Необходимо ждать это время после установки PDWN bit in the CNTR register, прежде чем очистить reset condotion со стороны usb (делается очищением FRES bit in the CNTR register). Очищение ISTR регистра затем, очищает любые ложные прерывания до любой другой macrocell operation is enabled.
В system reset МК должен инициализировать все регистры и packet buffer description table, что-бы сделать usb периферию способной генерировать прерывания и передачу данных.
USB reset
Когда происходит это событие, USB периферия ставится в то-же положение что и была в system reset(описанном в предыдущем пункте): communication отключена во всех регистрах конечных точек(usb периферия не реагирует на какие-либо пакеты).
Как ответ на USB reset usb функции должны включиться, имея usb адрес 0 и реализуя только стандартную для usb нулевую конечную точку. Это осуществляется установкой Enable Function (EF) bit of the USB_DADDR register и инициализацией EP0R register и связанным с ним usb буфером соответственно. В течении общения с хостом (ПК), должен быть установлен/записан адрес устройства в ADD[6:0] bits of the USB_DADDR register и настроены другие необходимые конечные точки.
When a RESET interrupt is received, the application software is responsible to enable again
the default endpoint of USB function 0 within 10mS from the end of reset sequence which
triggered the interrupt.
Structure and usage of packet buffers
Полученные данные хранятся в usb буфере в зарезервированном месте для этой конечной точки.
Каждая конечная точка ассоциируется с двумя usb буферами(один для передачи, другой для приема). Данные буферы могут находится в любом месте внутри usb буфера, потому что их адрес и размер указывается в buffer description table, которая также расположена в packet memory по адресу записанному в USB_BTABLE register. Каждая запись таблицы связана с endpoint register и состоит из четырех 16 битных слов.
Каждый packet buffer используется либо для передачи, либо для приема начиная с дна. Буферы конечных точек защищены от переполнения с изменением прилежащих буферов — если буфер переполнится, переполнение отбросится.
Endpoint initialization
Первый шаг для инициализации конечной точки записать соответствующие значения в ADDRn_TX/ADDRn_RX регистры. Таким образом USB периферия найдет данные для передачи или принятые. The EP_TYPE bits in the USB_EPnR register должен соответствовать типу конечной точки.
На стороне передатчика конечная точка должна быть включена установкой STAT_TX bits in the USB_EPnR register, а COUNTn_TX должен быть инициализирован.
На стороне приемника STAT_RX bits должен быть установлен для включения приемника и COUNTn_RX должен быть записан в соответствии с количеством принимаемых данных, определяя размер по BL_SIZE and
NUM_BLOCK fields.
Когда обмен данными завершился, проимсходит CTR прерывание/событие.
IN packets (data transmission)
Когда принимается IN token packet, если адрес совпадает с настроенным и правильно настроена конечная точка, USB периферии доступны ADDRn_TX and COUNTn_TX внутри usb буфера. USB периферия читает первое слово и передает его и начинается отправка DATA0 or
DATA1 PID в соответствие USB_EPnR bit DTOG_TX.
Когда PID завершен, первый байт слова читается из памяти, загружается в сдвиговый буфер и передается по USB. После последнего переданного байта передается уже CRC рассчитанное периферией USB. Если адресованная конечная точка была ошибочна при запросе с ПК, NAK или STALL подтверждение передается вместо пакета данных, в соответствие с STAT_TX bits in the USB_EPnR registe.
ADDR internal register используется как указатель на текущий место в буфере USB для передачи, а COUNT указывает сколько байт передать осталось.
Передача начинается с адреса указанного в ADDRn_TX и передается COUNTn_TX/2 слов(1 слово = 2 байта). Если передача состоит из нечетного количества байт, только нижняя половина последнего слова будет передана.
Получив ACK от хоста, USB_EPnR register обновляет следующие поля: DTOG_TX bit, конечная точка(если была неправильна) устанавливает STAT_TX=10 (NAK), CTR_TX.
Программа первым делом должна определить конечную точку к которой обращался ПК, для этого проверяется EP_ID and DIR bits in the USB_ISTR register. Обработка CTR_TX event начинается с сброса флага прерывания, программа готовит следующий буфер для передачи, обновляет в таблице COUNTn_TX, и в конце устанавливает STAT_TX to ‘11 (VALID) для очередного запуска передачи. Пока STAT_TX bits равен b10 (NAK), ответ на каждый запрос к данной конечной точки, бужет с NAK, и ПК(хост) будет слать запросы пока не будет успешного подтверждения(не NAK).
Это были обязательные последовательности действий для избежания потери данных.
OUT and SETUP packets (data reception)
OUT и SETUP пакеты обрабатываются примерно одинаково.
Когда принимается OUT/SETUP PID если адрес конечной точки правильный (конечная точка правильно настроена), USB периферия получает доступ к содержимому ADDRn_RX and COUNTn_RX внутри буфера USB, в месте соответствующем данной конечной точки. Содержание ADDRn_RX хранится по адресу во внутреннем регистре ADDR.
While COUNT is
now reset and the values of BL_SIZE and NUM_BLOCK bit fields, which are read within
COUNTn_RX content are used to initialize BUF_COUNT, внутренний счетчик который используется для предотвращения переполнения. Данные принимаются по USB словами по 2 байта, и затем переписываются в буфер по адресу ADDR, а BUF_COUNT уменьшается на 1, COUNT увеличивается на 1 с каждым принятым байтом.
После полного приема USB периферия проверяет CRC и если нет ошибок, отвечает ACK подтверждением на ПК(хост).
В случае ошибки CRC или какой-либо другой ошибки (bit-stuff violations, frame errors, etc), данные так-же копируются в USB буфер, но ACK не отправляется и устанавливается ERR bit in USB_ISTR register. Однако это не требует никаких действий со стороны программы: оправившись от ошибки usb периферия начнет принимать данные снова.
Если адрес конечной точки неправильный NAK или STALL подтверждения отправляются за место ACK и данные не пишутся в USB буфер.
Начало буфера с принятыми данными расположено по адресу в ADDRn_RX, а его длина соответствует длине принятого пакета, включая CRC, или последнему выделенному байту для этой конечной точки в usb буфере(определяется BL_SIZE and NUM_BLOCK). Вне конечной точки данные не могут попасть (защита). При переполнении — usb периферия детектирует это и STALL подтверждение отправляется вместо ACK и прерывание не генерируется.
Когда transaction завершена корректно, отправляется ACK подтверждение, внутренний COUNT register копируется назад в COUNTn_RX внутри usb буфера и в USB_EPnR register обновляются поля: DTOG_RX, если конечная точка была неправильная устанавливается STAT_RX = b10 (NAK) и устанавливается CTR_RX.