本帖最后由 凉白开 于 2022-6-22 14:41 编辑
功能介绍:
$Sub$$ 和 $Super$$ 是MDK(ARMCC)上特有的关键字,主要作用是替代某个函数和继承原有函数的功能。 l $Sub$$func() 用于替代func函数,$Sub$$func()函数被定义后,程序中所有调用func()函数的地方将会被替换成$Sub$$func()函数。 l $Super$$func() 在$Sub$$func()内部使用,在func()被替换后,使用$Sub$$func()可以调用原有func()函数的功能。 应用场景: l 对于无法修改或重新编译现有符号的情况,可以使用$Sub和$Super链接机制。例如,它位于外部库或ROM代码中。在这种情况下,您可以使用$Super$$和$Sub$$模式来修补现有的符号。 l 通常,将所有系统初始化代码与主应用程序分开是有益的。但是,系统初始化的某些组件,例如缓存和中断的启用,必须在执行 C 库初始化代码之后发生。 l 在进入main函数前,需要对系统进行初始化(时钟、中断、动态内存堆、定时器、调度器、main线程、idle线程等),使用$Sub$$main先调用一些要补充在main之前的功能函数,然后在再调用$Super$$main转到main函数执行。 示例代码: // 在main函数前初始化底层硬件 void $Sub$main(void) { extern int $Super$main(void); USART_Config_T usartConfigStruct;
/** USART configuration */ USART_ConfigStructInit(&usartConfigStruct); usartConfigStruct.baudRate = 115200; usartConfigStruct.mode = USART_MODE_TX_RX; usartConfigStruct.parity = USART_PARITY_NONE; usartConfigStruct.stopBits = USART_STOP_BIT_1; usartConfigStruct.wordLength = USART_WORD_LEN_8B; usartConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
/** COM1 init*/ APM_MINI_COMInit(COM1, &usartConfigStruct); $Super$main(); } //在外部库的函数中插入参数判断避免程序出错 int $Sub$ble_send_data(uint8_t *buf , int len) { extern int $Super$ble_send_data(void); if(len <= 20) { return $Super$ble_send_data(); } return 0; } //在外部库的函数前插入调试信息 void $Sub$light_lum_ct_set(int lum, int ct) { printf("lum=%d,ct=%d\r\n"mlum,ct); $Super$light_lum_ct_set(lum,ct); } //代替外部库中的校验功能,绕过芯片校验 int $Sub$chip_id_check(void) { return 1; } 注意事项: l $Sub与$Super要成对使用,而且要在$Sub$$foo中调用$Super$$foo,不能直接调用foo,否则会一直卡在$Sub$$foo中,找不到出口,陷入死循环。 l 在$Super$$foo函数调用上方需要用extern关键字外部声明它,即extern void $Super$$foo(void)。 l $Sub$$foo、$Super$$foo可以与原函数foo放在不同的C文件中,而且放在同一个C文件中也没有先后顺序之分。 l 不能在原函数foo中,调用$Sub$$foo和$Super$$foo,这属于递归调用。 l $Sub和$Super机制只在静态链接时起作用,$Super引用不能导入或导出到动态符号表中。 l foo函数必须是全局或弱定义,如果编译器内联了一个函数,那么就不可以再用替换函数$Sub来修补内联的函数。 l $Sub和$Super链接器机制只能对工具可见的符号定义和引用进行操作。例如,编译器可以在C程序中将对printf("Hello\n")的调用替换为puts("Hello")。只有对符号puts的引用对链接器可见,因此定义$Sub$$printf不会重定向此调用。
|