当前位置: 首页 > news >正文

毕节建设网站高级营销型网站建设

毕节建设网站,高级营销型网站建设,网站建设一般收费,德州做网站的公司一、APP跳转函数的分析 typedef void (*iapfun)(void); //定义一个函数类型的参数. 用于将PC指针指向新的APP程序的起始地址 typedef unsigned int uint32_t; #define __IO volatileiapfun jump2app; void iap_load_app(u32 appxaddr) {if(((*(__IO …

一、APP跳转函数的分析

typedef  void (*iapfun)(void);				//定义一个函数类型的参数.     用于将PC指针指向新的APP程序的起始地址
typedef unsigned           int uint32_t;
#define     __IO    volatileiapfun jump2app; void iap_load_app(u32 appxaddr)
{if(((*(__IO uint32_t*)appxaddr)&0x2FFE0000)==0x20000000)	//检查栈顶地址是否合法.(注:正常来说对应4K的RAM地址范围为 0x2000 0000 -- 0x2000 0FFF,所以检索相与值为0x2FFF EFFF){ RCC_DeInit();__disable_irq();	//禁止中断Delayms(5);jump2app=(iapfun)*(__IO uint32_t*)(appxaddr+4);		//用户代码区第二个字为程序开始地址(复位地址)		__set_MSP(*(__IO uint32_t*)appxaddr);					//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)jump2app();									//跳转到APP.}
}

1.函数类型的指针

void*

void*是怎样的存在? 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址,所以不管你存储的是int指针、float指针、long指针,对于存储指针的内存来说都是分配同样大小的内存的,这也为使用void指针可以存储任意类型的指针打下了基础,但是注意在使用void指针,要将其强制转换为具体的指针类型

具体解释:void*是怎样的存在? - 知乎

两种用法(这里使用的第二种):

(1)跳转函数

typedef void (*IapFun)(void);  //定义函数指针
void func(void);               //定义函数
IapFun fun  = func;            //为函数指针对象赋值
fun();                         //这里的fun()其实就相当于跳转到了func()里

(2)跳转至指定地址执行

typedef void (* IapFun)(void);          //定义函数指针
IapFun jump2app;                         //定义函数指针对象
jump2app=(IapFun) * (__IO uint32_t*)(appxaddr+4);	 //为函数指针对象赋值 appxaddr为函数指针地址,例如0x08000000
jump2app();                              //调用函数且jump2app函数的起始地址在上面赋值,可实现PC指针的跳转;

原函数:

void iapfun (void);	

对应定义函数指针的类型:

typedef  void (*iapfun)(void);	//iapfun类型是void ( * )void/*注:对比看一下
typedef unsigned int  UINT32;        // UINT32 类型是unsigned int UINT32UINT32 sum;                         // 定义一个变量:unsigned int sumtypedef  int  arr[3];               // arr 类型是 int[3];(存放int型数据的数组)arr a;                              // 定义一个数组:int a[3];
*/

这里理解为iapfun表示一个指向函数的指针类型的名字,该指针类型为“指向返回void类型并且无参数的函数的指针”,可以使用函数名对函数指针进行初始化(定义函数指针对象),也可以说是定义一种这样一种类型的函数名的函数指针。(参考:IAP跳转APP段代码理解 - 简书)

采用这个类型生成指向函数的指针(也可看做对应类型的函数的函数名):

iapfun jump2app; 

跳转地址赋值函数类型指针(APP函数复位运行地址):

jump2app=(iapfun)*(__IO uint32_t*)(appxaddr+4);	/*(__IO uint32_t*)(appxaddr+4)-->将复位地址值强制转化为32位的指针变量*(__IO uint32_t*)(appxaddr+4)-->取出复位地址保存的数据=中断向量的中断服务程序入口地址(iapfun)*(__IO uint32_t*)(appxaddr+4)-->将中断服务程序入口地址再转化成定义的函数指针类型jump2app=(iapfun)*(__IO uint32_t*)(appxaddr+4);	-->中断服务程序入口地址(iapfun类型的函数指针)赋值jump2app(定义的iapfun类型的函数指针其名为jump2app)
*/

(注: 从指针的层次上理解函数——函数的函数名实际上就是一个指针,函数名指向该函数的代码在内存中的首地址。)

如上图,jump2app这个函数首地址将指向APP的复位中断服务程序地址,实现IAP跳转至APP。

2.((*(__IO uint32_t*)appxaddr)&0x2FFE0000)==0x20000000//顶栈合法判断

以128 Kbytes的SRAM为例,地址范围是 0x2000 0000 --0x2001 FFFF;(1024*128-1=1FFFF)

堆栈指针(SP) 必须在 0x2000 0000 -- 0x2001 FFFF 这块区域,所以在校验顶栈地址是否合法时就校验其地址是否超过合法地址即可,所以 SP & 0x2FFE 0000 == 0x2000 0000时说明SP在合法范围内。

假如是 64 Kbytes 的 RAM,地址Region为 0x2000 0000 -- 0x2000 FFFF,那么此时应该这样写 SP & 0x2FFF 0000 == 0x2000 0000。当然,写成 SP & 0x2FFE 0000 也能执行,但是会带来隐患BUG。

二、中断向量的偏移(重映射)

1.M0内核

    u16 i_app;FLASH_Unlock();for(i_app = 0; i_app < 48; i_app++){*((uint32_t*)(0x20000000 + (i_app << 2)))=*(__IO uint32_t*)(APP_ADDR + (i_app<<2));}//APP_ADDR为APP的起始地址,将对应的中断向量表以及SP搬运到RAM中,下面启用SRAM的启动方式达到向量偏移的效果FLASH_Lock();/* Enable the SYSCFG peripheral clock*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Remap SRAM at 0x00000000 */SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);//采用SRAM启动方式

