From 8cee36b31a73b05920525d8f52577d2d25c39a8e Mon Sep 17 00:00:00 2001 From: Iwwww Date: Wed, 24 Dec 2025 22:12:19 +0300 Subject: [PATCH] =?UTF-8?q?feat(firmware):=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BC=D0=BE=D1=80=D0=B3=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B2=D0=B5=D1=82=D0=BE=D0=B4=D0=B8?= =?UTF-8?q?=D0=BE=D0=B4=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- firmware/App/Src/main.c | 69 +++++++++++++++++++++++-------------- firmware/Makefile | 2 +- firmware/stm32f103c8.ld | 2 ++ firmware/system_stm32f1xx.c | 1 + 4 files changed, 47 insertions(+), 27 deletions(-) create mode 120000 firmware/system_stm32f1xx.c diff --git a/firmware/App/Src/main.c b/firmware/App/Src/main.c index fcb0322..2deb42b 100644 --- a/firmware/App/Src/main.c +++ b/firmware/App/Src/main.c @@ -3,6 +3,9 @@ #include "task.h" #include "tusb.h" +// Глобальная переменная для CMSIS +/* uint32_t SystemCoreClock = 72000000; */ + // --- System Clock Config (72MHz from 8MHz HSE) --- void SystemClock_Config(void) { // Включаем HSE @@ -13,11 +16,6 @@ void SystemClock_Config(void) { FLASH->ACR |= FLASH_ACR_LATENCY_2; // PLL: HSE * 9 = 72 MHz - // PLLSRC = HSE (1), PLLMUL = 9 (0111) -> 0x001C0000 - // USB Prescaler = 1.5 (Div by 1.5 -> 48MHz) -> 0x00000000 (PLL/1.5 is - // default? No check bit) В F103 USBPRE бит в RCC_CFGR: 0 = div1.5, 1 = div1 - // Мы хотим 72MHz sysclk. Для USB нужно 48MHz. - // 72 / 1.5 = 48MHz. Значит USBPRE = 0 (reset state). RCC->CFGR |= (RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9); // Включаем PLL @@ -33,23 +31,23 @@ void SystemClock_Config(void) { // --- Задачи FreeRTOS --- -// Задача для стека TinyUSB (обработка событий USB) void usb_device_task(void *param) { (void)param; - while (1) { - tud_task(); // "Сердце" TinyUSB. Должно вызываться часто. - } + while (1) { tud_task(); } } -// Задача CDC (эхо) 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(buf, count); tud_cdc_write_flush(); } } @@ -57,42 +55,61 @@ void cdc_task(void *param) { } } +// Программный сброс 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(); - // Включаем тактирование USB и GPIOA (для USB пинов) + // Моргаем светодиодом + 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; - // Инициализация TinyUSB + // ВКЛЮЧАЕМ ПРЕРЫВАНИЯ 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, - configMAX_PRIORITIES - 1, - NULL); - xTaskCreate(cdc_task, "cdc", 128, NULL, configMAX_PRIORITIES - 2, NULL); + xTaskCreate(usb_device_task, "usbd", 128, NULL, 3, NULL); + xTaskCreate(cdc_task, "cdc", 128, NULL, 2, NULL); vTaskStartScheduler(); while (1); } -// --- Обработчики прерываний --- -// USB High Priority or CAN1 TX (Не используется в FS, но полезно объявить) +// Обработчики прерываний void USB_HP_CAN1_TX_IRQHandler(void) { tud_int_handler(0); } -// USB Low Priority or CAN1 RX0 (Основное прерывание для F103) void USB_LP_CAN1_RX0_IRQHandler(void) { tud_int_handler(0); } -// USB Wakeup void USBWakeUp_IRQHandler(void) { tud_int_handler(0); } diff --git a/firmware/Makefile b/firmware/Makefile index 3ac5608..eadd545 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -59,7 +59,7 @@ CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) -O2 -Wall -fdata-sections -ffunction-sec # Linker LDSCRIPT = stm32f103c8.ld LIBS = -lc -lm -lnosys -LDFLAGS = $(MCU) -T$(LDSCRIPT) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections +LDFLAGS = $(MCU) -T$(LDSCRIPT) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections -Wl,--no-warn-rwx-segments # --- Генерация списка объектов --- OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) diff --git a/firmware/stm32f103c8.ld b/firmware/stm32f103c8.ld index d617a4d..1902922 100644 --- a/firmware/stm32f103c8.ld +++ b/firmware/stm32f103c8.ld @@ -17,6 +17,8 @@ MEMORY /* Sections */ SECTIONS { + /* Disable warning about RWX segment */ + /* __GNU_EH_FRAME_HDR = 0; */ /* The startup code into "FLASH" Rom type memory */ .isr_vector : { diff --git a/firmware/system_stm32f1xx.c b/firmware/system_stm32f1xx.c new file mode 120000 index 0000000..9e17d8c --- /dev/null +++ b/firmware/system_stm32f1xx.c @@ -0,0 +1 @@ +/home/mikhail/repos/brightness-collector/firmware/Drivers/CMSIS/Device/ST/STM32F1xx/Source/Templates/system_stm32f1xx.c \ No newline at end of file