在应用程序编程中开发STM32的策略

4
我正在寻找有关如何开发应用内编程模块的想法。
我们使用“C”语言为STM32F2xx连接盒开发了一个Android系统。本质上,这只是一个多设备蓝牙信息桥接器。现在我正在考虑如何提供“应用内编程”模块,以便将来通过蓝牙串行端口升级这些盒子时无需进行物理连接。
对我来说,读写Flash不是问题,但我需要了解处理器如何运行程序,如何将程序划分为不同的Flash位置以及如何跳转到Flash存储器中的具体地址。我在哪里可以查找这些信息?

我尝试使用处理器附带的IAP引导程序,但正如ST在AN2606中所说,在STM32F2中启动引导程序的唯一方法是使用硬件引脚,而不是编程方式。 - rpr
1个回答

5

我想留下评论,但是我不能因为我是新手。所以我会尝试回答,希望您温柔点。

我用的IAP方法是:

  • 将新固件加载到安全位置(在eeprom、ext flash等中)
  • 检查固件的完整性,例如校验其哈希值
  • 将用于FLASH编程内部CPU闪存的例程复制到SRAM中。
  • 禁用所有中断
  • 调用FLASH编程例程。
  • 触发软件复位请求以启动新固件

现在,如果您升级CPU的整个固件,则上述方法有效。还假定您在闪存编程期间不需要中断。如果您确实需要在闪存编程期间具有中断,则情况会更加复杂。您必须在调用flash编程例程之前执行一些额外的步骤,以便将所有与中断相关的代码也复制到SRAM中。

  • 将新固件加载到安全位置(在eeprom、ext flash等中)
  • 检查固件的完整性,例如校验其哈希值
  • 将用于FLASH编程内部CPU闪存的例程复制到SRAM中。
  • 禁用所有中断
  • 分配足够的RAM以适应向量。
  • 将向量复制到该地址
  • 在闪存编程期间启用所需的中断。
  • 调用FLASH编程例程。
  • 触发软件复位请求以启动新固件

一个重要的事情

这种方法有一个非常棘手的部分。它是在SRAM中的代码之间的调用。编译器将函数的名称与0x0800000内存位置(即闪存)中的地址相关联。例如,函数void flash_byte(uint32_t address, uint8_t byte);存储在闪存中的某个位置。当您将此函数复制到RAM中,比如说到0x20001000,您必须在函数调用中具体说明。请记住,如果您尝试擦除整个闪存并重新编写它,则无法从闪存中调用函数。我使用的方法是通过函数指针进行调用。例如:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

/*
 * Function pointers
 */
typedef void (*flash_write_ft) (void);
typedef void (*flash_sub_call_ft) (uint32_t lala);

flash_write_ft      flash_write_pointer = (flash_write_ft)0;
flash_sub_call_ft   flash_sub_call_pointer = (flash_sub_call_ft)0;

/*
 *  Helper functions
 */
size_t get_function_size (uint32_t *address) {
    size_t s=0;
    // ...
    // s = calculate size;
    return s;
}

int copy_function (uint32_t *from, uint32_t *to, size_t s) {
    // ...
    return 0;   // OK!!
}

/*
 * Flash programming functions
 */
void flash_sub_call (uint32_t lala) {
    // lala tata
}

void flash_write (void) {
    uint32_t foo;
    // ...
    flash_sub_call_pointer (foo);   // call via pointer here
    // ...
}

int main(void) {
    size_t s;
    uint32_t *add;

    // Get firmware, check integrity etc...

    // copy to ram
    s = get_function_size ((uint32_t*)&flash_sub_call);
    add = (uint32_t*)malloc (s);
    copy_function ((uint32_t*)&flash_sub_call, add, s);
    flash_sub_call_pointer = (flash_sub_call_ft)add;

    s = get_function_size ((uint32_t*)&flash_write);
    add = (uint32_t*)malloc (s);
    copy_function ((uint32_t*)&flash_write, add, s);
    flash_write_pointer = (flash_sub_call_ft)add;

    // IAP
    flash_write_pointer ();

    return EXIT_SUCCESS;
}

在这个例子中,所有的函数调用都通过指向RAM的指针进行,因此当你将它们复制到RAM时,它们会正常工作。
额外信息:
1)闪存编程手册 2)Cortex-m3编程手册

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接