関数をフラッシュから RAM にコピーして実行したいと考えています。
IAR には、RAM で関数を定義できる関数用の __ramfunc タイプが含まれていることは知っていますが、次の 2 つの理由から使用したくありません。
- RAM関数は、初期化時にのみ使用するRAMメモリを使用しています
- コードを 2 回アップグレードした後 (私はファームウェア更新システムを実行しています)、__ramfunc が間違った場所を示しています。
基本的に私が欲しいのは、関数をフラッシュとして宣言し、実行時にそれをメモリにコピーして実行することです。私は次のコードを持っています:
void (*ptr)(int size);
ptr=(void (*)(int size))&CurrentFont;
memset((char *) ptr,0xFF,4096);
Debugprintf("FLASH FUNC %X",GrabarFirmware);
Debugprintf("RAM FUNC %X",ptr);
char *ptr1=(char *)ptr,*ptr2=(char *)GrabarFirmware;
//Be sure that alignment is right
unsigned int p=(int )ptr2;
p&=0xFFFFFFFE;
ptr2=(char *)p;
for(int i=0;i<4096;i++,ptr1++,ptr2++)
*ptr1=*ptr2;
FLASH_Unlock();
// Clear pending flags (if any)
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
ptr(*((unsigned int *)(tempptrb+8)));
詳細として:
- 関数の sizeof が機能しない
- リンカーが間違った関数アドレス (奇数アドレス) を返しました。デバッグ ツールで確認すると、それが間違っていることに気付きました。これが &0xFFFFFFFE を実行する理由です。
このコードの後、関数はRAMに完全にコピーされますが、まったく同じコードですが、これで実行すると:
ptr(*((unsigned int *)(tempptrb+8)));
例外 HardFault_Handler が発生します。多くのテストの後、このハードフォールト例外を修正できませんでした。
asm コードを確認すると、__ramfunc と通常のフラッシュ関数の呼び出しが異なり、おそらく HardFault 例外が発生する理由であることに気付きました。
これは、flash として定義されている場合に呼び出される方法です。
4782 ptr(*((unsigned int *)(tempptrb+8)));
\ 000000C6 0x6820 LDR R0,[R4, #+0]
\ 000000C8 0x6880 LDR R0,[R0, #+8]
\ 000000CA 0x47A8 BLX R5
4783 //(*ptr)();
直接呼び出すと、コードを __ramfunc として定義し、直接呼び出します。
4786 GrabarFirmware(*((unsigned int *)(tempptrb+8)));
\ 0000007A 0x6820 LDR R0,[R4, #+0]
\ 0000007C 0x6880 LDR R0,[R0, #+8]
\ 0000007E 0x.... 0x.... BL GrabarFirmware
例外の理由は、おそらくフラッシュから RAM にジャンプしているためであり、おそらくそれは皮質保護ですが、__ramfunc 修飾子を使用している場合もまったく同じであり、段階的にデバッグすると、関数にジャンプしません。 RAM、関数を呼び出すとすぐに例外に直接ジャンプします。
これをスキップする方法は、RAM メモリへの「goto」です。asm("...") 関数を使用して C と ASM in C を混在させようとしましたが、エラーが発生し、おそらくハードフォールト例外が発生します。
どんなヒントでも大歓迎です。