STM32 IAP升级遇到的问题总结

发布者:量子启示最新更新时间:2019-03-24 来源: eefocus关键字:STM32  IAP升级  问题总结 手机看文章 扫描二维码
随时随地手机看文章

一,串口通信问题


1,串口通信两端的TTL电平要一致,看选用的芯片,要么都是3.3V要么都是5V。。当两端电平不一致时通常是收不到数据的。。当检测程序等都没有问题但是依然收不到数据时,考虑检测一下两端的电平是否一致。。可用示波器查看收发数据时的电平


2,在写IAP是使用的官方的库函数,结果串口一直收不到正确的数据。不管我发什么,收到的都是0x58或者0xF6,而且我发5个字节只能收到2个。。确定自己的程序逻辑没问题,然后怀疑是使用的库函数有问题。使用beyond compare挨着对照了一下以前写过的正确的程序。。发现系统初始化时外部晶振没有改。。在SystemInit();时就是为了/* 配置系统时钟为168M 使用外部8M晶体+PLL*/ 在函数内有一个宏定义#define PLL_M      25.。。。库函数默认的是25但是我们必须要使用8M的晶振。。所以要把25改成8.。。。。。。改完测试通过。。。。。


3,在问题2的时候自己犯了个错误。当时我把另一个程序的库文件都拷过来了替换了原来的库文件,结果直接进不了中断了。有中断程序就死了。。。如图所示



有中断时汇编显示就跳到了黄色的那句话。然后程序就死了。。其实进不了中断首先想到的是中断向量表的问题。当时一着急没想到这个问题。。复制过来的库文件是我写的IAP的APP程序,我把其中的中断向量表改了,我不是在main函数中改的,我是直接改的库函数中的偏移量,然后就把这个问题给忘了,导致找了半天终于意识到是中断向量表出了问题。。。


4,串口一上电未初始化时就开始疯狂的发乱码,等初始化完成之后就不发了。如图




解决方法:我是看的官方的例程,如果需要更新再初始化串口,如果不需要更新的话就不初始化串口。所以把串口初始化部分写在了后面的判断中。。。这样操作会出现上述问题。把串口的初始化部分写到main函数的前端就不会出现这个问题了。。至于具体为什么会这样的原因还没搞明白。。。


经过询问大神们说不初始化的时候会有浮空电平,有时出现乱发一些数据也正常。。。。


5,我在写iap升级的时候,使用的是一次性全部接收完70K的bin文件,再去升级。。后期程序越写越多,最后编译完的bin文件大于了70K导致升级不能成功。前面的$HEAD命令能接收,发完bin文件后$TAIL命令接收不到。。。。。这是由于bin文件的大小超过了70k大小的buff后面的内容无法接收了。。。。正规的升级应该接收10k或者多少就编程一次。。。。


二,FLASH问题


1,flash的擦除

实际上是把flash的内容全部写1(擦除完再读的话读出来的全是0XFF),flash的编程要按字(32位)或半字(16位)编程,当接收的数据是奇数位是要补上0,凑够半字来编程。


2,写进flash跟读出来的不一样

注意编程flash时变量的存储接收等要用unsigned类型的。存储接收的变量类型要一致。以免造成越界问题,导致看到的数不一致


3,flash做存储用时

当时写了个程序,用flash来存数据,然后再读出来,遇到的问题是设备不断电时可以完整的读出来,设备断电后读不出了。要读多少个数我是把个数也存储在flash中的。最终发现问题是程序中一个标志位的操作有问题,每次断电后再上电会自动把这个个数写为0,导致每次都读不出来数。


三,数组越界问题


1,嵌入式程序通常要求少占内存,通常变量能定义8位不定义16位,一定要注意变量的最大值(细心一点)。在越界问题上,吃亏了好几次了。


eg:①,我定义了一个int16_t的变量来接收flash中的一个变量值0xABCD。。结果很显然越界了。。换成uint16_t即可


②,定义了一个串口接收数据计数器uint16_t 的变量,要接收60k的APP程序,自认为足够用了,但是串口发送60K大小的文件发送的字节数大于了65535,,,又耽误了好久时间。

谨记:要细心


四,关于APP与IAP互跳之间的中断处理问题

