3

TIAM3359armを実行しているビーグルボーンで深刻な問題に遭遇しました。私はコードソースを使用してコードをコンパイルしています。軽量IP(lwip)を使用してhttpサーバーを提供するenet_lwipという例の1つをコンパイルしようとしました。

アプリケーションは特定の時点でクラッシュします。デバッグすることで、このコードが原因であることがわかりました。

unsigned int lwIPInit(LWIP_IF *lwipIf)
{

    struct ip_addr ip_addr;

    struct ip_addr net_mask;

    struct ip_addr gw_addr;

    unsigned int *ipAddrPtr;

    static unsigned int lwipInitFlag = 0;

    unsigned int ifNum;

    unsigned int temp;

    /* do lwip library init only once */
    if(0 == lwipInitFlag)
    {
        lwip_init();
    }

これには非常に面白いことが起こります。lwipInitFlagが0に初期化されるため、関数はlwip_init()を呼び出すと予想されます。

さて、これは、lwIPInit関数が最初に呼び出されたときでも発生しません。これは、変数lwipInitFlagが0に設定されていないためです。

なぜなのか知りたいのですが。そのような初期化がコードに含まれている場合、コンパイラはそれをnullにするシーケンスを生成する必要があります。ただし、前に静的修飾子が付いているためか、「そのまま」のままにしておきます。なんで?

lwipInitFlagは、DDRメモリを指す.bssリンカーセクションにあります。このような静的な割り当てが初期化されることをどのように保証できますか?

今のところ、lwIPのコードをハックして、これが機能するかどうかを確認しますが、ライブラリのどこかに、初期化されない別の静的に宣言された変数がある可能性があることを警告します。

これを解決するためのヒントはありますか?


これにさらに情報を追加する:あなたの実りあるヒントの後、私はそれがどのように機能するかについてさらに混乱していると思います。だから:確かに、私はcrt*.oを呼び出したりリンクしたりしません。一方、TIスターターウェアプラットフォームには、BSSクリーンアップを行う初期化asmソースが含まれています。アドレス_bss_startと_bss_endの間でそれを行います。

リンカースクリプトを調べると、すべてがごく普通に見えます。

SECTIONS
{

        . = 0x80000000;
        . = ALIGN(4);
        .startcode     :
        {
               *init.o      (.text)
        }

        . = ALIGN(4);
        .text      :
        {
                *(.text)
        }

        . = ALIGN(4);

        .data :
        {
                *(.data)
        }

        . = ALIGN(4);

        _bss_start = .;
        .bss :
        {
                *(.bss)
        }
        . = ALIGN(4);

        _bss_end = .;

        _stack = 0x87FFFFF8;
}

したがって、_bss_startはBSSブロックの前のアドレスであり、_bss_endはブロックの最後にあります。問題は、Codesourceryが生成するマップです。

生成されたマップファイルでBSSの終わりを見ると、次のことがわかります。

 COMMON         0x80088f0c      0x200 ../binary/armv7a/gcc/am335x/system_config/Debug/libsystem_config.a(interrupt.o)
                0x80088f0c                fnRAMVectors
                0x8008910c                . = ALIGN (0x4)
                0x8008910c                _bss_end = .
                0x87fffff8                _stack = 0x87fffff8
LOAD ../binary/armv7a/gcc/am335x/drivers/Debug/libdrivers.a
LOAD ../binary/armv7a/gcc/utils/Debug/libutils.a
LOAD ../binary/armv7a/gcc/am335x/beaglebone/platform/Debug/libplatform.a
LOAD ../binary/armv7a/gcc/am335x/system_config/Debug/libsystem_config.a
LOAD /opt/CodeSourcery/arm-none-eabi/lib//libc.a
LOAD /opt/CodeSourcery/lib/gcc/arm-none-eabi/4.5.2//libgcc.a
LOAD ../binary/armv7a/gcc/am335x/drivers/Debug/libdrivers.a
LOAD ../binary/armv7a/gcc/utils/Debug/libutils.a
LOAD ../binary/armv7a/gcc/am335x/beaglebone/platform/Debug/libplatform.a
LOAD ../binary/armv7a/gcc/am335x/system_config/Debug/libsystem_config.a
LOAD /opt/CodeSourcery/arm-none-eabi/lib//libc.a
LOAD /opt/CodeSourcery/lib/gcc/arm-none-eabi/4.5.2//libgcc.a
OUTPUT(Debug/bbdidt.out elf32-littlearm)

.bss.pageTable  0x8008c000     0x4000
 .bss.pageTable
                0x8008c000     0x4000 Debug/enetLwip.o

.bss.ram        0x80090000        0x4
 .bss.ram       0x80090000        0x4 Debug/lwiplib.o

明らかに「何か」があります。_bss_endの後に別のBSSセクションがあり、ゼロ化されることが期待される多くのものが含まれていますが、ゼロ化は_bss_endで指定されたアドレスで終了するため、ゼロ化されません。

これがこのように行われる理由として考えられるのは、pageTableが静的に宣言されており、16kiBの境界アドレスが必要であるためです。

static volatile unsigned int pageTable[4*1024] __attribute__((aligned(16*1024)));

したがって、最後に宣言されたBSSセグメントとpageTableの間にギャップがあるため、_bss_endはbssセグメントの中央に配置されます。

ここで問題となるのは、リンカー(このarm-none-eabi-ldに使用している)に、_bss_endは実際にはBSSの最後にあり、途中ではないことを伝える方法です。

どうもありがとう

4

2 に答える 2

3

統計が初期化されていないという事実は私に不思議に思います:あなたはどのようにあなたのスタートアップコードを手に入れましたか?このコードは、初期化を実行するために必要です。

http://doc.ironwoodlabs.com/arm-arm-none-eabi/html/getting-started/sec-cs3-startup.html-セクション5.2.3を参照してください。


Cスタートアップ関数は次のように宣言されています。

void __cs3_start_c (void) __attribute__ ((noreturn));

この関数は、次の手順を実行します。

  • 内容をコピーして、すべての.dataのようなセクションを初期化します。たとえば、ROMプロファイルリンカースクリプトは、このメカニズムを使用して、読み取り専用データプログラムイメージからRAM内の書き込み可能なデータを初期化します。
  • ...など

そのコードが不足しているようです。

于 2013-02-26T10:30:09.603 に答える
2

これらすべてのコメントに感謝します。それは私にとってほとんど探偵の仕事でした。最後に、リンカースクリプトを次のように変更しました。

SECTIONS
{

        . = 0x80000000;
        . = ALIGN(4);
        .startcode     :
        {
               *init.o      (.text)
        }

        . = ALIGN(4);
        .text      :
        {
                *(.text)
        }

        . = ALIGN(4);

        .data :
        {
                *(.data)
        }

        . = ALIGN(4);

        _bss_start = .;
        .bss :
        {
                *(.bss)
                *(COMMON)
                *(.bss.*)
        }
        . = ALIGN(4);

        _bss_end = .;

        _stack = 0x87FFFFF8;
}

したがって、基本的に、リンカーにCOMMONおよび.bssで始まるすべてのサブセグメントをBSSセグメントに含めるように強制しました。。

リンカが正しいマップを生成するようになったため、これにより問題が明らかに解決され、_bss_endポインタが実際にBSSセクションの最後のアドレスに配置されます。

これで、ソフトが正しく実行され、PHYが実行されます。それでもDHCPを取得できませんが、これは初期化されていない.dataセグメントの問題だと思います。LwIPは、いくつかの場所で静的割り当てを次のように使用します

static u32_t xid = 0xABCD0000;

これは.dataセグメントに入りますが、明らかに初期化されていないため、DHCP応答を取得できません...しかしこれは別の話です

ありがとうございます

于 2013-02-27T08:01:10.047 に答える