IAP串口循环写入导入接收串口数据丢失,问题未解

问题一:数据丢失

串口IAP升级RAM有限,因此升级较大程序出现RAM不够的问题,因此引入循环写入方式;

main程序 

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "sdram.h"
#include "stmflash.h"
#include "iap.h"
#include "can.h"
/************************************************
 ALIENTEK 阿波罗STM32F429开发板实验52
 串口IAP实验-HAL库函数版
 技术支持:www.openedv.com
 淘宝店铺:http://eboard.taobao.com  
 关注微信公众平台微信号:"正点原子",免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者:正点原子 @ALIENTEK
************************************************/

int main(void)
{
	u8 t;
	u16 oldcount=0;				    //老的串口接收数据值
	u32 applenth=0;				    //接收到的app代码长度
//	u8 clearflag=0; 
    
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化USART
//    LED_Init();                     //初始化LED 
//    KEY_Init();                     //初始化按键
    SDRAM_Init();                   //初始化SDRAM
//		CAN1_Mode_Init(CAN_SJW_1TQ,CAN_BS2_6TQ,CAN_BS1_8TQ,24,CAN_MODE_NORMAL); //CAN初始化,波特率125Kbps      
//    LCD_Init();                     //初始化LCD
//    POINT_COLOR=RED;
//	LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7"); 
//	LCD_ShowString(30,70,200,16,16,"FLASH EEPROM TEST");	
//	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
//	LCD_ShowString(30,110,200,16,16,"2016/1/12");	 		
//	LCD_ShowString(30,130,200,16,16,"KEY_UP:Copy APP2FLASH");
//	LCD_ShowString(30,150,200,16,16,"KEY1:Erase SRAM APP");
//	LCD_ShowString(30,170,200,16,16,"KEY0:Run SRAM APP");
//	LCD_ShowString(30,190,200,16,16,"KEY2:Run FLASH APP");
//	POINT_COLOR=BLUE;
	//显示提示信息
//	POINT_COLOR=BLUE;//设置字体为蓝色	
	u8 t1=0;
	int update_step =0;
	#define cnt 6
	int Recive_wait_CNT=10;
	u32 delay_cnt=0;
	while(1)
	{
		if(enable_update_Flag)//等待执行刷新命令
		{
			enable_update_Flag = 0;
			USART_RX_CNT =0;
			CODE_UP_CNT = 0;
			update_step = 100;	
			enabled_update_Flag =1;	
			USART_CAN_RX_FLAG =0;	
			printf("等待用户刷新固件......\r\n");						
		}
		if(enabled_update_Flag)//已经打开升级功能
		{
			//printf("开始更新固件...\r\n");	
			if(CODE_UP_send_flag)
			{
				if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
				{	 
					iap_write_appbin(FLASH_APP1_ADDR+(CODE_UP_cycle_CNT-1)*Code_up_LEN,Code_up_BUF,Code_up_LEN);//更新FLASH代码   
					printf("固定长度更新  %x  \r\n",FLASH_APP1_ADDR+(CODE_UP_cycle_CNT-1)*Code_up_LEN);
					CODE_UP_send_flag =0;
				}else 
				{  
					printf("非FLASH应用程序!\r\n");
				}
			}
			/****************长时间判断是否有新的数据结束**************/
//			if((oldcount==USART_RX_CNT)&&(delay_cnt==0x7fffff))
//				delay_cnt++;
			delay_cnt++;
			if(delay_cnt==0x7fffff*1)//等待1秒
			{
				if((oldcount==USART_RX_CNT)&&(oldcount!=0))
				{
					if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
					{	 
//						iap_write_appbin(FLASH_APP1_ADDR+CODE_UP_cycle_CNT*Code_up_LEN,Code_up_BUF,CODE_UP_CNT);//更新FLASH代码   
						printf("固件尾端更新  %x-> 固件尾端地址  %x 更新长度: %d \r\n",FLASH_APP1_ADDR+CODE_UP_cycle_CNT*Code_up_LEN,FLASH_APP1_ADDR+CODE_UP_cycle_CNT*Code_up_LEN+CODE_UP_CNT,CODE_UP_cycle_CNT*Code_up_LEN+CODE_UP_CNT);	
						CODE_UP_send_flag =0;
					}else 
					{  
						printf("非FLASH应用程序!\r\n");
					}
				}else{
					oldcount=USART_RX_CNT;
				}
				delay_cnt=0;
				printf("循环时间:!!!!");
			}
			/*****************************/
		}
//		switch (update_step){
//			case	0:
//				t++;
//				delay_ms(10);
//				if(t==50)
//				{
//					LED0=!LED0;
//					t=0;
//					t1++;
//					printf("启动Flash倒计时%d...\r\n",cnt-t1);
//				}
//				if(t1>cnt)//延时函数3秒
//				{
//					update_step = 400;
//				}	else{
//					if(enable_update_Flag)
//					{
//						enable_update_Flag = 0;
//						USART_RX_CNT =0;	
//						update_step = 100;	
//						enabled_update_Flag =1;	
//						USART_CAN_RX_FLAG =0;	
//						printf("等待用户刷新固件......\r\n");						
//					}
//				}
//				break;
//			case 100:
//					if(USART_CAN_RX_FLAG)
//					{
//						if(t==0)	Recive_wait_CNT--;
//						if((t==0)&&(Recive_wait_CNT>=0)) 
//						{
//							printf("等待用户持续导入程序倒计时 %d !\r\n",Recive_wait_CNT);//10秒后,默认不在持续导入程序
//						}
//						if((oldcount==USART_RX_CNT)&&(t==0)&&(Recive_wait_CNT==0))//新周期内,没有收到任何数据,认为本次数据接收完成.
//						{
//							applenth=USART_RX_CNT;
//							oldcount=0;
//							USART_CAN_RX_FLAG=0;
//							printf("用户程序总共接收...\r\n");
//							printf("代码长度:%dBytes\r\n",applenth);
//							update_step = 300;
//						}else oldcount=USART_RX_CNT;	 
//					}
//					t++;
//					delay_ms(10);
//					if(t==100)
//					{
//						LED0=!LED0;
//						t=0;
//					}
					if (enable_update_Flag ==3)
					{
						for(int j=0;j<applenth/2;j++)
						{
						if (USART_RX_BUF[j]==USART_RX_BUF[j+applenth/2])
							;//printf("USART_RX_BUF[%d]:%x",j+applenth/2,USART_RX_BUF[j+applenth/2]);
						else
							printf("USART_RX_BUF[%d]:%x--->USART_RX_BUF[%d]:%x",j,USART_RX_BUF[j],j+applenth/2,USART_RX_BUF[j+applenth/2]);
						}
						printf("比对完成!!");enable_update_Flag =10;
					}
					if (enable_update_Flag ==4)
					{
						applenth = applenth/2;
						update_step = 300;
					}
					if (enable_update_Flag ==5)
					{
						for(int j=0;j<applenth;j++)
						{
							printf("USART_RX_BUF[%d]:%x",j,USART_RX_BUF[j]);
						}
					}
					if (enable_update_Flag ==6)
					{
						update_step = 300;
					}
//				break;
//			case 300:
//				if(applenth)
//				{
//					printf("开始更新固件...\r\n");	printf("FLASH_APP1_ADDR:%d;USART_RX_BUF:%d;applenth:%d;\r\n",FLASH_APP1_ADDR,USART_RX_CNT,applenth);
//					if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
//					{	 
//						iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码   
//						printf("固件更新完成!\r\n");	
//						update_step = 400;
//					}else 
//					{  
//						printf("非FLASH应用程序!\r\n");
//					}
//				}else 
//				{
//					printf("没有可以更新的固件!\r\n");
//				}
//				break;
//			case 400:
//				printf("开始执行FLASH用户代码!!\r\n");
//				if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
//				{	 
//					iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
//				}else 
//				{
//					printf("非FLASH应用程序,无法执行!\r\n");   
//				}
//				break;
//			}
		}
}

