0

我正在使用带有 Micron MT25Q Quad_SPI 闪存的 STM32F469 芯片。要对 Flash 进行编程,需要开发一个外部加载程序。一切正常,但问题是 QSPI Flash 的验证非常慢。

查看日志文件,它显示正在以 150K 字节块对 Flash 进行编程。但是,验证是在 1K 字节块中完成的。此外,在每次块检查之前,都会重新初始化芯片。我已经通过 STM32cubeIDE 和 STM32cubeProgrammer 直接尝试过这个。

外部编程器程序包含正确的芯片配置信息并指定 64K 页面大小。我看不出如何让程序员使用更大的块大小。看起来它了解使用了 SRAM 的哪一部分,并且正在使用板载 SRAM 中的 256K 的余额来对 QSPI 闪存进行编程。它可以使用相同的大小来读回数据,也可以使用外部加载器中的 Verify() 函数。它调用 Read() 然后检查数据本身。

有什么想法或提示吗?

让我添加一些关于创建新的外部加载器的意见。第一个观察是“不要”。如果您可以选择支持的外部芯片并将其固定以使用现有的加载器,那么就这样做。STM 只提供了 4 个示例程序,但它们必须有 50 个外部加载器。如果硬件设计复制了具有外部加载器的演示板的原理图,您应该没问题并避免进行开发工作。

外部加载程序不是完整的可执行文件。它提供了一组函数来执行基本操作,如 Init()、Erase()、Read() 和 Write()。诀窍是程序启动时没有 main() 并且没有运行启动代码。

外部加载器是一个 ELF 文件,重命名为“*.stldr”。编程工具查看调试信息以找到函数的位置。然后它设置寄存器来提供参数,PC 来运行函数,然后让它运行。有一些非常聪明的工作正在进行中来完成这项工作。程序员查看返回值 (R0) 以查看事情是否通过。它还可以确定函数是否使核心崩溃或超时。

编写外部超级有趣的是调试器正在运行程序,因此没有可用的调试器来查看代码在做什么。我决定在被调用函数的 return() 上输出错误和编码信息,以提示正在发生的事情。

外部加载程序不是“完整”程序。没有启动代码,很多片上的东西都没有设置好,有些就无法工作。至少我想不通。我不确定它是否配置不正确或调试器阻止了它的使用。查看示例外部加载程序,它们以非常简单的方式编写,不调用 HAL 或使用中断。您需要提供核心设置功能来配置时钟链。由于计时器和/或中断不工作,Hal_Delay() 方法将永远不会返回。我永远无法让它们工作,并怀疑 NVIC 不知何故被禁用了。我最终将 HAL_delay() 函数替换为基于核心时钟速率和每个循环的指令周期旋转的 for 循环。

应用笔记建议开发一个独立程序来调试基本功能。这是个好主意,但也是一个挑战。在启动外部加载程序之前,我让 QSPI 执行所需的操作,但来自调用 HAL 的 C++ 应用程序。从中创建一个外部加载器是一项长时间的剥离和替换功能的练习。提示是这些示例是在寄存器级别编写的。我不太擅长同时处理 QuadSPI 外设和芯片的指令集。

消除了程序的正常启动。在调用 main() 之前所做的一切(例如,在 startup_stm32f469nihx.s 中)取决于您。这包括设置时钟链以提升核心时钟并使外围总线正常工作。该程序在片上 SRAM 中运行,因此任何已初始化的变量都可以正确加载。不需要移动数据,但堆栈和未初始化的数据区域可以/应该仍然归零。

我希望这可以帮助别人!

4

1 回答 1

1

今天我遇到了同样的问题。

我可以通过两个简单的步骤提高验证速度,但验证仍然比编程慢得多,这很奇怪……如果有人找到改变 STM32CubeProgrammer 的 1KB 块读取的方法,我想知道 =)。按照我所做的更改来提高性能。

  1. 在 Init Function 中添加一种锁以避免多次初始化。这是最重要的变化,因为我在初始化过程中检查了 Flash ID。其他方法可能更安全,但这个简单的代码片段对我有用。

    int Init(void)
    {
        static uint32_t lock;
    
        if(lock != 0x43213CA5)
        {
            lock = 0x43213CA5;
    
            /* Init procedure goes here */
    
        }    
        return(1);
    }
    
  2. 缓存一个页面,而不是为每个调用读取外部存储器。如果您的外部存储器页面读取的开销太大,这将更有帮助,否则这个想法不会给出相关的结果。


于 2021-06-10T19:28:27.513 回答