Если не ошибаюсь, то момент соединения с шиной обозначается прерыванием по РЕСЕТ. У меня в STM32F303 тоже нет бита подтяжки. На плате резистор тупо припаян.
Собрал схему, для проверки достал где-то ещё завалявшуюся плату STM32 H-103.
По поводу событий при подключении.. прерывание по РЕСЕТ.? Нет, мне кажется, не совсем так. Подробнее. Первое событие RESET - это сброс FRES. Тут мы включаем тактирование, настраиваем флаги и т.д. По первому РЕСЕТу мы только конфигурируем и настраиваем девайс. Но на данном этапе данный RESET никак не свидетельствует о подключении шины.
Об подключении к шине непосредственно свидетельствует второй РЕСЕТ (флаг в ISTR первого РЕСЕТа не забываем очистить), о котором и упомянул Z_h_e, и который отправляется уже хостом. Но до этого хаб определяет наличие подтяжки D+. Тут я и стал.(Схему собрал, но не работает). Какое событие отвечает за обнаружение подтяжки D+. ?
Весь процесс я понимаю, идет так: - после включения девайса (только девайса, без подключения к шине) (и после конфигурирования модуля)устанавливается событие SUSP (более 3мс отсутствия активности на шине). Контроллер успешно уводит девайс в данный режим. Выставляется флаг. Флаг от первого РЕСЕТа (который по сбросу FRES) очищаем. Ждем второго РЕСЕТа от компа. - в это время (после установления SUSP) при подключении к шине должно произойти событие WKUP (пробуждение устройства и сброс бита low-power mode). Т.е. тут девайс должен определить наличие подтяжки и дать компу информацию о своем присутствии на шине.
Но последнее (именно событие WKUP) почему-то не проходит. Втыкаю девайс в комп - прерывание по WKUP молчит. Такое на двух платах. И на своей и на заводской от Olimex.
В общем вот. Всё перепроверил. Вроде всё верно. Но при подключении шнура USB комп ожидаемый Reset не отдает ну никак. При включении прерывания SUSP (пока закомментил) устройство уходит в приостановленный режим. РЕСЕТа нет.
А может ну его нафиг эти SUSP и WKUP? На первых порах мне хватало 2-х событий - RESET и CTR (correct transfer).
Код:
void USB_INIT(void) { RCC->CFGR |=RCC_CFGR_USBPRE;//выставляю делитель на 1 (работаю сразу на 48МГЦ) RCC->APB1ENR |= RCC_APB1ENR_USBEN;//USB clock enabled USB->CNTR &= ~USB_CNTR_PDWN;// включаю USB delay(8);//ждем примерно 1 мкс пока не запустится внутренний ИОН // USB->CNTR = 0;//и очищаю FRES delay(1);//ждем немного, чтобы установился флаг резета USB->ISTR = 0;//и сбрасываю этот флаг, т.к. всю настройку буду производить уже пофакту резета от компа USB->CNTR = USB_CNTR_RESETM|USB_CNTR_CTRM;//enable reset interrupt, correct transfer descr_init();//тут инициализирую таблицу дескрипторов NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);// включаю нужное прерывание
Продолжу о своих приключениях. Всё разрешилось. На отладочной плате всего-то сгорел буферный транзистор, из-за чего не было подтяжки к D+, и соответственно поэтому не приходил долгожданный RESET. Идем дальше. Сейчас вожусь с контрольными точками и дескрипторами. С первыми вроде всё ясно, но не до конца. Так и не понял, как их настраивать. Перечитал всю ветку. Но так и не понял. Значения скопипастил из постов.
С таблице контрольных точек вроде как разобрался немного. Итак.
Вот. Итак. С адресами всё вроде понятно. Вопрос тут следующий:
Код:
//Настройка буфера 0 Table->ADR0TX=0x0000; //количество данных для передачи хосту (32 байт) Table->COUNT0TX=0x0020; Table->ADR0RX=0x0100; //количество принимаемых данных от хоста(32 байт) Table->COUNT0RX=0x00004000;
Значение COUNT0RX взял из вашего примера. Но непонятно до конца. Как именно хекс 0x00004000 соответствует 32-м байтам?
Следующий вопрос. Не до конца понятно, как получить доступ к принятым данным в буфере. А именно как его прочесть. Я правильно понимаю, что в USB_ADDRn_RX хранится адрес буфера.
Цитата:
Это значит что данные, которые придут от компа в МК для конечной точки 0, будут лежать по адресу 0x40006000+0x0100*2.
В данном случае данные будут лежать по адресу 0x40006200?! Но то адрес!.. Туплю. А как с него данные то толком извлечь? Определяю, что мне приходит SETUP пакет. Как вскрыть его содержимое - пока не дошел.
isx, посмотрел ваш код. Меня тут смущает, что адрес приемного буфера у вас нечетный. (выделил) - 0x400060C1. Как такое получилось? Спойлерswitch (*(__IO uint32_t*)(0x400060C1)) { case 0x6:
А, всё. Кажись въехал.! Так понимаю, нечетный адрес получается, т.к. мы считываем поле Request из пакета SETUP, а у байта Request собственное смещение = 1? Правильно?
Мы берем адреса, которые использует USB, а их значение в два раза меньше.
Serg1987 писал(а):
Значение COUNT0RX взял из вашего примера. Но непонятно до конца. Как именно хекс 0x00004000 соответствует 32-м байтам?
Это значение имеет только одну единицу (в бинарном представлении) в бите номер 14. Посмотрить, что это значит в регистре COUNT0RX, а затем загляните в таблицу, которая под этим регистром в даташите.
Serg1987 писал(а):
В данном случае данные будут лежать по адресу 0x40006200?! Но то адрес!.. Туплю. А как с него данные то толком извлечь?
*(__IO uint16_t*)(0x40006080) = TXBuff; По каждому значению адреса в памяти хранится 4 байта информации, но 3-й и 4-й байты недоступны. Соответственно в моем примере TXBuff получит два байта из адреса. Делаем цикл и читаем данные как из массива в массив. Вроде так .
P.S. А вообще, значение адреса онлайн можно посмотреть в отладчике в KEIL ) .
0x80 0x06 - вот оно - Запрос дескриптора устройства 0x00 0x01 0x00 0x00 0x40 0x00
Да. Но вообще, если делать грамотно, то первый байт нужно также учитывать. Вообще по спецификации бывает 3 запроса на дескриптор (в основном): GET_DESC_DEVICE: 0x8006 GET_DESC_INTERFACE: 0x8106 GET_DESC_ENDPOINT: 0x8206 Так что учитывать необходимо 2 байта. Я думаю, до этого сам дойду. Пока для отладки использую мониторинг на 0x06, будучи уверенным, что придет именно GET_DESC_DEVICE.
Мы берем адреса, которые использует USB, а их значение в два раза меньше.
Спасибо, вроде начал вьезжать. А, понял. Объем памяти в блоке у нас 2 байта (15 бит равен 0). А в поле NUM_BLOCK записано количество блоков. В данном случае в десятичном представлении - это 0d16. 16*2=32. Поле COUNTn_RX[9:0] заполняется после прихода данных и содержит информацию о кол-ве принятых байт. Вроде стало на свои места всё.
Request 0x06 читается. Но при попытке прочитать значение из адреса 0x40006080 (самый первый байт. ожидаю там 0x80), то этого значения там нет. Может чего не так делаю.??
Вот, подрисовал рисунок в файле во вложении. Если у меня читается второй байт по адресу 0x40006081 (значение 0x06. как и должно быть), то почему не читается первый по адресу 0x40006080??
Посмотрите в отладчике, какие там у вас значения по адресам. Здесь в строке адреса указано C0, так как в регистр прописано 60 (в два раза меньше, помним ). Так можно посмотреть что на самом деле пришло нам в буфер.
P.S. Проглядел. Посмотрите внимательно, что у вас в CASE записано . Вообще не понятно. У вас по адресу .....81 читается 0x06, хотя должно быть 0x60. Возможно вам приходит что-то не то....
Все испробовал. Понятия не имею почему второй запрос не идет. Как только регистры и адреса уже не вертел, но в приемник залетает только дескриптор устройства.
Спойлер
Код:
void USB_LP_CAN_RX0_IRQHandler(void) {
if (USB->ISTR & USB_ISTR_CTR) { while ((USB->ISTR & USB_ISTR_CTR) != 0) {
if ((USB->EP0R & USB_EP_CTR_RX) != 0) { USB->EP0R &= ~USB_EP_CTR_RX;
switch (*(__IO uint32_t*)(0x40006101)) { case 0x6:
} if ((USB->EP0R & USB_EP_CTR_TX) != 0) { USB->EP0R |= USB_EP_RX_VALID; } i = 0; }
if (USB->ISTR & USB_ISTR_RESET) { USB->ISTR = 0; USB->CNTR |= USB_CNTR_CTRM | USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_SOFM; USB->BTABLE = BTableOffset; // таблица начинается с 0x0000
*(__IO uint32_t*)(0x40006000) = (uint16_t) 0x40; // начальный адрес USB_ADDR0_TX (такой адрес позволяет в дальнейшем добавить все 8 возможных контрольных точек, каждая имеет размер 1 байт) *(__IO uint32_t*)(0x40006004) = (uint16_t) 0x40; // размер исходящих данных - 32 байта USB_COUNT0TX *(__IO uint32_t*)(0x40006008) = (uint16_t) 0x80; // начальный адрес USB_ADDR0_RX *(__IO uint32_t*)(0x4000600C) = (uint16_t) 0x8400; // 32 байта входящих данных USB_ USB_COUNT0RX_BL_SIZE
USB->EP0R |= USB_EP_CONTROL; // режим - CONTROL
USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет USB->EP0R |= USB_EP_RX_VALID; // К приему готов test1 = *(__IO uint32_t*)(0x40006100);
USB->DADDR |= USB_DADDR_EF;
}
}
Вот дескриптор, который я отправляю (брал в интернете, проверял его, но вреде все нормально):
Спойлер
Код:
const uint8_t Virtual_Com_Port_DeviceDescriptor[] = { 0x12, // размер данного дескриптора 0x01, // тип данного дескриптора - device descriptor 0x00, 0x02, // 2 байта - версия usb 2.0 0x02, // класс устройства cdc 0x00, // подкласс 0x00, // протокол 0x40, // USB_MAX_PACKET0, // max размер пакета для нулевой конечной точки 0x83, 0x04, // 2 байта - VID 0x40, 0x57,// 2 байта - PID 0x00, 0x02,// 2 байта - версия (ревизия) устройства 0x01, // индекс строки с названием производителя 0x02, // индекс строки с названием устройства 0x03, // индекс строки с серийным номером устройства 0x01 // количество поддерживаемых конфигураций };
Подскажите пожалуйста, что делать. Я уже перепробовал все, что в голову пришло....
Четвертый раз говорю, пройдите по шагам все эти строки чудо кода и мониторьте регистр EP0R (с отключенным МК от USB). Проверьте флаг успешной отправки, которого я думаю нет и соответственно нет в ответ на него (от хоста к МК) пакета ZLP. Да, я разрешал прием и передачу поочередно, но возможно это неважно.
Serg1987 писал(а):
Да. Но вообще, если делать грамотно, то первый байт нужно также учитывать.
Правильно учитывать все поля запроса и обрабатывать неизвестный запрос тоже.
После 21 должно время появится, так как я буду на работе
Что у Вас за работа такая, на которой есть время сидеть на форумах?
Z_h_e писал(а):
Проверьте флаг успешной отправки, которого я думаю нет
Его и нет - прерывание по CTR не возникает. Только вот не ясно почему... Последнее, что удается отследить в отладке - это как USB_EP_TX становится в VALID, а потом в 0. При этом флаг ошибки тоже не срабатывает (тоже включал прерывание по ERR для диагностики). Буду ждать следующей недели, а пока попробую еще куда-нибудь ковырнуть .
Карма: 29
Рейтинг сообщений: 651
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2708 Откуда: г. Чайковский
Рейтинг сообщения:0 Медали: 1
Да ёлки-палки,isx . Пускай есть упрощенный 4х битный регистр EP (r1 r0 t1 t0), начальное состояние 0. Все биты типа тогл. Вы хотите установить прием и передачу в VALID, т.е. 0b1111. Что Вы делаете
Код:
EP|=0b1100; EP|=0b0011
Результат:
Код:
EP==0//начальное состояние EP==0b1100 EP==0b0011
Так понятно или написать как работает конструкция |= ??? Ах, да, я же уже писал и это. И не верю я, что в отладке этого не видно.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Это понятно, только вот после отработки установленного значения TX/RX они автоматически обнуляются. Вот скрин. После каждого шага значение регистра EP0 заносится в отдельную переменную. Как видим, все, по какой-то причине, отрабатывается правильно, но тугл так работать не должен .
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 22
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения