适用场景
如果一个函数位于一个外部库或ROM中,但是你又想替换它时怎么办呢?
答案是可以使用$Sub$$ 和 $Super$$
$Sub$$
:调用原函数 foo()
实际调用的是$Sub$$foo()
$Super$$
:如果想调用原函数foo()
则需要调用$Super$$foo()
下图是ARM官方文档《ARM Compiler v5.06 for µVision armlink User Guide》的说明
实验测试
会输出如下内容
test2
test1
void test(void)
{
printf("test1\r\n");
}
void $Sub$$test(void)
{
printf("test2\r\n");
}
extern void $Super$$test(void);
int main(void)
{
test();
$Super$$test();
}
分析RT-Thread中用到的$Sub$$
和 $Super$$
在移植RT-Thread到STM32的过程中,我发现并没有修改启动文件,那么默认应该跳转到main
,但是实际上是跳转到rtthread_startup()
因为RT-Thread定义了一个int $Sub$$main(void)
,实际上是会跳转到这里的
#ifdef __ARMCC_VERSION
extern int $Super$$main(void);
/* re-define main function */
int $Sub$$main(void)
{
rtthread_startup();
return 0;
}
在RT-Thread中原来的main()
变成了一个线程,看源码可知线程入口函数为main_thread_entry()
,其中又调用了$Super$$main()
即原来的main()
void rt_application_init(void)
{
rt_thread_t tid;
rt_err_t result;
tid = &main_thread;
result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(result == RT_EOK);
rt_thread_startup(tid);
}
void main_thread_entry(void *parameter)
{
#ifdef __ARMCC_VERSION
{
extern int $Super$$main(void);
$Super$$main(); /* for ARMCC. */
}
#endif
}