在多个嵌入式平台的代码库中处理 FAR 指针

Posted

技术标签:

【中文标题】在多个嵌入式平台的代码库中处理 FAR 指针【英文标题】:Dealing with FAR pointers in code library for multiple embedded platforms 【发布时间】:2011-06-09 18:44:34 【问题描述】:

我正在尝试为多个嵌入式平台维护一个包含示例的代码库。对于某些函数参数,我需要支持“远”(非 16 位)指针的概念。

我认为我有一个很好的解决方案,在某些平台上将宏 FAR 定义为 __far,而在具有 32 位指针的平台(嵌入式 Linux、Win32 等)上则没有。使用该宏,我可以轻松地将指针定义为somestruct_t FAR *foo

但后来我开始使用飞思卡尔处理器,他们的编译器需要 FAR 在星号和变量名之间。 (somestruct_t * __far foo)。

我想出的处理这种情况的最佳解决方案是将宏 FARPTR 定义为 __far ** __far 或只是 *,具体取决于平台。这允许somestruct_t FARPTR foo

有没有更清洁的解决方案? 特别是,我不喜欢阅读该代码的人看不到*我还担心在函数声明方面会遇到问题。从飞思卡尔编译器帮助中获取大量此语法:

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

最后一个杀了我——返回类型的限定符 inside 表示近函数?!而且我最近了解到,添加 __near 不足以将函数实际编译到内存附近——我需要将它包装在 pragma 中。

那么,有没有人看到比我的FARPTR 宏想法更好的解决方案?

【问题讨论】:

您的嵌入式系统真的如此受限以至于您不能仅使用“大”模型进行编译并让所有指针都远吗?这是最干净的解决方案。 这种语法似乎反映了const 处理指针的方式,__near 反映了 C++ 的mutable。这对我来说似乎并不陌生。 不能将FAR 定义为__farNEAR 类似)的最初想法仍然有效吗?你只需要确保FAR/NEAR 去飞思卡尔编译器想要它们的地方(喜欢与否)。在其他平台上,这些宏将是空格,因此它们在声明中的使用位置与它们无关。 @R:并非我使用过的所有嵌入式平台都支持“大型”模型。 @Michael Burr:问题是我需要支持一些在* 之前需要__far 的平台和一些在之后需要它的平台。 你确定支持第一种语法的编译器不支持飞思卡尔语法吗?即有可能对此进行标准化。 【参考方案1】:

飞思卡尔处理器的使用更符合标准类型限定符,例如const,这种放置会导致它引用指针而不是指向的数据。也就是说,由于“far data”而不是“far pointer”是没有意义的,你会认为这无关紧要,但更大的一致性可能有助于一个更简单的编译器解析器。

你可以使用一些笨拙的东西,例如:

#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 ) ) ;

如您所见,它很快就会变得难以阅读,类似声明性函数的宏通常是最好避免的。

【讨论】:

【参考方案2】:

我没有具体的更好的解决方案给你。但是,在多次处理过同样的问题后,我建议您回顾一下AUTOSARSpecification of Compiler Abstraction (PDF)。

它包括处理多个编译器的详细方法。

【讨论】:

【参考方案3】:

要添加到Clifford's post,虽然类似函数的宏可能不是一个好主意,但您可以使用宏来创建 typedef:

#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

【讨论】:

【参考方案4】:

我也与飞思卡尔合作,我自己的解决方案是以下之一:

1) 尽可能用纯整数替换远指针。这并不适用于所有情况,但在处理函数指针时特别有用,例如在编写中断向量表时。

2) 不要使用远指针,而是编写与编译器在远指针访问期间生成的代码相同的代码。以下是飞思卡尔 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 的静态分析器来检查它。

【讨论】:

这背后的基本原理是:太多的程序员盲目地使用交给他们的东西,不管标准与否。对于嵌入式程序员来说尤其如此。尝试跳出预制框来思考:远指针不是标准的,它们也不是一致的、可靠的或定义明确的。它们对您的程序是一个显着的危害,尤其是在移植时。在您的 C 程序中引入任何形式的非标准语法之前,请三思而后行!【参考方案5】:

定义两个 FAR 宏可能更简洁:一个用于 * 之前,另一个用于 * 之后。

【讨论】:

Ew。 void FAR1 * FAR2 foo;?我坚持使用void FARPTR foo; 并将FARPTR 定义为*__far ** __far,具体取决于平台。这允许void FARPTR FARPTR foo; 指向指针。

以上是关于在多个嵌入式平台的代码库中处理 FAR 指针的主要内容,如果未能解决你的问题,请参考以下文章

如何在命令库中嵌入消息

库的简介和分类

从 C++ 库中嵌入 Java 代码而不需要***程序来嵌入它?

嵌入式ARM处理器

QEP原理

创建单词嵌入,而不将fastText Vector文件保存在存储库中