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?
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 *. –
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? –
Bạn xây dựng/liên kết như thế nào? – Jarod42