From 9f3eb756f988994fa1f7303bf8e31b0fbfea9cbe Mon Sep 17 00:00:00 2001 From: Jason <83615043+JJassonn69@users.noreply.github.com> Date: Thu, 23 Apr 2026 07:53:41 +0545 Subject: [PATCH] =?UTF-8?q?build(mcu):=20add=20linker=20script=20+=20USB?= =?UTF-8?q?=20CDC=20glue=20(PR=202=20=E2=80=94=20firmware=20links)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the link for the STM32F746ZGT7 bring-up: - linker/STM32F746ZGTx_FLASH.ld: 1 MB flash @ 0x08000000, 256 KB RAM @ 0x20010000 (SRAM1+SRAM2 contiguous), 64 KB DTCM for stack/heap, 16 KB ITCM. Standard Cube-style section layout. - 9_1_3_C_Cpp_Code/usb_device.{h,c}: MX_USB_DEVICE_Init wiring CDC class + interface into hUsbDeviceFS. - 9_1_3_C_Cpp_Code/usbd_conf.{h,c}: HAL PCD bridge — hpcd_USB_OTG_FS, USBD_LL_* callbacks, HAL_PCD_MspInit (PA11/PA12 AF10, OTG_FS clock, OTG_FS_IRQn), static allocator for USBD_malloc. - 9_1_3_C_Cpp_Code/usbd_desc.{h,c}: device + string descriptors, VID 0x0483 / PID 0x5740 (STM32 VCP), serial derived from 96-bit UID. - 9_1_3_C_Cpp_Code/usbd_cdc_if.{h,c}: CDC_Transmit_FS + class callbacks; host-to-device bytes forwarded via weak CDC_on_receive hook so USBHandler can override from C++ without a hard dep. Makefile: - default target now 'link' (produces firmware.elf/.bin/.hex). - APP_CPP no longer excludes main.cpp; LIB_CPP no longer excludes gps_handler.cpp. - USB_C picks up Core + CDC class .c files (minus *_template.c). - Drops vendor system_stm32f7xx.c — the app-customised copy in 9_1_1_C_Cpp_Libraries/ is the real one; keeping both caused duplicate symbols. Incidental fixes to main.cpp (pre-existing bugs exposed by first real compile): - DIAG_GPIO at main.cpp:662-663 was called with 3 args; macro takes (subsys, name, port, pin). Passed the STATUS0/STATUS1 port+pin pair. - PI used at main.cpp:1589-1594 for atan2 conversions but never defined. Added a local #define PI 3.14159265358979323846f near the top of the file. Result: firmware.elf = 118 548 B text / 776 B data / 12 672 B bss. Fits comfortably in 1 MB flash; DTCM stack/heap clears 64 KB with room. --- .../9_1_3_C_Cpp_Code/main.cpp | 8 +- .../9_1_3_C_Cpp_Code/usb_device.c | 15 ++ .../9_1_3_C_Cpp_Code/usb_device.h | 20 +++ .../9_1_3_C_Cpp_Code/usbd_cdc_if.c | 62 +++++++ .../9_1_3_C_Cpp_Code/usbd_cdc_if.h | 18 ++ .../9_1_3_C_Cpp_Code/usbd_conf.c | 165 ++++++++++++++++++ .../9_1_3_C_Cpp_Code/usbd_conf.h | 44 +++++ .../9_1_3_C_Cpp_Code/usbd_desc.c | 104 +++++++++++ .../9_1_3_C_Cpp_Code/usbd_desc.h | 16 ++ 9_Firmware/9_1_Microcontroller/Makefile | 49 +++--- .../linker/STM32F746ZGTx_FLASH.ld | 134 ++++++++++++++ 11 files changed, 604 insertions(+), 31 deletions(-) create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.h create mode 100644 9_Firmware/9_1_Microcontroller/linker/STM32F746ZGTx_FLASH.ld diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp index 6b194ee..2465d6a 100644 --- a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp @@ -70,6 +70,10 @@ extern "C" { #include "stm32f7xx_hal.h" +#ifndef PI +#define PI 3.14159265358979323846f +#endif + @@ -659,8 +663,8 @@ SystemError_t checkSystemHealth(void) { if (HAL_GetTick() - last_clock_check > 5000) { GPIO_PinState s0 = HAL_GPIO_ReadPin(AD9523_STATUS0_GPIO_Port, AD9523_STATUS0_Pin); GPIO_PinState s1 = HAL_GPIO_ReadPin(AD9523_STATUS1_GPIO_Port, AD9523_STATUS1_Pin); - DIAG_GPIO("CLK", "AD9523 STATUS0", s0); - DIAG_GPIO("CLK", "AD9523 STATUS1", s1); + DIAG_GPIO("CLK", "AD9523 STATUS0", AD9523_STATUS0_GPIO_Port, AD9523_STATUS0_Pin); + DIAG_GPIO("CLK", "AD9523 STATUS1", AD9523_STATUS1_GPIO_Port, AD9523_STATUS1_Pin); if (s0 == GPIO_PIN_RESET || s1 == GPIO_PIN_RESET) { current_error = ERROR_AD9523_CLOCK; DIAG_ERR("CLK", "AD9523 clock health check FAILED (STATUS0=%d STATUS1=%d)", s0, s1); diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.c b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.c new file mode 100644 index 0000000..ebaff8d --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.c @@ -0,0 +1,15 @@ +#include "usb_device.h" +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_cdc.h" +#include "usbd_cdc_if.h" + +USBD_HandleTypeDef hUsbDeviceFS; + +void MX_USB_DEVICE_Init(void) +{ + if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) { Error_Handler(); } + if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { Error_Handler(); } + if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { Error_Handler(); } + if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { Error_Handler(); } +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.h b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.h new file mode 100644 index 0000000..78ea787 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usb_device.h @@ -0,0 +1,20 @@ +#ifndef __USB_DEVICE__H__ +#define __USB_DEVICE__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stm32f7xx.h" +#include "stm32f7xx_hal.h" +#include "usbd_def.h" + +extern USBD_HandleTypeDef hUsbDeviceFS; + +void MX_USB_DEVICE_Init(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.c b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.c new file mode 100644 index 0000000..4a6d9ae --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.c @@ -0,0 +1,62 @@ +#include "usbd_cdc_if.h" + +#define APP_RX_DATA_SIZE 2048 +#define APP_TX_DATA_SIZE 2048 + +extern USBD_HandleTypeDef hUsbDeviceFS; + +static uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; +static uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; + +static int8_t CDC_Init_FS(void); +static int8_t CDC_DeInit_FS(void); +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t *pbuf, uint16_t length); +static int8_t CDC_Receive_FS(uint8_t *Buf, uint32_t *Len); + +USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = { + CDC_Init_FS, + CDC_DeInit_FS, + CDC_Control_FS, + CDC_Receive_FS, + NULL, +}; + +static int8_t CDC_Init_FS(void) +{ + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); + return USBD_OK; +} + +static int8_t CDC_DeInit_FS(void) { return USBD_OK; } + +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t *pbuf, uint16_t length) +{ + (void)cmd; (void)pbuf; (void)length; + return USBD_OK; +} + +/* Called from usbd_cdc.c when host has sent bytes to device. + * The app handler (USBHandler::processUSBData) lives in C++; call it via a + * weak C hook so C++ can override without pulling USBHandler into this TU. */ +__attribute__((weak)) void CDC_on_receive(uint8_t *Buf, uint32_t Len) +{ + (void)Buf; (void)Len; +} + +static int8_t CDC_Receive_FS(uint8_t *Buf, uint32_t *Len) +{ + CDC_on_receive(Buf, *Len); + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]); + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + return USBD_OK; +} + +uint8_t CDC_Transmit_FS(uint8_t *Buf, uint16_t Len) +{ + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef *)hUsbDeviceFS.pClassDataCmsit[hUsbDeviceFS.classId]; + if (hcdc == NULL) return USBD_FAIL; + if (hcdc->TxState != 0) return USBD_BUSY; + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); + return USBD_CDC_TransmitPacket(&hUsbDeviceFS); +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.h b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.h new file mode 100644 index 0000000..edeac98 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_cdc_if.h @@ -0,0 +1,18 @@ +#ifndef __USBD_CDC_IF_H__ +#define __USBD_CDC_IF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "usbd_cdc.h" + +extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; + +uint8_t CDC_Transmit_FS(uint8_t *Buf, uint16_t Len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.c b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.c new file mode 100644 index 0000000..02216c6 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.c @@ -0,0 +1,165 @@ +#include "usbd_core.h" +#include "usbd_cdc.h" +#include "usbd_conf.h" + +PCD_HandleTypeDef hpcd_USB_OTG_FS; + +/* ---------- HAL → USBD LL bridge callbacks ---------- */ +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SetupStage((USBD_HandleTypeDef *)hpcd->pData, (uint8_t *)hpcd->Setup); +} + +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataOutStage((USBD_HandleTypeDef *)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); +} + +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_DataInStage((USBD_HandleTypeDef *)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); +} + +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_SOF((USBD_HandleTypeDef *)hpcd->pData); +} + +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_SpeedTypeDef speed = USBD_SPEED_FULL; + if (hpcd->Init.speed == PCD_SPEED_HIGH) speed = USBD_SPEED_HIGH; + USBD_LL_SetSpeed((USBD_HandleTypeDef *)hpcd->pData, speed); + USBD_LL_Reset((USBD_HandleTypeDef *)hpcd->pData); +} + +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_Suspend((USBD_HandleTypeDef *)hpcd->pData); + __HAL_PCD_GATE_PHYCLOCK(hpcd); +} + +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) +{ + USBD_LL_Resume((USBD_HandleTypeDef *)hpcd->pData); +} + +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef *)hpcd->pData, epnum); +} + +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + USBD_LL_IsoINIncomplete((USBD_HandleTypeDef *)hpcd->pData, epnum); +} + +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_DevConnected((USBD_HandleTypeDef *)hpcd->pData); } +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { USBD_LL_DevDisconnected((USBD_HandleTypeDef *)hpcd->pData); } + +/* ---------- HAL PCD MSP (clock + GPIO + NVIC) ---------- */ +void HAL_PCD_MspInit(PCD_HandleTypeDef *pcdHandle) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if (pcdHandle->Instance == USB_OTG_FS) + { + __HAL_RCC_GPIOA_CLK_ENABLE(); + /* PA11 = USB_OTG_FS_DM, PA12 = USB_OTG_FS_DP */ + GPIO_InitStruct.Pin = GPIO_PIN_11 | GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(OTG_FS_IRQn); + } +} + +void HAL_PCD_MspDeInit(PCD_HandleTypeDef *pcdHandle) +{ + if (pcdHandle->Instance == USB_OTG_FS) + { + __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11 | GPIO_PIN_12); + HAL_NVIC_DisableIRQ(OTG_FS_IRQn); + } +} + +/* ---------- USBD LL → HAL bridge ---------- */ +static USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status) +{ + switch (hal_status) { + case HAL_OK: return USBD_OK; + case HAL_ERROR: return USBD_FAIL; + case HAL_BUSY: return USBD_BUSY; + default: return USBD_FAIL; + } +} + +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) +{ + hpcd_USB_OTG_FS.pData = pdev; + pdev->pData = &hpcd_USB_OTG_FS; + + hpcd_USB_OTG_FS.Instance = USB_OTG_FS; + hpcd_USB_OTG_FS.Init.dev_endpoints = 6; + hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL; + hpcd_USB_OTG_FS.Init.dma_enable = DISABLE; + hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd_USB_OTG_FS.Init.Sof_enable = DISABLE; + hpcd_USB_OTG_FS.Init.low_power_enable = DISABLE; + hpcd_USB_OTG_FS.Init.lpm_enable = DISABLE; + hpcd_USB_OTG_FS.Init.vbus_sensing_enable= DISABLE; + hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = DISABLE; + + if (HAL_PCD_Init(&hpcd_USB_OTG_FS) != HAL_OK) Error_Handler(); + + HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 0x80); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 0x40); + HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 0x80); + return USBD_OK; +} + +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) { return USBD_Get_USB_Status(HAL_PCD_DeInit(pdev->pData)); } +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) { return USBD_Get_USB_Status(HAL_PCD_Start(pdev->pData)); } +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) { return USBD_Get_USB_Status(HAL_PCD_Stop(pdev->pData)); } + +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) +{ return USBD_Get_USB_Status(HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type)); } + +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { return USBD_Get_USB_Status(HAL_PCD_EP_Close(pdev->pData, ep_addr)); } +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { return USBD_Get_USB_Status(HAL_PCD_EP_Flush(pdev->pData, ep_addr)); } +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { return USBD_Get_USB_Status(HAL_PCD_EP_SetStall(pdev->pData, ep_addr)); } +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr){ return USBD_Get_USB_Status(HAL_PCD_EP_ClrStall(pdev->pData, ep_addr)); } + +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ + PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)pdev->pData; + if ((ep_addr & 0x80) == 0x80) return hpcd->IN_ep[ep_addr & 0x7F].is_stall; + return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; +} + +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) +{ return USBD_Get_USB_Status(HAL_PCD_SetAddress(pdev->pData, dev_addr)); } + +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) +{ return USBD_Get_USB_Status(HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size)); } + +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) +{ return USBD_Get_USB_Status(HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size)); } + +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) +{ return HAL_PCD_EP_GetRxCount(pdev->pData, ep_addr); } + +/* ---------- static allocator (USBD_malloc / free) ---------- */ +void *USBD_static_malloc(uint32_t size) +{ + static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef) / 4) + 1]; + (void)size; + return mem; +} + +void USBD_static_free(void *p) { (void)p; } diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.h b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.h new file mode 100644 index 0000000..8906fb7 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_conf.h @@ -0,0 +1,44 @@ +#ifndef __USBD_CONF__H__ +#define __USBD_CONF__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stm32f7xx.h" +#include "stm32f7xx_hal.h" +#include +#include +#include + +#define USBD_MAX_NUM_INTERFACES 1U +#define USBD_MAX_NUM_CONFIGURATION 1U +#define USBD_MAX_STR_DESC_SIZ 512U +#define USBD_SELF_POWERED 1U +#define USBD_DEBUG_LEVEL 0U +#define USBD_LPM_ENABLED 0U +#define USBD_SUPPORT_USER_STRING_DESC 0U +#define USBD_CDC_INTERVAL 2000U + +#define DEVICE_FS 0 + +#define USBD_malloc USBD_static_malloc +#define USBD_free USBD_static_free +#define USBD_memset memset +#define USBD_memcpy memcpy +#define USBD_Delay HAL_Delay + +#define USBD_UsrLog(...) do {} while (0) +#define USBD_ErrLog(...) do {} while (0) +#define USBD_DbgLog(...) do {} while (0) + +void *USBD_static_malloc(uint32_t size); +void USBD_static_free(void *p); + +void Error_Handler(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.c b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.c new file mode 100644 index 0000000..15bd9c4 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.c @@ -0,0 +1,104 @@ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_conf.h" + +#define USBD_VID 0x0483 /* STMicroelectronics */ +#define USBD_PID_FS 0x5740 /* STM32 Virtual COM Port */ +#define USBD_LANGID_STRING 0x0409 /* English (US) */ +#define USBD_MANUFACTURER_STRING "STMicroelectronics" +#define USBD_PRODUCT_STRING_FS "AERIS-10 Radar Virtual COM Port" +#define USBD_CONFIGURATION_STRING_FS "CDC Config" +#define USBD_INTERFACE_STRING_FS "CDC Interface" + +#ifndef USB_SIZ_STRING_SERIAL +#define USB_SIZ_STRING_SERIAL 0x1A +#endif + +static uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +static uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); + +USBD_DescriptorsTypeDef FS_Desc = { + USBD_FS_DeviceDescriptor, + USBD_FS_LangIDStrDescriptor, + USBD_FS_ManufacturerStrDescriptor, + USBD_FS_ProductStrDescriptor, + USBD_FS_SerialStrDescriptor, + USBD_FS_ConfigStrDescriptor, + USBD_FS_InterfaceStrDescriptor, +}; + +__ALIGN_BEGIN static uint8_t USBD_FS_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { + 0x12, /* bLength */ + USB_DESC_TYPE_DEVICE, /* bDescriptorType */ + 0x00, 0x02, /* bcdUSB 2.00 */ + 0x02, /* bDeviceClass: CDC */ + 0x02, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + USB_MAX_EP0_SIZE, /* bMaxPacketSize0 */ + LOBYTE(USBD_VID), HIBYTE(USBD_VID), + LOBYTE(USBD_PID_FS), HIBYTE(USBD_PID_FS), + 0x00, 0x02, /* bcdDevice 2.00 */ + USBD_IDX_MFC_STR, + USBD_IDX_PRODUCT_STR, + USBD_IDX_SERIAL_STR, + USBD_MAX_NUM_CONFIGURATION +}; + +__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), HIBYTE(USBD_LANGID_STRING), +}; + +__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; + +/* 12-char serial derived from 96-bit unique device ID */ +__ALIGN_BEGIN static uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = { + USB_SIZ_STRING_SERIAL, USB_DESC_TYPE_STRING, +}; + +static void IntToUnicode(uint32_t value, uint8_t *pbuf, uint8_t len) +{ + for (uint8_t idx = 0; idx < len; idx++) { + uint8_t nibble = (value >> 28) & 0x0F; + pbuf[2 * idx] = (nibble < 10) ? ('0' + nibble) : ('A' + nibble - 10); + pbuf[2 * idx + 1] = 0; + value <<= 4; + } +} + +static void Get_SerialNum(void) +{ + uint32_t deviceserial0 = *(uint32_t *)UID_BASE; + uint32_t deviceserial1 = *(uint32_t *)(UID_BASE + 4); + uint32_t deviceserial2 = *(uint32_t *)(UID_BASE + 8); + deviceserial0 += deviceserial2; + IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8); + IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); +} + +static uint8_t *USBD_FS_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ (void)speed; *length = sizeof(USBD_FS_DeviceDesc); return USBD_FS_DeviceDesc; } + +static uint8_t *USBD_FS_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ (void)speed; *length = sizeof(USBD_LangIDDesc); return USBD_LangIDDesc; } + +static uint8_t *USBD_FS_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ (void)speed; USBD_GetString((uint8_t *)USBD_PRODUCT_STRING_FS, USBD_StrDesc, length); return USBD_StrDesc; } + +static uint8_t *USBD_FS_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ (void)speed; USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); return USBD_StrDesc; } + +static uint8_t *USBD_FS_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ (void)speed; *length = USB_SIZ_STRING_SERIAL; Get_SerialNum(); return USBD_StringSerial; } + +static uint8_t *USBD_FS_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ (void)speed; USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING_FS, USBD_StrDesc, length); return USBD_StrDesc; } + +static uint8_t *USBD_FS_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ (void)speed; USBD_GetString((uint8_t *)USBD_INTERFACE_STRING_FS, USBD_StrDesc, length); return USBD_StrDesc; } diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.h b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.h new file mode 100644 index 0000000..4d9f769 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/usbd_desc.h @@ -0,0 +1,16 @@ +#ifndef __USBD_DESC_H +#define __USBD_DESC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "usbd_def.h" + +extern USBD_DescriptorsTypeDef FS_Desc; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/9_Firmware/9_1_Microcontroller/Makefile b/9_Firmware/9_1_Microcontroller/Makefile index 6fba2dc..dbce95e 100644 --- a/9_Firmware/9_1_Microcontroller/Makefile +++ b/9_Firmware/9_1_Microcontroller/Makefile @@ -1,19 +1,12 @@ # ============================================================================ -# AERIS-10 STM32F746ZGT7 firmware build (PR 1: compile-only) +# AERIS-10 STM32F746ZGT7 firmware build # ============================================================================ # Part: STM32F746ZGT7 (Cortex-M7, 1 MB flash, 320 KB RAM, 216 MHz, LQFP144) # Toolchain: arm-none-eabi-gcc 15.x (brew --cask gcc-arm-embedded) # -# PR 1 scope: compile every source file to an object. Linking is expected to -# fail because STM32CubeIDE-generated glue (main.c entry, SystemClock_Config, -# MX_*_Init, stm32f7xx_it.c, stm32f7xx_hal_msp.c, linker script, USB CDC -# glue) is missing. PR 2 will hand-write those files and close the link. -# # Targets: -# make -- compile all .c/.cpp/.s to objects (default) -# make compile -- same -# make link -- attempt to link (WILL FAIL in PR 1; left here so the -# missing-symbol list drives PR 2 scope) +# make -- compile + link, produces firmware.elf/.bin/.hex (default) +# make compile -- compile only (stops at objects) # make clean -- remove build/ # ============================================================================ @@ -63,25 +56,24 @@ CXXFLAGS := $(COMMON) -std=gnu++17 -fno-exceptions -fno-rtti -fno-threadsafe-sta ASFLAGS := $(MCU) $(DEFS) -g3 # ---- sources --------------------------------------------------------------- -# Application C/C++ -# main.cpp needs Cube-generated usb_device.h / usbd_cdc_if.h — PR 2 target. -# Exclude from PR 1 compile; um982_gps.c/.h compile cleanly and stay in. -APP_C := $(wildcard $(APP)/*.c) -APP_CPP_ALL := $(wildcard $(APP)/*.cpp) -APP_CPP := $(filter-out $(APP)/main.cpp, $(APP_CPP_ALL)) +# App C/C++ — PR 2 adds usb_device.c, usbd_conf.c, usbd_desc.c, usbd_cdc_if.c +# (wildcard picks them up) and re-enables main.cpp + gps_handler.cpp. +APP_C := $(wildcard $(APP)/*.c) +APP_CPP := $(wildcard $(APP)/*.cpp) LIB_C := $(wildcard $(LIB)/*.c) -# gps_handler.cpp includes usb_device.h (Cube glue) — deferred to PR 2 -LIB_CPP := $(filter-out $(LIB)/gps_handler.cpp, $(wildcard $(LIB)/*.cpp)) +LIB_CPP := $(wildcard $(LIB)/*.cpp) -# Vendor: all enabled HAL modules compile cleanly because each _hal_.c is -# guarded by `#ifdef HAL__MODULE_ENABLED` in stm32f7xx_hal_conf.h. -# Build every .c in Src/ and let the guard do the filtering. -# Exclude *_template.c — ST ships these as user-copy stubs, not compile targets +# Vendor HAL: each _hal_.c is guarded by HAL__MODULE_ENABLED in +# stm32f7xx_hal_conf.h, so compiling all of them is safe. Skip ST's +# *_template.c stubs (user-copy boilerplate, not compile targets). HAL_C := $(filter-out %_template.c, $(wildcard $(VENDOR)/stm32f7xx_hal_driver/Src/*.c)) -# USB Device Library requires a user-written usbd_conf.h (Cube glue, PR 2). -# PR 1 leaves this empty so the vendor tree compiles without that config. -USB_C := -SYS_C := $(VENDOR)/cmsis_device_f7/Source/Templates/system_stm32f7xx.c +# USB Device library: Core + CDC class (skip *_template.c user stubs). +USB_C := $(filter-out %_template.c, \ + $(wildcard $(VENDOR)/stm32_mw_usb_device/Core/Src/*.c) \ + $(wildcard $(VENDOR)/stm32_mw_usb_device/Class/CDC/Src/*.c)) +# system_stm32f7xx.c already lives in 9_1_1_C_Cpp_Libraries/ (app-customised); +# drop the vendor copy to avoid duplicate symbols. +SYS_C := STARTUP := $(VENDOR)/cmsis_device_f7/Source/Templates/gcc/startup_stm32f746xx.s SRCS_C := $(APP_C) $(LIB_C) $(HAL_C) $(USB_C) $(SYS_C) @@ -95,8 +87,7 @@ OBJS := \ DEPS := $(OBJS:.o=.d) -# ---- link (PR 2) ----------------------------------------------------------- -# Linker script is hand-written in PR 2 at linker/STM32F746ZGTx_FLASH.ld +# ---- link ------------------------------------------------------------------ LDSCRIPT := linker/STM32F746ZGTx_FLASH.ld LDFLAGS := $(MCU) -T$(LDSCRIPT) -Wl,--gc-sections -Wl,-Map=$(BUILD)/firmware.map \ -specs=nano.specs -specs=nosys.specs -static @@ -108,7 +99,7 @@ HEX := $(BUILD)/firmware.hex # ---- rules ----------------------------------------------------------------- .PHONY: all compile link clean size -all: compile +all: link compile: $(OBJS) @echo "compiled $(words $(OBJS)) objects" diff --git a/9_Firmware/9_1_Microcontroller/linker/STM32F746ZGTx_FLASH.ld b/9_Firmware/9_1_Microcontroller/linker/STM32F746ZGTx_FLASH.ld new file mode 100644 index 0000000..1b35406 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/linker/STM32F746ZGTx_FLASH.ld @@ -0,0 +1,134 @@ +/* +****************************************************************************** +** STM32F746ZGTx linker script (AERIS-10 PR 2) +** +** Memory layout (STM32F746ZGT7, LQFP144, 1 MB flash / 320 KB RAM): +** ITCM : 0x00000000, 16 KB (CPU tightly-coupled instruction RAM) +** FLASH : 0x08000000, 1 MB +** DTCM : 0x20000000, 64 KB (CPU tightly-coupled data RAM — stack/heap) +** RAM : 0x20010000,256 KB (SRAM1 240 KB + SRAM2 16 KB contiguous) +** +** Entry: Reset_Handler (from vendor/cmsis_device_f7 startup). +** Heap: grows up from _end. Stack: grows down from end of DTCM (_estack). +****************************************************************************** +*/ + +ENTRY(Reset_Handler) + +_estack = ORIGIN(DTCM) + LENGTH(DTCM); /* top of DTCM for MSP */ +_Min_Heap_Size = 0x200; +_Min_Stack_Size = 0x400; + +MEMORY +{ + ITCM (rx) : ORIGIN = 0x00000000, LENGTH = 16K + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K + DTCM (rw) : ORIGIN = 0x20000000, LENGTH = 64K + RAM (rw) : ORIGIN = 0x20010000, LENGTH = 256K +} + +SECTIONS +{ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) + . = ALIGN(4); + } >FLASH + + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + KEEP (*(.init)) + KEEP (*(.fini)) + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + _sidata = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + . = ALIGN(4); + _edata = .; + } >DTCM AT> FLASH + + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = .; + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + __bss_end__ = _ebss; + } >DTCM + + ._user_heap_stack (NOLOAD) : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >DTCM + + /* Larger buffers can be placed in .sram using __attribute__((section(".sram"))) */ + .sram (NOLOAD) : + { + . = ALIGN(4); + *(.sram) + *(.sram*) + . = ALIGN(4); + } >RAM + + /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } + + .ARM.attributes 0 : { *(.ARM.attributes) } +}