5

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;

}
4

3 に答える 3

3

オブジェクトが宣言されているかどうかは関係ありませんstatic const。書き込もうとしている文字列は、内部のポインターD4D_STRINGです。

typedef struct D4D_STRING_S 
{
  char *pText;

これは文字列リテラルから初期化され、文字列リテラル" Unit ID: 42949672955"に書き込む動作は未定義です。

コンパイラが-fwritable-stringsオプション (4.0 より前の gcc、clang の一部のバージョン) を受け入れる場合、そのオプションを使用して文字列リテラルを RAM に配置できます。推奨される代替手段は、変更可能な文字バッファーを使用することです。

char scrSplash_lblSID_params_text[] = "   Unit ID: 42949672955";
于 2013-05-20T12:24:22.270 に答える
2

TL;DR

タイトルの質問に対する簡単な答えは、C 言語標準で指定されていないためです。AC 実装は、静的な const オブジェクトを必要な場所に自由に格納できます。

また、文字列リテラルは読み取り専用メモリに配置できるため、変更しないでください。

于 2013-05-20T11:59:27.370 に答える