在多个嵌入式平台的代码库中处理 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
定义为__far
(NEAR
类似)的最初想法仍然有效吗?你只需要确保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 指针的主要内容,如果未能解决你的问题,请参考以下文章