G CC Linker помещает переменную в нежелательный раздел вместе с <object>, что приводит к конфликту типа раздела с - PullRequest
0 голосов
/ 18 июня 2020

в моей встроенной программе у меня есть несколько «объектов конфигурации», которые позволяют пользователю настраивать свое устройство. Все эти объекты имеют размер 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;
}
...