完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
因为我现在使用的单片机使用了大量原厂提供的库函数和标准初始化例程,而这一部分例程很大程度上都是通用的,而且无论是在boot里还是APP1还是APP2都要调用这部分程序,那为什么不将这部分共用的程序都放在同一片FLASH里,通过某种方式统一调用呢?
而实现这种方法的方式其实非常简单就是使用函数指针,只要函数指针指能够指向对应API所在Flash的地址,就能实现相应的功能。 具体方法如下:在boot中的某个位置固定好函数映射的地址表,然后再APP中调用 /*boot中使用*/ #if ThisBoot==1 /*---------------------------------------------------------------------- //固化API函数表 -----------------------------------------------------------------------*/ const uint32_t func_table[] __attribute__((section(".ARM.__at_0x00001000"))) = { //注:这里会存在一些警告,无可避免 //注:顺序要想改必须同步更改 API_xxx_Loc #if API_UseADC>0 (uint32_t)&API_ADC, #else (uint32_t)API_ADC_Loc, //如果不用于占位 #endif #if API_UseETIM>0 (uint32_t)&API_Etim_Init, #else (uint32_t)API_ETIM_Loc,//如果不用于占位 #endif #if API_UseIIC>0 (uint32_t)&API_I2C_Init, (uint32_t)&API_EEPROM_Read, (uint32_t)&API_EEPROM_Write, #else (uint32_t)API_I2C_Init_Loc,//如果不用于占位 (uint32_t)API_I2C_Read_Loc, (uint32_t)API_I2C_Write_Loc, #endif #if API_UseLPTIM>0 (uint32_t)&API_LPTIM_Init, #else (uint32_t)API_LPTIM_Loc,//如果不用于占位 #endif #if API_UseRTC>0 (uint32_t)&API_RTC_Init, (uint32_t)&API_GetTime, (uint32_t)&API_SetTIME, #else (uint32_t)API_RTC_Init_Loc,//如果不用于占位 (uint32_t)API_GetTime_Loc, (uint32_t)API_SetTIME_Loc, #endif #if API_UseUart>0 (uint32_t)&API_Uartx_Init, (uint32_t)&API_Uart_Send, #else (uint32_t)API_Uart_Init_Loc,//如果不用于占位 (uint32_t)API_Uart_Send_Loc, #endif #if API_UseLPUart>0 (uint32_t)&API_LPUart_Init, (uint32_t)&API_LPUart_Send, #else (uint32_t)API_LPUart_Init_Loc,//如果不用于占位 (uint32_t)API_LPUart_Send_Loc, #endif #if API_UseDataUp>0 (uint32_t)&API_UpData, #else (uint32_t)API_UpData_Loc, #endif #if API_UseNB>0 (uint32_t)&API_NB_Init, (uint32_t)&API_NB_Link, (uint32_t)&API_NB_Connect, (uint32_t)&API_NB_UartRx, (uint32_t)&API_NB_UartTx, (uint32_t)&API_NB_Clock, (uint32_t)&API_NB_End, (uint32_t)&API_NB_RxData, #else (uint32_t)API_NB_Init_Loc, (uint32_t)API_NB_Link_Loc, (uint32_t)API_NB_Connect_Loc, (uint32_t)API_NB_UartRx_Loc, (uint32_t)API_NB_UartTx_Loc, (uint32_t)API_NB_Clock_Loc, (uint32_t)API_NB_End_Loc, (uint32_t)API_NB_RXDATA_Loc, #endif #if API_UseLCD>0 (uint32_t)&API_Init_LCD, #else (uint32_t)API_LCD_Loc, #endif #if API_UseAES>0 (uint32_t)&API_AES, #else (uint32_t)API_AES_Loc, #endif #if API_UseIIC>0 (uint32_t)&G_I2C_Read_Contin_Step, (uint32_t)&G_I2C_Write_Contin_Step, #else (uint32_t)API_I2C_Read_Com_Loc,//如果不用于占位 (uint32_t)API_I2C_Write_Com_Loc, #endif (uint32_t)99 }; /*---------------------------------------------------------------------- //固化SYS函数表,不可更改 -----------------------------------------------------------------------*/ const uint32_t sys_table[] __attribute__((section(".ARM.__at_0x00000950"))) = { (uint32_t)&TicksDelayMs, (uint32_t)&TicksDelayUs, (uint32_t)&AnalogIO, (uint32_t)&InputtIO, (uint32_t)&OutputIO, (uint32_t)&AltFunIO, (uint32_t)&CloseeIO, (uint32_t)&Init_System, (uint32_t)&Sleep, (uint32_t)&RchfAdjust }; #endif 然后定义好函数指针,在APP中使用,方法如下 /*在APP中调用固化在boot中的函数*/ #if API_UseIIC>0 void API_I2C_Init(void) { api_iicinit iic=(void (*)(void))(table_base[API_I2C_Init_Loc] | 0x1); iic(); } uint08 API_EEPROM_Read(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len) { api_iicop iicrd=(uint08 (*)(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len))(table_base[API_I2C_Read_Loc] | 0x1); return iicrd(Device,Addr,AddrLen,Buf,Len); } uint08 API_EEPROM_Write(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len) { api_iicop iicwt=(uint08 (*)(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len))(table_base[API_I2C_Write_Loc] | 0x1); return iicwt(Device,Addr,AddrLen,Buf,Len); } uint08 API_I2C_Read_Com(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len) { api_iicop iicrd=(uint08 (*)(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len))(table_base[API_I2C_Read_Com_Loc] | 0x1); return iicrd(Device,Addr,AddrLen,Buf,Len); } uint08 API_I2C_Write_Com(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len) { api_iicop iicwt=(uint08 (*)(uint08 Device, uint16 Addr, uint08 AddrLen, uint08 *Buf, uint16 Len))(table_base[API_I2C_Write_Com_Loc] | 0x1); return iicwt(Device,Addr,AddrLen,Buf,Len); } #endif 通过这种方式,原先APP需要50K左右的代码量,减少至20K,boot原先16K代码量增至进40K,如果不使用外挂Flash远程升级APP2,可以节约很多空间。 |
|
|
|
只有小组成员才能发言,加入小组>>
3323 浏览 9 评论
3000 浏览 16 评论
3498 浏览 1 评论
9073 浏览 16 评论
4093 浏览 18 评论
1193浏览 3评论
613浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
603浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2341浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1899浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-29 17:41 , Processed in 0.827983 second(s), Total 77, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号