分析GD32H759 用vscode+eide开发的一些问题
GD32H759IMK6 芯片,野火的开发板用VSCode + EIDE + Arm GNU Toolchain 工具 11.3.Rell版编译xpack+openocd + fireDAP仿真器下载运行用VSCode带的 Cortex-Debug插件进行debug时,内存变量值经常取不到,都显示是个0。先怀疑是缓存的问题,使用SCB_InvalidateDCache_by_Addr命令先对要看的内存进行“Invalidate”操作后,可以看到断点时该变量的值。但只能对专门这样分配的全局内存数据起效果,对于局部变量没有用。只能进行一些简单的调试判断。今天又增加了LWIP功能,结果用gcc编译的在启动使用netconn api写的网络数据进程时,直接死掉了。调试因为变量无论怎么断点看都是个0值,没法调试看问题出在哪里。同样的工程在IAR上编译调度时,没有这个问题。都能正常运行。我是一份代码做了两个调试环境。IAR就没这些问题。另外,GD自己的模板生成系统生成的示例代码工程中,对GD32H7xx系列的*.ld文件过于简单,1024kB+16+ 16KB的RAM,ld文件里面只给定义了512kB。这个LD文件 有人扩写调试好的版本有没?除了Keil和IAR两个收费的开发工具外,开源的IDE工具还有哪些能用的?这些说的是什么?以下是对您所描述问题的分析及解决方案建议:
一、内存变量调试显示为0的问题
1. 局部变量无法显示值的原因
栈溢出或内存分配问题:GCC编译时栈消耗较大,可能引发栈溢出。虽然已尝试将`__stack_size`设为4K,但实际栈需求可能更高(尤其加入LWIP后)。建议进一步增大栈尺寸(如尝试8K或更大),并检查任务栈是否足够。
编译器优化导致变量未初始化:GCC的优化选项(如`-O2`或`-O3`)可能将未使用的局部变量优化掉,或在初始化前跳过赋值。可以尝试以下措施:
在变量声明后立即赋值(如`ip_addr_t server_ip = {0};`)。
编译时关闭优化(如使用`-O0`)以验证是否为优化问题。
检查是否有其他代码路径导致变量未正确初始化。
2. 缓存问题的影响
手动缓存失效的局限性:`SCB_InvalidateDCache_by_Addr`仅对全局变量有效,因为全局变量的地址是固定的,而局部变量的地址在栈中动态变化,难以手动失效。建议在调试时禁用缓存(通过链接器脚本或启动代码配置`SPECULATE_DISABLE`),或者在关键代码段前手动执行`__builtin_dsb()`和`__builtin_isb()`确保内存屏障。
二、增加LWIP后进程崩溃的分析
1. 可能的原因
内存分配冲突:LWIP需要大量RAM(如PBUF、TCP控制块等),如果堆栈与堆空间重叠或不足,可能导致内存破坏。需检查`ld`文件中`.bss`和`.heap`段的定义是否合理。
任务优先级或资源竞争**:LWIP的TCP/IP任务可能与其他任务竞争资源。建议参考第8条回复,调整LWIP任务优先级,并确保网络处理任务优先级较高。
初始化顺序问题**:LWIP初始化需在网络硬件(如以太网MAC)初始化之后。检查`NetComm_ClientProcess`调用前是否完成LWIP和硬件的初始化。
2. 调试建议
单步跟踪:在`Task_NetCommunate`中逐步执行,观察`server_ip.addr`何时被覆盖为0。
检查LWIP配置:确认LWIP的内存堆(`mem_init`)和线程安全配置是否正确。
对比IAR编译差异:比较GCC与IAR的编译选项(如优化等级、栈对齐方式),以及生成的映射文件(`.map`)是否一致。
三、GD32H7xx系列LD文件扩展问题
1. 默认LD文件的局限性
GD官方模板的`.ld`文件可能仅定义了部分RAM区域(如512KB),而实际芯片有1024KB RAM。需手动扩展`.ld`文件中的`RAM`段:
```ld
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 3840K
RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 1024K /* 扩展为1024KB */
}
SECTIONS
{
.bss :
{
__bss_start__ = .;
*(.bss)
*(COMMON)
__bss_end__ = .;
} > RAM
}
```
2. 野火开发板适配
若野火开发板的硬件设计支持完整1024KB RAM,可直接修改`.ld`文件。否则需检查是否存在内存分区冲突(如外设映射到高地址RAM)。
四、开源IDE工具推荐
除了Keil和IAR,以下开源工具可替代商业IDE:
1. VSCode + PlatformIO:
优势:跨平台、支持多种框架(如Arduino、STM32Cube)、集成库管理。
配置:安装`PlatformIO IDE`扩展,通过`platformio.ini`配置GD32编译工具链。
2. Eclipse + CDT(C/C++ Development Tooling):
优势:成熟稳定,支持GCC、OpenOCD调试。
配置:安装`CDT`插件,集成Arm GNU Toolchain和OpenOCD。
3. Zephyr RTOS IDE:
优势:专为嵌入式开发设计,支持GD32等架构,内置编译和调试工具。
官网:Zephyr Project
4. SEGGER Embedded Studio:
优势:免费版支持GCC,界面类似Keil,适合快速上手。
五、其他建议
1. 验证硬件连接:确保野火开发板的JTAG/SWD接口与fireDAP仿真器兼容,排除硬件故障。
2. 最小化测试:创建一个仅包含LWIP核心功能的空白工程,逐步添加代码以定位崩溃点。
3. 社区支持:参考GD32社区(如CSDN、GitHub)的类似问题,或联系野火科技获取技术支持。
通过以上步骤,您应能定位内存变量异常和LWIP崩溃的问题,并扩展`.ld`文件以充分利用芯片资源。如需进一步协助,可提供具体代码片段或编译日志。 关闭SCB_EnableDCache() 这个之后,再将栈调整到6kB,可以运行了,也有崩溃的时候。再调整栈大小到8K,不崩溃了。
但是只要打开了SCB_EnableDCache(),就必崩溃。
IAR中打开SCB_EnableDCache(),不会崩溃,检查了两个编译环境的宏,关于SCB_EnableDCache() 中两个是一样的,不存在IAR与GCC编译的源码不一样的情况。
两个程序map,再对比看看。 经过对比IAR与GCC的map文件
发现是0x30000000处这个SRAM0区域,在ld文件中没有定义,而在gd32h7xx_enet.c这个驱动文件中,
又是用
#elif defined (__GNUC__) /* GNU Compiler */
enet_descriptors_structrxdesc_tab __attribute__((section(".ARM.__at_0x30000000"))); /*!< ENET RxDMA descriptor */
enet_descriptors_structtxdesc_tab __attribute__((section(".ARM.__at_0x30000160"))); /*!< ENET TxDMA descriptor */
uint8_t rx_buff __attribute__((section(".ARM.__at_0x30000300"))); /*!< ENET receive buffer */
uint8_t tx_buff __attribute__((section(".ARM.__at_0x30002100"))); /*!< ENET transmit buffer */
#endif /* __CC_ARM */
造成了内存分配区的混乱
于是,将LD文件修改如下:
增加:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 3840K
RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 768K
SRAM0 (xrw) : ORIGIN = 0x30000000, LENGTH = 16K
SRAM1 (xrw) : ORIGIN = 0x30040000, LENGTH = 16K
}
增加
.enetram :
{
. = ALIGN(4);
_senetram = .;
__enetram_start__ = _senetram;
*(.ARM.__at_0x3*)
*(.ARM.__at_0x3)
. = ALIGN(4);
_eenetram = .;
__enetram_end__ = _eenetram;
} >SRAM0 AT> FLASH
再次打开DCache就没有问题了。
现在还有两个小问题,不得其解,上面的RAM如果把大小修改为1024K,同样会崩溃。
下面的内存分配段描述中,如果不加 AT>FLASH,下载到芯片时,会提示:
** Verify Started **
Error: checksum mismatch - attempting binary compare
embedded:startup.tcl:1136: Error: ** Verify Failed **
in procedure 'program'
in procedure 'program_error' called at file "embedded:startup.tcl", line 1197
at file "embedded:startup.tcl", line 1136
*终端进程“cmd.exe /C ""C:\Program Files (x86)\openocd\bin\openocd.exe" -s "c:\Users\*******\Documents\MCUProjects\GD32H7TestSample\xTUCoreBoardPrj" -f interface/cmsis-dap.cfg -f gd32h7xx.cfg -c "program \"c:/Users/********/Documents/MCUProjects/GD32H7TestSample/xTUCoreBoardPrj/GccBuild/Debug/xTUCoreBoardPrj.hex\" verify" -c "reset run" -c "exit""”已终止,退出代码: 1。
*终端将被任务重用,按任意键关闭。
这两个小问题暂时不知道如何解决
shuwei1984 发表于 2025-4-25 22:10
经过对比IAR与GCC的map文件
发现是0x30000000处这个SRAM0区域,在ld文件中没有定义,而在gd32h7xx_enet.c ...
我们同龄,年相近也,道相似也,
在AI浪潮下,
一个问题的价值高于答案,
问题指明了答案。
我估计是容量小了不行,未论证。
手上也没有你的开发板,
不过我相信你的能力,
相信一觉醒来,
你会给我答案。 丙丁先生 发表于 2025-4-25 22:40
我们同龄,年相近也,道相似也,
在AI浪潮下,
一个问题的价值高于答案,
老哥我很怀疑你是ai自动回复啊,不过我看了这个帖子我也没看明白是啥,可能是我GD的板子用的少的缘故吧。 cooldog123pp 发表于 2025-4-26 13:35
老哥我很怀疑你是ai自动回复啊,不过我看了这个帖子我也没看明白是啥,可能是我GD的板子用的少的缘故吧。 ...
GD32F427我有一块,没有深入研究,主要是没有例程和博文,我这就用起来,点灯/UART/PWM呼吸灯/舵机/上ST7735,IIC,温度值UART,好像别的我不会什么了,又好像可以用AI调试程序。其实上文的方法是通行的解决方法,解决问题的不是我,而是楼主自己,是更高级的调试,我也不懂,但是我相信AI给出的答案是对的,因为我有十几次以上运行AI的例程+自己的想法完成简单场景。是可靠的。 感谢关注。
页:
[1]