我将尽可能好地描述这个问题,并详细说明我尝试解决它的所有问题,但我不确定是否能够捕获所有问题,因为我一直在遇到一些奇怪的行为。我将首先说明这个问题,使用STM32CubeIDE时根本不会出现这个问题。这个问题只是在我使用VSCode for STM32(使用Makefile、OpenOCD、和GDB。显然我可以很容易地回到CubeIDE,但我想让东西与VSC工作,因为它是一个更好的界面。我也使用Mac和运行MacOS 13.0 Ventura。我所有的工具都安装了自制。
当我注意到我的代码在尝试运行一个初始化MPU-6000 acc/gyro,mpu6000Init()
的函数时会进入Hardfault处理程序时,这个问题第一次出现。这个函数没有什么特别之处。它通过SPI向IMU发送一系列数据,以初始化一些设置,发送之间存在延迟。更奇怪的是,当我逐行执行代码时,它运行得很好。也就是说,如果我在函数的开头放置一个断点,然后逐行运行,就没有问题。我真的不知道这意味着什么。当我检查调用堆栈时,它似乎来自延迟函数,但我不确定为什么,因为我之前使用延迟函数时没有问题。
我所有的代码都存在于here。重要的文件是Src/main.c
,Src/drv/drv_system.c
,Src/sensors/mpu6000.c
。
我知道其中一件事,可能是造成这个问题是,我已经编辑了我的链接器脚本有一个"虚拟eeprom",我部分的闪存,所以我有一些非易失性存储器,我可以保存设置等,当我关闭它.当我刷新代码,我的整个EEPROM被擦除,我不得不刷新设置。这是可能的,以避免使用链接器脚本?这看起来像这样:
/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K
EEPROM (rx) : ORIGIN = 0x08060000, LENGTH = 128K
}
...
.eeprom 0x08060000 :
{
. = ALIGN(4);
KEEP(*(.eeprom))
. = ALIGN(4);
} > EEPROM
然后在main.c
的顶部,我有这个const uint8_t __attribute__((__section__(".eeprom"), used)) eepromArray[131072];
提醒,所有这些都可以在CubeIDE中使用,只是我在VSC中使用的工具不起作用。
当我在STM32CubeProgrammer中运行此代码时,我使用了硬故障检测器,它为我提供了此
另一件值得注意的事是:当我运行代码时,"Output"窗口显示如下:
* Executing task: "/usr/bin/make" -j16 -f STM32Make.make flash
"/opt/homebrew/bin/openocd" -f ./openocd.cfg -c "program build/Autodrone32.elf verify reset exit"
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
Info : clock speed 2000 kHz
Info : STLINK V2J39M27 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.241885
Info : stm32f7x.cpu: hardware has 8 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f7x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080054a4 msp: 0x20040000
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
Info : Unable to match requested speed 8000 kHz, using 4000 kHz
** Programming Started **
Info : device id = 0x10006452
Info : flash size = 512 kbytes
Info : Flash write discontinued at 0x08008358, next section at 0x08060000
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
shutdown command invoked
* Terminal will be reused by tasks, press any key to close it.
有一行代码是Info : Flash write discontinued at 0x08008358, next section at 0x08060000
。老实说,我不知道它的确切含义,但我认为flash的编写方式有些奇怪。我试着查找这个问题,但没有找到任何有用的信息。
我使用的工具版本:
开放OCD
Open On-Chip Debugger 0.11.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
臂嵌入式工具链
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.07) 10.3.1 20210621 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
制造商
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i386-apple-darwin11.3.0
变结构控制
Version: 1.73.1
Commit: 6261075646f055b99068d3688932416f2346dd3b
Date: 2022-11-09T02:22:48.959Z (1 wk ago)
Electron: 19.0.17
Chromium: 102.0.5005.167
Node.js: 16.14.2
V8: 10.2.154.15-electron.0
OS: Darwin arm64 22.1.0
Sandboxed: No
希望这是所有需要的信息得到一个图片是怎么回事。也许其中一个工具箱只是不兼容我正在做的事情。也许mpu6000Init()
函数是在某处的堆栈是损坏的?我已经尝试运行在不同的芯片与相同的结果。我已经尝试注解掉这个函数,它通过正常。也许有'这是一些与SPI和延迟导致一个奇怪的时间问题。任何帮助是感激不尽的。让我知道如果你需要任何澄清信息或要我运行一些测试。
1条答案
按热度按时间mklgxw1f1#
原来问题实际上来自
Src/drv/drv_spi1.c
中的函数spi1WriteOneByte(uint8_t reg, uint8_t data)
。我命名了一个变量volatile uint8_t dummy __attribute((unused))
。然后这个变量被用作DMA传输的内存地址。我假设这导致了某种问题,因为DMA要么无法到达那个位置,要么导致了一些不稳定的行为。总之,我把它改成了static
而不是volatile
,它起作用了。如果有人能比我更好地解释这一点,请这样做。