我正在为使用相对复杂通信接口的ARM Cortex-M3编写引导程序;这与实际应用程序使用的相同。该应用程序使用Keil的RTX作为内核,通信堆栈依赖于此。当然,使用GCC。
引导加载程序执行以下基本步骤:
- 启动时,检查有效的应用程序映像;如果没有可用,则进入升级模式
- 它检查按下按钮是否请求进入升级模式;如果发现,则进入升级模式
- 在找到有效的映像并且没有升级请求后,它会"启动"应用程序
这是相当简化的,但它充分描述了场景,以达到我们的目的。
令人惊讶的是,最后一个困难的问题是启动应用程序。其想法是禁用中断,设置矢量表、堆栈指针,并在新的矢量表中跳转到应用程序的重置矢量。所有这些工作都很顺利,除了不久之后,我就犯了一个严重的错误。
通过实验,如果我在一个普通的引导加载程序(不使用RTX,当然也不使用comms堆栈)中这样做,那么引导到应用程序就可以很好地工作。所以RTX似乎是个问题。
问题是,真正的引导加载程序在进入升级模式之前不需要RTX。因此,显而易见的方法是,在我们确定需要RTX之前,不要启动它;然而,它似乎被黑客入侵到了启动代码中,所以当我进入引导程序代码时,已经太晚了;实际上,bootloader main()函数已经是一个线程了!
最好的方法似乎是在我需要之前不启动RTX(可惜我没有使用FreeRTOS!);然而,这似乎需要一些黑客攻击。另一种方法是以某种方式禁用所有中断和异常,但由于某种原因,我在这方面也没有成功。有人有这两种方法的例子吗?
如果有人遇到这种情况,解决方案实际上很简单。我刚刚在system_efm32g.c文件中自定义了SystemInit()函数!虽然_efm32gg是特定于供应商的,但system_X.c似乎是一种广泛使用的ARM结构——至少我在ST、NXP和EnergyMicro/SiliconLab中看到过——所以这是一种不错的通用方法。
我早该知道的叹息