STM32H750自制开发板调试经验

news/2025/1/18 7:00:46/

​本篇只是一个记录,没啥可看的。

 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模式进行烧写了。

https://img-blog.csdnimg.cn/1328ccdba5754eb5a119ac2a8369eb53.png

这里顺便说一句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文件系统, 实现文件夹建立、删除,数据表格导出、导入功能

   

 


http://www.ppmy.cn/news/8260.html

相关文章

小程序框架

目录 一、框架 1.页面管理 2.基础组件 3.丰富的API 二、小程序视图层 1.响应的数据绑定 2.列表渲染 3.条件渲染 4.模板 三、小程序事件 1.什么是事件 2.事件的使用方式 3.使用 WXS 函数响应事件 4.事件详解 ① 事件分类 ② 普通事件绑定 ③ 绑定并阻止…

2022年学习机器人和人工智能的一些期待

2022年学习机器人和人工智能的一些体会 2023年即将到来,满满的期待。 做好规划是非常非常重要的,有时候甚至比认真做事本身更为重要。 《礼记中庸》:“凡事豫则立,不豫则废。言前定则不跲,事前定则不困,行…

django笔记《内置用户认证系统》

文章目录1 前言2 django.contrib.auth3 使用django的用户认证系统3.1 创建一个新的django项目3.2 做数据库迁移3.3 auth_user表结构3.4 创建一个新用户3.5 User对象3.5.1 创建用户 create_user3.5.2 request.user3.5.3 用户在视图函数中登录3.5.4 关键函数3.6 保护视图函数的方…

【leetcode】剑指offer1

&#x1f308;1.Pow(x,n) -100.0 < x < 100.0-2^31 < n < 2^31-1n 是一个整数-10^4 < x^n < 10^4思路分析&#xff1a; 暴力求解直接一个for循环n个x相乘解决&#xff0c;但是你拿那代码怎么好意思拿高薪&#xff1f; 所以而且那个的时间复杂度是O(n),效率并…

RHCE第一天之Linux例行性工作at、crontab详解

文章目录一、学习内容总结1、单一执行的例行性工作at2、循环执行的例行性工作crontab二、作业at和crontab的使用一、学习内容总结 1、单一执行的例行性工作at **概念&#xff1a;**指仅处理执行一次就结束了的工作。 要使用单一工作调度时&#xff0c;linux上面需要有负责这个…

【django】HttpRequest对象的属性和路由补充

文章目录一、HttpRequest对象的常用属性1、request.GET&#xff1a;获取查询字符串参数案例:特别注意&#xff1a;2、request.POST&#xff1a;post请求数据&#xff0c;只能获取表单参数3、request.body&#xff1a;请求body&#xff0c;响应结果为字节类型4、request.method&…

第十二篇 1+X考证 Web前端测试题PHP篇(新)

单选题 1、以下关于PHP面向对象的说法错误的是&#xff08; A &#xff09; A、PHP可以多重继承&#xff0c;一个类可以继承多个父类 B、PHP使用new运算符来获取一个实例对象 C、一个类可以在声明中用extends关键字继承另一个类的方法和属性 D、PHP默认将var关键字解释为pu…

【linux】进程控制

文章目录一、进程创建1、三个小问题2、写时拷贝3、fork函数常规使用方法4、fork函数调用失败原因二、进程终止&#xff08;进程退出&#xff09;1、退出码2、echo $?指令3、进程退出场景4、进程如何退出5、exit和_exit的关系6、进程终止总结三、进程等待1、进程等待的必要2、w…