由于M0内核不支持SCB向量表重定义,在官方指导手册中提供了将向量表复制到SARM,然后从SARM启动程序的方案。(部分M0内核芯片单独添加了SCB->VTOR寄存器,此种情况可以直接使用此寄存器进行地址的便宜,此寄存器是基于m0内核设置的因此地址固定为0xE000ED08)

对应APP的编译文件从APP_ADDR处开始,因此第一段函数作用是将其SP与中断向量表复制到相应的RAM的位置,大小计算方式在下方介绍。

对应每个中断向量的地址占有4个字节,从.s启动文件中找到_Vectors开始,第一个为sp(堆栈指针),其他都为中断服务程序的入口地址,所以就有:

__Vectors_End(所在行)-__Vectors(所在行)-3(中间空的三行)=中断向量表以及SP的占用字节数。如下图:

 119-68-3=48,所需要在SARM中预留的大小为48*4=192=0xC0。

因此在设置RAM的空间时如下设置:

 且开头搬运偏移地址的大小也写为48.

 参考链接如下:STM32F0系列MCU中断向量表的重映射 - STM32/8

2.M0内核以外的芯片

① 直接操作寄存器

在APP程序的main函数的开头设置中断向量表偏移

SCB->VTOR = FLASH_BASE | 0x10000;

其中0x10000是偏移量。。也就是前面的IAP程序所占用的空间大小,要是你的main函数中有SystemInit();的话要在SystemInit();之后添加。

因为SystemInit();中有中断向量表的偏移操作

在void SystemInit (void)系统初始化函数中有初始化中断向量表的语句

#ifdef VECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* 使用内部SRAM启动设置这一句. */

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* 使用内部FLASH启动设置这句*/

#endif

可以直接修改VECT_TAB_OFFSE的值,这个值代表偏移量。不建议这么改,不建议修改库文件,应为后面其他程序用的话经常忘了这里动过中断向量表,导致中断不能正常运行(我就因为这个浪费了快一天时间,串口就是进不了中断)

其中

#define FLASH_BASE ((uint32_t)0x08000000) /*!<FLASH base address in the alias region */

#define SRAM_BASE ((uint32_t)0x20000000) /*!< SRAM baseaddress in the alias region */

对应keil设置中的(这是一般程序默认的,IAP升级中APP程序的这个地方还得根据中断偏移量改)

② 使用库函数设置偏移量

在库文件中有专门的一个函数

在APP程序初始化时调用函数NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x10000);

其中/* Vector Table Base----------------------------------*/

#define NVIC_VectTab_RAM ((u32)0x20000000)

#define NVIC_VectTab_FLASH ((u32)0x08000000)


NVIC_SetVectorTable(u32NVIC_VectTab, u32 Offset)函数如下:

/***********************************************************************Function Name : NVIC_SetVectorTable* Description : Sets the vector table location andOffset.* Input : - NVIC_VectTab: specifies if thevector table is in RAM or* FLASH memory.**********************************************************************/void NVIC_SetVectorTable (u32NVIC_VectTab, u32 Offset){/* Check the parameters */assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));assert_param(IS_NVIC_OFFSET(Offset));SCB->VTOR = NVIC_VectTab | (Offset & (u32)0x1FFFFF80);}

③修改库文件(不建议使用)

直接修改固件库里面的数值。在void SystemInit(void)下的

/* Configure the Vector Table location add offsetaddress ------------------*/

#ifdefVECT_TAB_SRAM

SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;/* Internal SRAM */

#else

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;/* Internal FLASH */

#endif

修改

#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.

This valuemust be a multiple of 0x200. */

为以下:

#define VECT_TAB_OFFSET 0x10000 /*!< Vector Table base offsetfield.

This valuemust be a multiple of 0x200. */

 转自链接:STM32中断向量偏移_zhuyong006的博客-CSDN博客_stm32中断向量偏移

http://www.yayakq.cn/news/917911/

相关文章:

  • 云空间网站开发网站 板块 模块
  • 重庆双八自助建设网站厦门网站开发网站建设网站
  • 扁平化配色方案网站厦门软件园网站建设
  • 装修公司网站建设设计作品学院网站建设情况总结
  • 深圳论坛网站建设最热门的短期培训课程
  • workpress做静态网站怎么利用QQ空间给网站做排名
  • 佛山市网站建设 乾图信息科技外贸网站每天多少ip
  • 哪个网站专做进口商品的设计师常用的设计论坛
  • 一站式服务大厅如何做网站app
  • 芜湖市建设路小学网站广州seo网站优化培训
  • 深圳网站建设 信科网络主要的cms系统有哪些
  • 创建网站首页青岛城乡建设局网站首页
  • 在线做头像网站flash网页制作
  • destoon 手机网站模板html网页设计期末作业
  • 什么是无主体新增网站建筑施工建设网站
  • 长春网站建设厂家wordpress随机广告
  • 苏州网站开发公司兴田德润优惠吗做个人网站要注意什么
  • 珠海网站建设优化推广微信群二维码大全网站
  • 贵州城乡和建设厅网站如何选择家居网站建设
  • 企业网站优化链接wordpress 能做哪些
  • 企业网站建站程序互联网企业100强名单
  • 廊坊企业建站模板苏州公司注册流程
  • 深圳市住房和建设局官网站做直播的网站
  • 网络营销怎么做网站飞阳建设网站
  • 微信扫码下单小程序怎么做seo优化网站技术排名百度推广
  • 哪个网站做新中式保之友微网站怎么建
  • 甘肃省城乡与住房建设厅网站首页高端电子网站建设
  • 做网站公司怎么备案客户网站中国外发加工网app
  • 网站seo外链建设网站在线统计代码
  • 电子商务网站建设教材怎么做网站聊天视频直播