Приветствую форумчан!
Вот уже 4-й месяц (с перерывами конечно

) бьюсь об USB, но он никак не хочет работать. Сейчас происходит следующее: После ресета и настройки EP0 получаю запрос от хоста GET_DESCRIPTOR, затем происходит прерывание по CTR_RX и я ухожу в ресет, а затем все повторяется еще три раза и ВУАЛЯ .... "Неопознанное устройство".
Делал в KEIL5, но сегодня портировал и в KEIL4 (думал в программе дело), но толку нет. Примет виртуального COM порта с microtechnic запускается и определяется нормально, но мне нужно без STM-овских библиотек завести (не люблю я их

).
Может кто-нибудь подсказать, что я делаю не так?
P.S. Все переменные со словом
test в названии служат исключительно для диагностики и не вносят изменений в процесс общения МК с хостом.
CODE
#include "stm32f30x.h"
//#define USB_MAX_PACKET0 ((uint8_t) 0x40)
//#define USB_EP0_BIT ((uint32_t *)(0x420B8000))
uint32_t iTemp = 0;
uint32_t test1 = 0x00000000;
uint32_t test2 = 0x00000000;
uint32_t test3 = 0x00000000;
uint32_t test4 = 0x00000000;
uint32_t test5 = 0x00000000;
uint32_t test6 = 0x00000000;
uint16_t testMASK = 0x0000;
uint32_t testflag = 0x00000000;
uint32_t BTableOffset = 0x00000000; // указываем значение BTABLE
uint8_t i = 0;
uint16_t TXBuff = 0;
uint16_t RXBuff[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t TestBuff[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
uint8_t TestBuffCountRX[20] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
uint8_t TestBuffCountTX[20] = {99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
uint8_t CountTestBuffCountRX = 0;
uint8_t CountTestBuffCountTX = 0;
uint8_t CountTestBuff = 0;
void SetRXTX (uint8_t EPNum, uint8_t EPStatus, uint8_t RXTX) //номер регистра EPnR, S - Disabled,Stall,NAK,Valid, f - TX отправить RX прием
{
/*
EPNum EPStatus RXTX
0 to 7 0 - Disable 0 - RX
1 - Stall 1 - TX
2 - NAK
3 - VALID
*/
uint16_t buff;
uint8_t stat;
buff=((uint16_t*)0x40005C00)[EPNum]; //0x40005C00 базовый адрес регистров юсб
if (RXTX == 1)////////////////////////////////RXTX = 1 = TX
{
stat = (buff>>4) & 3;
switch (stat)
{
case 0: //DISABLE
switch (EPStatus)
{
case 0:
break;
case 1:
buff^=0x0010; buff&=0x8FBF; break; //TX
case 2:
buff^=0x0020; buff&=0x8FBF; break; //TX
case 3:
buff^=0x0030; buff&=0x8FBF; break; //TX
}
break;
case 1: //STALL
switch (EPStatus)
{
case 0:
buff^=0x0010; buff&=0x8FBF; break; //TX
case 1:
break;
case 2:
buff^=0x0030; buff&=0x8FBF; break; //TX
case 3:
buff^=0x0020; buff&=0x8FBF; break; //TX
}
break;
case 2: //NAK
switch (EPStatus)
{
case 0:
buff^=0x0020; buff&=0x8FBF; break; //TX
case 1:
buff^=0x0030; buff&=0x8FBF; break; //TX
case 2:
break;
case 3:
buff^=0x0010; buff&=0x8FBF; break; //TX
}
break;
case 3: //VALID
switch (EPStatus)
{
case 0:
buff^=0x0030; buff&=0x8FBF; break; //TX
case 1:
buff^=0x0020; buff&=0x8FBF; break; //TX
case 2:
buff^=0x0010; buff&=0x8FBF; break; //TX
case 3:
break;
}
break;
default: break;
}
}
else //////////////////////////////////////// RXTX = 0 = RX
{
stat = (buff>>12) & 3;
switch (stat)
{
case 0: //DISABLE
switch (EPStatus)
{
case 0:
break;
case 1:
buff^=0x1000; buff&=0xBF8F; break; //RX
case 2:
buff^=0x2000; buff&=0xBF8F; break; //RX
case 3:
buff^=0x3000; buff&=0xBF8F; break; //RX
}
break;
case 1: //STALL
switch (EPStatus)
{
case 0:
buff^=0x1000; buff&=0xBF8F; break; //RX
case 1:
break;
case 2:
buff^=0x3000; buff&=0xBF8F; break; //RX
case 3:
buff^=0x2000; buff&=0xBF8F; break; //RX
}
break;
case 2: //NAK
switch (EPStatus)
{
case 0:
buff^=0x2000; buff&=0xBF8F; break; //RX
case 1:
buff^=0x3000; buff&=0xBF8F; break; //RX
case 2:
break;
case 3:
buff^=0x1000; buff&=0xBF8F; break; //RX
}
break;
case 3: //VALID
switch (EPStatus)
{
case 0:
buff^=0x3000; buff&=0xBF8F; break; //RX
case 1:
buff^=0x2000; buff&=0xBF8F; break; //RX
case 2:
buff^=0x1000; buff&=0xBF8F; break; //RX
case 3:
break;
}
break;
}
}
((uint16_t*)0x40005C00)[EPNum]=buff;
}
const uint8_t Virtual_Com_Port_DeviceDescriptor[] = // second
{
0x12, // длина дескриптора в байтах;
0x01, // тип дескриптора: 1-Device descriptor
0x00, // 2 байта - версия USB: 2.0
0x02, //
0x02, // класс устройства: 2-CDC class code
0x00, // подкласс: 0-CDC class sub code
0x00, // протокол: 0-CDC Device protocol
0x40, // максимальный размер пакета для "нулевой конечной точки"
0xEB, // 2 байта - код производителя VID
0x03, //
0x27, // 2 байта - код устройства PID
0x61, //
0x10, // 2 байта - версия (ревизия) устройства
0x01, //
0x01, // индекс строки с названием производителя
0x02, // индекс строки с названием устройства
0x03, // индекс строки с серийным номером устройства
0x01 // количество поддерживаемых конфигураций
};
void MyUSBinit(void)
{
/*------------------------------USB----------------------------------*/
//здесь нужно включать бит подтяжки резистора (но на моей плате STM32F3Discovery он припаян)
*(__IO uint16_t*)(0x40006100) = (uint16_t) (0x0000);
RCC->CFGR &= ~RCC_CFGR_USBPRE; // Настраиваем частоту USB (= частота ядра / 1.5)
RCC->APB1ENR |= RCC_APB1ENR_USBEN; // Включаем тактирование USB от шины APB1
USB_CNTR &= ~USB_CNTR_PDWN;
USB_CNTR |= USB_CNTR_FRES;
USB_CNTR &= ~USB_CNTR_FRES;
USB_ISTR = 0;
NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
USB_CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | 0; // | USB_CNTR_ERRM; //;
}
void USB_LP_CAN1_RX0_IRQHandler (void)
{
if (USB_ISTR & USB_ISTR_CTR) //
{
USB_ISTR &= ~USB_ISTR_CTR;
if ((USB_EP0R & USB_EP_CTR_TX) != 0) //
{
TestBuffCountTX[CountTestBuffCountTX] = *(__IO uint8_t*)(0x4000600C);
CountTestBuffCountTX++;
TestBuff[CountTestBuff] = 7;
CountTestBuff++;
test1 = USB_EP0R;
USB_EP0R &= ~USB_EP_CTR_TX; // сброс CTR_TX - бит 7
test2 = USB_EP0R;
SetRXTX(0, 3, 0); //to Valid RX
test5 = USB_EP0R;
test5 = USB_EP0R;
return;
}
/*
if ((USB->EP0R & USB_EP_SETUP) != 0) ///////////////////////// развить
{
TestBuff[CountTestBuff] = 5;
CountTestBuff++;
test4 = *(__IO uint32_t*)(0x40006101); ///////////////////////// 32
test4 = 0;
}
*/
if (USB_EP0R & USB_EP_CTR_RX)
{
TestBuffCountRX[CountTestBuffCountRX] = *(__IO uint8_t*)(0x40006105);
CountTestBuffCountRX++;
TestBuff[CountTestBuff] = 8;
CountTestBuff++;
test1 = USB_EP0R;
USB_EP0R &= ~USB_EP_CTR_RX; // сброс CTR_RX
test2 = USB_EP0R;
switch (*(__IO uint8_t*)(0x40006101))
{
case 0x06:
test6 = USB_EP0R;
for (i = 0; i < 18; i+=2) // i = 18
{
TXBuff = Virtual_Com_Port_DeviceDescriptor[i] + (Virtual_Com_Port_DeviceDescriptor[i+1] << 8);
*(__IO uint16_t*)(0x40006080 + i*2) = TXBuff;
}
i = 0;
*(__IO uint16_t*)(0x40006004) = (uint16_t) 18; // i = 0x0012
USB_EP0R |= USB_EP_CONTROL;
test3 = USB_EP0R;
SetRXTX(0, 3, 1); // to Valid TX
test5 = USB_EP0R;
test5 = USB_EP0R;
break;
default:
test4 = *(__IO uint16_t*)(0x40006101);
test4 = 0;
break;
}
return;
}
i = 0;
}
if (USB_ISTR & USB_ISTR_RESET)
{
TestBuff[CountTestBuff] = 9;
CountTestBuff++;
USB_ISTR &= ~USB_ISTR_RESET;
//USB_ISTR = 0;
USB_BTABLE = 0; // таблица начинается с 0x0000
*(__IO uint16_t*)(0x40006000) = (uint16_t) 0x0040; // начальный адрес USB_ADDR0_TX (такой адрес позволяет в
//дальнейшем добавить все 8 возможных контрольных точек, каждая имеет размер 1 байт)
*(__IO uint16_t*)(0x40006004) = (uint16_t) 0x0040; // размер исходящих данных - 64 байта USB_COUNT0TX
*(__IO uint16_t*)(0x40006008) = (uint16_t) 0x0080; // начальный адрес USB_ADDR0_RX
*(__IO uint16_t*)(0x4000600C) = (uint16_t) 0x8400; // 64 байта входящих данных USB_ USB_COUNT0RX_BL_SIZE
USB_EP0R |= USB_EP_CONTROL;
test3 = *(__IO uint16_t*)(0x40006100);
SetRXTX(0, 3, 0); // to Valid RX
SetRXTX(0, 2, 1); // to NAK TX
test4 = *(__IO uint16_t*)(0x40006100);
USB_DADDR |= USB_DADDR_EF;
return;
}
}
Настройка периферии и прочие мелочи (main)
CODE
#include <stm32f30x.h>
#include <MyUSBsetting.h>
void TIM1_BRK_TIM15_IRQHandler(void) //??????? ??????????? ?????????? ?? ??????? 6
{
TIM15->SR &= ~TIM_SR_UIF;
if ((GPIOE->ODR &= GPIO_ODR_8) == 0)
GPIOE->ODR |= GPIO_ODR_8;
else
GPIOE->ODR &= ~GPIO_ODR_8;
;}
int main()
{
/*Тактируем ядро*/
//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_PLLMULL; //Очистить PLLMULL
RCC->CFGR |= RCC_CFGR_PLLMULL_0 | RCC_CFGR_PLLMULL_1 | RCC_CFGR_PLLMULL_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->APB2ENR |= RCC_APB2ENR_TIM15EN;
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOEEN; // Включаем тактирование портов А и Е
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Включаем тактирование SYSCFG (хз что это, но так надо

)
/*------------------------------GPIO----------------------------------*/
/*Настраиваем Порт А*/
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11 | GPIO_OSPEEDER_OSPEEDR12; // Скорость 50 МГц
GPIOA->MODER |= GPIO_MODER_MODER11_1 | GPIO_MODER_MODER12_1; // Режим альтернативной функции (для USB)
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; // Указанные пины на выход
/*------------------------------EXTI----------------------------------*/
//EXTI->RTSR |= EXTI_RTSR_TR18; // внешнее прерывание №18 (USBWakeUp) по возрастающему фронту
//EXTI->IMR |= EXTI_IMR_MR18; // Включаем прерывание по пинам
//EXTI->EMR |= EXTI_EMR_MR18; // Включаем прерывание по событию (USBWakeUp - по обнаружению устройства)
/*------------------------------NVIC----------------------------------*/
NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 8);
//NVIC_EnableIRQ(USBWakeUp_IRQn); // Разрешаем глобально прерывание USBWakeUp
NVIC_EnableIRQ(TIM1_BRK_TIM15_IRQn);
NVIC_SetPriority(TIM1_BRK_TIM15_IRQn, 5);
/*-----------------------------TIM15---------------------------------*/
TIM15->PSC = 7200 - 1;
TIM15->ARR = 10000;
TIM15->DIER |= TIM_DIER_UIE;
TIM15->CR1 |= TIM_CR1_CEN;
MyUSBinit();
GPIOE->BSRR |= GPIO_BSRR_BS_8;
__enable_irq ();
while(1)
{
}
}
TIM15 срабатывает раз в секунду (мигание диода - 1 ГЦ), значит частота тактирования ядра правильная (72МГц).
Сообщение отредактировал IgorKossak - Aug 10 2016, 12:41
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!