コメントしようと思ったのですが、初心者なのでできません。だから私は答えてみます、優しくしてください。
私が IAP に使用する方法は次のとおりです。
- 新しいファームウェアを安全な場所 (eeprom、ext flash など) にロードします。
- たとえば、そのハッシュに対してファームウェアの整合性を確認します
- 内部 CPU フラッシュをフラッシュ プログラミングするためのルーチンを SRAM にコピーします。
- すべての割り込みを無効にする
- FLASH プログラミング ルーチンを呼び出します。
- ソフトウェア リセット要求をトリガーして、新しいファームウェアを起動します。
CPUのファームウェア全体をアップグレードすると、上記の方法が機能するようになりました。また、フラッシュ プログラミング中に割り込みが必要ないと仮定します。フラッシュプログラミング中に割り込みが必要な場合は、もう少し複雑です。すべての割り込み関連コードを SRAM にもコピーするために、フラッシュ プログラミング ルーチンを呼び出す前に、いくつかの追加の手順を実行する必要があります。
- 新しいファームウェアを安全な場所 (eeprom、ext flash など) にロードします。
- たとえば、そのハッシュに対してファームウェアの整合性を確認します
- 内部 CPU フラッシュをフラッシュ プログラミングするためのルーチンを SRAM にコピーします。
- すべての割り込みを無効にする
- ベクトルを収めるのに十分な RAM を割り当てます。
- ベクターをそのアドレスにコピーする
- フラッシュ プログラミング中に必要な割り込みを有効にします。
- FLASH プログラミング ルーチンを呼び出します。
- ソフトウェア リセット要求をトリガーして、新しいファームウェアを起動します。
1つの重要なこと
この方法には非常にトリッキーな部分があります。これは、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 プログラミングマニュアル