本篇只是一个记录,没啥可看的。
STM32H750硬件相关
STM32H750可以通过USB-OTG下载程序,也可以使用SWD进行调试,所以设计板子得时候将PA13和PA12预留出来即可,后续也可以用作usb虚拟串口(CDC)功能或者模拟U盘功能,这里使用常规USB(12MHz)即可,高速USB需要外置USB控制IC,比较麻烦。
SWD接口不用多说了,直接引出来就可以了,直接使用DAP、STLink、JTAG都可以进行烧写调试。
使用USB烧写程序,需要用到STM32CubeProgrammer就可以烧写程序了,上电时按住BOOT键,就可以进入DFU模式进行烧写了。或者按住BOOT键时再按RST键也可以进入DFU模式,注意,如果程序已经将USB作为其他功能,比如模拟U盘或者虚拟串口功能,此时电脑只会显示USB拔出,但不会显示DFU的COM口,或者显示错误的设备,此时就需要将设备删除了,使用方法1即在上电时按住BOOT键就可以正常进入DFU模式进行烧写了。
这里顺便说一句CuebIDE如何使用DAP进行调试
可以参考这篇文章:
STM32CubeIDE用DAP调试的超级无敌简单方法——2022.01.07_ZZZ_XXJ的博客-CSDN博客_stm32cubeide调试
最后晒一下我设计的板子
STM32H750主频相关
这里我用的晶振是8Mhz,通过PLL倍频到400MHz,虽然官方手册上说明STM32H750支持480Mhz,但是我经过测试,主频超过400Mhz,电路就工作不正常。经过网上搜索,似乎第一批出货的STM32H750ZBT6的VCO最高输出就836Mhz,即经过二分频后也就是418Mhz,后面批次的STM32H750ZBT6才可以支持到480Mhz。
使用CubeMX配置时钟树,如果选择STM32H750ZBT6如果配置的主频超过400Mzh,MX也会提示时钟配置错误。所以这里索性统一配置为400Mhz,为了后面方便调试。
STM32H750内存相关
CubeIDE默认的ld文件是将变量加载到AXI SARM,代码在Flash中执行的,没有用到其自带Dcach和Icach,所以我们可以修改ld文件使其代码加载到Icach中执行和重要数据加载到Dcach中,这两块cache都400Mhz的,和CPU直接连接,但是只有128Kb,所以要做好规划。
以下是我编写的LD文件
/*
******************************************************************************
**
** File : LinkerScript.ld
**
** Author : STM32CubeIDE
**
** Abstract : Linker script for STM32H7 series
** 128Kbytes FLASH and 1056Kbytes RAM
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
**
** Distribution: The file is distributed as is, without any warranty
** of any kind.
**
*****************************************************************************
** @attention
**
** Copyright (c) 2022 STMicroelectronics.
** All rights reserved.
**
** This software is licensed under terms that can be found in the LICENSE file
** in the root directory of this software component.
** If no LICENSE file comes with this software, it is provided AS-IS.
**
****************************************************************************
*//* Entry Point */
ENTRY(Reset_Handler)/* Highest address of the user mode stack */
_estack = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM); /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x1000; /* required amount of heap */
_Min_Stack_Size = 0x1000; /* required amount of stack *//* Specify the memory areas */
MEMORY
{FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 3*128KDTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128KRAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512KRAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288KRAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64KITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
}/* Define output sections */
SECTIONS
{/* The startup code goes first into FLASH */.isr_vector :{. = ALIGN(4);KEEP(*(.isr_vector)) /* Startup code */. = ALIGN(4);} >FLASH/* The program code and other data goes into FLASH */.text :{. = ALIGN(4);*(.text) /* .text sections (code) */*(.text*) /* .text* sections (code) */*(.glue_7) /* glue arm to thumb code */*(.glue_7t) /* glue thumb to arm code */*(.eh_frame)KEEP (*(.init))KEEP (*(.fini)). = ALIGN(4);_etext = .; /* define a global symbols at end of code */} >FLASH/* Constant data goes into FLASH */.rodata :{. = ALIGN(4);*(.rodata) /* .rodata sections (constants, strings, etc.) */*(.rodata*) /* .rodata* sections (constants, strings, etc.) */. = 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/* used by the startup to initialize data */_sidata = LOADADDR(.data);/* Initialized data sections goes into RAM, load LMA copy after code */.data :{. = ALIGN(4);_sdata = .; /* create a global symbol at data start */*(.data) /* .data sections */*(.data*) /* .data* sections */*(.RamFunc) /* .RamFunc sections */*(.RamFunc*) /* .RamFunc* sections */. = ALIGN(4);_edata = .; /* define a global symbol at data end */} >DTCMRAM AT> FLASH/* Uninitialized data section */. = ALIGN(4);.bss :{/* This is used by the startup in order to initialize the .bss section */_sbss = .; /* define a global symbol at bss start */__bss_start__ = _sbss;*(.bss)*(.bss*)*(COMMON). = ALIGN(4);_ebss = .; /* define a global symbol at bss end */__bss_end__ = _ebss;} >DTCMRAM/* User_heap_stack section, used to check that there is enough RAM left */._user_heap_stack :{. = ALIGN(8);PROVIDE ( end = . );PROVIDE ( _end = . );. = . + _Min_Heap_Size;. = . + _Min_Stack_Size;. = ALIGN(8);} >DTCMRAM.RAM_D1(NOLOAD) :{. = ALIGN(4);*(.RAM_D1) /* .data sections */ . = ALIGN(4);} >RAM_D1.RAM_D2(NOLOAD) :{. = ALIGN(4);*(.RAM_D2) /* .data sections */ . = ALIGN(4);} >RAM_D2.RAM_D3(NOLOAD) :{. = ALIGN(4);*(.RAM_D3) /* .data sections */ . = ALIGN(4);} >RAM_D3.ITCM :{. = ALIGN(4);__itcm_start = .;*(.ITCM). = ALIGN(4);__itcm_end = .;} > ITCMRAM AT>FLASH__itcm_rom_start = LOADADDR(.ITCM);__itcm_size = SIZEOF(.ITCM);/* Remove information from the standard libraries *//DISCARD/ :{libc.a ( * )libm.a ( * )libgcc.a ( * )}.ARM.attributes 0 : { *(.ARM.attributes) }
}
以下是C初始化代码
void ICache_Copy(void)
{uint32_t* p__itcm_start= &__itcm_start;uint32_t* p__itcm_rom_start= &__itcm_rom_start;uint32_t* p__itcm_size= &__itcm_size;memcpy(p__itcm_start,p__itcm_rom_start,(uint32_t)p__itcm_size);
}
void MPU_Cache_Init(void)
{MPU_Region_InitTypeDef MPU_InitStruct;HAL_MPU_Disable();__HAL_RCC_D2SRAM1_CLK_ENABLE();__HAL_RCC_D2SRAM2_CLK_ENABLE();__HAL_RCC_D2SRAM3_CLK_ENABLE();/* 配置 AXI SRAM 的 MPU 属性为 Write back, Read allocate,Write allocate */MPU_InitStruct.Enable = MPU_REGION_ENABLE;MPU_InitStruct.BaseAddress = 0x24000000;MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;MPU_InitStruct.Number = MPU_REGION_NUMBER0;MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;MPU_InitStruct.SubRegionDisable = 0x00;MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);/* 配置 SRAM1 的属性为 Write through, read allocate,no write allocate */MPU_InitStruct.Enable = MPU_REGION_ENABLE;MPU_InitStruct.BaseAddress = 0x30000000;MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_128KB;MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;MPU_InitStruct.Number = MPU_REGION_NUMBER2;MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;MPU_InitStruct.SubRegionDisable = 0x00;MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);/* 配置 SRAM2 的属性为 Write through, read allocate,no write allocate */MPU_InitStruct.Enable = MPU_REGION_ENABLE;MPU_InitStruct.BaseAddress = 0x30020000;MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_128KB;MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;MPU_InitStruct.Number = MPU_REGION_NUMBER3;MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;MPU_InitStruct.SubRegionDisable = 0x00;MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);/* 配置 SRAM3 的属性为 Write through, read allocate,no write allocate */MPU_InitStruct.Enable = MPU_REGION_ENABLE;MPU_InitStruct.BaseAddress = 0x30040000;MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_32KB;MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;MPU_InitStruct.Number = MPU_REGION_NUMBER4;MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;MPU_InitStruct.SubRegionDisable = 0x00;MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);/* 配置 SRAM4 的属性为 Write through, read allocate,no write allocate */MPU_InitStruct.Enable = MPU_REGION_ENABLE;MPU_InitStruct.BaseAddress = 0x38000000;MPU_InitStruct.Size = ARM_MPU_REGION_SIZE_64KB;MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;MPU_InitStruct.Number = MPU_REGION_NUMBER5;MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;MPU_InitStruct.SubRegionDisable = 0x00;MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;HAL_MPU_ConfigRegion(&MPU_InitStruct);/*使能 MPU */HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);/* 使能 I-Cache */SCB_EnableICache();/* 使能 D-Cache */SCB_EnableDCache();}
需要相关变量保存到特定内存,可以这样写
__attribute__((section (".RAM_D1"))) uint64_t AppMallocAXISRAM[256*1024/8];
需要相关代码保存到Icache中,可以这样写
__attribute__((section (".ITCM"))) void MPU_Cache_TestProgess(void)
{uint32_t *AXISRAM_Addres0;mem_head_t *AXISRAMUsed;osRtxMemoryInit(AppMallocAXISRAM, sizeof(AppMallocAXISRAM));AXISRAM_Addres0 = osRtxMemoryAlloc(AppMallocAXISRAM, 5000, 0);AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);usb_printf("AXI SRAM Total Size = %d Byte,apply for size is 5000 Byte,Now Used Byte = %d Byte\r\n",AXISRAMUsed->size, AXISRAMUsed->used);osRtxMemoryFree(AppMallocAXISRAM, AXISRAM_Addres0);AXISRAMUsed = MemHeadPtr(AppMallocAXISRAM);usb_printf("Free AXI SRAM apply 5000 Byte,Now Used Byte = %d Byte\r\n", AXISRAMUsed->used);
}
STM32H750板子自测
USB-CDC
高精度/高频率可调PWM
1Mhz PWM @ 精度0.25%
25% 1MHz 10ns死区 互补输出
ADC
12Bit 20Mhz ADC 量程3.3V 绝对误差约为0.09V 相对误差为 4.09% 量程误差为2.34%
SPI-FLASH
工作频率100Mhz Flash QSPI 读取/写入速度:48.83MB/S
SD卡
工作频率50Mhz
外扩SD卡读取\写入速度:25MB/S
搭配FatFS文件系统, 实现文件夹建立、删除,数据表格导出、导入功能