一,ZYNQ使用网口实现BOOT.BIN在线升级
1,这个模块能使用的前提是在vivado工程中勾选FLASH配置和eth0或eth1支持(不然硬件不支持后面文件会报错)。无论是裸机还是带操作系统升级程序都需要勾选。
2,SDK裸机实现程序升级,进入需要使能 lwip 141库,并进行设置
3,将use_axieth_on_zynq 和 use_emaclite_on_zynq 设为 0;修改 lwip_memory_options 设置,将 mem_size,memp_n_pbuf 这 2 个参数值设大,这样会提高 UDP 传输效率。修改 pbuf_options 设置,将 pbuf_pool_size 设大,增加可用的 pbuf 数量,这样同样会提高 UDP 传输效率。修改 tcp_options 设置,将 lwip_tcp 设置为 false,tcp_queue_ooseq 设为 0,关闭 tcp功能;配置如图:
4,此项不是必须设置的,如果为了提高升级效率可以进行配置。修改 temac_adapter_options 设置,将 n_rx_descriptors 和 n_tx_descriptors 参数设大。这样可以提高 zynq 内部 emac dma 的数据搬移效率:
5,使能 DHCP 功能,将 memory 空间尽可能设置大一些,增大缓存空间,提高效率,,前面已经设置过了
6,将qspi_update模块添加到SDK工程里面,里面包含了qspi.h和qspi.c头文件
qspi.h
#ifndef SRC_QSPI_H_
#define SRC_QSPI_H_
#include "xparameters.h" /* SDK generated parameters */
#include "xqspips.h" /* QSPI device driver */
#include "xil_printf.h"
#define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
#define WRITE_STATUS_CMD 0x01
#define WRITE_CMD 0x02
#define READ_CMD 0x03
#define WRITE_DISABLE_CMD 0x04
#define READ_STATUS_CMD 0x05
#define WRITE_ENABLE_CMD 0x06
#define FAST_READ_CMD 0x0B
#define DUAL_READ_CMD 0x3B
#define QUAD_READ_CMD 0x6B
#define BULK_ERASE_CMD 0xC7
#define SEC_ERASE_CMD 0xD8
#define READ_ID 0x9F
#define COMMAND_OFFSET 0 /* FLASH instruction */
#define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_OFFSET 4 /* Dummy byte offset for fast, dual and quad
reads */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual and
quad reads */
#define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
#define BULK_ERASE_SIZE 1 /* Bulk Erase command size */
#define SEC_ERASE_SIZE 4 /* Sector Erase command + Sector address */
#define OVERHEAD_SIZE 4
#define SECTOR_SIZE 0x10000
#define NUM_SECTORS 0x100
#define NUM_PAGES 0x10000
#define PAGE_SIZE 256
#define PAGE_COUNT 16
#define TEST_ADDRESS 0x00055000
#define UNIQUE_VALUE 0x05
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
int update_qspi(XQspiPs *QspiInstancePtr, u16 QspiDeviceId, unsigned int TotoalLen, char *FlashDataToSend) ;
#endif /* SRC_QSPI_H_ */
/***************************** Include Files *********************************/
#include "qspi.h"
#include "xtime_l.h"
#include "stdio.h"
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void FlashWriteEnable(XQspiPs *QspiPtr);
void FlashWriteDisable(XQspiPs *QspiPtr) ;
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount);
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command);
int FlashReadID(void);
void print_percent(int percent) ;
/************************** Variable Definitions *****************************/
XQspiPs QspiInstance;
/*
* The following variables are used to read and write to the flash and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[PAGE_SIZE + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];
int update_qspi(XQspiPs *QspiInstancePtr, u16 QspiDeviceId, unsigned int TotoalLen, char *FlashDataToSend)
{
int Status;
int i ;
unsigned int HasSendNum = 0 ;
unsigned int WriteAddr = 0 ;
unsigned int HasRecvNum = 0 ;
unsigned int ReadAddr = 0 ;
XTime TimerStart, TimerEnd;
float elapsed_time ;
int PercentCurr = -1 ;
int PercentLast = -1 ;
XQspiPs_Config *QspiConfig;
/*
* Initialize the QSPI driver so that it's ready to use
*/
QspiConfig = XQspiPs_LookupConfig(QspiDeviceId);
if (NULL == QspiConfig) {
return XST_FAILURE;
}
Status = XQspiPs_CfgInitialize(QspiInstancePtr, QspiConfig,
QspiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XQspiPs_SetOptions(QspiInstancePtr, XQSPIPS_MANUAL_START_OPTION |
XQSPIPS_FORCE_SSELECT_OPTION |
XQSPIPS_HOLD_B_DRIVE_OPTION);
XQspiPs_SetClkPrescaler(QspiInstancePtr, XQSPIPS_CLK_PRESCALE_8);
XQspiPs_SetSlaveSelect(QspiInstancePtr);
FlashReadID();
printf("Performing Erase Operation...\r\n") ;
XTime_SetTime(0) ;
XTime_GetTime(&TimerStart) ;
FlashErase(QspiInstancePtr, 0, TotoalLen);
XTime_GetTime(&TimerEnd) ;
printf("100%%\r\n") ;
elapsed_time = ((float)(TimerEnd-TimerStart))/((float)COUNTS_PER_SECOND) ;
printf("INFO:Elapsed time = %.2f sec\r\n", elapsed_time) ;
printf("Erase Operation Successful.\r\n") ;
printf("Performing Program Operation...\r\n") ;
XTime_SetTime(0) ;
XTime_GetTime(&TimerStart) ;
do
{
PercentCurr = (int)(((float)HasSendNum/(float)TotoalLen)*10) ;
if (PercentCurr != PercentLast)
print_percent(PercentCurr) ;
PercentLast = PercentCurr ;
if ((HasSendNum+PAGE_SIZE) > TotoalLen)
{
for (i = 0 ; i < PAGE_SIZE ; i++)
{
if (i >= TotoalLen-HasSendNum)
{
WriteBuffer[DATA_OFFSET + i] = 0 ;
}
else
{
WriteBuffer[DATA_OFFSET + i] = (u8)(FlashDataToSend[HasSendNum+i]);
}
}
FlashWrite(QspiInstancePtr, WriteAddr, PAGE_SIZE, WRITE_CMD);
printf("100%%\r\n") ;
XTime_GetTime(&TimerEnd) ;
elapsed_time = (float)(TimerEnd-TimerStart)/(COUNTS_PER_SECOND) ;
printf("INFO:Elapsed time = %.2f sec\r\n", elapsed_time) ;
printf("Program Operation Successful.\r\n") ;
HasSendNum+= PAGE_SIZE ;
}
else
{
for (i = 0 ; i < PAGE_SIZE ; i++)
{
WriteBuffer[DATA_OFFSET + i] = (u8)(FlashDataToSend[HasSendNum+i]);
}
FlashWrite(QspiInstancePtr, WriteAddr, PAGE_SIZE, WRITE_CMD);
HasSendNum+= PAGE_SIZE ;
WriteAddr+= PAGE_SIZE ;
}
}while(HasSendNum < TotoalLen) ;
HasSendNum = 0 ;
WriteAddr = 0 ;
printf("Performing Verify Operation...\r\n") ;
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
XTime_SetTime(0) ;
XTime_GetTime(&TimerStart) ;
do{
PercentCurr = (int)(((float)HasRecvNum/(float)TotoalLen)*10) ;
if (PercentCurr != PercentLast)
print_percent(PercentCurr) ;
PercentLast = PercentCurr ;
if ((HasRecvNum+PAGE_SIZE) > TotoalLen)
{
FlashRead(QspiInstancePtr, ReadAddr, PAGE_SIZE, FAST_READ_CMD);
for (i = 0 ; i < TotoalLen-HasRecvNum; i++)
{
if (ReadBuffer[DATA_OFFSET + DUMMY_SIZE+i] != (u8)(FlashDataToSend[HasRecvNum+i]))
{
printf("Verify data error, address is 0x%x\tSend Data is 0x%x\tRead Data is 0x%x\r\n", ReadAddr+i+1,FlashDataToSend[HasRecvNum+i], ReadBuffer[DATA_OFFSET + DUMMY_SIZE+i]) ;
break ;
}
}
HasRecvNum+= PAGE_SIZE ;
printf("100%%\r\n") ;
XTime_GetTime(&TimerEnd) ;
elapsed_time = (float)(TimerEnd-TimerStart)/(COUNTS_PER_SECOND) ;
printf("INFO:Elapsed time = %.2f sec\r\n", elapsed_time) ;
printf("Verify Operation Successful.\r\n") ;
}
else
{
FlashRead(QspiInstancePtr, ReadAddr, PAGE_SIZE, FAST_READ_CMD);
for (i = 0 ; i < PAGE_SIZE ; i++)
{
if (ReadBuffer[DATA_OFFSET + DUMMY_SIZE+i] != (u8)(FlashDataToSend[HasRecvNum+i]))
{
printf("Verify data error, address is 0x%x\tSend Data is 0x%x\tRead Data is 0x%x\r\n",
ReadAddr+i+1,FlashDataToSend[HasRecvNum+i], ReadBuffer[DATA_OFFSET + DUMMY_SIZE+i]) ;
break ;
}
}
HasRecvNum+= PAGE_SIZE ;
ReadAddr+= PAGE_SIZE ;
}
}while(HasRecvNum < TotoalLen) ;
HasRecvNum = 0 ;
ReadAddr = 0 ;
return XST_SUCCESS;
}
void FlashWrite(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,sizeof(WriteEnableCmd));
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
ByteCount + OVERHEAD_SIZE);
while (1)
{
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
if ((FlashStatus[1] & 0x01) == 0)
{
break;
}
}
}
void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)
{
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
if ((Command == FAST_READ_CMD) || (Command == DUAL_READ_CMD) ||
(Command == QUAD_READ_CMD))
{
ByteCount += DUMMY_SIZE;
}
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,ByteCount + OVERHEAD_SIZE);
}
void FlashErase(XQspiPs *QspiPtr, u32 Address, u32 ByteCount)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
int Sector;
unsigned int EraseSecNum ;
int PercentCurr = -1 ;
int PercentLast = -1 ;
if (ByteCount == (NUM_SECTORS * SECTOR_SIZE))
{
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
WriteBuffer[COMMAND_OFFSET] = BULK_ERASE_CMD;
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,
BULK_ERASE_SIZE);
while (1)
{
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
if ((FlashStatus[1] & 0x01) == 0)
{
xil_printf("Bulk Erase Done!\r\n") ;
break;
}
}
return;
}
EraseSecNum = ((ByteCount / SECTOR_SIZE) + 1) ;
xil_printf("Erase Size is %u Bytes\r\n", EraseSecNum*SECTOR_SIZE) ;
for (Sector = 0; Sector < EraseSecNum ; Sector++)
{
PercentCurr = (int)(((float)Sector/(float)EraseSecNum)*10) ;
if (PercentCurr != PercentLast)
print_percent(PercentCurr) ;
PercentLast = PercentCurr ;
XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,sizeof(WriteEnableCmd));
WriteBuffer[COMMAND_OFFSET] = SEC_ERASE_CMD;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)(Address >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)(Address >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,SEC_ERASE_SIZE);
while (1)
{
XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,
FlashStatus,
sizeof(ReadStatusCmd));
if ((FlashStatus[1] & 0x01) == 0)
{
break;
}
}
Address += SECTOR_SIZE;
}
}
int FlashReadID(void)
{
int Status;
WriteBuffer[COMMAND_OFFSET] = READ_ID;
WriteBuffer[ADDRESS_1_OFFSET] = 0x23; /* 3 dummy bytes */
WriteBuffer[ADDRESS_2_OFFSET] = 0x08;
WriteBuffer[ADDRESS_3_OFFSET] = 0x09;
Status = XQspiPs_PolledTransfer(&QspiInstance, WriteBuffer, ReadBuffer,RD_ID_SIZE);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
xil_printf("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2],ReadBuffer[3]);
return XST_SUCCESS;
}
void print_percent(int percent)
{
switch(percent)
{
case 0 : xil_printf("0%%..") ; break ;
case 1 : xil_printf("10%%..") ; break ;
case 2 : xil_printf("20%%..") ; break ;
case 3 : xil_printf("30%%..") ; break ;
case 4 : xil_printf("40%%..") ; break ;
case 5 : xil_printf("50%%..") ; break ;
case 6 : xil_printf("60%%..") ; break ;
case 7 : xil_printf("70%%..") ; break ;
case 8 : xil_printf("80%%..") ; break ;
case 9 : xil_printf("90%%..") ; break ;
case 10 : xil_printf("100%..") ; break ;
default : break ;
}
}
7,主函数中加入文件
(1)在主函数main.ct中添加头文件#include "src/qspi_update/qspi.h"
然后再主函数外面添加下列定义:
static struct udp_pcb *udp8080_pcb = NULL;//PS端软件端口号
unsigned int ReceivedCount = 0 ;
unsigned int StartUpdate = 0;//程序升级标志
struct ip_addr target_addr;//接收来自电脑的目标IP地址
#define MAX_FLASH_LEN 32*1024*1024
char FlashRxBuffer[MAX_FLASH_LEN] ;
XQspiPs QspiInstance;
#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)//绑定IP地址
(2)在主函数添加udp判断函数:udp_recive(void *arg, struct udp_pcb *pcb, struct pbuf *p_rx,struct ip_addr *addr, u16_t port)
用来判断上位机或网口助手发过来得是否是升级程序BOOT.BIN文件,如果是,就将升级程序标志位置1,准备升级
void udp_recive(void *arg, struct udp_pcb *pcb, struct pbuf *p_rx,struct ip_addr *addr, u16_t port)
{
char *pData;
if (p_rx != NULL)
{
pData = (char *) p_rx->payload;
int udp_len = p_rx->len ;
if (udp_len == 6 && !(memcmp("update", p_rx->payload, 6)))
{
xil_printf("Received Size is %u Bytes\r\n", ReceivedCount) ;
xil_printf("Initialization done, programming the memory\r\n") ;
StartUpdate = 1 ;
}
else
{
memcpy(&FlashRxBuffer[ReceivedCount], pData, udp_len);
ReceivedCount += udp_len ;
}
pbuf_free(p_rx);
}
}
(3)主函数main.c中加入:
udp8080_pcb = udp_new();
udp_bind(udp8080_pcb, IP_ADDR_ANY, 8080);
udp_recv(udp8080_pcb, udp_recive, 0);
IP4_ADDR(&target_addr, 192,168,0,223);//上位机IP
while(1)
{
xemacif_input(echo_netif);
if (StartUpdate)
{
int Status = update_qspi(&QspiInstance, QSPI_DEVICE_ID, ReceivedCount, FlashRxBuffer) ;
if (Status != XST_SUCCESS)
xil_printf("Write Flash Error!\r\n") ;
else
{
StartUpdate = 0 ;
ReceivedCount = 0;
}
}
}
8,run as或debug 加载该程序程序(zynq ps ip设为192.168.0.16):
IP4_ADDR(&(echo_netif->ip_addr), 192, 168, 0, 16);
IP4_ADDR(&(echo_netif->netmask), 255, 255, 255, 0);
IP4_ADDR(&(echo_netif->gw), 192, 168, 0, 1);
此时从cmd中能ping通192.168.0.16就说明加载的程序已经运行起来了可以开始升级
9,SDK程序升级,使用网口助手发送:
(1)选择UDP协议类型,填入电脑本地的IP地址和端口号(自己定一个),填入ZYNQ PS端的IP地址192.168.0.16和端口号8080;点击启用文件数据源,从文件夹中选择要升级的文件BOOT.bin并打开,最后点击发送直到发送完成;
(2)去掉启用文件数据源,然后从网口助手输入“update”字符串,最后点击发送ZYNQ主控收到字符串就会拉高标志位,然后执行程序升级,然后等一段时间等待升级完成。
(3)重启板子电源,然后从cmd ping 192.168.0.10(新程序BOOT.bin的IP),能ping通,说明新程序裸机升级到ZYNQ成功;
二,使用串口串口升级并将BOOT.bin存入SD卡
1,vivado配置:勾选flash和sd和uart
2,sdk端 C代码
(1)sd.c
/*
* sd.c
*
* Created on: 2021年8月3日
* Author: wangjie
*/
#include
#include "xparameters.h"
#include "xsdps.h"
#include "ff.h"
static FATFS SD_Dev; // File System instance
char *SD_Path = "0:/"; // string pointer to the logical drive number
FIL gfile;
int SD_init()
{
FRESULT result;
//-----------------------mount dev------------------------
result = f_mount(&SD_Dev,SD_Path, 0);
if (result != 0) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
int SD_read(char *FileName,u8 *DestinationAddress,u32 ByteLength)
{
FIL file;
FRESULT result;
UINT BytesRd;
result = f_open(&file,FileName,FA_READ);
if(result)
{
return XST_FAILURE;
}
result = f_lseek(&file, 0);
if(result)
{
return XST_FAILURE;
}
result = f_read(&file, (void*)DestinationAddress,ByteLength,&BytesRd);
if(result)
{
return XST_FAILURE;
}
result = f_close(&file);
if(result)
{
return XST_FAILURE;
}
return XST_SUCCESS;
}
int SD_write(u8 *SourceAddress,u32 ByteLength)
{
FRESULT result;
UINT BytesWr;
INT oft = 0;
/*result = f_open(&file,FileName,FA_OPEN_ALWAYS |FA_WRITE);
if(result)
{
return XST_FAILURE;
}*/
oft = f_tell(&gfile);
if(oft < 0)
{
return XST_FAILURE;
}
//result = f_lseek(&file, 0);
result = f_lseek(&gfile,oft);
if(result)
{
return XST_FAILURE;
}
//result = f_write(&file,(void*) SourceAddress,ByteLength,&BytesWr);
result = f_write(&gfile,(void*) SourceAddress,ByteLength,&BytesWr);
if(result)
{
return XST_FAILURE;
}
/*result = f_close(&file);
if(result)
{
return XST_FAILURE;
}*/
return XST_SUCCESS;
}
void SD_END()
{
f_close(&gfile);
}
int SD_main(char *file_name)
{
FRESULT result;
//char FileName[32] = "src.bin"; // name of the log
//memset(&gfile,0,sizeof(FIL));
SD_init();
//result = f_open(&gfile,FileName,FA_CREATE_ALWAYS |FA_WRITE);
result = f_open(&gfile,file_name,FA_CREATE_ALWAYS |FA_WRITE);
if(result)
{
return XST_FAILURE;
}
return 0;
}
(2)main升级代码
#include
#include "types.h"
#include "qspi_g128_flash.h"
#include "uartps_intr.h"
#include "sd.h"
#define UP_FRM_MAX_LEN 4112
#define CRC32_POLYNOMIAL 0xEDB88320L
#define FRM_HEAD_LEN 12
#define FRM_CRC_LEN 4
#define FILE_BASE_ADDR 0x10000000
#define READ_BASE_ADDR 0x11000000
#define WRITE_BASE_ADDR 0x12000000
#define BIN_SYNC1 0xAA
#define BIN_SYNC2 0x44
#define BIN_SYNC3 0x12
#define LOG_MSG_ID_UPGRADE 1000
int8u *p_file;
int8u *p_rd_buf;
int8u *p_wr_buf;
volatile int32u file_cnt = 0;
/***********************************************************************
Function name : CRC32Value
Description : Calculate 32bit CRC
Input parameter :
Output parameter:
Date : 2018.04.26
Author :
***********************************************************************/
static int32u CRC32Value(int32u i)
{
int32s j = 0;
int32u ulCRC = 0;
ulCRC = i;
for (j = 8; j > 0; j--)
{
if(ulCRC & 1)
ulCRC = (ulCRC >> 1) ^ CRC32_POLYNOMIAL;
else
ulCRC >>= 1;
}
return ulCRC;
}
int32u CalculateBlockCRC32(int32u ulCount, int8u *ucBuffer)
{
int32u ulTemp1 = 0;
int32u ulTemp2 = 0;
int32u ulCRC = 0;
while (ulCount-- != 0)
{
ulTemp1 = (ulCRC >> 8) & 0x00FFFFFFL;
ulTemp2 = CRC32Value(((int)ulCRC ^ *ucBuffer++) & 0xff);
ulCRC = ulTemp1 ^ ulTemp2;
}
return(ulCRC);
}
static void ReturnBinCommand(int8u *p_buf, int16u msg_len)
{
int32u temp_len = 0;
int32u crc32 = 0;
//32-bit CRC
temp_len = FRM_HEAD_LEN + msg_len;
crc32 = CalculateBlockCRC32(temp_len, p_buf);
memcpy(p_buf + temp_len, &crc32, 4);
temp_len += 4;
XUartPs_Send(&UartPs, p_buf,temp_len);
}
/***********************************************************************
Function name : CreateBinaryHead
Description :
Input parameter :
Output parameter:
Date : 2018.05.17
Author :
***********************************************************************/
static int32u CreateBinaryHead2(int8u *buf, int16u msg_id, int16u msg_len)
{
int8u msg_type = 0;
//Message header
buf[0] = BIN_SYNC1;
buf[1] = BIN_SYNC2;
buf[2] = BIN_SYNC3;
//Length of the header
buf[3] = FRM_HEAD_LEN;
//Message ID number
buf[4] = msg_id & 0xFF;
buf[5] = msg_id >> 8;
//Message Type
buf[6] = msg_type | 0x80;
buf[7] = 0;
//Message Length
buf[8] = msg_len & 0xFF;
buf[9] = msg_len >> 8;
buf[10] = 0;
buf[11] = 0;
return TRUE;
}
static void SendUpgradeResult(int8u stage, int8u result)
{
int16u msg_len = 2;
int8u temp_buf[64] = {0};
memset(temp_buf, 0, sizeof(temp_buf));
CreateBinaryHead2(temp_buf, LOG_MSG_ID_UPGRADE, msg_len);
temp_buf[FRM_HEAD_LEN] = 1;//stage;
temp_buf[FRM_HEAD_LEN + 1] = result;
ReturnBinCommand(temp_buf, msg_len);
}
int8u update_checksyncserial(void *p_buf,int32u idx,int32u *p_len,int32u len)
{
int8u *buf = NULL;
int32u dat_len = 0;
int32u file_type = 0;
int32u frm_total = 0;
int32u frm_num = 0;
int32u i,j;
int8u tmp_buf[UP_FRM_MAX_LEN] = {0};
int8u ret = FALSE;
int32u calc_crc = 0;
int32u read_crc = 0;
int32u oft = 0;
if(!p_buf)
{
return FALSE;
}
buf = p_buf;
//if(idx >= BUFFER_SIZE - UP_FRM_MAX_LEN)
{
for(i = 0;i < len;i++)
{
j = (idx+i)%BUFFER_SIZE;
tmp_buf[i] = buf[j];
}
buf = tmp_buf;
}
if ((buf[0] == 0xaa) && (buf[1] == 0x44) && (buf[2] == 0x12) && (buf[3] == 0xc))
{
file_type = (buf[4]<<8)|buf[5];
dat_len = (buf[6]<<8)|buf[7];
frm_total = (buf[8]<<8)|buf[9];
frm_num = (buf[10]<<8)|buf[11];
*p_len = dat_len+FRM_HEAD_LEN+FRM_CRC_LEN;
//SendUpgradeResult(buf[FRM_HEAD_LEN], 0);
if(frm_num > frm_total)
{
ret = FALSE;
}
else
{
if ((dat_len != UP_FRM_MAX_LEN - FRM_HEAD_LEN - FRM_CRC_LEN) && (frm_num < frm_total))
{
ret = FALSE;
}
else
{
oft = FRM_HEAD_LEN + dat_len;
calc_crc = CalculateBlockCRC32(oft,buf);
read_crc = (buf[oft] << 24)|(buf[oft+1] << 16)|(buf[oft+2] << 8)|buf[oft+3];
if(calc_crc != read_crc)
{
ret = FALSE;
}
else
{
memcpy(p_file + file_cnt, &buf[FRM_HEAD_LEN],dat_len);
file_cnt += dat_len;
SD_write(&buf[FRM_HEAD_LEN],dat_len);
if(frm_num == frm_total)
{
SD_END();
update_flash(p_file, p_rd_buf, p_wr_buf, file_cnt);
}
SendUpgradeResult(buf[FRM_HEAD_LEN],dat_len);
ret = TRUE;
}
}
}
}
return ret;
}
int32s update_main(void)
{
int32s len,i;
int32u r_len = 0;
while(UpdateReadCnt != UpdateWriteCnt)
{
len = (UpdateWriteCnt + BUFFER_SIZE - UpdateReadCnt)%BUFFER_SIZE;
//if(len >= UP_FRM_MAX_LEN)
if(len > 0)
{
if(update_checksyncserial(RecvUpdateBuf,UpdateReadCnt,&r_len,len))
{
UpdateReadCnt = (UpdateReadCnt+r_len)%BUFFER_SIZE;
}
else
{
UpdateReadCnt = (UpdateReadCnt+1)%BUFFER_SIZE;
printf("update err:%d,%d\n",UpdateWriteCnt,UpdateReadCnt);
}
}
else
{
break;
}
}
return 0;
}
void update_init()
{
p_file = (int8u *)FILE_BASE_ADDR;
p_rd_buf = (int8u *)READ_BASE_ADDR;
p_wr_buf = (int8u *)WRITE_BASE_ADDR;
}
三,附录:ZYNQ带系统实现程序升级:
使用TFTP从PC机将需要升级的文件传输到系统替换原来的新程序,在系统中使用脚本自动运行程序,就算升级完成。