Я столкнулся с серьезными проблемами с бигльбоуном под управлением TI AM3359arm. Я использую исходный код для компиляции кода. Я попытался скомпилировать один из примеров, названный enet_lwip, который использует легковесный IP (lwip) для предоставления http-сервера.
Приложение вылетает в определенный момент. Путем отладки я обнаружил, что за это отвечает вот этот кусок кода:
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.
Я хотел бы знать, почему это так. Если такая инициализация появляется в коде, компилятор должен сгенерировать последовательность для ее обнуления. Но, вероятно, поскольку ему предшествует модификатор static, он оставляет его «как есть». Почему?
lwipInitFlag находится в разделе компоновщика .bss, который указывает на память DDR. Как я могу гарантировать, что такие статические присваивания будут инициализированы?
На данный момент я взломаю код для lwIP, чтобы посмотреть, работает ли это, но для меня это просто предупреждение, что где-то в библиотеках могут быть другие статически объявленные переменные, которые не инициализируются.
Любая подсказка, как решить эту проблему?
Добавлю к этому дополнительную информацию: после ваших плодотворных советов я думаю, что у меня еще больше беспорядка в том, как это должно работать. Итак: Это правда, что я не называю/линкую crt*.o. С другой стороны, стартовая платформа TI содержит исходный код asm для инициализации, который ВЫПОЛНЯЕТ очистку BSS. Он делает это между адресами _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 после _bss_end, который содержит много вещей, которые должны быть обнулены, но не обнуляются, потому что обнуление заканчивается по адресу, заданному _bss_end.
Вероятная причина, по которой это делается именно так, заключается в том, что pageTable объявлена статически и должна иметь граничный адрес 16 КБ:
static volatile unsigned int pageTable[4*1024] __attribute__((aligned(16*1024)));
Так как существует разрыв между последним объявленным компоновщиком сегментом BSS и pageTable, он помещает _bss_end в середину сегмента bss.
Теперь вопрос в том, как сообщить компоновщику (я использую для этого arm-none-eabi-ld), что _bss_end действительно должен быть в конце BSS, а не где-то посередине?
Большое спасибо
init.o
? У вас есть источник?init.o
традиционно отвечает за очисткуBSS
и настройку стека. Тот факт, что вы можете отлаживать что угодно, указывает на то, что у вас есть код запуска. Кроме того, как это запускается? Это записывается во флэш-память, поэтому вектор сброса переходит к первой части двоичного файла, или вы загружаетесь через загрузчик? Загрузчик может настроить стек и т. д. - person artless noise   schedule 27.02.2013