|
Отправка пакета через USB из LPC1778 в ПК |
|
|
|
Dec 21 2014, 18:42
|
Местный
  
Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085

|
Пытаюсь отправить пакет в ПК, где его ждёт программа-монитор USBTrace. При включении подтягивающего резистора в мониторе вижу, что винда отправила какой-то запрос, все байты на виду, но мне они пока не нужны. Жду окончания запроса и пытаюсь отправить свой пакет, но почему-то пока никак. Делаю всё по описанию - включаю изохронную точку на выход, указываю максимальную длину пакета и начальное значение счётчика, затем записываю данные в буфер и вызываю команду проверки буфера, после которой при первом прерывании фрейма этот буфер улетает в ПК. Для индикации прерываний фреймов задействовал одну ножку и на осциллографе наблюдаю импульсы через каждую миллисекунда с точностью до микросекунд, т.е. тактирование настроено правильно. Код #include "iolpc1778.h" #include "LPC17xx.h" unsigned int i; void main(void) {
{ //INIT SCS |= 0x20; //подключение осциллятора while(!(SCS&0x40)){} //ожидание запуска //Настройка тактирования ЦПУ PLL0CON |= 0x01; //включение PLL0 PLL0CFG |= 0x09; //умножение частоты на 10 PLL0FEED = 0xAA; //разрешение PLL0FEED = 0x55; //изменений CCLKSEL |= 0x100; //переключение источника тактирования //настройка тактирования USB PLL1CON |= 0x01; //Включение PLL1 PLL1CFG |= 0x03; //Умножаем частоту на 4 (12МГц*4=48МГц) PLL1FEED = 0xAA; //разрешение PLL1FEED = 0x55; //изменений USBCLKSEL = 0x201; //Тактирование USB от PLL1 и частота тактирования 48МГц IOCON_P1_25 = 0; //PIO FIO1DIR = 0x2000000; //Выход PIN1_25 для индикации прерывания { //init USB PCONP |= 0x80000000; //включение питания USB USBCLKCTRL |= 0x12; //устанавливаем флаги DEV_CLK_EN + AHB_CLK_EN while(!(USBCLKST & 0x12)){}//ждём установки флагов USBCLKCTRL |= 8; //устанавливаем флаг доступа к регистру выбора конфигурации функции порта while(!(USBCLKST & 0x08)){}//ждём установки флага USBPORTSEL = 3; //U2 - ведомый USBCLKCTRL &=~8; //сброс флага доступа IOCON_P0_31 = 1; //функция ножк U2D+, на U2D- других функций нет IOCON_P0_14 = 0; //USBCONNECT - управление подтягивающим резистором FIO0DIR |= 0x4000; //bit 14 - OUT USBDEVINTEN = 0x01; //разрешение прерываний FRAME } PCLKSEL = 1; //тактирование переферии 1:1 CLKSRCSEL |= 1; //тактирование CPU от PLL0 AIRCR = 0x05FA0200; //настройка IP1 = 0x00000800; //и разрешение NVIC_EnableIRQ(USB_IRQn); //прерываний }
while(1) { FIO0SET |= 0x4000; //1.5 kOm USBREEP |= 0x80; //задействована изохронная точка 7 (IN) while(!(USBDEVINTST & 0x100)){} //ждём установки флага EP_RLZED for(i=0; i<0x2FFFFFF; i++ ) { __NOP(); } //небольшая пауза для пропуска запроса от windows USBTXPLEN = 40; //начальное значение счётчика байтов в пакете USBEPIN = 7; //индекс конечной точки USBMAXPSIZE = 40; //максимальный размер пакета для указанной конечной точки while(!(USBDEVINTST & 0x100)){} //ждём установки флага EP_RLZED USBCMDCODE = 0x0500 + 0x070000; //выбор конечной точик USBCTRL = 0x2 + 0xC; //WP_EN = 1, LOG_ENDPOINT = 3; TDATA = 0x12345678; TDATA = 0x91011121; TDATA = 0x31415161; TDATA = 0x71819202; TDATA = 0x12223248; TDATA = 0x12345678; TDATA = 0x12345678; TDATA = 0x12345678; TDATA = 0x12345678; TDATA = 0x98765432; //после этой команды сбрасывается WP_EN
USBCMDCODE = 0x0500 + 0xFA0000; //команда + проверка буфера for(i=0; i<0x8FFFFFF; i++ ){__NOP(); } FIO0CLR |= 0x4000; //отключение резистора 1.5 кОм for(;;){} } }
void USB_IRQHandler (void) { USBDEVINTCLR |= 0x3FF; //clear alls interrupt FIO1CLR = 0x2000000; FIO1SET = 0x2000000; FIO1CLR = 0x2000000; NVIC_ClearPendingIRQ(USB_IRQn); return; } что я не так делаю?
Прикрепленные файлы
LPC.rar ( 929.05 килобайт )
Кол-во скачиваний: 11
|
|
|
|
|
Dec 22 2014, 11:03
|
Местный
  
Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085

|
Цитата(jcxz @ Dec 22 2014, 14:09)  Ну если получаете фреймовые прерывания, тогда разве трудно поставить туда бряк и посмотреть - что у Вас в этом прерывании делается - отправляется-ли изохронный кадр? Чем бряк поможет? Аппаратную часть из программы не видно, остаётся наслово верить руководству, что пакет оправляется при очередном прерывании фрейма после проверки буфера. Я ожидаю увидеть свои байты в мониторе USBTrace. Как ещё можно увидеть, что кадр отправлен? Если только через какие-то флаги смотреть, но в конечном итоге нужно увидеть принимаемые данные на компе в мониторе. 12.14.3 Data transfer for IN endpoints When writing data to an endpoint buffer, WR_EN (Section 12.10.4.5 ”USB Control register”) is set and software writes to the number of bytes it is going to send in the packet to the TxPLen register (Section 12.10.4.4). It can then write data continuously in the TxData register. When the number of bytes programmed in TxPLen have been written to TxData, the WR_EN bit is cleared, and the TxENDPKT bit is set in the DevIntSt register. Software issues a Validate Buffer (Section 12.12.14 ”Validate Buffer (Command: 0xFA, Data: none)”) command. The endpoint is now ready to send the packet. For IN isochronous endpoints, the data in the buffer will be sent only if the buffer is validated before the next FRAME interrupt occurs; otherwise, an empty packet will be sent in the next frame. If the software clears WR_EN before the entire packet is written, writing will start again from the beginning the next time WR_EN is set for this endpoint. Both RD_EN and WR_EN can be high at the same time for the same logical endpoint. Interleaved read and write operation is possible.
Сообщение отредактировал ДЕЙЛ - Dec 22 2014, 11:13
|
|
|
|
|
Dec 22 2014, 13:44
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(ДЕЙЛ @ Dec 22 2014, 17:03)  Чем бряк поможет? Аппаратную часть из программы не видно, остаётся наслово верить руководству, что пакет оправляется при очередном прерывании фрейма после проверки буфера Если Вы его не отправляете в ISR то откуда же он возьмется??? А у Вас ISR пустой совсем. В ISR нужно, проверив причину прерывания, и узнав что это фреймовое прерывание, явно выбрать соответствующий буфер конечной точки и загрузить его. Откройте любой пример для данного МК и посмотрите что там делается в обработчике прерывания. В IAR есть хороший пример для изохронной точки для данного МК.
|
|
|
|
|
Dec 22 2014, 19:18
|
Местный
  
Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085

|
Цитата(jcxz @ Dec 22 2014, 17:44)  Если Вы его не отправляете в ISR то откуда же он возьмется??? А у Вас ISR пустой совсем. В ISR нужно, проверив причину прерывания, и узнав что это фреймовое прерывание, явно выбрать соответствующий буфер конечной точки и загрузить его. Что куда и как отправлять? Как это будет выглядеть на примере моего кода? Что нужно дописать или изменить? Цитата(jcxz @ Dec 22 2014, 17:44)  Откройте любой пример для данного МК и посмотрите что там делается в обработчике прерывания. В IAR есть хороший пример для изохронной точки для данного МК. Приятно удивило, что там добрая сотня файлов, в которых мне копаться неделю надо. Пока хочу с простейшего начать.
|
|
|
|
|
Dec 22 2014, 20:07
|
Местный
  
Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085

|
Цитата(toweroff @ Dec 22 2014, 23:29)  ой ли? не знаю, как там в Яре, по идее то же самое, что и в Кейле. А там - всего-то 4 файла - usbcore.c, usbdesc.c, usbhw.c и usbuser.c в папке с примером 107 файлов. Покрутил эти 4 файла - наглядности маловато и пример не для моей платы. Хочется увидеть минимальный код для отправки пакета, а потом уже глубже копать. Светодиодом моргать никто не начинал с распутывания килобайтов кода. Если не трудно, то напишите последовательность действий для отправки пакета в комп. Как в общих четрах строить алгоритм? Какие биты менять, какие проверяить и что в обработчике прерывания писать?
|
|
|
|
|
Dec 22 2014, 20:15
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
QUOTE (ДЕЙЛ @ Dec 21 2014, 20:42)  Пытаюсь отправить пакет в ПК, где его ждёт программа-монитор USBTrace. При включении подтягивающего резистора в мониторе вижу, что винда отправила какой-то запрос, все байты на виду, но мне они пока не нужны. Жду окончания запроса и пытаюсь отправить свой пакет, но почему-то пока никак.
что я не так делаю? Для начала уяснить принципы юсб. Если хост не инициировал транзакцию на шине, можете до посинения ждать - ничего не произойдет. Далее - сниферы ничего не "ждут". Они фиксируют шинный трафик и отображают его в более менее понятном виде. И как упоминали выше, самый простой стек в примерах от кейла.
|
|
|
|
|
Dec 22 2014, 20:32
|
Местный
  
Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085

|
Цитата(ig_z @ Dec 23 2014, 00:15)  Если хост не инициировал транзакцию на шине, можете до посинения ждать - ничего не произойдет. Инициирование программное? Хост отправил какие-то данные, их примет EP0, потом контроллер посмотрит, что принято и после этого будет думать, что дальше сделать. Так?
Сообщение отредактировал ДЕЙЛ - Dec 22 2014, 20:32
|
|
|
|
|
Dec 22 2014, 20:43
|
Местный
  
Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085

|
Цитата(toweroff @ Dec 23 2014, 00:36)  В общем виде - да. Если инициирование программное, то после него ведомое устройство может передавать данные в комп? Если оно может передавать данные, то почему нельзя их передать без инициации самовольно? Мне пока не нужно, чтобы комп правильно определил тип устройства, просто хочу увидеть свои байты в нём.
|
|
|
|
|
Dec 22 2014, 20:48
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(ДЕЙЛ @ Dec 22 2014, 23:43)  Мне пока не нужно, чтобы комп правильно определил тип устройства, просто хочу увидеть свои байты в нём. Это невозможно. Так протокол устроен, пока хост не попросил данных, их отправить нельзя. Подготовить к отправке - можно - но физически они никуда не отправятся. Таким образом: Сначала - вся енумерация и корректное определение в компе - это обязательно (без этого следующий шаг невозможен). Потом - драйвер в компе, который делает запрос на IN передачу - это тоже обязательно (без этого, тоже, следующий шаг невозможен). И только потом, когда устройство увидит IN токен, инициированный драйвером, оно реально отправит данные. Без этого никак.
|
|
|
|
|
Dec 23 2014, 06:21
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(ДЕЙЛ @ Dec 23 2014, 01:18)  Приятно удивило, что там добрая сотня файлов, в которых мне копаться неделю надо. Пока хочу с простейшего начать. Сказать что Вы сильно преувеличиваете - значит ничего не сказать. Открываем IAR6.50 - там в USB-ядре всего 3 файла: usb_buffer.c, usb_hw.c, usb_t9.c Вам нужен: EWARM 6.50.3\arm\examples\NXP\LPC17xx\IAR-LPC-1788-SK\AudioDevice\modules\usb_hw.c ISR в нём: USB_IRQHandler() - вот в нём и разбирайтесь. На поиск у меня ушло 2 минуты... Цитата(ig_z @ Dec 23 2014, 02:15)  Далее - сниферы ничего не "ждут". Они фиксируют шинный трафик и отображают его в более менее понятном виде. Маленькая поправочка: снифферы не "фиксируют шинный трафик", они "фиксируют вызовы API к USB-драйверу ядра".
|
|
|
|
|
Feb 17 2015, 05:03
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Цитата Понапридумывают же... sm.gif Попробую ещё раз перечитать про USB, мошть понятнее станет. Есть такая книжка: Агуров, Интерфейс USB.Практика использования и программирования. 2004 Там по-русски и вполне понятно для начинающего объяснено про устройство USB
|
|
|
|
|
Mar 10 2015, 20:36
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Цитата(ДЕЙЛ @ Mar 10 2015, 17:06)  Опять вернулся к этой теме. Почитал Агурова и описание модуля. В моём представлении вырисовывается такая картина: 1. Подключаем разъём к ноуту, хост видит, что резистор притянул линию и отсылает запрос; 2. Устройство принимает байты запроса в буфер нулевой конечной точки, смотрит эти байты и формирует массив данных, которые хостом воспринимаются как дескриптор устройства; 3. На основании данных дескриптора хост отправляет более конкретную команду устройству и т.д. до окончания инициализации соединения. Мои соображения похожи на правду? в общем да каждый запрос имеет свой идентификатор и, соответственно, структуру себя родимого и ответа делается все в switch-case для каждого типа запроса. Если что-то не реализовано, отрабатывается STALL смотреть во всех кейловских примерах (в яре, по-моему, то же самое было), файл usbcore.c, функция USB_EndPoint0примерно так: CODE void USB_EndPoint0 (U32 event) {
switch (event) { case USB_EVT_SETUP: USB_SetupStage(); USB_DirCtrlEP(SetupPacket.bmRequestType.BM.Dir); EP0Data.Count = SetupPacket.wLength; /* Number of bytes to transfer */
switch (SetupPacket.bmRequestType.BM.Type) {
case REQUEST_STANDARD: switch (SetupPacket.bRequest) {
case USB_REQUEST_GET_STATUS: if (!USB_ReqGetStatus()) { goto stall_i; } USB_DataInStage(); break;
case USB_REQUEST_CLEAR_FEATURE: if (!USB_ReqSetClrFeature(0)) { goto stall_i; } USB_StatusInStage(); break;
case USB_REQUEST_SET_FEATURE: if (!USB_ReqSetClrFeature(1)) { goto stall_i; } USB_StatusInStage(); break;
case USB_REQUEST_SET_ADDRESS: if (!USB_ReqSetAddress()) { goto stall_i; } USB_StatusInStage(); break;
case USB_REQUEST_GET_DESCRIPTOR: if (!USB_ReqGetDescriptor()) { goto stall_i; } USB_DataInStage(); break;
case USB_REQUEST_SET_DESCRIPTOR: /*stall_o:*/ USB_SetStallEP(0x00); /* not supported */ EP0Data.Count = 0; break;
case USB_REQUEST_GET_CONFIGURATION: if (!USB_ReqGetConfiguration()) { goto stall_i; } USB_DataInStage(); break;
case USB_REQUEST_SET_CONFIGURATION: if (!USB_ReqSetConfiguration()) { goto stall_i; } USB_StatusInStage(); break;
...... и так далее сама функция дергается из USB-прерывания ( usbhw.c)
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|