118 lines
2.9 KiB
C
118 lines
2.9 KiB
C
#include "FreeRTOS.h"
|
||
#include "stm32f1xx.h"
|
||
#include "task.h"
|
||
#include "tusb.h"
|
||
|
||
void SystemClock_Config(void) {
|
||
RCC->CR |= RCC_CR_HSEON;
|
||
while (!(RCC->CR & RCC_CR_HSERDY));
|
||
|
||
FLASH->ACR |= FLASH_ACR_LATENCY_2;
|
||
|
||
// ЯВНО обнуляем бит USBPRE (div 1.5 для получения 48MHz USB)
|
||
RCC->CFGR &= ~RCC_CFGR_USBPRE; // <-- ДОБАВЛЕНО!
|
||
RCC->CFGR |= (RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9);
|
||
|
||
RCC->CR |= RCC_CR_PLLON;
|
||
while (!(RCC->CR & RCC_CR_PLLRDY));
|
||
|
||
RCC->CFGR |= RCC_CFGR_SW_PLL;
|
||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
|
||
|
||
SystemCoreClock = 72000000;
|
||
}
|
||
|
||
// Задача USB (ТОЛЬКО tud_task, ничего больше!)
|
||
void usb_device_task(void *param) {
|
||
(void)param;
|
||
while (1) {
|
||
tud_task();
|
||
// Без задержки! tud_task() должен вызываться как можно чаще
|
||
}
|
||
}
|
||
|
||
// Задача CDC
|
||
void cdc_task(void *param) {
|
||
(void)param;
|
||
while (1) {
|
||
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(10)); // 10мс достаточно
|
||
}
|
||
}
|
||
|
||
// Задача LED (отдельно!)
|
||
void led_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));
|
||
}
|
||
}
|
||
|
||
void force_usb_reset(void) {
|
||
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
|
||
GPIOA->CRH &= ~GPIO_CRH_CNF12;
|
||
GPIOA->CRH |= GPIO_CRH_MODE12_1;
|
||
GPIOA->BSRR = GPIO_BSRR_BR12;
|
||
for (volatile int i = 0; i < 500000; i++) __NOP();
|
||
GPIOA->CRH &= ~GPIO_CRH_MODE12;
|
||
GPIOA->CRH |= GPIO_CRH_CNF12_0;
|
||
}
|
||
|
||
int main(void) {
|
||
SystemClock_Config();
|
||
|
||
// Настройка LED
|
||
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
|
||
GPIOC->CRH &= ~GPIO_CRH_CNF13;
|
||
GPIOC->CRH |= GPIO_CRH_MODE13_1;
|
||
|
||
force_usb_reset();
|
||
|
||
// Включаем USB
|
||
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();
|
||
|
||
// УВЕЛИЧИЛИ стек до 256!
|
||
xTaskCreate(
|
||
usb_device_task,
|
||
"usbd",
|
||
256,
|
||
NULL,
|
||
configMAX_PRIORITIES - 1,
|
||
NULL);
|
||
xTaskCreate(cdc_task, "cdc", 256, NULL, configMAX_PRIORITIES - 2, NULL);
|
||
xTaskCreate(led_task, "led", 128, NULL, 1, 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);
|
||
}
|