в моей встроенной программе у меня есть несколько «объектов конфигурации», которые позволяют пользователю настраивать свое устройство. Все эти объекты имеют размер const
(с указателем на память, который можно настроить) и помещаются в указанный раздел (чтобы объекты из разных единиц компиляции были в одном месте). Структура и пример такого объекта следующие:
class CObjectParams
{
public:
OMB::ObjectId ObjectID;
TMODULE_ID ModuleID;
void* pData;
unsigned short u16Length;
TAccessControl AccessControl;
CConverter* pConverter;
int ReadObject(void* pDataDestination) const;
int WriteObject(void* pDataSource) const;
};
Пример:
const volatile TSoftwareDescriptor* const BootloaderSoftwareDescriptor = (const volatile TSoftwareDescriptor* const) (FLASH_BASE + DESCRIPTOR_OFFSET);
const CObjectParams __attribute__((used, section("_objects_section"))) BootloaderSoftwareVersionObjectParams =
{
OMB::ObjectId::BOOTLOADER_SOFTWARE_VERSION,
TMODULE_ID::MODULE_ID_FIRMWARE,
(void*) &BootloaderSoftwareDescriptor->u32FirmwareVersion,
sizeof(BootloaderSoftwareDescriptor->u32FirmwareVersion),
{
(ACCESS_READ),
LOCATION_DIRECT,
FIXED_LENGTH,
},
nullptr,
};
Проблема, я думаю, в том, что компоновщик не может разрешить &BootloaderSoftwareDescriptor->u32FirmwareVersion
адрес во время ссылки и поэтому пытается поместить его в раздел .data
для инициализации во время запуска. После снятия ограничения section("_objects_section")
и анализа файла .map
мои опасения подтвердились. Так почему же компоновщик не может разрешить упомянутый адрес во время компоновки, поскольку BootloaderSoftwareDescriptor
является постоянным указателем и известен во время компиляции?
Вот пример кода, который показывает эту ошибку:
#include <stdio.h>
#define FIXED_LENGTH 0
#define LOCATION_DIRECT 0
#define ACCESS_READ 0b000010
enum ObjectId : unsigned short
{
NO_OBJECT = 0x000,
A,
B,
C,
D
};
enum TMODULE_ID : unsigned short
{
MODULE_ID_CONFIG = 0x00,
MODULE_ID_DIAGNOSTICS = 0x01,
MODULE_ID_FIRMWARE = 0x04,
};
struct TAccessControl
{
unsigned char b6Access : 6;
unsigned char b4Location : 2;
unsigned char b1LengthType : 1;
unsigned char b7Unused : 7;
};
class CConverter
{
public:
virtual void ConvertTo(void* pDestination, void* pSource, int size) {};
virtual void ConvertFrom(void* pDestination, void* pSource, int size) {};
};
class CObjectParams
{
public:
ObjectId ObjectID;
TMODULE_ID ModuleID;
void* pData;
unsigned short u16Length;
TAccessControl AccessControl;
CConverter* pConverter;
int ReadObject(void* pDataDestination) const;
int WriteObject(void* pDataSource) const;
};
struct TSoftwareDescriptor
{
unsigned int u32FirmwareCrc;
unsigned int u32FirmwareSize;
unsigned int u32HardwareVersion;
unsigned int u32FirmwareVersion;
const char S8BuildDate[12]; // Mmm-dd-yyyy\0
const char S8BuildTime[9]; // HH:mm:ss\0
unsigned int U32RFU[10] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
};
#define FLASH_BASE (0x08000000UL)
#define DESCRIPTOR_OFFSET 50
const volatile TSoftwareDescriptor* const BootloaderSoftwareDescriptor = (const volatile TSoftwareDescriptor* const) (FLASH_BASE + DESCRIPTOR_OFFSET);
const CObjectParams __attribute__((used, section("_objects_section"))) NullObjectParams =
{
ObjectId::A,
TMODULE_ID::MODULE_ID_FIRMWARE,
nullptr,
sizeof(int),
{
(ACCESS_READ),
LOCATION_DIRECT,
FIXED_LENGTH,
},
nullptr,
};
const CObjectParams __attribute__((used, section("_objects_section"))) BootloaderSoftwareVersionObjectParams =
{
ObjectId::B,
TMODULE_ID::MODULE_ID_FIRMWARE,
(void*) &BootloaderSoftwareDescriptor->u32FirmwareVersion,
sizeof(BootloaderSoftwareDescriptor),
{
(ACCESS_READ),
LOCATION_DIRECT,
FIXED_LENGTH,
},
nullptr,
};
int main()
{
printf("%d\n%d\n", NullObjectParams.pData, BootloaderSoftwareVersionObjectParams.pData);
return 0;
}