我在用KL16做bootloader时,使用ymodem进行串口数据接收,在将数据写入flash时调用FTFA_PGM4(INT32U addr, INT32U data)一次写4字节,FTFA_PGM4(addr, 0x11223344);用常量写OK,一旦使用FTFA_PGM4(addr, *pdata);使用指针就挂掉跑到HardFault_Handler。
其他地方的函数调用FTFA_PGM4时使用指针代入也是OK,最大的差别只是ymodem接收函数判断比较多,其他地方函数结构简单点。为什么会跑到HardFault_Handler?
ymodem接收函数如下:
int8_t Ymodem_Receive_File(void)
{
char back,file_lenth[8]="",file_name[FILE_NAME_LENGTH]="";
uint16_t i=0,ret,C_count=0;
uint8_t lenth_cnt, *file_ptr;
int32_t packet_length,packets_received, session_done, file_done, errors, session_begin;
uint32_t k,file_len=0;
uint8 sector=0;
uint16_t offset = 0;
uint32 addr,*pdata;
file_ptr = file_ptr;
//格式化APPBak区域
DISABLE_INT(); /* 关中断 */
FTFA_ERSSCRS(AppBakSector,AppBakSectorNum);
ENABLE_INT(); /* 开中断 */
for (session_done = 0, errors = 0, session_begin = 0; ;)
{
for (packets_received = 0, file_done = 0/*, buf_ptr = buf*/; ;)
{
back = Ymodem_Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT);
switch (back)
{
case 0:
errors = 0;
switch (packet_length)
{
/* Abort by sender */
case - 1:
Send_Byte(ACK);
return 0;
/* End of transmission */
case 0://说明PC发送完了,单片机收到了EOT
packets_received=0;//将本次文件接收到数据包计数清零
Send_Byte(ACK);
Send_Byte(CRC16);//此时发送方将会开启新的一次传输,若只发一个文件则会有一包全为0的数据。
break;
case -2: //CRC校验出错
Send_Byte(NAK);
break;
/* Normal packet packet_size */
default:
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
Send_Byte(NAK);
}
else
{
if (packets_received == 0)
{
/* 接收文件名Filename packet */
if (packet_data[PACKET_HEADER] != 0)
{
for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);)
{
file_name[i++] = *file_ptr++;
}
file_name[i] = '\0';
// uart2SendString((uint8 *)"file_name:");
// uart2SendString((uint8 *)file_name);
// uart2SendString((uint8 *)"\r\n");
file_ptr++;//跳过0字节,指向文件长度起始字节
lenth_cnt=0;
while(*file_ptr != 0x20)//取出文件长度描述
{
file_lenth[lenth_cnt++]=*file_ptr++;
}
file_lenth[lenth_cnt]=0;
// uart2SendString((uint8 *)"file_lenth:");
// uart2SendString((uint8 *)file_lenth);
// uart2SendString((uint8 *)"\r\n");
k=1;
while(lenth_cnt--)//
{
file_len+=(file_lenth[lenth_cnt]-0x30)*k;
k=k*10;
}
uart2SendIntNum(file_len);
// uart2SendData(packet_data,packet_length+PACKET_OVERHEAD);
sector=AppBakSector;//APP备份去起始sector
addr = sector*4096;
pdata=(uint32 *)(packet_data + PACKET_HEADER);
Send_Byte(ACK);
Send_Byte(CRC16);//接收文件描述信息所在的第一包后需要发送一个C给PC,PC才会启动发送数据。
}
/* Filename packet is empty, end session */
//说明文件传输完毕,发送方无下一个传输文件可传
else
{
Send_Byte(ACK);//这个ACK回应后,本次通信正式结束,发送端将不再发送任何数据
file_done = 1;
session_done = 1;
break;
}
}
/* Data packet */
else
{
//msDelay(100);
if(packet_length == 1024)
{
//DISABLE_INT();
FTFA_PGM_Data(sector,offset,1024,packet_data + PACKET_HEADER);
//ENABLE_INT();
// FTFA_PGM4(addr, *pdata);
// FTFA_PGM4(addr, 0x11223344);
// addr+=4;
// pdata++;
//根据本次写的数据量,计算准备好下一次写的地址
offset +=1024; //下一次的开始写地址
if(offset == 1024)
{
offset = 0;
sector++;
}
}
else
{
FTFA_PGM_Data(sector,offset,128,packet_data + PACKET_HEADER);
// FTFA_PGM4(addr, *pdata);
// addr+=4;
// pdata++;
offset +=128;
if(offset == 1024)
{
offset = 0;
sector++;
}
}
Send_Byte(ACK);//数据包接收完后只需要ACK回复,PC就会发送下一个包
}
packets_received ++;
session_begin = 1;
}
}
break;
/*abort by user*/
case 1:
Send_Byte(CA);
Send_Byte(CA);
return -3;
/*timeout or packet error*/
default:
if (session_begin > 0)
{
errors ++;
if (errors > MAX_ERRORS)
{
Send_Byte(CA);
Send_Byte(CA);
return -2;
}
}
if(packets_received == 0)// 第0包数据还没接收到,则继续发送‘C’
{
// LED_YELL_TOGGLE();
Send_Byte(CRC16);
C_count++;
if(C_count==800)//大约800*26ms=20.8s
{
C_count = 0;
return -1;
}
}
}
if (file_done != 0)
{
break;
}
}
if (session_done != 0)
{
break;
}
}
return 1;
} |