串口程序

#include "usart.h"
#include "delay.h"
#include "string.h"
// 	 
//如果使用os,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//os 使用	  
#endif
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F429开发板
//串口1初始化		   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2015/9/7
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//V1.0修改说明 
// 	  
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)	
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}
#endif 

#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	

u8 USART_RX_BUF[USART_REC_LEN] __attribute__ ((at(0X20001000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000+0x2D000=0X2002E000.  
u8  Code_up_BUF[Code_up_LEN] __attribute__ ((at(0X2002E000)));//接收缓冲,最Code_up_LEN个字节,起始地址为0X2002E000+0x400=0X2002E400.  //中转升级buff
//u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	
u32 USART_RX_CNT=0;			//接收的字节数 
u8 USART_CAN_RX_FLAG=0;	//	接收标志
u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler; //UART句柄


//初始化IO 串口1 
//bound:波特率
void uart_init(u32 bound)
{	
	//UART 初始化设置
	UART1_Handler.Instance=USART1;					    //USART1
	UART1_Handler.Init.BaudRate=bound;				    //波特率
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()会使能UART1
	
	//HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量(使用回调函数处理中断需要调用该函数)
  
}

//UART底层初始化,时钟使能,引脚配置,中断配置
//此函数会被HAL_UART_Init()调用
//huart:串口句柄

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟
	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FAST;		//高速
		GPIO_Initure.Alternate=GPIO_AF7_USART1;	//复用为USART1
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		__HAL_UART_DISABLE_IT(huart,UART_IT_TC);
#if EN_USART1_RX
		__HAL_UART_ENABLE_IT(huart,UART_IT_RXNE);		//开启接收中断
		HAL_NVIC_EnableIRQ(USART1_IRQn);				//使能USART1中断通道
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//抢占优先级3,子优先级3
#endif	
	}

}


 

u8 USART1RecFlag = 0;
u8 enable_update_Flag=0;
u8 enabled_update_Flag=0;
u32 CODE_UP_CNT =0;
u32 CODE_UP_cycle_CNT =0;
u8 CODE_UP_send_flag =0;
//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ 
	u8 Res;
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	if(USART1RecFlag==0)
	{
		USART_RX_CNT = 0;
	}
	USART_CAN_RX_FLAG = 1;USART1RecFlag = 1;CANRecFlag =0;
	if((__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_RXNE)!=RESET))  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
        HAL_UART_Receive(&UART1_Handler,&Res,1,1000); 
		if(USART_RX_CNT<USART_REC_LEN)
		{
			USART_RX_BUF[USART_RX_CNT]=Res;
			USART_RX_CNT++;
			CODE_UP_CNT++;
			if(CODE_UP_CNT==Code_up_LEN)
			{	
				if(CODE_UP_send_flag)
					printf("上次未成功刷入固件!!");
				printf("USART_RX_CNT:%d----CODE_UP_CNT:%d",USART_RX_CNT,CODE_UP_CNT);
				CODE_UP_cycle_CNT++;
				memcpy(Code_up_BUF,&USART_RX_BUF[USART_RX_CNT-CODE_UP_cycle_CNT*Code_up_LEN],Code_up_LEN);
				CODE_UP_CNT = 0;
				CODE_UP_send_flag =1;
				
			}		
		}else 
		{		
			USART_RX_CNT =0;//循环存取
		}
		/*****************************/
		if(enabled_update_Flag==0){
			if(USART_RX_CNT>=3)
			{
				if((USART_RX_BUF[0]==0x6d)&&(USART_RX_BUF[1]==0x6a)&&(USART_RX_BUF[2]==0x6d))//mjm
				{
					enable_update_Flag = 1;
				}
			}
		}
	/**************************/
	}
	HAL_UART_IRQHandler(&UART1_Handler);	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
} 
#endif	

