[014] [RT-Thread学习笔记] Keil中的$Sub与$Super的使用

RT-Thread
学习笔记
功能介绍
应用场景
应用示例
注意事项

RT-Thread版本:4.0.5
MCU型号:STM32F103RCT6(ARM Cortex-M3 内核)

1 功能介绍

  • $Super$$foo
    标识原函数foo(),调用$Super$$foo相当于直接调用foo()
  • $Sub$$foo
    标识被调用的新函数,而不是原函数foo。在原函数之前或之后添加处理,即可在$Super$$foo调用前后都可以执行一些语句。

2 应用场景

  • 对于无法修改或重新编译现有符号的情况,可以使用$Sub$Super链接机制。例如,它位于外部库或ROM代码中。在这种情况下,您可以使用$Super$$$Sub$$模式来修补现有的符号。
  • 通常,将所有系统初始化代码与主应用程序分开是有益的。但是,系统初始化的某些组件,例如缓存和中断的启用,必须在执行 C 库初始化代码之后发生。
  • 在RT-Thread中的应用:在进入main函数前,需要对系统进行初始化(时钟、中断、动态内存堆、定时器、调度器、main线程、idle线程等),使用$Sub$$main先调用一些要补充在main之前的功能函数,然后在再调用$Super$$main转到main函数执行。

3 应用示例

extern int $Super$$main(void);	// 外部声明函数(由链接器导入)

void $Sub$$main(void)
{
	HSE_SetSysClk(RCC_PLLMul_9);
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
    SysTick_Config(SystemCoreClock / 1000); 
	Usart_Init(115200);
	UART_DEBUG("$Sub$$main: init over!");
	
	$Super$$main();
//	main();	// 不能直接调用main
}

//__inline void func(void)	// 不可以是内联函数 Error:Not enough information to list image symbols.
//{
//	UART_DEBUG("func: hello");
//}
	
void func(void)
{
	UART_DEBUG("func: hello");
}


extern int $Super$$func(void);	
void $Sub$$func(void)
{
	UART_DEBUG("$Sub$$func: start");
	$Super$$func();
	UART_DEBUG("$Sub$$func: end");
}

int main(void)
{
	UART_DEBUG("main: hello");
//	$Sub$$main();		// 递归调用$Sub$$main
//	$Super$$main();		// 递归调用main自身
	UART_DEBUG("----------------------");
	
	func();			// 这里的func相当于$Sub$$func();
	UART_DEBUG("----------------------");
	$Super$$func();	// 真正的func
	
	while(1)			// 不加while(1)程序会一直复位,这是mdk做的处理, 避免程序跑飞
	{
		
	}
}

打印信息:

[UART DEBUG] [17]$Sub$$main: init over!
[UART DEBUG] [38]main: hello
[UART DEBUG] [41]----------------------
[UART DEBUG] [31]$Sub$$func: start
[UART DEBUG] [25]func: hello
[UART DEBUG] [33]$Sub$$func: end
[UART DEBUG] [44]----------------------
[UART DEBUG] [25]func: hello

4 注意事项

  • $Sub$Super要成对使用,而且要在$Sub$$foo中调用$Super$$foo,不能直接调用foo,否则会一直卡在$Sub$$foo中,找不到出口,陷入死循环。
  • $Super$$foo函数调用上方需要用extern关键字外部声明它,即extern void $Super$$foo(void)
  • $Sub$$foo$Super$$foo可以与原函数foo放在不同的C文件中,而且放在同一个C文件中也没有先后顺序之分。
  • 不能在原函数foo中,调用$Sub$$foo$Super$$foo,这属于递归调用。
  • $Sub$Super机制只在静态链接时起作用,$Super引用不能导入或导出到动态符号表中。
  • foo函数必须是全局或弱定义,如果编译器内联了一个函数,那么就不可以再用替换函数$Sub来修补内联的函数。
  • $Sub$Super链接器机制只能对工具可见的符号定义和引用进行操作。例如,编译器可以在C程序中将对printf("Hello\n")的调用替换为puts("Hello")。只有对符号puts的引用对链接器可见,因此定义$Sub$$printf不会重定向此调用。(ps:这是官方解释,个人猜测应该是做了宏替换处理

参考资料:

  1. Use of S u p e r Super Super$ and S u b Sub Sub$ to patch symbol definitions
  2. Use of $Sub and $Super
  3. 关于 $ Super $ $ 和 $ Sub $ $ 的用法

END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柯西的彷徨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值