Add shared emulator services, waveform generation and STM32 USB boot ports

This commit is contained in:
2026-09-28 11:54:17 +03:00
parent 5260186c16
commit 79411dbc26
56 changed files with 3627 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
/* STM32G474 USB FS device, dedicated PA11/PA12 pins, single-buffer PMA. */
#include "usbd_core.h"
#include "usbd_cdc.h"
static PCD_HandleTypeDef pcd;
/* Единственный статический объект CDC вместо heap. Контракт предполагает один экземпляр класса. */
static USBD_CDC_HandleTypeDef class_memory;
/* Проверяет размер запроса и возвращает статический объект либо NULL. Не является универсальным malloc. */
void *BoardUsb_Alloc(uint32_t size) { return size<=sizeof(class_memory)?&class_memory:NULL; }
/* Освобождение не требуется: объект существует до перезапуска MCU. */
void BoardUsb_Free(void *ptr) { (void)ptr; }
/* Согласует enum HAL и USB: OK -> OK, BUSY -> BUSY, остальные результаты -> FAIL. */
static USBD_StatusTypeDef status(HAL_StatusTypeDef s) {
return s==HAL_OK?USBD_OK:s==HAL_BUSY?USBD_BUSY:USBD_FAIL;
}
/* Единственная точка входа USB ISR; события декодирует HAL_PCD_IRQHandler. */
void USB_LP_IRQHandler(void) { HAL_PCD_IRQHandler(&pcd); }
/* Передаёт 8-байтовый SETUP control-запрос стандартному обработчику USB Device. */
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *h) { (void)USBD_LL_SetupStage(h->pData,(uint8_t *)h->Setup); }
/* OUT: хост отправил данные устройству; передаём номер endpoint и его принятый буфер. */
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *h,uint8_t ep) { (void)USBD_LL_DataOutStage(h->pData,ep,h->OUT_ep[ep].xfer_buff); }
/* IN: завершена передача данных от устройства к хосту; уведомляем USB Device. */
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *h,uint8_t ep) { (void)USBD_LL_DataInStage(h->pData,ep,h->IN_ep[ep].xfer_buff); }
/* Передаёт событие начала USB-кадра; в текущей конфигурации SOF-прерывания отключены. */
void HAL_PCD_SOFCallback(PCD_HandleTypeDef *h) { (void)USBD_LL_SOF(h->pData); }
/* При reset шины фиксируем Full Speed и сбрасываем состояние USB Device. */
void HAL_PCD_ResetCallback(PCD_HandleTypeDef *h) {
(void)USBD_LL_SetSpeed(h->pData,USBD_SPEED_FULL); (void)USBD_LL_Reset(h->pData);
}
/* Сообщает middleware о приостановке шины; аппаратный low-power режим здесь не включается. */
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *h) { (void)USBD_LL_Suspend(h->pData); }
/* Сообщает middleware о возобновлении обмена после suspend. */
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *h) { (void)USBD_LL_Resume(h->pData); }
/* Уведомление верхнего уровня о подключении контроллера. */
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *h) { (void)USBD_LL_DevConnected(h->pData); }
/* Уведомление верхнего уровня об отключении контроллера. */
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *h) { (void)USBD_LL_DevDisconnected(h->pData); }
/* Переадресует незавершённую изохронную IN-передачу; обычный CDC использует bulk endpoints. */
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *h,uint8_t ep) { (void)USBD_LL_IsoINIncomplete(h->pData,ep); }
/* Переадресует незавершённую изохронную OUT-передачу для полноты порта PCD. */
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *h,uint8_t ep) { (void)USBD_LL_IsoOUTIncomplete(h->pData,ep); }
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *d) {
/* Dedicated USB pins: no GPIO alternate-function selection on G474. */
__HAL_RCC_USB_CLK_ENABLE();
pcd.Instance = USB; pcd.Init.dev_endpoints = 8;
pcd.Init.speed = PCD_SPEED_FULL; pcd.Init.phy_itface = PCD_PHY_EMBEDDED;
pcd.Init.Sof_enable = DISABLE; pcd.Init.low_power_enable = DISABLE;
pcd.Init.lpm_enable = DISABLE; pcd.Init.battery_charging_enable = DISABLE;
pcd.pData = d; d->pData = &pcd;
if (HAL_PCD_Init(&pcd) != HAL_OK) return USBD_FAIL;
/* BTABLE: 0x00..0x3f; EP0 RX/TX 64 bytes each; CDC data RX/TX 64;
* CDC notification 16. Byte offsets are disjoint within the 1 KB PMA. */
if (HAL_PCDEx_PMAConfig(&pcd, 0x00, PCD_SNG_BUF, 0x40) != HAL_OK ||
HAL_PCDEx_PMAConfig(&pcd, 0x80, PCD_SNG_BUF, 0x80) != HAL_OK ||
HAL_PCDEx_PMAConfig(&pcd, CDC_OUT_EP, PCD_SNG_BUF, 0xc0) != HAL_OK ||
HAL_PCDEx_PMAConfig(&pcd, CDC_IN_EP, PCD_SNG_BUF, 0x100) != HAL_OK ||
HAL_PCDEx_PMAConfig(&pcd, CDC_CMD_EP, PCD_SNG_BUF, 0x140) != HAL_OK)
return USBD_FAIL;
HAL_NVIC_SetPriority(USB_LP_IRQn, 7, 0); HAL_NVIC_EnableIRQ(USB_LP_IRQn);
return USBD_OK;
}
/* Запрещает USB IRQ до деинициализации контроллера, чтобы callbacks не работали с разобранным состоянием. */
USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *d) {
HAL_NVIC_DisableIRQ(USB_LP_IRQn); return status(HAL_PCD_DeInit(d->pData));
}
/* Включает USB device через HAL после завершения настройки класса и endpoints. */
USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *d) { return status(HAL_PCD_Start(d->pData)); }
/* Останавливает контроллер USB device; память состояния остаётся статической. */
USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *d) { return status(HAL_PCD_Stop(d->pData)); }
/* Открывает endpoint: ep содержит номер и направление (бит 7), type — тип, mps — максимальный пакет в байтах. */
USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *d,uint8_t ep,uint8_t type,uint16_t mps) { return status(HAL_PCD_EP_Open(d->pData,ep,mps,type)); }
/* Закрывает endpoint по USB-адресу ep, включая бит направления. */
USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *d,uint8_t ep) { return status(HAL_PCD_EP_Close(d->pData,ep)); }
/* Очищает FIFO указанного endpoint через HAL. */
USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *d,uint8_t ep) { return status(HAL_PCD_EP_Flush(d->pData,ep)); }
/* Устанавливает STALL: endpoint отклоняет неподдерживаемую операцию хоста. */
USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *d,uint8_t ep) { return status(HAL_PCD_EP_SetStall(d->pData,ep)); }
/* Снимает STALL по запросу верхнего уровня USB Device. */
USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *d,uint8_t ep) { return status(HAL_PCD_EP_ClrStall(d->pData,ep)); }
/* Применяет адрес устройства, назначенный хостом при перечислении USB. */
USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *d,uint8_t address) { return status(HAL_PCD_SetAddress(d->pData,address)); }
/* Запускает IN-передачу size байтов из buf. Буфер должен жить до callback завершения; копии здесь нет. */
USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *d,uint8_t ep,uint8_t *buf,uint32_t size) { return status(HAL_PCD_EP_Transmit(d->pData,ep,buf,size)); }
/* Взводит OUT endpoint для приёма в buf ёмкостью size байтов; завершение придёт через callback PCD. */
USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *d,uint8_t ep,uint8_t *buf,uint32_t size) { return status(HAL_PCD_EP_Receive(d->pData,ep,buf,size)); }
/* Читает состояние endpoint из HAL handle: bit7 выбирает IN, младшие 7 бит — номер. */
uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *d,uint8_t ep) {
PCD_HandleTypeDef *h=d->pData; return ep&0x80?h->IN_ep[ep&0x7F].is_stall:h->OUT_ep[ep].is_stall;
}
/* Возвращает фактическое число принятых байтов последней OUT-передачи. */
uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *d,uint8_t ep) { return HAL_PCD_EP_GetRxCount(d->pData,ep); }
/* Блокирующая задержка ST middleware в миллисекундах HAL; требует работающего SysTick. */
void USBD_LL_Delay(uint32_t ms) { HAL_Delay(ms); }