2017-01-24 6 views
7

ARM STM32F4用のC/C++の混合プログラムを開発していますが、C言語で定義されたグローバル変数にアクセスする際に問題があります。 問題を再現するための簡単なテストコードです。CとC++間のグローバル変数

TEST.H:

#ifndef TEST_H_ 
#define TEST_H_ 

#ifdef __cplusplus 
extern "C" { 
#endif 

extern const char* strings[]; 

#ifdef __cplusplus 
} 
#endif 

#endif /* TEST_H_ */ 

test.cの:

#include <test.h> 
const char* strings[] = {"string a", "string b", "string c" }; 

main.hpp

#ifndef MAIN_HPP_ 
#define MAIN_HPP_ 

#define STM32F4 

#include <test.h> 
#include <libopencm3/stm32/rcc.h> 
#include <libopencm3/stm32/gpio.h> 

#endif /* MAIN_HPP_ */ 

main.cppに:

#include <main.hpp> 

int main(void) 
{ 
    char s2[3][9]; 

    rcc_periph_clock_enable(RCC_GPIOD); 
    gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 
    GPIO12); 

    while (1) { 
     for (int i = 0; i < 3; i++) { 
      for (int j = 0; j < 9; j++) { 
       s2[i][j] = strings[i][j]; 
       if (s2[i][j] == 'i') { 
        gpio_toggle(GPIOD, GPIO12); 
       } 

       for (int k = 0; k < 1000000; k++) { 
        __asm__("nop"); 
       } 
      } 
     } 
    } 
} 

しかし、デバッガで実行すると、string [0](たとえば)が指しているメモリが完全にゼロになっていることがわかります。

注:whileループの部分は関係ありません。私はちょっとフィードバックを加え、コンパイラが文字列の未使用値を取り除くのを避けるために追加しました。

ここで私は何が間違っていますか?

EDIT

私はLinuxでのEclipseで働いている、GNU-アームなし、EABI。

コンパイラとリンカのコマンドラインと出力:

arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-move-loop-invariants -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wconversion -Wpointer-arith -Wpadded -Wshadow -Wlogical-op -Waggregate-return -Wfloat-equal -g3 -I"/home/andrea/ownCloud/src/arm/libopencm3/include" -I"/home/andrea/ownCloud/src/arm/testt/src" -std=gnu++11 -fabi-version=0 -fno-exceptions -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics -Wabi -Wctor-dtor-privacy -Wnoexcept -Wnon-virtual-dtor -Wstrict-null-sentinel -Wsign-promo -MMD -MP -MF"src/main.d" -MT"src/main.o" -c -o "src/main.o" "../src/main.cpp" 
In file included from /home/andrea/ownCloud/src/arm/libopencm3/include/libopencm3/stm32/rcc.h:32:0, 
       from /home/andrea/ownCloud/src/arm/testt/src/main.hpp:14, 
       from ../src/main.cpp:20: 
/home/andrea/ownCloud/src/arm/libopencm3/include/libopencm3/stm32/f4/rcc.h:640:11: warning: padding struct to align 'rcc_clock_scale::plln' [-Wpadded] 
    uint16_t plln; 
     ^
/home/andrea/ownCloud/src/arm/libopencm3/include/libopencm3/stm32/f4/rcc.h:644:11: warning: padding struct to align 'rcc_clock_scale::flash_config' [-Wpadded] 
    uint32_t flash_config; 
     ^
Finished building: ../src/main.cpp 

Building file: ../src/test.c 
Invoking: Cross ARM C Compiler 
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-move-loop-invariants -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wconversion -Wpointer-arith -Wpadded -Wshadow -Wlogical-op -Waggregate-return -Wfloat-equal -g3 -I"/home/andrea/ownCloud/src/arm/libopencm3/include" -I"/home/andrea/ownCloud/src/arm/testt/src" -std=gnu11 -Wmissing-prototypes -Wstrict-prototypes -Wbad-function-cast -MMD -MP -MF"src/test.d" -MT"src/test.o" -c -o "src/test.o" "../src/test.c" 
Finished building: ../src/test.c 

Building target: testt.elf 
Invoking: Cross ARM C++ Linker 
arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -fno-move-loop-invariants -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wconversion -Wpointer-arith -Wpadded -Wshadow -Wlogical-op -Waggregate-return -Wfloat-equal -g3 -T "/home/andrea/ownCloud/src/arm/testt/src/stm32f407g-discovery.ld" -T "/home/andrea/ownCloud/src/arm/testt/src/libopencm3_stm32f4.ld" -nostartfiles -Xlinker --gc-sections -L"/home/andrea/ownCloud/src/arm/libopencm3/lib" -Wl,-Map,"testt.map" --specs=nano.specs -o "testt.elf" ./src/main.o ./src/test.o -lopencm3_stm32f4 
Finished building target: testt.elf 

リンカスクリプト(ないきれいな1、私はそれにいくつかのテストをしました)。

MEMORY 
{ 
    rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K 
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 
} 

_stack_size = 0x400; 
/* Include the common ld script. */ 
INCLUDE libopencm3_stm32f4.ld 

libopencm3_stm32f4.ld:

/* Enforce emmition of the vector table. */ 
EXTERN (vector_table) 

/* Define the entry point of the output file. */ 
ENTRY(reset_handler) 

/* Define sections. */ 
SECTIONS 
{ 
    .text : { 
     *(.vectors) /* Vector table */ 
     *(.text*) /* Program code */ 
     . = ALIGN(4); 
     *(.rodata*) /* Read-only data */ 
     . = ALIGN(4); 
    } >rom 

    /* C++ Static constructors/destructors, also used for __attribute__ 
    * ((constructor)) and the likes */ 
    .preinit_array : { 
     . = ALIGN(4); 
     __preinit_array_start = .; 
     KEEP (*(.preinit_array)) 
     __preinit_array_end = .; 
    } >rom 
    .init_array : { 
     . = ALIGN(4); 
     __init_array_start = .; 
     KEEP (*(SORT(.init_array.*))) 
     KEEP (*(.init_array)) 
     __init_array_end = .; 
    } >rom 
    .fini_array : { 
     . = ALIGN(4); 
     __fini_array_start = .; 
     KEEP (*(.fini_array)) 
     KEEP (*(SORT(.fini_array.*))) 
     __fini_array_end = .; 
    } >rom 

    /* 
    * Another section used by C++ stuff, appears when using newlib with 
    * 64bit (long long) printf support 
    */ 
    .ARM.extab : { 
     *(.ARM.extab*) 
    } >rom 
    .ARM.exidx : { 
     __exidx_start = .; 
     *(.ARM.exidx*) 
     __exidx_end = .; 
    } >rom 

    . = ALIGN(4); 
    _etext = .; 

    .data : { 
     _data = .; 
     *(.data*) /* Read-write initialized data */ 
     . = ALIGN(4); 
     _edata = .; 
    } >ram AT >rom 
    _data_loadaddr = LOADADDR(.data); 

    .bss : { 
     *(.bss*) /* Read-write zero initialized data */ 
     *(COMMON) 
     . = ALIGN(4); 
     _ebss = .; 
    } >ram 
    . = ALIGN(4); 

    _end_bss = .; 
    end = .; 
    _end = .; 
    _heap_bottom = .; 
    _heap_top = ORIGIN(ram)+LENGTH(ram)-_stack_size; 

    _stack_bottom =_heap_top; 
    _stack_top = ORIGIN(ram) + LENGTH(ram); 
    /* 
    * The .eh_frame section appears to be used for C++ exception handling. 
    * You may need to fix this if you're using C++. 
    */ 
    /DISCARD/ : { *(.eh_frame) } 
} 

PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); 

EDIT

私が問題に探していますが、私は少し困惑しています。

スタートアップコードは、次のものが含まれます。

for (src = &_data_loadaddr, dest = &_data; 
    dest < &_edata; 
    src++, dest++) { 
    *dest = *src; 
} 

だから、それは私にはOKらしいです。私は、デバッガを実行したとき、私は右スタート& _data == & _edata == 0x2000000cから、私もその_data気づくことがわかり、今

.data   0x0000000020000000  0xc load address 0x000000000800038c 
       0x0000000020000000    _data = . 
*(.data*) 
.data.strings 0x0000000020000000  0xc ./src/test.o 
       0x0000000020000000    strings 
       0x000000002000000c    . = ALIGN (0x4) 
       0x000000002000000c    _edata = . 
       0x000000002000000c    _data = . 
*(.data*) 
       0x000000002000000c    . = ALIGN (0x4) 
       0x000000002000000c    _edata = . 
       0x000000000800038c    _data_loadaddr = LOADADDR (.data) 

.igot.plt  0x000000002000000c  0x0 load address 0x0000000008000398 

.MAPファイルには、以下に関する情報を提供します.mapファイルに2回あります。

リンカスクリプトにエラーがありますか?

+1

現在の問題とは関係ありませんが、 'main'のループで' strings [i] 'の範囲外に出ます。それだけで*未定義の動作*につながります。 –

+3

さらにあなたの問題に関連して、どのようにプログラムをビルドしますか?あなたのプログラムをコンパイルしてリンクするためにどのコマンド(またはどのIDE)を使用していますか? –

+2

どのようにビルド/リンクしていますか? – Jarod42

答えて

0

問題は最終的にEclipseのプロジェクト構成で発生しました.2つの.ldファイルをスクリプトに含めて指定しましたが、 2番目のファイルのインクルードディレクティブ。これにより、double _dataの指定と、起動コードの誤った動作が発生しました。

5

Olafがコメントで述べたように、あなたは文字列テーブルを定数として宣言していませんでした。したがって、読み出し専用データの代わりに、初期化された読み出し/書き込みデータとしてコンパイラ/リンカによって考慮されます。

初期化コード(メインエントリポイントの前に実行される)によって、初期化されたデータがフラッシュからRAMに正しくコピーされないことがあります。クイックフィックスとして

、あなたの文字列テーブルを定数として作ってみる:

char const * const strings[] = {"string a", "string b", "string c" }; 

それが動作する場合、あなたはその後、リンカに与えられた-nostartfiles引数に見てください...メモリの初期化の問題を調査することができ(確認する)スタートアップコードが無効になっている可能性があります。

+0

あなたの構文では動作しますが、私は起動コード(libopencm3によって提供される)を見ていきます。 – apalazzi

関連する問題