215 lines
5.6 KiB
C
215 lines
5.6 KiB
C
#include <stdio.h>
|
||
#include <string.h>
|
||
#include "FreeRTOS.h"
|
||
#include "audio_adc.h"
|
||
#include "stm32f1xx.h"
|
||
#include "task.h"
|
||
#include "tusb.h"
|
||
|
||
// System Clock Configuration
|
||
|
||
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
|
||
|
||
// 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);
|
||
|
||
SystemCoreClock = 72000000;
|
||
}
|
||
|
||
// Audio Processing Callback
|
||
|
||
// Буфер для отправки статистики через USB
|
||
static char usb_tx_buffer[128];
|
||
static volatile uint32_t total_samples = 0;
|
||
|
||
void audio_buffer_ready(audio_sample_t *buffer, uint32_t size) {
|
||
// Эта функция вызывается из прерывания DMA
|
||
// Не делать тяжелых операций здесь
|
||
|
||
total_samples += size;
|
||
|
||
// мин/макс значения
|
||
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;
|
||
}
|
||
|
||
uint16_t avg = sum / size;
|
||
|
||
// Каждые 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);
|
||
}
|
||
}
|
||
|
||
// FreeRTOS 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;
|
||
|
||
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'; // Очищаем буфер
|
||
}
|
||
}
|
||
|
||
// Echo для тестирования
|
||
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));
|
||
}
|
||
}
|
||
|
||
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));
|
||
}
|
||
}
|
||
|
||
// 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 (PC13)
|
||
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 ADC
|
||
if (!audio_adc_init(audio_buffer_ready)) {
|
||
// Ошибка инициализации - быстро мигаем LED
|
||
while (1) {
|
||
GPIOC->BSRR = GPIO_BSRR_BR13;
|
||
for (volatile int i = 0; i < 100000; i++);
|
||
GPIOC->BSRR = GPIO_BSRR_BS13;
|
||
for (volatile int i = 0; i < 100000; i++);
|
||
}
|
||
}
|
||
|
||
// Запускаем захват аудио
|
||
audio_adc_start();
|
||
|
||
// Создаем задачи FreeRTOS
|
||
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);
|
||
}
|
||
|
||
// USB Interrupt 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);
|
||
}
|