跳转时中断问题还是一个比较棘手的问题。。经常跳转之后无法进入中断,然后百度了一下,自己理解大概是,跳转时只是强制改变了PC指正的位置,但是里面的中断寄存器什么的都没有变,这样中断存在,但是中断函数什么的都没有了,造成程序死掉。。我在写的过程中也遇到了问题,第一次从iap跳到app正常,但是从app跳回iap的时候由于残留的中断太多,在iap中程序死了。我的处理方式是把app中的跳转命令换成了系统复位NVIC_SystemReset();(不同的固件库可能函数名不同)其他的处理理的方式据我所知还有有①跳转之前复位或者关闭所有打开的中断②跳转后在初始化时加入RCC_DeInit();,,NVIC_DeInit ();等让中断恢复默认值。。具体可参考下面这篇文章http://dzdesigned80.blog.163.com/blog/static/203259238201272425313152/ 总之要注意中断寄存器的复位。也可以直接软件复位管他什么中断寄存器残留的.从iap跳到app前可以用USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);来关闭串口接收中断。从app跳转回iap可以用软件复位。


五,总结一下在IAP升级中APP程序的中断向量表的偏移


1.      关于APP程序的中断向量表地址偏移(三种方法,stm32F2与F4系列通用。三种方法本质一样只是看到网上的各种例程的表现形式不一样)


① 直接操作寄存器

在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) /*!

#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)

/***********************************************************************

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. */

 

2.关于IAP程序与APP程序keil中的设置

Stm32的flash都是从0x8000000开始的,结束地址看片子的flash大小。Stm32的sram都是从0x2000000开始的,结束地址看片子的sram大小。

IAP程序基本默认就行,跟普通程序一样


在APP程序中需要设置一下偏移量



