diff --git a/client/src/test_usb.py b/client/src/test_usb.py new file mode 100644 index 0000000..2d95c35 --- /dev/null +++ b/client/src/test_usb.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import serial +import time + +port = serial.Serial("/dev/ttyACM0", 115200, timeout=1) +print(f"Connected to {port.name}") + +port.write(b"test\n") +time.sleep(0.1) + +# Читаем 5 секунд +start = time.time() +while time.time() - start < 5: + if port.in_waiting: + data = port.read(port.in_waiting) + print(f"RX: {data.decode('utf-8', errors='replace')}", end="") + time.sleep(0.1) + +port.close() diff --git a/firmware/App/Inc/FreeRTOSConfig.h b/firmware/App/Inc/FreeRTOSConfig.h index 6351f5b..117226a 100644 --- a/firmware/App/Inc/FreeRTOSConfig.h +++ b/firmware/App/Inc/FreeRTOSConfig.h @@ -1,6 +1,8 @@ #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H +#define configCHECK_FOR_STACK_OVERFLOW 2 + #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 diff --git a/firmware/App/Inc/audio_config.h b/firmware/App/Inc/audio_config.h index 826cf8c..3d5654c 100644 --- a/firmware/App/Inc/audio_config.h +++ b/firmware/App/Inc/audio_config.h @@ -4,31 +4,18 @@ #include // Audio Configuration -#define AUDIO_SAMPLE_RATE 22050U // Hz (22.05 kHz) -#define AUDIO_BUFFER_SIZE 512U // Samples per buffer (для FFT) -#define AUDIO_NUM_BUFFERS 2U +#define AUDIO_SAMPLE_RATE 22050U +#define AUDIO_BUFFER_SIZE 512U // ADC Configuration #define AUDIO_ADC_CHANNEL 1U // PA1 = ADC1_IN1 -#define AUDIO_ADC_GPIO_PORT GPIOA -#define AUDIO_ADC_GPIO_PIN 1U // PA1 -// Timer Configuration -// Timer2 будет триггерить ADC на частоте AUDIO_SAMPLE_RATE -// APB1 Timer clock = 72 MHz (на STM32F103 при SYSCLK=72MHz) -// Формула: Timer_Freq = Timer_Clock / ((PSC + 1) * (ARR + 1)) -// Для 22050 Hz: 72000000 / 22050 = 3265.3 -// Используем PSC=0, ARR=3264 → 72MHz / 3265 = 22051 Hz (погрешность 0.004%) +// Timer Configuration (TIM2 для 72 MHz) #define AUDIO_TIMER_PRESCALER 0U -#define AUDIO_TIMER_PERIOD 3264U // ARR value - -// DMA Configuration -#define AUDIO_DMA_CHANNEL DMA1_Channel1 // ADC1 использует DMA1_CH1 +#define AUDIO_TIMER_PERIOD 3264U // 72MHz / 3265 ≈ 22050 Hz // Data Types typedef uint16_t audio_sample_t; - -// Callback вызывается когда буфер заполнен typedef void ( *audio_buffer_ready_callback_t)(audio_sample_t* buffer, uint32_t size); diff --git a/firmware/App/Inc/tusb_config.h b/firmware/App/Inc/tusb_config.h index c16c1d0..8e65c0a 100644 --- a/firmware/App/Inc/tusb_config.h +++ b/firmware/App/Inc/tusb_config.h @@ -19,8 +19,8 @@ extern "C" { // Конфигурация CDC (Communication Device Class) #define CFG_TUD_CDC 1 -#define CFG_TUD_CDC_RX_BUFSIZE 64 -#define CFG_TUD_CDC_TX_BUFSIZE 64 +#define CFG_TUD_CDC_RX_BUFSIZE 256 +#define CFG_TUD_CDC_TX_BUFSIZE 256 // Endpoint буферизация #define CFG_TUD_ENDPOINT0_SIZE 64 diff --git a/firmware/App/Src/audio_adc.c b/firmware/App/Src/audio_adc.c index a59dcc7..d6add33 100644 --- a/firmware/App/Src/audio_adc.c +++ b/firmware/App/Src/audio_adc.c @@ -2,12 +2,8 @@ #include #include "stm32f1xx.h" -// Двойные буферы для DMA -static audio_sample_t audio_buffer_0[AUDIO_BUFFER_SIZE] = {0}; -static audio_sample_t audio_buffer_1[AUDIO_BUFFER_SIZE] = {0}; - -// Указатель на активный буфер для обработки -static volatile uint8_t active_buffer_index = 0; +// Один непрерывный DMA-буфер: 2 * 512 = 1024 семпла +static audio_sample_t dma_buffer[2 * AUDIO_BUFFER_SIZE]; // Callback функция static audio_buffer_ready_callback_t user_callback = NULL; @@ -24,11 +20,10 @@ static void audio_adc_hw_init(void); static void audio_dma_init(void); bool audio_adc_init(audio_buffer_ready_callback_t callback) { - if (callback == NULL) { return false; } + if (callback == NULL) return false; user_callback = callback; - // Инициализация компонентов audio_gpio_init(); audio_timer_init(); audio_adc_hw_init(); @@ -38,24 +33,14 @@ bool audio_adc_init(audio_buffer_ready_callback_t callback) { } void audio_adc_start(void) { - // Запускаем DMA DMA1_Channel1->CCR |= DMA_CCR_EN; - - // Запускаем ADC ADC1->CR2 |= ADC_CR2_ADON; - - // Запускаем Timer2, начинаем генерировать TRGO события - TIM2->CR1 |= TIM_CR1_CEN; + TIM3->CR1 |= TIM_CR1_CEN; } void audio_adc_stop(void) { - // Останавливаем Timer - TIM2->CR1 &= ~TIM_CR1_CEN; - - // Останавливаем ADC + TIM3->CR1 &= ~TIM_CR1_CEN; ADC1->CR2 &= ~ADC_CR2_ADON; - - // Останавливаем DMA DMA1_Channel1->CCR &= ~DMA_CCR_EN; } @@ -63,176 +48,121 @@ uint32_t audio_adc_get_buffer_count(void) { return buffer_count; } -// Private Functions - static void audio_gpio_init(void) { - // Включаем тактирование GPIOA RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; - // PA1 как Analog Input (CNF=00, MODE=00) - GPIOA->CRL &= ~(GPIO_CRL_CNF1 | GPIO_CRL_MODE1); - // По умолчанию уже 0000, но явно устанавливаем - GPIOA->CRL &= ~(0xF << 4); // Биты [7:4] для Pin 1 + // PA1 analog + GPIOA->CRL &= ~(0xF << 4); } static void audio_timer_init(void) { - // Включаем тактирование Timer2 - RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; + // Включаем тактирование Timer3 + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; - // Настраиваем Timer2 для генерации TRGO на частоте 22050 Hz - TIM2->PSC = AUDIO_TIMER_PRESCALER; - TIM2->ARR = AUDIO_TIMER_PERIOD; + // Настраиваем TIM3 для 22050 Hz + TIM3->PSC = AUDIO_TIMER_PRESCALER; + TIM3->ARR = AUDIO_TIMER_PERIOD; - // Master Mode Selection: Update event as TRGO - // MMS[2:0] = 010 (Update) - TIM2->CR2 &= ~TIM_CR2_MMS; - TIM2->CR2 |= TIM_CR2_MMS_1; // 010 + // TRGO = Update event + TIM3->CR2 &= ~TIM_CR2_MMS; + TIM3->CR2 |= TIM_CR2_MMS_1; - // Auto-reload preload enable - TIM2->CR1 |= TIM_CR1_ARPE; - - // Генерируем Update event для загрузки PSC/ARR - TIM2->EGR |= TIM_EGR_UG; + TIM3->CR1 |= TIM_CR1_ARPE; + TIM3->EGR |= TIM_EGR_UG; + TIM3->CNT = 0; } static void audio_adc_hw_init(void) { - // Включаем тактирование ADC1 RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; - // ADC Clock = PCLK2 / 6 = 72MHz / 6 = 12MHz (макс 14MHz для STM32F1) RCC->CFGR &= ~RCC_CFGR_ADCPRE; RCC->CFGR |= RCC_CFGR_ADCPRE_DIV6; - // Сброс ADC1 ADC1->CR2 = 0; ADC1->CR1 = 0; - // Конфигурация ADC1 - - // Scan mode disabled (один канал) ADC1->CR1 &= ~ADC_CR1_SCAN; - - // Continuous mode disabled (будет триггериться Timer2) ADC1->CR2 &= ~ADC_CR2_CONT; - // External trigger: Timer2 TRGO - // EXTSEL[2:0] = 011 (Timer2 TRGO для ADC1) + // EXTSEL = 011 (Timer2 TRGO), EXTTRIG enable ADC1->CR2 &= ~ADC_CR2_EXTSEL; - ADC1->CR2 |= ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1; // 011 - - // External trigger enable for regular channels + ADC1->CR2 |= (0x4U << 17); // TIM3_TRGO ADC1->CR2 |= ADC_CR2_EXTTRIG; - // 5. DMA mode enable ADC1->CR2 |= ADC_CR2_DMA; - - // Data alignment: right aligned ADC1->CR2 &= ~ADC_CR2_ALIGN; - // Настройка канала - - // Regular sequence length = 1 (только один канал) ADC1->SQR1 &= ~ADC_SQR1_L; - - // First conversion in regular sequence: Channel 1 (PA1) ADC1->SQR3 &= ~ADC_SQR3_SQ1; ADC1->SQR3 |= (AUDIO_ADC_CHANNEL << ADC_SQR3_SQ1_Pos); - // Sample time для Channel 1: 7.5 cycles (минимум для 12MHz ADC) - // SMPR2[5:3] для CH1 = 001 (7.5 cycles) ADC1->SMPR2 &= ~ADC_SMPR2_SMP1; - ADC1->SMPR2 |= ADC_SMPR2_SMP1_0; // 001 + ADC1->SMPR2 |= ADC_SMPR2_SMP1_0; // 7.5 cycles - // Калибровка ADC - - // Включаем ADC + // calibration ADC1->CR2 |= ADC_CR2_ADON; - - // Ждем stabilization time (1 мкс) - for (volatile int i = 0; i < 1000; i++); - - // Запускаем калибровку + for (volatile int i = 0; i < 1000; i++) {} ADC1->CR2 |= ADC_CR2_CAL; + while (ADC1->CR2 & ADC_CR2_CAL) {} - // Ждем завершения калибровки - while (ADC1->CR2 & ADC_CR2_CAL); - - // Выключаем ADC (для запуска использовать audio_adc_start) ADC1->CR2 &= ~ADC_CR2_ADON; } static void audio_dma_init(void) { - // Включаем тактирование DMA1 RCC->AHBENR |= RCC_AHBENR_DMA1EN; - // Отключаем DMA1 Channel1 перед конфигурацией DMA1_Channel1->CCR &= ~DMA_CCR_EN; + while (DMA1_Channel1->CCR & DMA_CCR_EN) {} - // Ждем отключения - while (DMA1_Channel1->CCR & DMA_CCR_EN); + // ADC1 DR -> RAM + DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; - // Конфигурация DMA + // ВАЖНО: CMAR указывает на непрерывный буфер 1024 samples + DMA1_Channel1->CMAR = (uint32_t)dma_buffer; - // Peripheral address: ADC1 Data Register - DMA1_Channel1->CPAR = (uint32_t)&(ADC1->DR); + // ВАЖНО: 2 * 512 = 1024 samples + DMA1_Channel1->CNDTR = 2 * AUDIO_BUFFER_SIZE; - // Memory address: начинаем с buffer_0 - DMA1_Channel1->CMAR = (uint32_t)audio_buffer_0; - - // Number of data to transfer: размер обоих буферов (для circular mode) - DMA1_Channel1->CNDTR = AUDIO_BUFFER_SIZE * 2; - - // Конфигураци uint32_t ccr = 0; - ccr |= DMA_CCR_MINC; // Memory increment mode - ccr |= DMA_CCR_CIRC; // Circular mode - ccr |= DMA_CCR_HTIE; // Half transfer interrupt enable - ccr |= DMA_CCR_TCIE; // Transfer complete interrupt enable - ccr |= DMA_CCR_PL_1; // Priority level: High (10) - - // Data size: 16-bit (MSIZE и PSIZE = 01) - ccr |= DMA_CCR_MSIZE_0; // Memory size: 16-bit - ccr |= DMA_CCR_PSIZE_0; // Peripheral size: 16-bit + ccr |= DMA_CCR_MINC; + ccr |= DMA_CCR_CIRC; + ccr |= DMA_CCR_HTIE; + ccr |= DMA_CCR_TCIE; + ccr |= DMA_CCR_PL_1; // high + ccr |= DMA_CCR_MSIZE_0; // 16-bit + ccr |= DMA_CCR_PSIZE_0; // 16-bit DMA1_Channel1->CCR = ccr; - // Включаем прерывание DMA1_Channel1 в NVIC - NVIC_SetPriority(DMA1_Channel1_IRQn, 6); // Приоритет 6 (ниже USB) + NVIC_SetPriority(DMA1_Channel1_IRQn, 6); NVIC_EnableIRQ(DMA1_Channel1_IRQn); } -// DMA Interrupt Handler - void DMA1_Channel1_IRQHandler(void) { uint32_t isr = DMA1->ISR; - // Half Transfer Interrupt (первая половина буфера заполнена) if (isr & DMA_ISR_HTIF1) { - DMA1->IFCR = DMA_IFCR_CHTIF1; // Сбрасываем флаг + DMA1->IFCR = DMA_IFCR_CHTIF1; dma_half_transfer_count++; - // Первая половина = buffer_0 готов к обработке - if (user_callback != NULL) { - user_callback(audio_buffer_0, AUDIO_BUFFER_SIZE); - } + // первая половина: [0 .. 511] + if (user_callback) { user_callback(&dma_buffer[0], AUDIO_BUFFER_SIZE); } buffer_count++; } - // Transfer Complete Interrupt (вторая половина буфера заполнена) if (isr & DMA_ISR_TCIF1) { - DMA1->IFCR = DMA_IFCR_CTCIF1; // Сбрасываем флаг + DMA1->IFCR = DMA_IFCR_CTCIF1; dma_full_transfer_count++; - // Вторая половина = buffer_1 готов к обработке - if (user_callback != NULL) { - user_callback(audio_buffer_1, AUDIO_BUFFER_SIZE); + // вторая половина: [512 .. 1023] + if (user_callback) { + user_callback(&dma_buffer[AUDIO_BUFFER_SIZE], AUDIO_BUFFER_SIZE); } buffer_count++; } - // Transfer Error if (isr & DMA_ISR_TEIF1) { - DMA1->IFCR = DMA_IFCR_CTEIF1; // Сбрасываем флаг - // TODO: обработка ошибки + DMA1->IFCR = DMA_IFCR_CTEIF1; + // TODO: error handling } } diff --git a/firmware/App/Src/main.c b/firmware/App/Src/main.c index 7059c63..6bf66b7 100644 --- a/firmware/App/Src/main.c +++ b/firmware/App/Src/main.c @@ -2,35 +2,48 @@ #include #include "FreeRTOS.h" #include "audio_adc.h" +#include "queue.h" #include "stm32f1xx.h" #include "task.h" #include "tusb.h" -// System Clock Configuration +void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) { + (void)xTask; + (void)pcTaskName; + // Мигаем LED очень быстро при переполнении стека + while (1) { + GPIOC->ODR ^= GPIO_ODR_ODR13; + for (volatile int i = 0; i < 50000; i++); + } +} + +// === Структура данных для очереди === + +typedef struct { + uint16_t min_val; + uint16_t max_val; + uint16_t avg_val; + uint32_t buffer_num; +} audio_stats_packet_t; + +static QueueHandle_t audio_stats_queue = NULL; + +// === System Clock === void SystemClock_Config(void) { - // Настройка на 72 MHz через HSE + PLL - - // 1. Включаем HSE (внешний кварц 8 МГц) RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)); - // 2. Настраиваем Flash: 2 цикла ожидания для 72 MHz FLASH->ACR = FLASH_ACR_LATENCY_2; - // 3. Настраиваем PLL: 8 MHz * 9 = 72 MHz RCC->CFGR &= ~RCC_CFGR_PLLMULL; RCC->CFGR |= RCC_CFGR_PLLMULL9; - RCC->CFGR |= RCC_CFGR_PLLSRC; // Источник PLL = HSE + RCC->CFGR |= RCC_CFGR_PLLSRC; + RCC->CFGR &= ~RCC_CFGR_USBPRE; - // 4. USB делитель: 72 MHz / 1.5 = 48 MHz - RCC->CFGR &= ~RCC_CFGR_USBPRE; // USBPRE = 0 (делитель 1.5) - - // 5. Включаем PLL RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)); - // 6. Переключаем системную частоту на PLL RCC->CFGR &= ~RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); @@ -38,19 +51,15 @@ void SystemClock_Config(void) { SystemCoreClock = 72000000; } -// Audio Processing Callback - -// Буфер для отправки статистики через USB -static char usb_tx_buffer[128]; -static volatile uint32_t total_samples = 0; +// === Audio Callback === void audio_buffer_ready(audio_sample_t *buffer, uint32_t size) { - // Эта функция вызывается из прерывания DMA - // Не делать тяжелых операций здесь + static uint32_t buffer_counter = 0; + buffer_counter++; - total_samples += size; + // Мигаем LED при каждом вызове + if (buffer_counter % 5 == 0) { GPIOC->ODR ^= GPIO_ODR_ODR13; } - // мин/макс значения uint16_t min_val = 4095; uint16_t max_val = 0; uint32_t sum = 0; @@ -62,27 +71,23 @@ void audio_buffer_ready(audio_sample_t *buffer, uint32_t size) { sum += val; } - uint16_t avg = sum / size; + if (buffer_counter % 10 == 0) { + audio_stats_packet_t packet = { + .min_val = min_val, + .max_val = max_val, + .avg_val = (uint16_t)(max_val - min_val), + .buffer_num = buffer_counter}; - // Каждые 2 секунды отправляем статистику: каждый 100-й буфер - static uint32_t report_counter = 0; - report_counter++; - - if (report_counter >= 100) { - report_counter = 0; - - snprintf( - usb_tx_buffer, - sizeof(usb_tx_buffer), - "ADC Stats - Min: %4u, Max: %4u, Avg: %4u, Total samples: %lu\r\n", - min_val, - max_val, - avg, - total_samples); + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xQueueSendFromISR( + audio_stats_queue, + &packet, + &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } } -// FreeRTOS Tasks +// === Tasks === void usb_device_task(void *param) { (void)param; @@ -94,44 +99,115 @@ void usb_device_task(void *param) { void cdc_task(void *param) { (void)param; + char tx_buffer[256]; + uint32_t heartbeat_counter = 0; + uint32_t last_buffer_count = 0; while (1) { - if (tud_cdc_connected()) { - // Отправка статистики если есть данные - if (usb_tx_buffer[0] != '\0') { - size_t len = strlen(usb_tx_buffer); - if (tud_cdc_write_available() >= len) { - tud_cdc_write(usb_tx_buffer, len); - tud_cdc_write_flush(); - usb_tx_buffer[0] = '\0'; // Очищаем буфер - } + heartbeat_counter++; + + // Heartbeat + ДИАГНОСТИКА регистров каждые 100 циклов + if (heartbeat_counter % 100 == 0 && tud_cdc_connected()) { + uint32_t current_buffer_count = audio_adc_get_buffer_count(); + + int len = snprintf( + tx_buffer, + sizeof(tx_buffer), + "HB:%lu Q:%u BC:%lu | " + "TIM3_CR1:%lX TIM3_CNT:%lu | " + "ADC1_CR2:%lX ADC1_SR:%lX | " + "DMA_CCR:%lX DMA_CNDTR:%lu\r\n", + heartbeat_counter, + (unsigned)uxQueueMessagesWaiting(audio_stats_queue), + current_buffer_count, + TIM3->CR1, + TIM3->CNT, + ADC1->CR2, + ADC1->SR, + DMA1_Channel1->CCR, + DMA1_Channel1->CNDTR); + + if (tud_cdc_write_available() >= len) { + tud_cdc_write(tx_buffer, len); + tud_cdc_write_flush(); } - // Echo для тестирования - if (tud_cdc_available()) { - uint8_t buf[64]; - uint32_t count = tud_cdc_read(buf, sizeof(buf)); - tud_cdc_write(buf, count); + last_buffer_count = current_buffer_count; + } + + // Остальной код без изменений + audio_stats_packet_t packet; + if (xQueueReceive(audio_stats_queue, &packet, pdMS_TO_TICKS(10)) == + pdPASS) { + int len = snprintf( + tx_buffer, + sizeof(tx_buffer), + "Buf:%lu Min:%u Max:%u Avg:%u\r\n", + packet.buffer_num, + packet.min_val, + packet.max_val, + packet.avg_val); + + if (tud_cdc_connected() && len > 0 && + tud_cdc_write_available() >= len) { + tud_cdc_write(tx_buffer, len); tud_cdc_write_flush(); } } - vTaskDelay(pdMS_TO_TICKS(10)); + // Echo + if (tud_cdc_available()) { + uint8_t buf[64]; + uint32_t count = tud_cdc_read(buf, sizeof(buf)); + if (tud_cdc_connected() && count > 0) { + tud_cdc_write(buf, count); + tud_cdc_write_flush(); + } + } } } void led_task(void *param) { (void)param; - while (1) { - GPIOC->BSRR = GPIO_BSRR_BR13; // LED ON - vTaskDelay(pdMS_TO_TICKS(100)); - GPIOC->BSRR = GPIO_BSRR_BS13; // LED OFF - vTaskDelay(pdMS_TO_TICKS(900)); + GPIOC->BSRR = GPIO_BSRR_BR13; + vTaskDelay(pdMS_TO_TICKS(500)); + GPIOC->BSRR = GPIO_BSRR_BS13; + vTaskDelay(pdMS_TO_TICKS(500)); } } -// USB Reset +// === Задача инициализации аудио === +void audio_init_task(void *param) { + (void)param; + + // Индикация старта инициализации (мигнем 3 раза быстро) + for (int i = 0; i < 3; i++) { + GPIOC->ODR ^= GPIO_ODR_ODR13; + vTaskDelay(pdMS_TO_TICKS(100)); + } + + if (!audio_adc_init(audio_buffer_ready)) { + // Ошибка: мигаем очень быстро + while (1) { + GPIOC->ODR ^= GPIO_ODR_ODR13; + vTaskDelay(pdMS_TO_TICKS(50)); + } + } + + // Запускаем ADC после старта FreeRTOS + audio_adc_start(); + + // Индикация успешного запуска (мигнем 5 раз медленно) + for (int i = 0; i < 5; i++) { + GPIOC->ODR ^= GPIO_ODR_ODR13; + vTaskDelay(pdMS_TO_TICKS(200)); + } + + vTaskDelete(NULL); +} + +// === USB Reset === void force_usb_reset(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; @@ -143,19 +219,19 @@ void force_usb_reset(void) { GPIOA->CRH |= GPIO_CRH_CNF12_0; } -// Main +// === Main === int main(void) { SystemClock_Config(); - // Настройка LED (PC13) + // LED RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; GPIOC->CRH &= ~GPIO_CRH_CNF13; GPIOC->CRH |= GPIO_CRH_MODE13_1; force_usb_reset(); - // Включаем USB + // USB RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; RCC->APB1ENR |= RCC_APB1ENR_USBEN; @@ -169,21 +245,16 @@ int main(void) { tusb_init(); - // Инициализация Audio ADC - if (!audio_adc_init(audio_buffer_ready)) { - // Ошибка инициализации - быстро мигаем LED + // Очередь создаем ДО старта планировщика + audio_stats_queue = xQueueCreate(10, sizeof(audio_stats_packet_t)); + if (audio_stats_queue == NULL) { while (1) { - GPIOC->BSRR = GPIO_BSRR_BR13; - for (volatile int i = 0; i < 100000; i++); - GPIOC->BSRR = GPIO_BSRR_BS13; + GPIOC->ODR ^= GPIO_ODR_ODR13; for (volatile int i = 0; i < 100000; i++); } } - // Запускаем захват аудио - audio_adc_start(); - - // Создаем задачи FreeRTOS + // Задачи xTaskCreate( usb_device_task, "usbd", @@ -191,15 +262,16 @@ int main(void) { NULL, configMAX_PRIORITIES - 1, NULL); - xTaskCreate(cdc_task, "cdc", 256, NULL, configMAX_PRIORITIES - 2, NULL); + xTaskCreate(cdc_task, "cdc", 320, NULL, configMAX_PRIORITIES - 2, NULL); xTaskCreate(led_task, "led", 128, NULL, 1, NULL); + xTaskCreate(audio_init_task, "audio_init", 128, NULL, 2, NULL); vTaskStartScheduler(); while (1); } -// USB Interrupt Handlers +// === USB Handlers === void USB_HP_CAN1_TX_IRQHandler(void) { tud_int_handler(0); diff --git a/firmware/stm32f103c8.ld b/firmware/stm32f103c8.ld index 1902922..16d5ab1 100644 --- a/firmware/stm32f103c8.ld +++ b/firmware/stm32f103c8.ld @@ -4,8 +4,8 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ -_Min_Heap_Size = 0x200; /* required amount of heap */ -_Min_Stack_Size = 0x400; /* required amount of stack */ +_Min_Heap_Size = 0x400; /* required amount of heap */ +_Min_Stack_Size = 0xa00; /* required amount of stack */ /* Memories definition */ MEMORY