#include "FreeRTOS.h" #include "stm32f1xx.h" #include "task.h" #include "tusb.h" // Глобальная переменная для CMSIS /* uint32_t SystemCoreClock = 72000000; */ // --- System Clock Config (72MHz from 8MHz HSE) --- void SystemClock_Config(void) { // Включаем HSE RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)); // Настраиваем Flash latency (2 wait states) FLASH->ACR |= FLASH_ACR_LATENCY_2; // PLL: HSE * 9 = 72 MHz RCC->CFGR |= (RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9); // Включаем PLL RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)); // Переключаем System Clock на PLL RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); SystemCoreClock = 72000000; } // --- Задачи FreeRTOS --- void usb_device_task(void *param) { (void)param; while (1) { tud_task(); } } void cdc_task(void *param) { (void)param; while (1) { GPIOC->BSRR = GPIO_BSRR_BR13; // LED ON vTaskDelay(pdMS_TO_TICKS(500)); GPIOC->BSRR = GPIO_BSRR_BS13; // LED OFF vTaskDelay(pdMS_TO_TICKS(500)); if (tud_cdc_connected()) { if (tud_cdc_available()) { uint8_t buf[64]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); tud_cdc_write(buf, count); tud_cdc_write_flush(); } } vTaskDelay(pdMS_TO_TICKS(1)); } } // Программный сброс USB (Soft-Connect) void force_usb_reset(void) { // Включаем тактирование порта A RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Настраиваем PA12 (USB D+) как Output Push-Pull GPIOA->CRH &= ~GPIO_CRH_CNF12; GPIOA->CRH |= GPIO_CRH_MODE12_1; // Output 2MHz // Прижимаем к земле (Logic 0) на 10 мс GPIOA->BSRR = GPIO_BSRR_BR12; for (volatile int i = 0; i < 500000; i++) __NOP(); // ~10ms при 72MHz // Возвращаем в состояние Input Floating GPIOA->CRH &= ~GPIO_CRH_MODE12; GPIOA->CRH |= GPIO_CRH_CNF12_0; // Floating input } int main(void) { SystemClock_Config(); // Моргаем светодиодом RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // Включаем GPIOC GPIOC->CRH &= ~GPIO_CRH_CNF13; // PC13 (LED) GPIOC->CRH |= GPIO_CRH_MODE13_1; // Output 2MHz force_usb_reset(); // Включаем тактирование USB и GPIOA RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; RCC->APB1ENR |= RCC_APB1ENR_USBEN; // ВКЛЮЧАЕМ ПРЕРЫВАНИЯ USB (КРИТИЧНО!) NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); tusb_init(); xTaskCreate(usb_device_task, "usbd", 128, NULL, 3, NULL); xTaskCreate(cdc_task, "cdc", 128, NULL, 2, NULL); vTaskStartScheduler(); while (1); } // Обработчики прерываний void USB_HP_CAN1_TX_IRQHandler(void) { tud_int_handler(0); } void USB_LP_CAN1_RX0_IRQHandler(void) { tud_int_handler(0); } void USBWakeUp_IRQHandler(void) { tud_int_handler(0); }