...Передавать надо ровно столько данных, сколько просит хост, по крайней мере не длиннее.
да-да, я не так выразился.
Хост в запросе говорит что максимальная длина пакета 0x40 байт, допустимо отправить не больше этого значения.
На любой косяк хост "обижается". Вы должны четко соблюдать протокол. Описание дескрипторов, их длина. Очередность передачи и т.д. Если хост требует что-то сделать, но не требуются данные. Вы должны помахать в ответ ZLP. Например пришла команда установить адрес. Вы отвечаете ZLP, как от безадресного устройства, затем дальше все должно работать по адресу. Отправили дескриптор хосту, если хост его съест , то он отправит zlp.
Ну да, это понятно что чуть что и хост пошлет кривое устройство куда подальше. Буду дальше искать косяк.
Есть соображения почему не попадаю в прерывание по отправке. Может быть дело в том, что хост отвечает NAK или STALL. Тогда флаг CTR_TX не выставляется и прерывание не срабатывает. Но вот как узнать чем ответил хост?
Z_h_e писал(а): Вы в буфер его правильно положили? Учли что 2 и 3 байты недоступны в 32 ом слове?
Да, там все верно. Смотрел в Memory watch - 2 и 3 байт 32-битного слова не используются. Сейчас под рукой нету функции, которая заполняет буферную память на основе исходного массива (в смысле не могу показать).
Думаю может дескриптор не корректный. Хотя, вряд ли хост сразу сообразит, что дескриптор не корректный/
Сообразит сообразит. Например, когда я ставил в дескрипторе устройства версию 2.0 и размер конфиг пакета отличный от 0x40, то хосту он не нравился. Но в любом случае если Вы отправили успешно данные, пускай даже с кривым дескриптором, флаг должен установится.
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Вот и я о том. Флаг выставляется только если попробовать передать 0 байт - COUNT_TX = 0. В случае COUNT_TX = 0x12 (18 байт) тишина.
Грешил на то что ноги неверно настроил, но в моем F103 вроде не нужно особым образом настраивать ноги. При включении USB ноги конфигурируются автоматически.
Наше одну хрень при использование отладчика. Если попытаться посмотреть память в отладчике по адресу, то показывает всякую фигню, но если записать память в переменную, то в отладчике начинают отображаться нормальные значения.
Может кому поможет .
Поправил код. Теперь проблема такая: не смотря на строчку USB->EP0R |= USB_EP_TX_NAK;, значение все равно сбрасывается в 0 (такая же фигня, если пытаться установить галочку в отладчике).
Также не приходит прерывание по CTR. Пол дня уже голову ломаю, вроде все выставил как положено, но работать никак не хочет Спойлер
#include "stm32f303xc.h"
#define USB_MAX_PACKET0 ((uint16_t) 0x02)
//uint32_t test1 = 0x00000000;
uint32_t BTableOffset = 0x00000000; // указываем значение BTABLE
void MyUSBinit(void)
{
uint32_t temp2;
/*Тактируем ядро*/
//RCC->CR |= RCC_CR_HSION; //Включить генератор HSI
//RCC->CR &= ~RCC_CR_HSEON;
RCC->CFGR &= ~RCC_CFGR_SW; //Очистка битов выбора источника тактового сигнала
RCC->CR |= RCC_CR_HSEON;
// FLASH->ACR |= FLASH_ACR_HLFCYA;
FLASH->ACR |= FLASH_ACR_LATENCY_1;
FLASH->ACR |= FLASH_ACR_PRFTBE;
while((FLASH->ACR & FLASH_ACR_PRFTBS)==0) {}
while((RCC->CR & RCC_CR_HSERDY)==0) {} //Ожидание готовности HSE
RCC->CFGR |= RCC_CFGR_PLLSRC; //Источником сигнала для PLL выбран HSE (внешний - кварц на 8 МГц)
RCC->CR &= ~RCC_CR_PLLON; //Отключить генератор PLL
RCC->CFGR &= ~RCC_CFGR_PLLMUL; //Очистить PLLMULL
RCC->CFGR |= RCC_CFGR_PLLMUL_0 | RCC_CFGR_PLLMUL_1 | RCC_CFGR_PLLMUL_2; //Коефициент умножения 9 (будет 72 МГЦ)
RCC->CFGR |= RCC_CFGR_PPRE1_2;
RCC->CR |= RCC_CR_PLLON; //Включить генератор PLL
while((RCC->CR & RCC_CR_PLLRDY)==0) {} //Ожидание готовности PLL
//Переключиться на тактирование от 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_PUPDR12_0;
GPIOA->AFR[1] |= 0x000EE000; // Номер и пины альтернативной фунции (у нас пины 11 и 12 для альтернативной функции номер 14 - USB)
/*Настраиваем Порт Е*/
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9 | GPIO_OSPEEDER_OSPEEDR10 |
GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12 | GPIO_OSPEEDER_OSPEEDR13 |
GPIO_OSPEEDER_OSPEEDR14 | GPIO_OSPEEDER_OSPEEDR15; // Скорость для указанных пинов 50 МГц
GPIOE->MODER |= GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0 | GPIO_MODER_MODER10_0 |
GPIO_MODER_MODER11_0 | GPIO_MODER_MODER12_0 | GPIO_MODER_MODER13_0 |
GPIO_MODER_MODER14_0 | GPIO_MODER_MODER15_0; // Указанные пины на выход
//GPIOE->OTYPER = 0x00000000;
//GPIOE->PUPDR = 0x00000000;
//GPIOE->AFR[1] |= 0x00000000;
/*----------------------------------------------------------------*/
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)
/*----------------------------------------------------------------*/
//здесь нужно включаить бит подтяжки резистора (но на плате STM32F3Discovery он припаян)
USB->CNTR = 0x3;
USB->CNTR &= ~USB_CNTR_PDWN;
for ( temp2=10000000; temp2 != 0; temp2--);
USB->CNTR &= ~USB_CNTR_FRES;
//USB->ISTR = 0;
USB->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM;
}
void USB_LP_CAN_RX0_IRQHandler(void)
{
//uint8_t tmp = 0;
if (USB->ISTR & USB_ISTR_CTR)
{
USB->ISTR &= ~USB_ISTR_CTR;
}
if (USB->ISTR & USB_ISTR_RESET)
{
USB->ISTR &= ~USB_ISTR_RESET; // сбрасываем флаг прерывания по Reset
USB->BTABLE = BTableOffset; // таблица начинается с 0x0000
*(__IO uint32_t*)(0x40006000) = 0x0040; // начальный адрес USB_ADDR0_TX (такой адрес позволяет в дальнейшем добавить все 8 возможных контрольных точек, каждая имеет размер 1 байт)
*(__IO uint32_t*)(0x40006004) = 0x0020; // размер исходящих данных - 32 байта USB_COUNT0TX
*(__IO uint32_t*)(0x40006008) = 0x0060; // начальный адрес USB_ADDR0_RX
*(__IO uint32_t*)(0x4000600C) = 0x8000; // 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*)(0x40006000);
USB->DADDR |= USB_DADDR_EF;
}
И еще вопрос, есть ли такие программы, которые позволяют мониторить данные с USB в таком состоянии (когда еще не произошла передача дескрипторов)? Может отладка в кейле сбивает работу USB?
isx писал(а):И еще вопрос, есть ли такие программы, которые позволяют мониторить данные с USB в таком состоянии (когда еще не произошла передача дескрипторов)? Может отладка в кейле сбивает работу USB?
Если я правильно понимаю, то для этого еще ставится промежуточная штуковина между хостом и девайсом, которая слушает шину.
В отладкеу у меня ничего не сбивалось, правда у меня Кокос. Я на точках останова выдергивал шнур из USB, чтобы не успел пройти резет.
isx писал(а):USB->ISTR &= ~USB_ISTR_CTR;
Bit 15CTR: Correct transfer
This bit is set by the hardware to indicate that an endpoint has successfully completed a
transaction; using DIR and EP_ID bits softwarecan determine which endpoint requested the
interrupt. This bit is read-only.
USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов
Подумайте хорошенько что Вы тут сделали, выполните по шагам эти команды.
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Это я знаю, просто нужно было добавить какую-нибудь строку, чтоб была возможность установить точку останова. Однако прерывание там ни разу не произошло .
Z_h_e писал(а):USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов
Убрал USB->EP0R |= USB_EP_TX_NAK;. Ситуация не изменилась ( .
Насколько я понял - при резете сбрасываются регистры USB и контрольных точек. Поэтому их и настраивают заново при резете. Отладчик обычно не очень шустро работает. И Хост успевает послать резет, запросить дескриптор, подождать ответа, опять послать резет, опять дескриптор и т.д. Как результат установлнные значения успевают сброситься. И наверное при отладке это и происходит.
Странно, я по крайней мере получал прерывание по резету, в нем настраивался и выходил из прерывания. Далее получал прерывание по приему, точнее запрос типа SETUP и смотрю второй принятый байт - там 0x06
Если мне не изменяет память, то хост до трех раз пытается определить что к нему подключено, соответственно резетов должно быть три в Вашем случае и потом винда должна сказать что не удалось понять что к ней подключилось. Поставте счетчик чтоли для резетов. Если этих резетов нет на самом деле, то тут что то не так. Возможно у Вас ложный резет в момент подключения разъема. У меня так бывало. Винда то ругается на неопознанное устройство?
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Блин... Простите мне мою рукожопость .
Забыл, что отключил пару дней назад пользовательский разъем от компа (портов не хватало).
Резет по прежнему один, однако теперь в памяти вырисовывается запрос дескриптора устройства (если не ошибаюсь). Как тогда мне отследить момент, чтобы вовремя отреагировать на запрос?
Во первых правильно настройте EP0R. Для TX Nack должен быть, тогда хост вежливо подождет какое-то время. И вообще вопрос непонятен. По прерыванию, как еще то?
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Z_h_e писал(а): Для TX Nack должен быть, тогда хост вежливо подождет какое-то время.
USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов
А на какую ошибку тогда вы здесь указали?