Files
sound-analyze/firmware/App/Src/main.c

287 lines
7.5 KiB
C

#include <stdio.h>
#include <string.h>
#include "FreeRTOS.h"
#include "audio_adc.h"
#include "queue.h"
#include "stm32f1xx.h"
#include "task.h"
#include "tusb.h"
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) {
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY));
FLASH->ACR = FLASH_ACR_LATENCY_2;
RCC->CFGR &= ~RCC_CFGR_PLLMULL;
RCC->CFGR |= RCC_CFGR_PLLMULL9;
RCC->CFGR |= RCC_CFGR_PLLSRC;
RCC->CFGR &= ~RCC_CFGR_USBPRE;
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY));
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
SystemCoreClock = 72000000;
}
// === Audio Callback ===
void audio_buffer_ready(audio_sample_t *buffer, uint32_t size) {
static uint32_t buffer_counter = 0;
buffer_counter++;
// Мигаем 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;
for (uint32_t i = 0; i < size; i++) {
uint16_t val = buffer[i];
if (val < min_val) min_val = val;
if (val > max_val) max_val = val;
sum += val;
}
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};
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(
audio_stats_queue,
&packet,
&xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
// === Tasks ===
void usb_device_task(void *param) {
(void)param;
while (1) {
tud_task();
vTaskDelay(pdMS_TO_TICKS(1));
}
}
void cdc_task(void *param) {
(void)param;
char tx_buffer[256];
uint32_t heartbeat_counter = 0;
uint32_t last_buffer_count = 0;
while (1) {
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();
}
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();
}
}
// 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;
vTaskDelay(pdMS_TO_TICKS(500));
GPIOC->BSRR = GPIO_BSRR_BS13;
vTaskDelay(pdMS_TO_TICKS(500));
}
}
// === Задача инициализации аудио ===
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;
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;
}
// === Main ===
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;
NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, 6);
NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 6);
NVIC_SetPriority(USBWakeUp_IRQn, 6);
NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
NVIC_EnableIRQ(USBWakeUp_IRQn);
tusb_init();
// Очередь создаем ДО старта планировщика
audio_stats_queue = xQueueCreate(10, sizeof(audio_stats_packet_t));
if (audio_stats_queue == NULL) {
while (1) {
GPIOC->ODR ^= GPIO_ODR_ODR13;
for (volatile int i = 0; i < 100000; i++);
}
}
// Задачи
xTaskCreate(
usb_device_task,
"usbd",
256,
NULL,
configMAX_PRIORITIES - 1,
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 Handlers ===
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);
}