/****************************************************************************************/
/****************************************************************************************/
/*************************下面程序通过在回调函数中编写中断控制逻辑*********************/
/****************************************************************************************
***************************************************************************************************

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//如果是串口1
	{
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}

	}
}
 
//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ 
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntEnter();    
#endif
	
	HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数
	
    while (HAL_UART_GetState(&UART1_Handler) != HAL_UART_STATE_READY);//等待就绪

	while(HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE) != HAL_OK);//一次处理完成之后,重新开启中断并设置RxXferCount为1
	
#if SYSTEM_SUPPORT_OS	 	//使用OS
	OSIntExit();  											 
#endif
} 
 

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


问题:使用只循环接收接收数据传输正常:不进行FLash数据写入操作;

接收数据正常

发送开始命令;

发送文件:4572kb;接收4572kb.无错误;

引入FLash写入后出现数据丢失问题:

数据丢失:

发送数据:4572kb;        接收:3073kb;

数据丢失;

已经修改串口中断优先级,但是依然没有效果;

问题二:大文件buff宕机,原因未知

因为RAM给了180kb,所以发送大文件时,进行RAM满以后从新循环存如RAM(下标清零);

但是程序执行至:第一次满180kb以后,在接收第二次数据的第一组后宕机了。

程序停止于:

原因未知:

望各路大神帮我答疑解惑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值