Работа с указателями FAR в библиотеке кода для нескольких встроенных платформ - PullRequest
7 голосов
/ 09 июня 2011

Я пытаюсь поддерживать библиотеку кода с примерами для нескольких встроенных платформ. Мне нужно поддерживать концепцию "дальних" (не 16-битных) указателей для некоторых параметров функции.

Я подумал, что у меня есть хорошее решение с определением макроса FAR как __far на некоторых платформах и ничего на платформах с 32-битными указателями (встроенный Linux, Win32 и т. Д.). С помощью этого макроса я мог легко определить указатели как somestruct_t FAR *foo.

Но затем я начал работать с процессорами Freescale, и их компилятору требуется FAR для перехода между звездочкой и именем переменной. (somestruct_t * __far foo).

Лучшее решение, которое я придумал для обработки этого случая, - это определить макрос FARPTR как __far *, * __far или просто * в зависимости от платформы. Это позволяет somestruct_t FARPTR foo.

Есть ли более чистые решения? В частности, мне не нравится, что кто-то, читающий этот код, не видит *. Я также беспокоюсь, что у меня возникнут проблемы, когда дело доходит до объявлений функций. Загрузите этот синтаксис из справки компилятора Freescale:

int __far *f();          // __far function returning a pointer to int
int * __far f();         // Function returning a __far pointer to int
int __near * __far f();  // __near function returning a __far pointer to int

Этот последний убивает меня - квалификатор внутри возвращаемого типа указывает на близкую функцию ?! И недавно я узнал, что добавления __near недостаточно для фактической компиляции функции в почти памяти - мне нужно обернуть ее в прагмы.

Итак, кто-нибудь видел лучшее решение, чем моя FARPTR макро идея?

Ответы [ 5 ]

2 голосов
/ 10 июня 2011

У меня нет конкретного лучшего решения для вас. Однако, поскольку я несколько раз сталкивался с одной и той же проблемой, я рекомендую просмотреть AUTOSAR Спецификацию абстракции компилятора (PDF) .

Включает подробный подход к работе с несколькими компиляторами.

2 голосов
/ 10 июня 2011

Использование процессора freescale более соответствует стандартным квалификаторам типов, таким как const, поэтому размещение указывает на указатель, а не на данные, на которые он указывает.Тем не менее, поскольку « дальние данные » вместо « дальний указатель » были бы бессмысленными, вы бы подумали, что это не имеет значения, но большая согласованность, по-видимому, делает более простымпарсер компилятора.

Вы можете использовать что-то вроде kludgey, например:

#if defined __SOME_ARCHITECTURE__

    #define DECLARE_FARPTR( type, identifier ) type __far * identifier

#if defined __SOME_OTHER_ARRCHITECTURE__

    #define DECLARE_FARPTR( type, identifier ) type * __far identifier

#else

    #define DECLARE_FARPTR( type, identifier )

#endif

Тогда ваши объявления будут выглядеть так:

DECLARE_FARPTR( somestruct_t, foo ) ;

или в прототипе функции с указателемпараметр:

void fn( DECLARE_FARPTR( somestruct_t, foo )  ) ;

или функция, возвращающая дальний указатель:

DECLARE_FARPTR( somestruct_t, fn( void ) ) ;

Как вы можете видеть, он быстро становится трудным для чтения и декларативный функционально-подобный макрос обычно этого лучше избегать.

1 голос
/ 10 июня 2011

Я также работаю с Freescale, и мое собственное решение этой проблемы заключается в следующем:

1) Замените дальние указатели на простые целые числа, когда это возможно.Это не работает в каждой ситуации, но особенно полезно при работе с указателями функций, например, при написании таблиц векторов прерываний.

2) Вместо использования дальних указателей пишите код, который идентичен к тому, что компилятор выдаст при доступе к дальнему указателю.Вот пример для Freescale MCU:

unsigned char readFromPage (unsigned char page, const unsigned char* address) 
{   
  unsigned char value;   
  unsigned char tmp = PPAGE;

  SAFE_DisableInterrupts;
    PPAGE = page;
    value = *address;
    PPAGE = tmp;
  SAFE_EnableInterrupts;

  return value; 
}

(этот код может быть встроен в зависимости от случая)

3) Используйте #pragmas, насколько это возможно.

В результате в моем коде нет ни одного дальнего или ближнего указателя, он переносим (настолько переносим, ​​насколько это возможно с аппаратным кодом), и я могу проверить его с помощью статических анализаторов, которые понимают только стандарт C.

1 голос
/ 10 июня 2011

Чтобы добавить к сообщение Клиффорда , хотя функциональные макросы, вероятно, плохая идея, вы можете использовать макрос для создания typedefs:

#ifdef SOME_ARCH
#define DEF_FAR_PTR(type, farptr_typename) typedef type __far *farptr_typename;
#elsif SOME_OTHER_ARCH
#define DEF_FAR_PTR(type, farptr_typename) typedef type * __far farptr_typename;
#else
#define DEF_FAR_PTR(type, farptr_typename) typedef type * farptr_typename;
#endif
0 голосов
/ 10 июня 2011

Может быть, проще определить два макроса FAR: один для до * и другой для после *.

...