STM32 и USB (практика)

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Открыл глаза
Аватара пользователя
Сообщения: 45
Зарегистрирован: Пн июн 14, 2010 17:09:55
Откуда: Москва

Сообщение Radist_M »

...Передавать надо ровно столько данных, сколько просит хост, по крайней мере не длиннее.
да-да, я не так выразился.
Хост в запросе говорит что максимальная длина пакета 0x40 байт, допустимо отправить не больше этого значения.
На любой косяк хост "обижается". Вы должны четко соблюдать протокол. Описание дескрипторов, их длина. Очередность передачи и т.д. Если хост требует что-то сделать, но не требуются данные. Вы должны помахать в ответ ZLP. Например пришла команда установить адрес. Вы отвечаете ZLP, как от безадресного устройства, затем дальше все должно работать по адресу. Отправили дескриптор хосту, если хост его съест , то он отправит zlp.
Ну да, это понятно что чуть что и хост пошлет кривое устройство куда подальше. Буду дальше искать косяк.

На MSDN неплохо разрисовано.
MSDN пример обмена
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 45
Зарегистрирован: Пн июн 14, 2010 17:09:55
Откуда: Москва

Сообщение Radist_M »

Есть соображения почему не попадаю в прерывание по отправке. Может быть дело в том, что хост отвечает NAK или STALL. Тогда флаг CTR_TX не выставляется и прерывание не срабатывает. Но вот как узнать чем ответил хост?
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Radist_M писал(а):В Буфере передатчика лежит заготовленный дескриптор (заранее положил туда), тогда я выставляю
Вы в буфер его правильно положили? Учли что 2 и 3 байты недоступны в 32 ом слове?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Открыл глаза
Аватара пользователя
Сообщения: 45
Зарегистрирован: Пн июн 14, 2010 17:09:55
Откуда: Москва

Сообщение Radist_M »

Z_h_e писал(а): Вы в буфер его правильно положили? Учли что 2 и 3 байты недоступны в 32 ом слове?
Да, там все верно. Смотрел в Memory watch - 2 и 3 байт 32-битного слова не используются. Сейчас под рукой нету функции, которая заполняет буферную память на основе исходного массива (в смысле не могу показать).
Думаю может дескриптор не корректный. Хотя, вряд ли хост сразу сообразит, что дескриптор не корректный/
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Сообразит сообразит. Например, когда я ставил в дескрипторе устройства версию 2.0 и размер конфиг пакета отличный от 0x40, то хосту он не нравился. Но в любом случае если Вы отправили успешно данные, пускай даже с кривым дескриптором, флаг должен установится.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 45
Зарегистрирован: Пн июн 14, 2010 17:09:55
Откуда: Москва

Сообщение Radist_M »

Вот и я о том. Флаг выставляется только если попробовать передать 0 байт - COUNT_TX = 0. В случае COUNT_TX = 0x12 (18 байт) тишина.
Грешил на то что ноги неверно настроил, но в моем F103 вроде не нужно особым образом настраивать ноги. При включении USB ноги конфигурируются автоматически.
Реклама
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Наше одну хрень при использование отладчика. Если попытаться посмотреть память в отладчике по адресу, то показывает всякую фигню, но если записать память в переменную, то в отладчике начинают отображаться нормальные значения.
Может кому поможет :) .
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Поправил код. Теперь проблема такая: не смотря на строчку USB->EP0R |= USB_EP_TX_NAK;, значение все равно сбрасывается в 0 (такая же фигня, если пытаться установить галочку в отладчике).
Также не приходит прерывание по CTR. Пол дня уже голову ломаю, вроде все выставил как положено, но работать никак не хочет :dont_know:
Спойлер

Код: Выделить всё

#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?
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

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; // К приему готов
Подумайте хорошенько что Вы тут сделали, выполните по шагам эти команды.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Z_h_e писал(а): This bit is read-only.
Это я знаю, просто нужно было добавить какую-нибудь строку, чтоб была возможность установить точку останова. Однако прерывание там ни разу не произошло :( .
Z_h_e писал(а):USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов
Убрал USB->EP0R |= USB_EP_TX_NAK;. Ситуация не изменилась ( .
Открыл глаза
Аватара пользователя
Сообщения: 45
Зарегистрирован: Пн июн 14, 2010 17:09:55
Откуда: Москва

Сообщение Radist_M »

Насколько я понял - при резете сбрасываются регистры USB и контрольных точек. Поэтому их и настраивают заново при резете. Отладчик обычно не очень шустро работает. И Хост успевает послать резет, запросить дескриптор, подождать ответа, опять послать резет, опять дескриптор и т.д. Как результат установлнные значения успевают сброситься. И наверное при отладке это и происходит.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Ну может состояние Tx NACK нужно. Хотя вроде как по логике он же для передачи :dont_know: . Что там у Вас в EP0R ?
Radist_M писал(а):И наверное при отладке это и происходит.
Между резетами очень приличный интервал времени. Ставите точку останова где-то и в момент останова легко успеваешь выдернуть разъем.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Изображение
Z_h_e писал(а):Между резетами очень приличный интервал времени. Ставите точку останова где-то и в момент останова легко успеваешь выдернуть разъем.
У меня только один резет - в начале. Дальше прерывание вообще молчит...
Открыл глаза
Аватара пользователя
Сообщения: 45
Зарегистрирован: Пн июн 14, 2010 17:09:55
Откуда: Москва

Сообщение Radist_M »

Странно, я по крайней мере получал прерывание по резету, в нем настраивался и выходил из прерывания. Далее получал прерывание по приему, точнее запрос типа SETUP и смотрю второй принятый байт - там 0x06
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Если мне не изменяет память, то хост до трех раз пытается определить что к нему подключено, соответственно резетов должно быть три в Вашем случае и потом винда должна сказать что не удалось понять что к ней подключилось. Поставте счетчик чтоли для резетов. Если этих резетов нет на самом деле, то тут что то не так. Возможно у Вас ложный резет в момент подключения разъема. У меня так бывало. Винда то ругается на неопознанное устройство?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Блин... Простите мне мою рукожопость :) .
Забыл, что отключил пару дней назад пользовательский разъем от компа (портов не хватало).

Резет по прежнему один, однако теперь в памяти вырисовывается запрос дескриптора устройства (если не ошибаюсь). Как тогда мне отследить момент, чтобы вовремя отреагировать на запрос?
Изображение
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Во первых правильно настройте EP0R. Для TX Nack должен быть, тогда хост вежливо подождет какое-то время. И вообще вопрос непонятен. По прерыванию, как еще то?
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Z_h_e писал(а): Для TX Nack должен быть, тогда хост вежливо подождет какое-то время.
USB->EP0R |= USB_EP_TX_NAK; // Готовы к передаче, но данных для передачи нет
USB->EP0R |= USB_EP_RX_VALID; // К приему готов

А на какую ошибку тогда вы здесь указали? :dont_know:
Z_h_e писал(а): По прерыванию, как еще то?
В том то и дело, что нет никакого прерывания... :dont_know:
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

isx писал(а):А на какую ошибку тогда вы здесь указали?
Мы с Вами уже обсуждали биты типа togle регистров EPnR. Ссылку давать не буду, не смешно уже. Я же написал Вам, выполните эти операции по шагам.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
isx
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2316
Зарегистрирован: Вс июн 26, 2011 20:03:21

Сообщение isx »

Так если по умолчанию значения нули, то при попытке записи значений произойдет тот же тугл... :dont_know:
Ответить

Вернуться в «ARM»