STM32应用程序开发策略
Strategies to develop STM32 in application programming
我正在寻找有关如何开发应用程序编程模块的想法。
我们在 "C" 为我们的 android 系统开发了一个 STM32F2xx 接线盒。本质上这只是一个多设备到蓝牙的信息桥梁。现在我在考虑如何提供一个 "in application programming" 模块,以便将来从蓝牙串口升级这个盒子,而不需要物理连接。
对我来说读写flash都不是问题,但是我需要了解处理器是如何运行程序的,程序如何划分到flash的不同位置,如何跳转到flash的具体地址记忆。我在哪里可以搜索此信息?
我打算发表评论,但我不能,因为我是菜鸟。所以我会尝试回答,温柔点。
我使用的内购方法是:
- 将新固件加载到安全位置(在 eeprom、ext 闪存等中...)
- 例如根据其散列值检查固件的完整性
- 将内部 CPU 闪存的 FLASH 程序复制到 SRAM 中。
- 禁用所有中断
- 调用 FLASH 编程例程。
- 触发软件重置请求以启动新固件
现在,如果您升级 CPU 的整个固件,上述方法就可以使用了。还假设您在闪存编程期间不需要中断。如果您确实需要在闪存编程期间中断,事情会稍微复杂一些。在调用闪存编程例程之前,您必须执行一些额外的步骤,以便将所有与中断相关的代码也复制到 SRAM 中。
- 将新固件加载到安全位置(在 eeprom、ext 闪存等中...)
- 例如根据其散列值检查固件的完整性
- 将内部 CPU 闪存的 FLASH 程序复制到 SRAM 中。
- 禁用所有中断
- 分配足够的 ram 以容纳向量。
- 将向量复制到该地址
- 在闪存编程期间启用您需要的中断。
- 调用 FLASH 编程例程。
- 触发软件重置请求以启动新固件
一件重要的事
这个方法有一个非常棘手的部分。这是您在 SRAM 中的代码之间的调用。编译器将函数名称与 0x0800000 内存位置(闪存)中的地址相关联。例如函数 void flash_byte(uint32_t address, uint8_t byte);
存在于 flash 中的某个地方。当您将此函数复制到 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 时它们将起作用。
更多信息:
我正在寻找有关如何开发应用程序编程模块的想法。
我们在 "C" 为我们的 android 系统开发了一个 STM32F2xx 接线盒。本质上这只是一个多设备到蓝牙的信息桥梁。现在我在考虑如何提供一个 "in application programming" 模块,以便将来从蓝牙串口升级这个盒子,而不需要物理连接。
对我来说读写flash都不是问题,但是我需要了解处理器是如何运行程序的,程序如何划分到flash的不同位置,如何跳转到flash的具体地址记忆。我在哪里可以搜索此信息?
我打算发表评论,但我不能,因为我是菜鸟。所以我会尝试回答,温柔点。
我使用的内购方法是:
- 将新固件加载到安全位置(在 eeprom、ext 闪存等中...)
- 例如根据其散列值检查固件的完整性
- 将内部 CPU 闪存的 FLASH 程序复制到 SRAM 中。
- 禁用所有中断
- 调用 FLASH 编程例程。
- 触发软件重置请求以启动新固件
现在,如果您升级 CPU 的整个固件,上述方法就可以使用了。还假设您在闪存编程期间不需要中断。如果您确实需要在闪存编程期间中断,事情会稍微复杂一些。在调用闪存编程例程之前,您必须执行一些额外的步骤,以便将所有与中断相关的代码也复制到 SRAM 中。
- 将新固件加载到安全位置(在 eeprom、ext 闪存等中...)
- 例如根据其散列值检查固件的完整性
- 将内部 CPU 闪存的 FLASH 程序复制到 SRAM 中。
- 禁用所有中断
- 分配足够的 ram 以容纳向量。
- 将向量复制到该地址
- 在闪存编程期间启用您需要的中断。
- 调用 FLASH 编程例程。
- 触发软件重置请求以启动新固件
一件重要的事
这个方法有一个非常棘手的部分。这是您在 SRAM 中的代码之间的调用。编译器将函数名称与 0x0800000 内存位置(闪存)中的地址相关联。例如函数 void flash_byte(uint32_t address, uint8_t byte);
存在于 flash 中的某个地方。当您将此函数复制到 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 时它们将起作用。
更多信息: