2017-01-24 22 views
7

Tôi đang phát triển một chương trình C/C++ hỗn hợp cho ARM STM32F4, nhưng tôi gặp sự cố khi truy cập các biến toàn cầu được xác định trong phần C. Đây là mã thử nghiệm đơn giản để tái tạo sự cố.Biến toàn cầu giữa C và 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"); 
       } 
      } 
     } 
    } 
} 

Tuy nhiên, khi tôi chạy nó trong trình gỡ lỗi, tôi có thể thấy rằng bộ nhớ trong đó chuỗi [0] (ví dụ) đang trỏ là hoàn toàn bằng không.

Lưu ý: phần trong vòng lặp while không liên quan, tôi vừa thêm nó để có một số phản hồi và để tránh trình biên dịch cắt các giá trị không sử dụng của chuỗi.

Vì vậy, tôi đang làm gì sai ở đây?

EDIT

Tôi đang làm việc với Eclipse dưới Linux, gnu-cánh tay-none-EABI.

biên dịch và mối liên kết dòng lệnh và đầu ra:

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 

Linker kịch bản (không phải là sạch nhất một, tôi đã làm một số thử nghiệm với nó).

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

Tôi đang xem xét sự cố nhưng tôi là một chút bối rối.

mã khởi động bao gồm:

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

Vì vậy, nó có vẻ ok với tôi.

File .map cung cấp cho các infos sau:

.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 

Bây giờ, khi tôi chạy trình gỡ lỗi tôi thấy rằng ngay từ đầu & _data == & _edata == 0x2000000c, và tôi cũng nhận thấy rằng _data có mặt hai lần trong tệp .map.

Vì vậy, có lỗi trong tập lệnh trình liên kết không?

+1

Không liên quan đến vấn đề hiện tại của bạn, nhưng trong các vòng lặp trong 'main' bạn thoát khỏi giới hạn của' chuỗi [i] '. Điều đó một mình dẫn đến * hành vi không xác định *. –

+3

Có liên quan nhiều hơn đến vấn đề của bạn, làm thế nào để bạn xây dựng chương trình của bạn? Bạn đang sử dụng lệnh nào (hoặc IDE) nào để biên dịch và liên kết chương trình của mình? –

+2

Bạn xây dựng/liên kết như thế nào? – Jarod42

Trả lời

0

Vấn đề cuối cùng là với cấu hình dự án trong Eclipse: Tôi đã chỉ định cả tệp .ld dưới dạng tập lệnh, nhưng đầu tiên đã có bao gồm chỉ thị cho tệp thứ hai; điều này gây ra đặc tả _data đôi và hành vi sai của mã khởi động.

5

Như Olaf đã nói trong một nhận xét, bạn không khai báo bảng chuỗi của bạn là hằng số. Vì vậy, nó được xem xét bởi trình biên dịch/linker như khởi tạo đọc/ghi dữ liệu, thay vì chỉ đọc dữ liệu.

Có thể mã khởi tạo của bạn (được thực hiện trước điểm nhập chính) không sao chép đúng dữ liệu được khởi tạo từ flash sang RAM.

Là một sửa chữa nhanh chóng, cố gắng làm cho bảng chuỗi của bạn như liên tục:

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

Nếu nó hoạt động, sau đó bạn có thể điều tra các vấn đề bộ nhớ khởi tạo ... Có một cái nhìn đến -nostartfiles luận trao cho các mối liên kết , có thể có thể vô hiệu hóa mã khởi động (để được xác nhận) ...

+0

Với cú pháp của bạn nó hoạt động, tôi sẽ xem xét mã khởi động (được cung cấp bởi libopencm3). – apalazzi

Các vấn đề liên quan