本篇只是一个记录,没啥可看的。
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*128K
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
ITCMRAM (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文件系统, 实现文件夹建立、删除,数据表格导出、导入功能