本文主要是介绍WX:jump_table,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
第一次接触dialog
看SDK代码注意到一个有意思的数组 jump_table_base
并且第二个成员是main函数
现在仅凭个人经验分析一下
注意它是一个数组哦!
const uint32_t* const jump_table_base[92] __attribute__((section("jump_table_mem_area"))) ={(const uint32_t*) TASK_APP, (const uint32_t*) main_func, XXXXX}
既然是数组那么每个成员都是 uint32_t *
它对于 数据 和 函数 不做区分 统统放进去!1---这样做是干啥呢?
官方工程师的回答
https://support.dialog-semiconductor.com/jumptablebase88
The jump_table is an array in retention memory where pointers to different functions and variables are stored.
This memory area is powered even in Deep Sleep mode and will retain its content.It is not advised to make changes to this array 2---函数如何调用呢?
参考
jump table usage
https://stackoverflow.com/questions/9932212/jump-table-examples-in-c
小弟不才曾经写过一个复旦微电子FM1208的CPU的操作模块 和上位机对应的 乱点鸳鸯谱 原来学名叫做函数指针jumptable
XXXXXX
但是 这样的操作 需要数组的每一个成员都是函数!现在dialog 这个数组每个都是U32*
现在测试一下 它的好处#include<stdio.h>
#include <string.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;typedef void (*Cmdfunc)(void);
#define SHOWME rt_kprintf("---%s--%d---\n",__FUNCTION__,__LINE__);
void fun0(void){SHOWME}
void fun1(void){SHOWME}
void fun2(void){SHOWME}
void jumptest()
{Cmdfunc FunList[3]={fun0,fun1,fun2};for(int i=0;i<3;i++)FunList[i]();}int main(void)
{jumptest();return 0;
}typedef void (*Cmdfunc)(void);
typedef int (*Cmdfunc2)(void);#define SHOWME rt_kprintf("---%s--%d---\n",__FUNCTION__,__LINE__);
void fun0(void){SHOWME}
void fun1(void){SHOWME}
int fun2(void){SHOWME}
void jumptest()
{uint32_t* FunList[3]={(uint32_t*)fun0,(uint32_t*)fun1,(uint32_t*)fun2};Cmdfunc pf;Cmdfunc2 pf2;pf = (Cmdfunc)FunList[0];pf2 = (Cmdfunc2)FunList[2];pf();pf2();}这样的好处是可以差异化!!!FunList 只是中间桥梁而已
比如先是Cmdfunc fun0--在转为uint32_t放在数组--在转回Cmdfunc执行
所以中间的数组写为 uint32_t FunList[3]={(uint32_t)fun0,(uint32_t)fun1,(uint32_t)fun2};
也是没有问题!!!http://blog.sina.cn/dpool/blog/s/blog_abee94340102xdox.html
描述了main函数的调用想到另外一个JUMP的问题以前项目在STM32OTA升级 有这个函数void jump_application( void )
{if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x1FFE0000 ) == 0x10000000) //stack use ram1{log(DEBUG,"跳转至应用程序\n\n\n");/* Jump to user application */__set_PRIMASK(1); //must be close en allJumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);JumpToApplication = (pFunction) JumpAddress;/* Initialize user application's Stack Pointer */__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);JumpToApplication();} else { log(DEBUG,"没有应用程序\n"); }
}
或者
typedef void (*iapfun)(void);
iapfun jump2app;
void iap_load_app(uint32_t appxaddr)
{//*(uint32_t*)appxaddr = 0X20017450printf("[%08x]--[%08X]\r\n",*(uint32_t*)appxaddr,((*(uint32_t*)appxaddr)&0x2FFE0000));if(((*(uint32_t*)appxaddr)&0x2FFE0000)==0x20000000) //¼ì²éÕ»¶¥µØÖ·ÊÇ·ñºÏ·¨.{ __set_PRIMASK(1);//ûÓÐÕâ¾ä»°-¹Ø±ÕÖжÏ-¾Í»áÌøתʧ°Ü£¡£¡printf("--JUMP--\r\n");jump2app=(iapfun)*(uint32_t*)(appxaddr+4); //Óû§´úÂëÇøµÚ¶þ¸ö×ÖΪ³ÌÐò¿ªÊ¼µØÖ·(¸´Î»µØÖ·) MSR_MSP(*(uint32_t*)appxaddr); //³õʼ»¯APP¶ÑÕ»Ö¸Õë(Óû§´úÂëÇøµÄµÚÒ»¸ö×ÖÓÃÓÚ´æ·ÅÕ»¶¥µØÖ·)jump2app(); //Ìøתµ½APP.}
} 我能不能这样 把一个函数放在绝对的地址 然后在调用这个地址呢?#define SHOWME rt_kprintf("---%s--%d---\n",__FUNCTION__,__LINE__);
void kfun(void) __attribute((section(".ARM.__at_0x08008000")));
void kfun(void)
{SHOWME}typedef void (*iapfun)(void); int main(void)
{kfun();//可以执行成功iapfun jump2app; jump2app=(iapfun) *(uint32_t*)(0x08008000);jump2app(); //马上死机 return 0;
}看上去 是函数 放在绝对地址 这个操作有问题可以把函数放在绝对地址吗?
地址有问题!!
#define SHOWME rt_kprintf("---%s--%d---\n",__FUNCTION__,__LINE__);
void kfun(void){SHOWME}typedef void (*iapfun)(void);
int main(void)
{kfun();iapfun jump2app; uint32_t JumpAddress = ( uint32_t) (kfun);jump2app=(iapfun) JumpAddress;jump2app(); return 0;
}#define SHOWME rt_kprintf("---%s--%d---\n",__FUNCTION__,__LINE__);
void kfun(void){SHOWME}typedef void (*iapfun)(void);
int main(void)
{kfun();iapfun jump2app; uint32_t JumpAddress = ( uint32_t) (&kfun);jump2app=(iapfun) JumpAddress;jump2app(); return 0;
}#define SHOWME rt_kprintf("---%s--%d---\n",__FUNCTION__,__LINE__);
void kfun(void) __attribute((section(".ARM.__at_0x08000140")));
void kfun(void){SHOWME}typedef void (*iapfun)(void);
int main(void)
{kfun();iapfun jump2app; uint32_t JumpAddress = ( uint32_t) (&kfun);jump2app=(iapfun) JumpAddress;jump2app(); return 0;
}下面也可以!
void kfun(void) __attribute((section(".ARM.__at_0x08000200")));
main.o(.text) refers to main.o(.ARM.__at_0x08000200) for kfun
kfun 0x08000201 Thumb Code 14 main.o(.ARM.__at_0x08000200)可以写到绝对地址 但是自动偏移一位!!!
#define SHOWME rt_kprintf("---%s--%d---\n",__FUNCTION__,__LINE__);
void kfun(void) __attribute((section(".ARM.__at_0x08000200")));
void kfun(void){SHOWME}typedef void (*iapfun)(void);
int main(void)
{kfun();iapfun jump2app; #if 1 uint32_t JumpAddress = ( uint32_t) (kfun);jump2app=(iapfun) JumpAddress;#elsejump2app=(iapfun) 0x08000201;//WHY 这里+1了?MAP文件也是的#endifrt_kprintf("--0X%X---\n",jump2app);jump2app(); return 0;
}
我想写一个函数放在绝对地址 然后用指针去指向这个地址调用 实际我发现这个函数好像会自动偏移一个字节 这是为啥呢
这篇关于WX:jump_table的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!