默认的条件下,图中IROM1的起始地址(Start)一般为0X08000000,大小(Size)为0X100000,即从0X08000000开始的1M空间为我们的程序存储(因为我们的STM32F4的FLASH大小是1M)。而图中,我们设置起始地址(Start)为0X08010000,即偏移量为0X10000(64K字节),因而,留给APP用的FLASH空间(Size)只有0X100000-0X10000=0XF0000(960K字节)大小了。设置好Start和Szie,就完成APP程序的起始地址设置。

       这里的64K字节,需要大家根据Bootloader程序大小进行选择,比如我们本章的Bootloader程序为22K左右,理论上我们只需要确保APP起始地址在Bootloader之后,并且偏移量为0X200的倍数即可(相关知识,请参考:http://www.openedv.com/posts/list/392.htm)。这里我们选择64K(0X10000)字节,留了一些余量,方便Bootloader以后的升级修改。

注意:设置的起始地址要与程序中设置的中断向量表的偏移量对应起来(如果给IAP程序64k的空间则APPkeil中起始地址为0x8010000相应的程序中中断向量偏移0x10000)我用的1M  flash大小的片子。。具体的大小设置,看自己的片子。


关键字:STM32  IAP升级  问题总结 引用地址:STM32 IAP升级遇到的问题总结

上一篇:STM32-USB之Buffer Description Table
下一篇:STM32 NVIC简化理解

推荐阅读最新更新时间:2024-03-16 16:26

基于STM32微处理器和NaI探测器实现γ能谱仪的系统设计
随着对天然辐射场中低能量γ谱学及其应用的深入研究,γ能谱仪不仅在固体矿产勘探、油气普查、水文和工程地质调查等工业生产及科学研究方面,甚至在民用的环境辐射场调查、建材与建筑装饰材料放射性检测方面,都得到广泛的应用,应用场合的复杂多样化对核辐射测量仪器提出新的需求。传统的核辐射测量仪器常采用探头与主控仪器分离的方式,而且主控仪器通常采用32位ARM7处理器甚至8位单片机系统来进行控制,数据采集常采用速度较低的ADC芯片。硬件电路复杂、体积大、集成度低、功能单一。近年ARM公司Cortex—M系列ARM核的推出将微控制器的性能提高到一个崭新的高度,同时功耗与成本大大降低。本文介绍一种主要基于最新Cortex—M3核的STM32微处理器,
[单片机]
基于<font color='red'>STM32</font>微处理器和NaI探测器实现γ能谱仪的系统设计
STM32学习笔记(串口、IAP
串口: 一. USART_ITConfig(USART1, USART_IT_TXE, ENABLE): 只要发送寄存器为空,就会一直有中断,因此,要是不发送数据时,把发送中断关闭,只在开始发送时,才打开。 二. 以下是字符发送的配置过程,注意第6点,在设置USART_CR1中的TE位时,会发送一个空闲帧作为第一次数据发送,所以即便你执行了USART_ClearFlag(USART1, USART_FLAG_TC); (这个函数肯定在空闲帧数据发送完成前执行),所以当空闲帧发送完后,就进入发送完成中断。 配置步骤: 1. 通过在USART_CR1寄存器上置位UE位来激活USART 2. 编程USART_CR1的M位来定义
[单片机]
STM32微控制器SPI接口NSS管理分析
看了很多关于NSS片选信号配置的资料,感觉没有说清楚的,自己写了一些个人的看法,希望对大家有用。 首先看我们看下NSS的结构图,如下。 从上图中我们可以看出左边的NSS代表硬件的引脚,右边的internalnss是内部NSS,微处理器根据这个内部的NSS来确定不同的操作。 和NSS相关的寄存器标志位主要是SSM、SSI以及SSOE。SSM用来配置是硬件模式还是软件模式。SSI用来确定在软件模式下NSS输入的极性,SSOE用来决定是否允许内部NSS信号送出的NSS引脚上。 对NSS的管理有硬件模式和软件模式之分,所谓硬件模式(SSM=0,二选一处0端有效),就是内部NSS的信号来自于外部NSS引脚,是确确实实的硬东西(引脚)
[单片机]
<font color='red'>STM32</font>微控制器SPI接口NSS管理分析
在MDK上建立一个C++的STM32开发工程
最近,我惊讶地发现居然可以用C++进行嵌入式程序开发,甚至是裸系统程序。之前,做单片机开发、STM32上程序开发,想到的都是C语言、汇编语言,根本就没有考虑过还可以用C++语言做开发。近日,在学习公司的项目之后,发现C++有其独道之处。开发起来比C语言更方便架构搭建与程序管理。 我之前对C++有曲解,总认为C++只适合做上层应用软件开发,不适用于单片机开发。一方面是因为C++喜欢来不不就new一个对象。对于内存空间非常紧张的单片机,只能望海兴叹。二是C++生成的代码量较C庞大,效率上可能没有C高。对于主频较低的单片机,也用一点勉强。但是,这并不能掩盖C++的优势。C++是面向对象的程序语言,能非常灵活地进行继承与派生
[单片机]
如何使用STM32的窗口看门狗
32F的窗口看门狗中有一个7位的递减计数器,它会在出现下述2种情况之一时产生看门狗复位: 1)当计数器的数值从0x40减到0x3F时 2)当刷新看门狗时计数器的数值大于某一设定数值时,此设定数值在WWDG_CFR寄存器定义 对于一般的看门狗,程序可以在它产生复位前的任意时刻刷新看门狗,但这有一个隐患,有可能程序跑乱了又跑回到正常的地方,或跑乱的程序正好执行了刷新看门狗操作,这样的情况下一般的看门狗就检测不出来了;如果使用窗口看门狗,程序员可以根据程序正常执行的时间设置刷新看门狗的一个时间窗口,保证不会提前刷新看门狗也不会滞后刷新看门狗,这样可以检测出程序没有按照正常的路径运行非正常地跳过了某些程序段的情况。 WWDG与
[单片机]
STM32正交编码器接口
一、主要内容 芯片型号、使用引脚及初始化程序源码 TIM2端口重映射问题 与JTAG接口冲突时的现象及解决方法 二、芯片型号、使用引脚及初始化程序源码 芯片型号:STM32F103RET6 使用定时器:TIM2、TIM3、TIM4、TIM5 使用引脚:      TIM2—PA15、PB3(remap)      TIM3—PA6、PA7      TIM4—PB6、PB7      TIM5—PA0、PA1 初始化程序源码: (其中TIM2的配置有特殊需要注意的地方,其他配置相同,调试时遇到的问题和解决方法见下文) #include stm32f10x.h #include encoder.h void TI
[单片机]
STM32学习笔记-点亮第一个led
点亮第一个led灯之前要先大概了解一下单片机的工作方式并且有一定的编程基础,能看懂程序 单片机上有很多引脚,被称作io口,io口是通过总线(信号传输的通路)与内部处理系统(执行程序的硬件的总称)相连接,内部处理系统执行c语言程序可以直接控制io口,硬件机器只能识别机器码,但是已经有人一层一层的从底层封装,封装好了stm32 c语言库函数.因此,我们只需调用库函数即可. 点亮第一个io口的核心问题就是io口的配置(初始化) void GPIOC13(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph
[单片机]
stm32上移植linux的实操案例经验分享
刚从硬件跳槽为嵌软时,没有任何一丝的准备。一入职,领导就交代了一项特难的任务——在stm32上移植linux! 瞬间我就懵了,没办法硬着头皮上吧,先搜集资料,我之前跑的是ok6410的板子上运行的linux,现在是在stm32上移植,以前stm32倒是玩过,研究生期间就捣鼓过它,但现在还没从抓烙铁的硬件当中缓过神来,就转到嵌入式软件的开发,更头疼的是stm32没有MMU!没有MMU!找了一下,好吧,有个uClinux! 于是开始学习各种相关的知识,了解到linux的启动一般是u-boot——》liunx内核——》根文件系统,那么首先要做个基于stm32的u-boot,先初始化时钟、外设、中断什么的,看了韦东山老师的视频感觉
[单片机]
<font color='red'>stm32</font>上移植linux的实操案例经验分享
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved