MDK中使用C++的发现

来源:互联网 发布:华泰大智慧软件下载 编辑:程序博客网 时间:2024/05/16 09:25

                                               MDK中使用C++的发现

 

·对象:MDK安装目录中的c++ 例程C:\Keil\ARM\Examples\C++\Example1

·问题:例程中如何将标准输入cin、输出cout对象与硬件串口映射起来的?

·发现:首先,main()前有一段说明


上面说的是Serial.c里面的$Sub$$__rt_entry()做了串口初始化的工作,先不管是不是它说的那样,看main里面并没有做串口的任何操作就能使用cin和cout将数据从串口读入和写出。肯定是main进入之前就将他们之间的映射做好了,回过头来看Serial.c代码,里面有一处比较特别的地方:

/*----------------------------------------------------------------------------

  Superclass to initialize the serial interface

 *----------------------------------------------------------------------------*/

extern void$Super$$__rt_entry(void);

 

void$Sub$$__rt_entry(void)  {

  SER_Init();

  $Super$$__rt_entry();

}

这些奇怪的东西是怎么调用的?我们看下程序充零开始执行的过程:


(注:图片来源ARM官网)


(注:图片来源网络)

__main是用来设置内存,__rt_entry是用来设置运行时环境(设置堆栈、初始化库函数、静态数据和调用顶层C++构造器)然后才进入用户的main代码,用户main执行完后__rt_entry还会去关掉库等。

好吧,那上面的代码又是如何做到在main前就做串口初始化的工作的呢?

额,利用 $Sub 和 $Super 函数包装符可以插入一个紧接主应用程序之前执行的例程。 这一机制使您能在不改变源代码的情况下扩展函数。(厉害。。。)

· 使用 $Super$$ 和 $Sub$$ 覆盖符号定义

在某些情况下,无法修改现有符号,例如,由于符号位于外部库或 ROM 代码中。

可以使用 $Super$$ 和 $Sub$$ 模式来修补现有符号。

例如,要修补函数 foo() 的定义,请按如下方式使用 $Super$$foo() 和 $Sub$$foo()

$Super$$foo

标识未修补的原始函数 foo()。 使用它可以直接调用原函数。

$Sub$$foo

标识调用的新函数,而不是原始函数 foo()。 可以使用此模式在原始函数之前或之后添加处理。

Note

$Sub 和 $Super 机制只在静态链接时起作用,$Super$$ 引用无法导入或导出到动态符号表中。

Example 4.4 说明修改遗留函数 foo() 而导致调用 ExtraFunc() 和 foo()。 有关详细信息,请参阅《ARM 体系结构的 ELF》。

Example 4.4. 使用 $Super$$ 和 $Sub$$

extern void ExtraFunc(void);

extern void $Super$$foo(void):

 

/* this function is called instead of the original foo() */

void $Sub$$foo(void)

{

  ExtraFunc();    /* does some extra setup work */

  $Super$$foo();  /* calls the original foo() function */

}

 

所有说是用这两个东东修补了__rt_entry的定义了哦(其实是添加了),明显就是标示了新的__rt_entry添加了自己要初始化的部分后又调用了原来的entry嘛。

其他的代码应该简单了哈。

0 0
原创粉丝点击