Codewarrior から Crossworks に、恐ろしく難読化されたコードを移植しようとしています。ライブラリは C で書かれていますが、C++ オブジェクトを模倣しようとしていると思います。
これらのオブジェクトが宣言されるとき、それらはマクロを使用するマクロで宣言されるため、従うのが非常に難しくなります! 少し理解しやすいように、プリプロセッサを使用してそれらを展開しました。
現在、[稼働中の] Codwarrior Eclipse ベースのシステムの下に、ソース コードで static const として指定されたテキストのセクションがあり、最終的に RAM に保存されます。私が見る限り、 static const として指定されている他のものは、リンカがフラッシュに入れます。Crossworks では、すべてがフラッシュで終了します。これは私にとって理にかなっています。
マクロから展開された後の問題のある宣言の例を次に示します。
static const D4D_LABEL scrSplash_lblSID_params
= { { " Unit ID: 42949672955" , sizeof(" Unit ID: 42949672955"), 0, &scrSplash_lblSID_strPrties}, { 6, 76 }, { 118, 16 }, 8 };
D4D ラベルは次のように定義されます。
typedef struct
{
D4D_STRING textBuff; // label text
D4D_POINT scrPos; // position on the screen
D4D_SIZE scrSize; // size on the screen (focus rect only, bitmaps have own size)
D4D_COOR radius; // corner radius
} D4D_LABEL;
また、D4D_STRING は次のように定義されています。
typedef struct D4D_STRING_S
{
char *pText;
D4D_INDEX buffSize;
D4D_FONT fontId;
D4D_STR_PROPERTIES *str_properties;
D4D_INDEX printLen;
D4D_INDEX printOff;
}D4D_STRING;
この D4D_LABEL は、次のように D4D_OBJECT に入れられます。
const D4D_OBJECT scrSplash_lblSID = { (void*)&(scrSplash_lblSID_params), (D4D_OBJECT_SYS_FUNCTION*)&d4d_labelSysFunc,
(void*)0, (void*)0, (0x01 | 0x02 | 0x40), &(scrSplash_lblSID_flags), (void*)0, &(scrSplash_lblSID_pScreen) };
そして、D4D_OBJECT は次のように定義されます。
// this is allocated in ROM always
typedef struct D4D_OBJECT_S
{
void* pParam;
D4D_OBJECT_SYS_FUNCTION* pObjFunc;
Byte (*OnUsrMessage)(struct D4D_MESSAGE_S* pMsg);
void *userPointer;
D4D_OBJECT_INITFLAGS initFlags;
D4D_OBJECT_FLAGS* flags;
struct D4D_CLR_SCHEME_S* clrScheme;
struct D4D_SCREEN_S** pScreen;
} D4D_OBJECT;
私の知る限り、D4D_OBJECT scrSplash_lblSID に最初に入れられるのは、D4D_LABEL scrSplash_lblSID_params へのポインターです。その D4D ラベルは static const として宣言されているため、フラッシュに配置されます。Crossworks はそれを行いますが、Codewarrior は RAM にそれを持っています。
この機能を使用する場合:
void D4D_SetText(D4D_OBJECT_PTR pObject, char* pText)
{
D4D_STRING* p_TextBuff = NULL;
if(pObject->pObjFunc->GetTextBuffer)
p_TextBuff = pObject->pObjFunc->GetTextBuffer((D4D_OBJECT*)pObject);
// ABOVE line equates to: return &(((D4D_LABEL*)((pThis)->pParam))->textBuff);
if(p_TextBuff)
{
D4D_ChangeText(p_TextBuff, pText, 0);
D4D_InvalidateObject(pObject, D4D_FALSE);
}
}
次の行で:
D4D_SetText(&scrSplash_lblSID, SIdString);
p_TextBuff は、Codewarrior の RAM の場所であり、Crossworks のフラッシュの場所です。ChangeText 関数は、pText が指す文字列をフラッシュにコピーしようとします。もちろん、プロセッサ (Freescale の Cortex M4 - Kinetis プロセッサ) がクラッシュします。
上記は、私にアドバイスできるほど十分な情報に近いものですか? Codewarrior プロジェクトのリンカ ファイルには、関連する文字列をフラッシュではなく RAM に格納する何らかの方法があると推測しています。リンカがその static const を RAM に置き、他のもののようにフラッシュしないことを魔法のように知っている方法がわかりません!
関連する可能性がある場合に備えて、リンカー ファイルを以下に示します。
どうもありがとう!
# Default linker command file.
MEMORY {
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x000001E0 # Interrupts
m_text (RX) : ORIGIN = 0x00004400, LENGTH = 0x0003BC00 # Code and read only data
m_data (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x00020000 # Read/write data
}
KEEP_SECTION { .vectortable }
KEEP_SECTION { .cfmconfig }
SECTIONS {
.interrupts :
{
__vector_table = .;
* (.vectortable)
. = ALIGN (0x4);
} > m_interrupts
# All the stuff that lives in flash: the application (.text), read only data (.rodata) and .init - whatever the latter is
.app_text:
{
ALIGNALL(4);
* (.init)
* (.text)
.= ALIGN(0x8) ;
* (.rodata)
.= ALIGN(0x4) ;
___ROM_AT = .;
} > m_text
# App data is INITIALISED data. So stuff that was specified in flash, but gets copied to RAM at boot
.app_data: AT(___ROM_AT)
{
* (.sdata)
* (.data)
.= ALIGN(0x4) ;
*(.ARM.extab)
.= ALIGN(0x4) ;
__exception_table_start__ = .;
EXCEPTION
__exception_table_end__ = .;
.= ALIGN(0x4) ;
__sinit__ = .;
STATICINIT
.= ALIGN(0x8) ;
} > m_data
# .bss is UNINITIALISED data that just lives in normal RAM - after the initialised stuff
.bss :
{
.= ALIGN(0x4) ;
__START_BSS = .;
* (.bss)
__END_BSS = .;
.= ALIGN(0x8) ;
} >> m_data
_romp_at = ___ROM_AT + SIZEOF(.app_data);
.romp : AT(_romp_at)
{
__S_romp = _romp_at;
WRITEW(___ROM_AT);
WRITEW(ADDR(.app_data));
WRITEW(SIZEOF(.app_data));
WRITEW(0);
WRITEW(0);
WRITEW(0);
}
__SP_INIT = . + 0x00008000;
__heap_addr = __SP_INIT;
__heap_size = 0x00008000;
}