Files
templates/c/set-protocol/ports/stm32g474-usb-boot/boot_usb_port.c

95 lines
8.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 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); }