Приветствую форумчан! Наконец-то появилась возможность продолжить свои практические занятия . Начал разбираться с USB. Сделал все как в этой статье: http://microtechnics.ru/stm32-peredacha-dannyx-po-usb/ - работает. Только появились вопросы... Есть две функции: /*******************************************************************************/
да без проблем. Наверняка это callback функции к каким либо событиям. Просто по обеим событиям делается одно и то же. Ну а что это за события - добро пожаловать в документацию на USB и библиотеку, даташит, код библиотеки и т.д.
Эти два события обычно используются для bulk endpoint. Вероятно, если после начала фрейма на первый IN запрос контроллер ответит NAK, то хост больше не будет слать IN запросы какое-то время. Так что в Handle_USBAsynchXfer заряжается буфер для первого IN запроса. Кстати, в STM примерах для bulk эндпоинта забыли сделать отсылку пакета нулевой длинны если данных больше нет, а последний пакет был равен размеру буфера. Если не отсылать такой пакет, со стороны хоста это будет выглядеть как подвисание при чтении.
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
if(bDeviceState == CONFIGURED) { if (FrameCount++ == VCOMPORT_IN_FRAME_INTERVAL) { /* Reset the frame counter */ FrameCount = 0;
/* Check the data to be sent through IN pipe */ Handle_USBAsynchXfer(); } } }
Я сейчас читаю книги и статьи по USB (учусь), но такое количество информации просто разрывает мозг, поэтому могу написать глупость... Как я понимаю, то пакет SOF отправляется хостом для того чтоб спросить устройство, хочет ли оно нам что-то передать. Приняв такой пакет устройство либо отвечает пустым пакетом, либо осуществляет передачу данных через EndPoint-ы. Но тогда появляется вопрос - какого фига данные, впихнутые через функцию SOF вообще отправляются?
BorisSPB писал(а):
Так что в Handle_USBAsynchXfer заряжается буфер для первого IN запроса.
Если я Вас правильно понял, то только первая партия данных летит через Handle_USBAsynchXfer(), а остальные через EP1_IN_Callback? Тогда такой вопрос: размер буфера в обоих случаях будет одинаковым (таким каким мы его объявили в дескрипторе)? И еще вопрос: получается для отправки третьего пакета данных (если мы передаем одну партию данных) нужно только повторно вызвать EP1_IN_Callback (в данном случае) и скормить ему нужные данные?
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:2 Медали: 1
isx писал(а):
просто разрывает мозг
Согласен, я тоже не нашел легко написанной книги по этому вопросу.
isx писал(а):
какого фига данные, впихнутые через функцию SOF вообще отправляются?
Цитата:
Как я понимаю, то пакет SOF отправляется хостом для того чтоб спросить устройство, хочет ли оно нам что-то передать.
SOF - это начало кадра, и не имеет прямого отношения к устройству. В STM32 много флагов событий от USB и соответственно прерываний. Я тоже потихоньку мучаю USB (т.е. он меня), только я не использую готовых библиотек. Вроде что-то более-менее получается, конечно с кучей подвисших вопросов в воздухе. Так вот, я использую всего два события, это SE0 (событие подключения устройства к компу) и событие успешного трансфера (в любую сторону). В последнем можно определить направравление передачи и для какой точки. Смысл такой. -Сначала инициализируется модуль USB. просто вкючаете, подкючаете генератор и т.д. - По событию SE0 (воткнули девайс в комп) инициализируете нужные регистры, это событие кстати сбросит их в начальное состояние само. -Затем устанавливаете в регистре EP0 VALID RX, т.е. МК готов принять данные для нулевой точки. -Возникает прерывание об успешной транзакции. Расшифровываете и понимаете что что то получили. - читаете что лежит в буфере приема, там будет запрос дескриптора устройства. -ложите в буфер отправки дескриптор устройства и выставляете в регистре EP0 VALID TX и контроллер сам все отправит. -после события об успешной отправки опять переводите МК в состояние в готов принять.
После успешной транзакции состояние VALID само сменится на NACK . Т.е. неготовность принятия или отправки данных. Вы же уже поняли что МК сам ничего не отправит и не примет, только по инициативе хоста. И МК может долго отвечать NACK и хост на это никак не обижается. Я к тому что мне непонятно зачем отлавливать SOF. Ну пропустили начало кадра, ответит МК NACKом сам, и отвечать будет всегда пока не подготовите данные. Хотя мне непонятно может потом, у что мне в USB много чего еще непонятно.
Если интересно, я в ехселе сделал частичный протокол обменамоего МК по USB/
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Последний раз редактировалось Z_h_e Чт май 05, 2016 14:04:20, всего редактировалось 1 раз.
Если отправлять нечего, то аппаратный буфер будет пустой и контроллер при запросе на этот эндпоинт ответит NAKом. Если размер данных в аппаратном буфере меньше максимального, то хост считает что пачка закончилась и приостанавливает IN запросы. EP1_IN_Callback вызывается в прерывании USB, если есть данные, заряжаем буфер, если нет - посылаем пакет нулевой длинны и далее ждем до следующего SOF.
Карма: 1
Рейтинг сообщений: 7
Зарегистрирован: Чт май 14, 2015 15:11:39 Сообщений: 424 Откуда: Саратов
Рейтинг сообщения:0
Тоже начал разбираться с USB, правда на STMF3. Хочу отправить данные с датчика (1 байт) данных, но получается вот такое: Спойлер Отправляют так: Спойлер
Код:
uint8_t data = '\n'; USB_SIL_Write(EP1_IN, &data, 1); SetEPTxValid(ENDP1); USBprintNumber((uint32_t)GyroRawData[0]);
Спойлер
Код:
void USBprintNumber(uint32_t x) { uint8_t* value; char i = 0;
do { value[i++] = (char) (x%10) + '0'; x /= 10; } while(x);
Согласен, я тоже не нашел легко написанной книги по этому вопросу.
Тут не только книги, а еще куча всяких статей. Пока читаешь - вроде все понятно, как только переходишь к делу - ступор полный .
Z_h_e писал(а):
SOF - это начало кадра, и не имеет прямого отношения к устройству.
Я просто не могу понять, почему в этой библиотеке SOF связан с передачей данных...
Z_h_e писал(а):
Я тоже потихоньку мучаю USB (т.е. он меня), только я не использую готовых библиотек.
Я тоже не сторонник библиотек (до сих пор даже SPL-ом не пользовался), но боюсь не потяну сразу USB на уровне регистров (хотя подумываю об этом)...
Z_h_e писал(а):
Если интересно, я в ехселе сделал частичный протокол обменамоего МК по USB/
У Вас уже реализован полный обмен данными МК с ПК в обе стороны или пока с дескрипторами разбираетесь? В любом случае, буду признателен если скинете кусок кода с инициализацией и работой USB. Нужно еще подумать что проще, разбирать код чужой библиотеки, или сразу перейти на регистры...
BorisSPB писал(а):
EP1_IN_Callback вызывается в прерывании USB, если есть данные, заряжаем буфер,
Пока понять еще не могу, как обновляются данные буфера между отправками? Вот зарядили мы первую партию в EP1, затем отправили их, после этого ждем срабатывание SOF, обновляем данные и отправляем - и так по кругу. Я правильно понимаю?
FireProoF писал(а):
правда на STMF3
Я кстати тоже) . В статье (адрес в первом посте) производится отправка на МК 2 байт, с последующим приемом МК 2 байт. Статья из трех частей. Я по ней деле проект - он заработал, но пока не совсем ясно каким образом . Посмотрите, может чем поможет....
Карма: 1
Рейтинг сообщений: 7
Зарегистрирован: Чт май 14, 2015 15:11:39 Сообщений: 424 Откуда: Саратов
Рейтинг сообщения:0
Я тоже с неё начал) С отправкой чисел разобрался. Теперь встал вопрос частоты отправки данных. У меня отправка происходит по переполнению таймера. Эксперементальным путём установил, что при частоте переполнения свыше 150 Гц stm32 перестаёт определяться компьютером. На 100 Гц всё норм. Добавил задержку перед включением таймера. Вроде подключилось, открыл терминал, а он повис. Подождал чуток, отсоединил стм. На терминале показались данные. Видимо комп не справляется с потоком? Не могли бы Вы проделать такой же эксперимент, дабы убедиться, что при частой отправке данных, линия зависает?
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:1 Медали: 1
isx писал(а):
У Вас уже реализован полный обмен данными МК с ПК в обе стороны или пока с дескрипторами разбираетесь?
Вроде как допилить осталось чуток. И в божеский вид привести. Но это вроде. Я сначала через первую точку хотел обмен сделать, даже принял данные через winapi функцией READFILE. Но если данных нет, то там зависнешь. HidD_GetInputReport из библиотеки HID.dll отказалась читать, сейчас уже есть предположение почему. Решил через Feature репорты обмен делать. Вроде получилось и пока ничего больше не делал, надо пнуть себя и сегодня еще поработать. Вобщем то о своих мытарствах я тут писал, надо будет туда и дописать чем дело кончилось, приведу код в боле менее вид, может и скину. А сама инициализация вот она, она простая. Только радиокот все табуляции кода выкинул, почти все сплошняком. Спойлер
Данные хосту отправляются автоматически по IN запросу если в аппаратном буфере что-то есть, запись в аппаратный буфер происходит с помощью
Код:
USB_SIL_Write(EP1_IN, &tempData, 1);
Обменом управляет хост, насильно хосту данные не скормить, только по IN запросу. HID устройство удобно тем что не нужен специальный драйвер, но скорость ограничена 64 кб/сек. Если в дескрипторе HID для типа устройства указать нули, обмен можно производить пакетами с помощью ReadFile/WriteFile, за разбор пакета при этом отвечает приложение.
Очередной раз убедился в том, что ковырять чужие библиотеки - для меня проблема... Даже не смог найти выход к регистрам USB через SPL Решил идти с нуля, чтоб уж точно знать, как оно там работает. По пути буду снабжать код подробными комментариями (может кому в будущем пригодится) ибо для себя я такого примера так и не нашел. P.S. За пол года перерыва в практике общения с паяльником и кодом многое подзабылось, поэтому не пинайте сильно.
Итак, начинаем с самого начала:
Спойлер
Код:
int main(void) { /*----------*/
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; //включаем тактирование SYSCFG (хз что это, но так надо :) ) RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOEEN; //включаем тактирование портов А и Е
/*----------*/
GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR11 | GPIO_OSPEEDR_OSPEEDR12; // Скорость 50 МГц GPIOA->MODER |= GPIO_MODER_MODER11_0 | GPIO_MODER_MODER12_0; // Режим альтернативной функции //GPIOA->OTYPER = 0x00000000; //GPIOA->PUPDR = GPIO_PUPDR_PUPDR11 | GPIO_PUPDR_PUPDR12; GPIOA->AFR[1] |= 0x000EE000; // Номер и пины альтернативной фунции (у нас пина 11 и 12 для альтернативной функции номер 14 - USB)
NVIC_EnableIRQ(USBWakeUp_IRQn); // Разрешаем прерывание USBWakeUp //NVIC_SetPriority(USBWakeUp_IRQn, 3); // Приоритет прерывания (не могу определится для USB)
//Переключиться на тактирование от PLL RCC->CFGR &= ~RCC_CFGR_SW; //Очистка битов выбора источника тактового сигнала RCC->CFGR |= RCC_CFGR_SW_PLL; //Выбрать источником тактового сигнала PLL while((RCC->CFGR&RCC_CFGR_SWS)!=0x08){} //Ожидание переключения на PLL
/*---------- ----------*/
}
Делал на основе вскрытия библиотеки USB-FS. Если с GPIO все понятно, то вот докопаться до сути EXTI так и не вышло. С SPL ранее не работал, поэтому так и не нашел на какие регистры воздействуют эти строки:
У себя в коде прописал как самому показалось верным. Итак, Set_System(); разложена, поехал ковырять Set_USBClock(); Прошу поглядеть на код, может где-то напортачил или поставил не соответствующий комментарий...
Расковырял Set_USBClock();. Добавилось всего 2 строчки. Выносить тактирование USB в отдельный блок не стал, поэтому просто добавил в общий код. Инициализацию переписал немного, заодно уточнил некоторые комментарии: Спойлер
//Переключиться на тактирование от PLL RCC->CFGR &= ~RCC_CFGR_SW; //Очистка битов выбора источника тактового сигнала RCC->CFGR |= RCC_CFGR_SW_PLL; //Выбрать источником тактового сигнала PLL while((RCC->CFGR&RCC_CFGR_SWS)!=0x08){} //Ожидание переключения на PLL
/*Тактируем периферию*/ RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOEEN; // Включаем тактирование портов А и Е RCC->CFGR |= RCC_CFGR_USBPRE; // Настраиваем частоту USB (= частота ядра / 1.5) RCC->APB2ENR |= RCC_APB1ENR_USBEN; // Включаем тактирование USB от шины APB1 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Включаем тактирование SYSCFG (хз что это, но так надо :) )
/*----------*/
/*Настраиваем Порт А*/ GPIOA->OSPEEDR |= GPIO_OSPEEDR_OSPEEDR11 | GPIO_OSPEEDR_OSPEEDR12; // Скорость 50 МГц GPIOA->MODER |= GPIO_MODER_MODER11_0 | GPIO_MODER_MODER12_0; // Режим альтернативной функции (для USB) //GPIOA->OTYPER = 0x00000000; //GPIOA->PUPDR = GPIO_PUPDR_PUPDR11 | GPIO_PUPDR_PUPDR12; GPIOA->AFR[1] |= 0x000EE000; // Номер и пины альтернативной фунции (у нас пины 11 и 12 для альтернативной функции номер 14 - USB)
однако, сразу поперли вопросы... Помимо USB_LP_CAN1_RX0_IRQn, есть USB_HP_CAN1_TX_IRQn. Почему используется именно она, в чем их разница и вообще, за что они отвечают? И еще, вопрос по приоритетам. Как их выставлять? Запустил рабочий код с USB (про который я говорил в первом посте), там приоритет USB_LP_CAN1_RX0_IRQn стоит 128, а USBWakeUp_IRQn приоритет 1. Можно конечно и просто подставить эти значения, но хочется таки разобраться.... Пока пойду ковырять самую веселую часть инициализации - USB_Init(); .
В общем наковырял всю инициализацию и проверил (проект перенес на Keil 5, так как там оказался полезный файлик - stm32f303xc.h, который заменяет stm32f30x.h и имеет дополнительно прописанные регистры USB). Вот что получилось: Спойлер
//Переключиться на тактирование от PLL // RCC->CFGR |= RCC_CFGR_SW_1 ; //Выбрать источником тактового сигнала PLL
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} //Ожидание переключения на PLL
/*Тактируем периферию*/ RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOEEN; // Включаем тактирование портов А и Е RCC->CFGR &= ~RCC_CFGR_USBPRE; // Настраиваем частоту USB (= частота ядра / 1.5) RCC->APB1ENR |= RCC_APB1ENR_USBEN; // Включаем тактирование USB от шины APB1 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Включаем тактирование SYSCFG (хз что это, но так надо :) )
/*----------*/
/*Настраиваем Порт А*/ GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12; // Скорость 50 МГц GPIOA->MODER |= GPIO_MODER_MODER11_1 | GPIO_MODER_MODER12_1; // Режим альтернативной функции (для USB) //GPIOA->OTYPER = 0x00000000; //GPIOA->PUPDR = GPIO_PUPDR_PUPDR11 | GPIO_PUPDR_PUPDR12; GPIOA->AFR[1] |= 0x000EE000; // Номер и пины альтернативной фунции (у нас пины 11 и 12 для альтернативной функции номер 14 - USB)
EXTI->RTSR |= EXTI_RTSR_TR18; // внешнее прерывание №18 (USBWakeUp) по возрастающему фронту EXTI->IMR |= EXTI_IMR_MR18; // Включаем прерывание по пинам //EXTI->EMR |= EXTI_EMR_MR18; // Включаем прерывание по событию (USBWakeUp - по обнаружению устройства)
/*----------*/
NVIC_EnableIRQ(USB_LP_CAN_RX0_IRQn); NVIC_SetPriority(USB_LP_CAN_RX0_IRQn, 8); NVIC_EnableIRQ(USBWakeUp_IRQn); // Разрешаем глобально прерывание USBWakeUp //NVIC_SetPriority(USBWakeUp_IRQn, 3); // Приоритет прерывания (не могу определится для USB) }
В отладке все работает правильно. Теперь нужно переходить к самому USB.
Как я понял, раскуривая стандартные библиотеки, начинать нужно с подтяжки D+ к питанию через специальный регистр, но такого я в мануале на свой камень не нашел Дальше идут следующие действия:
Код:
// здесь должна быть подтяжка резистора USB->CNTR &= ~USB_CNTR_PDWN; //подаем питание USB->CNTR |= USB_CNTR_FRES; //На всякий случай устанавливаем флаг (хотя он итак должен стоять при включении) USB->CNTR = 0; // в результате FRES сбрасывается в ноль, происходит ресет и генерируется прерывание USB_LP_IRQHandler.
В итоге, единственный мост для нашего общения с USB - это прерывание USB_LP_IRQHandler, значит в нем и происходит дальнейшая работа. С помощью флага определяем - от чего произошло прерывание. Первое прерывание, как я понял, произойдет сразу же, по FRES. Затем, уже в прерывании:
Дальнейшее поведение библиотеки отследить не удалось. Скорее всего дальше происходит настройка нулевой контрольной точки, но в какой последовательности все это происходит в камне - не известно. Перечитываю кучи статей на сайтах, но описания пока не могу найти. Буду признателен, если ткнете на подобную статейку или дадите какую-нибудь подсказку...
//Регистры конечных точек 0 USB_REGISTR->EP0R=0x0| //номер точки bit13|bit12| //STAT_RX - VALID // bit8 |//какой то статус аут bit5|//bit4| //STAT_TX - NAK /*bit10|*/ bit9 ; /*00 BULK //10-9 тип точки. в данном случае Контрол 01 CONTROL 10 ISO 11 INTERRUPT*/
//Регистры конечных точек 1
USB_REGISTR->EP1R=0x1| //номер точки1 bit13|//bit12| //STAT_RX - NAK bit5 |// bit4| //STAT_TX - NAK (10) Valid (11) bit10|bit9 ; /*00 BULK //10-9 тип точки. в данном случае Контрол 01 CONTROL 10 ISO 11 INTERRUPT*/ /* //Регистры конечных точек 2 USB_REGISTR->EP2R=0x2| //номер точки2 bit13|//bit12| //STAT_RX - NAK bit5|//bit4| //STAT_TX - NAK bit10|bit9 ; /*00 BULK //10-9 тип точки. в данном случае Контрол 01 CONTROL 10 ISO 11 INTERRUPT */ USB_REGISTR->DADDR=bit7;//EF:Enable function, Включение ЮСБ с нулевым адресом
FlagAddress=0; //устройство не пришла команда установки адреса // FlagZLP=0;
}
Цитата:
USB->CNTR |= USB_CNTR_FRES; //На всякий случай устанавливаем флаг (хотя он итак должен стоять при включении)
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:0 Медали: 1
isx писал(а):
Вот пока главный вопрос - откуда берутся значения этих адресов?
Я их сам определил, т.е. сделал такими какие мне нужны. Есть область памяти 0x4000 6000- 0x4000 63FF. Именно с ней работает USB. Есть хитрый момент, 2 и 3ый байты слова в этой области недоступны (т.е. как 16битнай память). Модуль USB работает как 16 битной памятью с адреса 0, ядро как 32ух с адреса 0x4000 6000. Вы определяете область памяти для каждой конечной точки. Например Вы указали адрес
Код:
DiscrTable->ADR0RX=0x0100;
. Это значит что данные, которые придут от компа в МК для конечной точки 0, будут лежать по адресу 0x40006000+0x0100*2. Регистры с адресами (таблица дескрипторов) лежит в этой же памяти. Адрес таблицы указывается в регистре USB_REGISTR->BTABLE=0. Такая запись указывает что таблица находится по адресу 0x4000 6000+0*2.Спойлер
Это еще что, поглядите как устанавливаются биты регистров конечной точки USB_EPnR. Часть битов обычный доступ, часть только чтение, часть стирание 0, а часть типа togle (инвертирование при записи 1). Так что тут конструкция R|=(n<<m) просто так не сработает.
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Я их сам определил, т.е. сделал такими какие мне нужны. Есть область памяти 0x4000 6000- 0x4000 63FF. Именно с ней работает USB.
Пока я не могу понять, почему нельзя просто сделать эти адреса друг за другом . Например, указываем адрес для входящих данных EP0 (образно) 0х00, длину - 0х09. Затем указываем для исходящих данных адрес 0х10, длину 0х19 и.т.д. Почему, часто, в дескрипторе эти адреса разбросаны?
Z_h_e писал(а):
Адрес таблицы указывается в регистре USB_REGISTR->BTABLE=0. Такая запись указывает что таблица находится по адресу 0x4000 6000+0*2.
И зачем здесь вообще указывать что-то другое, если можно поставить ноль, и плясать от него? P.S. Уверен, что эти тупые вопросы от непонимания происходящего . Но это только пока не разберусь. Как разберусь, будут другие тупые вопросы .
Z_h_e писал(а):
Это еще что, поглядите как устанавливаются биты регистров конечной точки USB_EPnR.
Глядел. Пока все прозрачно вроде, но уверен, как только дойду до практики, грабли дадут о себе знать (да и лето как-никак, пора бы им уже поработать )
И вот еще понял, что нифига не понимаю что в этой строке происходит:
Что за "маски" тут настраиваются? Такой код автоматически разрешает прерывание? Если нет, то что будет если включить прерывание, а маску нет? (то что работать не будет понятно, но что происходит на аппаратном уровне..)
Карма: 29
Рейтинг сообщений: 645
Зарегистрирован: Сб май 14, 2011 21:16:04 Сообщений: 2694 Откуда: г. Чайковский
Рейтинг сообщения:1 Медали: 1
isx писал(а):
Пока я не могу понять, почему нельзя просто сделать эти адреса друг за другом
Очень даже можно. Только надо помнить, что там же таблица адресов.
isx писал(а):
И зачем здесь вообще указывать что-то другое, если можно поставить ноль, и плясать от него?
Ну можно ж ее в конце памяти разместить, а буфера тогда можно с самого начала или несколько таблиц иметь и переключать их.
isx писал(а):
Глядел. Пока все прозрачно вроде, но уверен,...
Предствате что у Вас биты STAT_TX[1:0] устновлены в 10 (NACK). А Вам надо установить в состояние 11 (VALID) . Тогда такая конструкция EP|= STAT_TX1 | STAT_TX0 не прокатит.
isx писал(а):
Что за "маски" тут настраиваются?
Дык маски ж прерываний. Но я включил только CTRM и RESETM. Мне хватило этого.
Цитата:
Если нет, то что будет если включить прерывание, а маску нет?
Прошел по USB пакет SOF. Тут же в регистре USB_ISTR устанавливается флаг SOF (он так и будет висеть пока не сбросите), но так как у меня маска SOFM не установлена, то прерывание не возникнет.
Прерывание для всех событий USB одно. Вам надо самому разбираться в нем из-за чего прерывание возникло.Спойлер
Код:
//обработчик прерывания низкого уровня ЮСБ void USB_LP_CAN1_RX0_IRQHandler(void) {
// SUSPM:Suspend mode interrupt mask // if (USB_REGISTR->ISTR&bit11){ // USB_REGISTR->ISTR&=~bit11;// сброс флага события // USB_REGISTR->CNTR|=bit1; //установим PWDN. Тем самым вsключим ЮСБ // return; //выходим из обработчика прерываний // }
//прерывание изза резета SE0 if (USB_REGISTR->ISTR & bit10){ USB_REGISTR->ISTR &=~bit10;// сброс флага события резет USB_Reset(); //делаем то что нужно после резета return; //выходим из обработчика прерываний } //CTRM:Correct transfer interrupt mask //Конечно точка что то удачно сделала. //информация об это в битах DIR и EP_ID[3:0] if (USB_REGISTR->ISTR & bit15){ //USB_REGISTR->ISTR&=~bit15;// сброс флага события этот флаг только для чтения Correct_Transfer(); return; //выходим из обработчика прерываний } //Ошбика если контроллер вовремя не ответил или ... // if (USB_REGISTR->ISTR & bit14){ // USB_REGISTR->ISTR&=~bit14;// сброс флага события // return; //выходим из обработчика прерываний // }
////ERRM:Error interrupt mask //ошибка CRC и прочей хрени. вобщем то можно на нее не реагировать. Нужно для отладки //if (USB_REGISTR->ISTR&bit13){ // USB_REGISTR->ISTR&=~bit13;// сброс флага события // return; //выходим из обработчика прерываний // } //Wakeup interrupt mask // if (pUSB_REGISTR->USB_ISTR&bit12){ // pUSB_REGISTR->USB_ISTR&=~bit12;// сброс флага события // return; //выходим из обработчика прерываний // }
//SOFM:Start of frame interrupt mask //if (pUSB_REGISTR->USB_ISTR&bit9){ // pUSB_REGISTR->USB_ISTR&=~bit9;// сброс флага события // return; //выходим из обработчика прерываний // }
//ESOFM:Expected start of frame interrupt mask // if (pUSB_REGISTR->USB_ISTR&bit8){ // pUSB_REGISTR->USB_ISTR&=~bit8;// сброс флага события // return; //выходим из обработчика прерываний // } }
_________________ Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения