第十节,uart远程加载

ZYNQUART加载

1 加载方法

ZYNQ的启动镜像是由FSBL程序(bootloader),PL配置文件(硬件比特流文件),应用层软件三个部分组成,其通过SDK的软件生成工具把三个部分按规定的格式拼凑成一个.bin文件,最终将这个文件写入到QSPIFLASH中,整个ZYNQ在配置好启动方式为FLASH启动后,便可做到上电自启动运行下载到FLASH中的用户程序。

为了实现远程加载,抛开仿真器,通过UART的方式将固定的.bin文件发送给ZYNQ,然后将文件写入到FLASH。其分三个步骤完成整个程序的更新:第一,搭建UART的传输,通过规定的握手协议,PC机将.bin文件以串口的形式发送给ZYNQ;第二,ZYNQ将收到的文件存储在指定的DDR3内存当中;第三,ZYNQ将DDR3中的文件数据写入到FLASH,写完以后在读出来与接收的数据作对比,做一个校验。

串口交互形式:

开启PC机加载程序,等待任务机发送加载信号;

ZYNQ上电后第一时间给UART发送加载信号0xee,随后监测UART上的回应信号;

PC机监测UART上的加载信号,若是0xee,则发送回应信号0xab,表示PC机做好了进入加载的准备,若不是0xee则不会发送回应信号;

ZYNQ收到回应信息0xab以后,进入加载流程,发送获取长度指令信号0xcc给PC机;

PC机监测UART上的获取长度指令信号,若是0xcc,则发送数据总包数n给PC机(长度=128*n);

ZQNY收到数据长度数据后,发送应答信号0xaa给PC机,表示接收到数据长度了;

PC机监测UART上的应答信号,接收到应答信号0xaa后,PC机进入发送数据流程,监测ZYNQ的准备好接收数据信号0xdd;

ZYNQ接收完数据长度以后,发送准备好接收数据信号0xdd给PC机;

PC机监测UART上的准备好接收数据信号0xdd,收到准备好信号0xdd信号以后,发送一包数据(128byte)给ZYNQ,发送完了以后又监测准备好信号0xdd,然后又发送一包数据(128byte)给ZYNQ,往复循环,直到数据包发送完,发送完数据后监测数据接收完信号0xbb;

ZYNQ接收完数据后,发送接收完信号0xbb给PC机;

PC机监测数据接收完信号0xbb;收到接收完信号0xbb后,数据交互流程完成,ZYNQ监测FLASH写入操作完成信号;

ZYNQ将接收到的数据写入到FLASH,写入完了以后发送FLASH写入操作完成信号0xaf给PC机;

PC机监测到接收完成信号0xaf后,提示用户写flash操作完成;进入到监测FLASH数据校验阶段;

ZYNQ写完flash后,将对应数据从flash中读出来做校验,校验成功则发送校验完成信号0xcf给PC机,若校验失败则发送失败信号0xef给PC机;

PC机监测到校验完成信号或者校验失败信号后提示用户校验完成,整个加载程序完成。

交互流程如图1所示。

图1 加载数据交互流程

2 UART与QSPI读写函数的设计

Uart初始化流程:

  1. 通过uart设备ID找到对应的外设信息;
  2. 填充uart外设寄存器基地址和一些相关信息;
  3. uart外设自检;
  4. 配置uart的fifo的触发等级;
  5. 使能uart外设;

源码如下:

void Init_Uart(void)

{

   XUartPs_Config *UartConifgPtr;

   s32 temp;

   //find device

   UartConifgPtr = XUartPs_LookupConfig(XPAR_PS7_UART_1_DEVICE_ID);

   //config xuartps data struct

   XUartPs_CfgInitialize(&Uart_1,UartConifgPtr, UartConifgPtr->BaseAddress);

   //self test

   temp = XUartPs_SelfTest(&Uart_1);

   if(temp != XST_SUCCESS)

   {

       return;

   }

// XUartPs_SetDataFormat(&Uart_1,XUARTPS_FORMAT_EVEN_PARITY);

   //set uart fifo level

   XUartPs_SetFifoThreshold(&Uart_1,8);

   //uart enable

   XUartPs_EnableUart(&Uart_1);

}

Uart接收字节函数:

判断RX的FIFO是否为空,如果处于空的状态,一直等待;如果不为空,读取RX的FIFO里面的数据,源码如下:

u8 Uart_RecvByte(void)

{

u8 byte = 0;

while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x02) == 0x02));

byte = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET);

return byte;

}

Uart发送字节函数:

判断TX的FIFO是否满,如果处于满的状态,一直等待;如果未满,则把需要发送的数据写入到TX的FIFO中,源码如下:

void Uart_SendByte(u8 byte)

{

while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x10) == 0x10));

XUartPs_WriteReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET,byte);

}

初始化QSPI流程:

  1. 通过qspi设备ID找到对应的外设信息;
  2. 填充qspi外设寄存器基地址和一些相关信息;
  3. Qspi外设自检;
  4. 配置qspi的工作模式;
  5. 配置qspi的工作频率;
  6. 配置qspi的为从设备选择;

源码如下:

void Init_Qspi(void)

{

XQspiPs_Config *QspiConfig;

//find device

QspiConfig = XQspiPs_LookupConfig(XPAR_XQSPIPS_0_DEVICE_ID);

//config XQspiPs data struct QspiInstance

XQspiPs_CfgInitialize(&QspiInstance, QspiConfig,QspiConfig->BaseAddress);

//self test

XQspiPs_SelfTest(&QspiInstance);

//set qspi option

XQspiPs_SetOptions(&QspiInstance,XQSPIPS_MANUAL_START_OPTION |XQSPIPS_FORCE_SSELECT_OPTION |XQSPIPS_HOLD_B_DRIVE_OPTION);

//set qspi clk

XQspiPs_SetClkPrescaler(&QspiInstance, XQSPIPS_CLK_PRESCALE_8);

//set slave select of qspi

XQspiPs_SetSlaveSelect(&QspiInstance);

}

Flash擦除函数流程:

  1. 根据需要写入数据的大小判断需要整片擦除还是扇区擦除;
  2. 通过qspi接口将写使能命令写入到flash;
  3. 通过qspi接口将写命令和需要擦除的flash地址以及数据发送到flash;
  4. 等待数据的传输完成;

函数源码:

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;

 

   /*

    * If erase size is same as the total size of the flash, use bulk erase

    * command

    */

   if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {

       /*

        * Send the write enable command to the FLASH so that it can be

        * written to, this needs to be sent as a seperate transfer

        * before the erase

        */

       XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,

                 sizeof(WriteEnableCmd));

 

       /*

        * Setup the bulk erase command

        */

       WriteBuffer[COMMAND_OFFSET]   = BULK_ERASE_CMD;

 

       /*

        * Send the bulk erase command; no receive buffer is specified

        * since there is nothing to receive

        */

       XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,

                   BULK_ERASE_SIZE);

 

       /*

        * Wait for the erase command to the FLASH to be completed

        */

       while (1) {

           /*

            * Poll the status register of the device to determine

            * when it completes, by sending a read status command

            * and receiving the status byte

            */

           XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,

                       FlashStatus,

                       sizeof(ReadStatusCmd));

 

           /*

            * If the status indicates the write is done, then stop

            * waiting; if a value of 0xFF in the status byte is

            * read from the device and this loop never exits, the

            * device slave select is possibly incorrect such that

            * the device status is not being read

            */

           if ((FlashStatus[1] & 0x01) == 0) {

               break;

           }

       }

 

       return;

   }

 

   /*

    * If the erase size is less than the total size of the flash, use

    * sector erase command

    */

   for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {

       /*

        * Send the write enable command to the SEEPOM so that it can be

        * written to, this needs to be sent as a seperate transfer

        * before the write

        */

       XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,

                   sizeof(WriteEnableCmd));

 

       /*

        * Setup the write command with the specified address and data

        * for the FLASH

        */

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

 

       /*

        * Send the sector erase command and address; no receive buffer

        * is specified since there is nothing to receive

        */

       XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,

                   SEC_ERASE_SIZE);

 

       /*

        * Wait for the sector erse command to the FLASH to be completed

        */

       while (1) {

           /*

            * Poll the status register of the device to determine

            * when it completes, by sending a read status command

            * and receiving the status byte

            */

           XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,

                       FlashStatus,

                       sizeof(ReadStatusCmd));

 

           /*

            * If the status indicates the write is done, then stop

            * waiting, if a value of 0xFF in the status byte is

            * read from the device and this loop never exits, the

            * device slave select is possibly incorrect such that

            * the device status is not being read

            */

           if ((FlashStatus[1] & 0x01) == 0) {

               break;

           }

       }

 

       Address += SECTOR_SIZE;

   }

}

Flash写入函数流程:

  1. 通过qspi接口将写使能发送给flash;
  2. 通过qspi接口将写命令和需要写入数据的flash地址以及数据发送到flash;
  3. 等待数据传输完成;

源码如下:

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];

   /*

    * Send the write enable command to the FLASH so that it can be

    * written to, this needs to be sent as a seperate transfer before

    * the write

    */

   XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,

               sizeof(WriteEnableCmd));

 

   /*

    * Setup the write command with the specified address and data for the

    * FLASH

    */

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

 

   /*

    * Send the write command, address, and data to the FLASH to be

    * written, no receive buffer is specified since there is nothing to

    * receive

    */

   XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,

               ByteCount + OVERHEAD_SIZE);

 

   /*

    * Wait for the write command to the FLASH to be completed, it takes

    * some time for the data to be written

    */

   while (1) {

       /*

        * Poll the status register of the FLASH to determine when it

        * completes, by sending a read status command and receiving the

        * status byte

        */

       XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,

                   sizeof(ReadStatusCmd));

 

       /*

        * If the status indicates the write is done, then stop waiting,

        * if a value of 0xFF in the status byte is read from the

        * device and this loop never exits, the device slave select is

        * possibly incorrect such that the device status is not being

        * read

        */

       if ((FlashStatus[1] & 0x01) == 0) {

           break;

       }

   }

}

Flash读函数流程:

  1. 判断读指令是普通读指令还是其他的读指令;
  2. 根据判断使用对应的读指令,将对应指令和flash写入到flash,并根据需要读多少个数据,写入对应个无效数据到flash,以获取flash中对应地址的数据;

函数源码如下:

void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)

{

  /*

   * Setup the write command with the specified address and data for the

   * FLASH

   */

  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;

  }

  /*

   * Send the read command to the FLASH to read the specified number

   * of bytes from the FLASH, send the read command and address and

   * receive the specified number of bytes of data in the data buffer

   */

  XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,

             ByteCount + OVERHEAD_SIZE);

}

3 加载程序源码

Zynq加载代码:

/*

 * uart_flash.c

 *

 *  Created on: 2019年3月12日

 *      Author: dz

 */

 

#include "xuartps.h"

#include "xil_types.h"

#include "xparameters.h" /* SDK generated parameters */

#include "xqspips.h"        /* QSPI device driver */

 

 

 

 

/

#define UART_DEVICE_ID  XPAR_PS7_UART_1_DEVICE_ID

 

#define HEAD_LEN 2

 

XUartPs Uart_1;

 

XUartPs *InstancePtr = &Uart_1;

 

int Data_Len = 0;

int Len_Count = 0;

int Data_Count = 0;

 

u8 Uart_ReadBuffer[128];

u8 Uart_WriteBuffer[128];

u8 ReadCMD[10];

 

u8 WriteHeadLen[HEAD_LEN] = {0xcc,0x55};

u8 WriteLenOver[HEAD_LEN] = {0xaa,0x55};

u8 WriteHeadData[HEAD_LEN] = {0xdd,0x55};

u8 WriteDataOver[HEAD_LEN] = {0xbb,0x55};

 

u8 WritePowerOn[HEAD_LEN] = {0xee,0x55};

 

u8 Uart_RecvByte(void);

void Uart_SendByte(u8 byte);

int Uart_SendBuffer(u8 *buff,int length);

void Init_Uart(void);

int find_Head(u8 *src,u8 *dst,u8 length);

void delay(u32 count);

 

//

 

 

 

//

#define USER_DDR_BASE_ADDR 0x3e000000

u32 DDR_Base_Addr = USER_DDR_BASE_ADDR;

 

///

 

 

///

#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 quadreads */

#define DUMMY_SIZE         1 /* Number of dummy bytes for fast, dual andquad 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             0x00000000//0x00055000

#define UNIQUE_VALUE            0x05

 

#define MAX_DATA              PAGE_COUNT * PAGE_SIZE

 

void Init_Qspi(void);

 

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

 

 

 

XQspiPs QspiInstance;

unsigned int Flash_Address = 0x000000;

 

u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];

u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];

///

 

 

int main(void)

{

 

      int recv_count = 0,i = 0,j = 0,verify_flag = 0;

      u8 tt;

      Init_Uart();

      Init_Qspi();

 

      // recv start signal

      delay(10000);

      //1 send power on to pc

      Uart_SendBuffer(WritePowerOn,1);

      delay(10000);

      //recv power on ack

      ReadCMD[0] = Uart_RecvByte();

      delay(10000);

      //2,ack right goto load

      if(ReadCMD[0] == 0xab)

      {

             //3,send get data_len to pc

             Uart_SendBuffer(WriteHeadLen,1);

             delay(1000);

             //4,recv length

             while(1)

             {

                    if(Len_Count > 1)

                    {

                           //5,send len tran over to pc

                           Uart_SendBuffer(WriteLenOver,1);

                           //6,data_len option

                           Data_Len |= ReadCMD[0] << 8;

                           Data_Len |= ReadCMD[1];

                           break;

                    }

                    ReadCMD[Len_Count] = Uart_RecvByte();

                    Len_Count++;

             }

             //7,sent get data to pc

             delay(100000);

             while(1)

             {

                    //send over data

                    if(Data_Count >= Data_Len)

                    {

                           // send data over to pc

                           Uart_SendBuffer(WriteDataOver,1);

                           break;

                    }

                    // send get data to pc

                    Uart_SendBuffer(WriteHeadData,1);

                    while(1)

                    {

                           //get data to buffer

                           Uart_ReadBuffer[recv_count] = Uart_RecvByte();

                           if(recv_count >= 127)

                           {

                                  break;

                           }

                           recv_count++;

                    }

                    recv_count = 0;

                    //write ddr3

                    for(i = 0,DDR_Base_Addr = USER_DDR_BASE_ADDR + Data_Count * 128;i < 128;i++,DDR_Base_Addr++)

                    {

                           *(unsigned int *)DDR_Base_Addr = Uart_ReadBuffer[i];

                    }

                    Data_Count++;

             }

 

             //flash program

             Flash_Address = 0x000000;

             DDR_Base_Addr = USER_DDR_BASE_ADDR;

             //erase

             FlashErase(&QspiInstance,0x000000, Data_Len * 128);

 

             //write flash

             for(i = 0;i < (Data_Len * 128 / PAGE_SIZE + 1);i++)

             {

                    for(j = 0;j < PAGE_SIZE;j++)

                    {

                           WriteBuffer[j + 4] = *(unsigned int *)(DDR_Base_Addr +  PAGE_SIZE * i + j);

                    }

                    FlashWrite(&QspiInstance, Flash_Address,PAGE_SIZE,WRITE_CMD);

                    Flash_Address += PAGE_SIZE;

             }

             Uart_SendByte(0xaf);

             //verify Data

             Flash_Address = 0x000000;

             DDR_Base_Addr = USER_DDR_BASE_ADDR;

             for(i = 0;i < (Data_Len * 128 / PAGE_SIZE + 1);i++)

             {

                   FlashRead(&QspiInstance, Flash_Address,PAGE_SIZE,READ_CMD);

                    Flash_Address += PAGE_SIZE;

 

                    for(j = 0;j < PAGE_SIZE;j++)

                    {

                           tt = *(unsigned int *)(DDR_Base_Addr +  PAGE_SIZE * i + j);

                           if(ReadBuffer[j + 4] == tt)

                           {

                                  verify_flag = 0;

                           }

                           else

                           {

                                  verify_flag = 1;

                           }

                    }

             }

             if(verify_flag == 1)

             {

                    Uart_SendByte(0xcf);

             }

             else

             {

                    Uart_SendByte(0xef);

             }

             while(1)

             {

 

             }

 

      }

      else

      {

             print("author:660 dz!!\r\n");

             print("timer:2019/3/13!!\r\n");

             while(1)

             {

 

             }

      }

 

      return 0;

}

 

void Init_Uart(void)

{

      XUartPs_Config *UartConifgPtr;

      s32 temp;

      //find device

     UartConifgPtr = XUartPs_LookupConfig(XPAR_PS7_UART_1_DEVICE_ID);

      //config xuartps data struct

      XUartPs_CfgInitialize(&Uart_1,UartConifgPtr, UartConifgPtr->BaseAddress);

      //self test

      temp = XUartPs_SelfTest(&Uart_1);

      if(temp != XST_SUCCESS)

      {

             return;

      }

 

//    XUartPs_SetDataFormat(&Uart_1,XUARTPS_FORMAT_EVEN_PARITY);

      //set uart fifo level

      XUartPs_SetFifoThreshold(&Uart_1,8);

 

      //uart enable

      XUartPs_EnableUart(&Uart_1);

}

 

u8 Uart_RecvByte(void)

{

      u8 byte = 0;

 

while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x02) == 0x02));

 

      byte = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET);

 

      return byte;

}

 

void Uart_SendByte(u8 byte)

{

while((((XUartPs_ReadReg(InstancePtr->Config.BaseAddress,XUARTPS_SR_OFFSET)) & 0x10) == 0x10));

 

XUartPs_WriteReg(InstancePtr->Config.BaseAddress,XUARTPS_FIFO_OFFSET,byte);

 

}

 

int Uart_SendBuffer(u8 *buff,int length)

{

      int i = 0;

      for(i = 0;i < length;i++)

      {

             Uart_SendByte(buff[i]);

      }

      return i;

}

 

 

int find_Head(u8 *src,u8 *dst,u8 length)

{

      int i = 0,ret = 0;

      for(i = 0;i < length - 1;i++)

      {

             if((src[i] == dst[0]) && (src[i + 1] == dst[1]))

             {

                    ret = 1;

             }

      }

      return ret;

}

 

void delay(u32 count)

{

      unsigned int i = 0;

      for(i = 0;i < count;i++)

      ;

}

 

 

void Init_Qspi(void)

{

      XQspiPs_Config *QspiConfig;

      //find device

      QspiConfig = XQspiPs_LookupConfig(XPAR_XQSPIPS_0_DEVICE_ID);

      //config XQspiPs data struct QspiInstance

      XQspiPs_CfgInitialize(&QspiInstance, QspiConfig,QspiConfig->BaseAddress);

      //self test

      XQspiPs_SelfTest(&QspiInstance);

      //set qspi option

      XQspiPs_SetOptions(&QspiInstance,XQSPIPS_MANUAL_START_OPTION |XQSPIPS_FORCE_SSELECT_OPTION |XQSPIPS_HOLD_B_DRIVE_OPTION);

      //set qspi clk

      XQspiPs_SetClkPrescaler(&QspiInstance, XQSPIPS_CLK_PRESCALE_8);

      //set slave select of qspi

      XQspiPs_SetSlaveSelect(&QspiInstance);

 

}

 

 

 

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;

 

      /*

       * If erase size is same as the total size of the flash, use bulk erase

       * command

       */

      if (ByteCount == (NUM_SECTORS * SECTOR_SIZE)) {

             /*

              * Send the write enable command to the FLASH so that it can be

              * written to, this needs to be sent as a seperate transfer

              * before the erase

              */

             XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,

                             sizeof(WriteEnableCmd));

 

             /*

              * Setup the bulk erase command

              */

             WriteBuffer[COMMAND_OFFSET]   = BULK_ERASE_CMD;

 

             /*

              * Send the bulk erase command; no receive buffer is specified

              * since there is nothing to receive

              */

             XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,

                                  BULK_ERASE_SIZE);

 

             /*

              * Wait for the erase command to the FLASH to be completed

              */

             while (1) {

                    /*

                     * Poll the status register of the device to determine

                     * when it completes, by sending a read status command

                     * and receiving the status byte

                     */

                    XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,

                                         FlashStatus,

                                         sizeof(ReadStatusCmd));

 

                    /*

                     * If the status indicates the write is done, then stop

                     * waiting; if a value of 0xFF in the status byte is

                     * read from the device and this loop never exits, the

                     * device slave select is possibly incorrect such that

                     * the device status is not being read

                     */

                    if ((FlashStatus[1] & 0x01) == 0) {

                           break;

                    }

             }

 

             return;

      }

 

      /*

       * If the erase size is less than the total size of the flash, use

       * sector erase command

       */

      for (Sector = 0; Sector < ((ByteCount / SECTOR_SIZE) + 1); Sector++) {

             /*

              * Send the write enable command to the SEEPOM so that it can be

              * written to, this needs to be sent as a seperate transfer

              * before the write

              */

             XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,

                                  sizeof(WriteEnableCmd));

 

             /*

              * Setup the write command with the specified address and data

              * for the FLASH

              */

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

 

             /*

              * Send the sector erase command and address; no receive buffer

              * is specified since there is nothing to receive

              */

             XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,

                                  SEC_ERASE_SIZE);

 

             /*

              * Wait for the sector erse command to the FLASH to be completed

              */

             while (1) {

                    /*

                     * Poll the status register of the device to determine

                     * when it completes, by sending a read status command

                     * and receiving the status byte

                     */

                    XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd,

                                         FlashStatus,

                                         sizeof(ReadStatusCmd));

 

                    /*

                     * If the status indicates the write is done, then stop

                     * waiting, if a value of 0xFF in the status byte is

                     * read from the device and this loop never exits, the

                     * device slave select is possibly incorrect such that

                     * the device status is not being read

                     */

                    if ((FlashStatus[1] & 0x01) == 0) {

                           break;

                    }

             }

 

             Address += SECTOR_SIZE;

      }

}

 

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];

      /*

       * Send the write enable command to the FLASH so that it can be

       * written to, this needs to be sent as a seperate transfer before

       * the write

       */

      XQspiPs_PolledTransfer(QspiPtr, &WriteEnableCmd, NULL,

                           sizeof(WriteEnableCmd));

 

      /*

       * Setup the write command with the specified address and data for the

       * FLASH

       */

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

 

      /*

       * Send the write command, address, and data to the FLASH to be

       * written, no receive buffer is specified since there is nothing to

       * receive

       */

      XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, NULL,

                           ByteCount + OVERHEAD_SIZE);

 

      /*

       * Wait for the write command to the FLASH to be completed, it takes

       * some time for the data to be written

       */

      while (1) {

             /*

              * Poll the status register of the FLASH to determine when it

              * completes, by sending a read status command and receiving the

              * status byte

              */

             XQspiPs_PolledTransfer(QspiPtr, ReadStatusCmd, FlashStatus,

                                  sizeof(ReadStatusCmd));

 

             /*

              * If the status indicates the write is done, then stop waiting,

              * if a value of 0xFF in the status byte is read from the

              * device and this loop never exits, the device slave select is

              * possibly incorrect such that the device status is not being

              * read

              */

             if ((FlashStatus[1] & 0x01) == 0) {

                    break;

             }

      }

}

 

void FlashRead(XQspiPs *QspiPtr, u32 Address, u32 ByteCount, u8 Command)

{

      /*

       * Setup the write command with the specified address and data for the

       * FLASH

       */

      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;

      }

      /*

       * Send the read command to the FLASH to read the specified number

       * of bytes from the FLASH, send the read command and address and

       * receive the specified number of bytes of data in the data buffer

       */

      XQspiPs_PolledTransfer(QspiPtr, WriteBuffer, ReadBuffer,

                           ByteCount + OVERHEAD_SIZE);

}

 

int FlashReadID(void)

{

      int Status;

 

      /*

       * Read ID in Auto mode.

       */

      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;

      }

 

 

      return XST_SUCCESS;

}

 

上位机的VC程序:

// serialPYL.cpp : Defines the entry point for the console application.

//

 

#include "stdafx.h"

#include <windows.h>

#include <stdio.h>

#include <stdlib.h>

#include "string.h"

 

HANDLE hComm;

 

FILE *fp;

unsigned int LenFile_Bytes;

unsigned int SendTime_128Bytes_shang;

unsigned int SendTime_128Bytes_yu;

unsigned char ReadFile_bytes[128];

unsigned char ReadSerial_bytes[2];

unsigned char WriteSerial_bytes[128];

 

unsigned int Count;

 

bool openport(char *portname);

bool setupdcb(int rate_arg);

bool setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant);

 

bool ReadSerial(void);

bool WriteSerial(int SendByteNum);

 

void ParseFile(char *filename);

 

void delay(int count);

 

int main(int argc, char* argv[])

{

      int i=0,j=0;

      unsigned int toDSP_SendTime = 0;

      unsigned int SendTimeRecord = 0;

      bool open;

      int SerialNum;

      unsigned char lode_value = 0x00;

      int SerialBaudRate = 115200;

      char FileName[20] = "BOOT.bin";

 

      printf("Input Serial Num:");    //输入串口号

      scanf("%d",&SerialNum);

      //     printf("Input Serial BaudRate:");   //输入波特率

      //     scanf("%d",&SerialBaudRate);

      //

      //     printf("Input FileName(二进制):");     //输入二进制文件名

      //    scanf("%s",FileName);

     

      SerialBaudRate = 115200;

      //     FileName = "app.bin";

      printf("|------------------------------------------------------------------|\n");

      printf("|              The Uart0 BaudRate is 115200                        |\n");

      printf("|              user code file is app.bin                           |\n");

     

     

      if(SerialNum > 9)

      {

             char num[15];

             memset(num,'\0',15);

             sprintf(num,"\\\\.\\COM%d",SerialNum);

             open=openport(num);

      }

      else

      {

             char num[15];

             memset(num,'\0',15);

             sprintf(num,"COM%d",SerialNum);

             open=openport(num);

      }    

      if(open)        //1、打开串口

      {

             printf("|              open comport success!                               |\n");

      }

      else

      {

             return 0;

      }

     

      if(setupdcb(SerialBaudRate)) //2、设置串口DCB

      {

//           printf("setupDCB success!\n");

      }

      else

      {

             return 0;

      }

     

//    if(setuptimeout(1000,0,0,500,2000))    //2、设置串口超时    //意外收获,设置为0却变好了。

      if(setuptimeout(1000,500,2000,1000,10000))

      {

//           printf("setuptimeout success!\n");

      }

      else

      {

             return 0;

      }

      SetupComm(hComm,4096,4096);        //2、设置串口缓存

     

      SetCommMask(hComm, EV_RXCHAR);

     

PurgeComm(hComm,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);

     

     

      //解析传输文件

      ParseFile(FileName);

      printf("|              please power on your device!                        |\n");

 

      printf("|------------------------------------------------------------------|\n");  

      //---------------------------------------------------//

      //0xff: DSP请求发送新数据

      //0xdf: DSP请求重发数据

      //0xef: DSP报告发送数据完毕

      //---------------------------------------------------//

      memset(ReadFile_bytes,'\0',128);

      while(1)

      {

             if(ReadSerial())

             {

                    if(ReadSerial_bytes[0] == 0xee)

                    {

                           printf("Load or not,inout 1 loader: ");   //输入串口号

                           scanf("%d",&lode_value);

                           if(lode_value == 1)

                           {

                                  ReadFile_bytes[0] = 0xab;

                           }

                           else

                           {

                                  ReadFile_bytes[0] = 0xff;

                           }

                          

                           WriteSerial(1);

                           break;

                    }

                    else

                    {

                          

                    }

             }

      }

 

      while(1)

      {

             if(ReadSerial())

             {

                    if(ReadSerial_bytes[0] == 0xcc)

                    {

                           if(SendTime_128Bytes_yu > 0)

                           {

                                  toDSP_SendTime = SendTime_128Bytes_shang + 1;

                           }

                           ReadFile_bytes[0] = (toDSP_SendTime >> 8) & 0x0FF; //高8位

                           ReadFile_bytes[1] = toDSP_SendTime & 0x0FF;                   //低8位

                          

                           WriteSerial(2);

                    }

                    else if(ReadSerial_bytes[0] == 0xaa)

                    {

                           //    printf("---start send text---\n");

                           break;

                    }

                    else

                    {

                          

                    }

             }

      }

      printf("|              start send text                                     |\n");

      //    printf("second while(1)\n");

      memset(ReadFile_bytes,'\0',128);

      while(1)

      {

             delay(1000);

             if(ReadSerial())

             {

                    if(ReadSerial_bytes[0] == 0xdd)

                    {

                           SendTimeRecord = SendTimeRecord + 1;

                           printf("|              SendTimeRecord = %4d                               |\n",SendTimeRecord);

                           if(SendTimeRecord <= SendTime_128Bytes_shang)

                           {

                                  fread(ReadFile_bytes, 1, 128, fp);

                                  WriteSerial(128);

                                 

                           }

                           else if(SendTime_128Bytes_yu > 0)

                           {

                                  memset(ReadFile_bytes,0xFF,128);

                                  fread(ReadFile_bytes, SendTime_128Bytes_yu, 1, fp);

                                  WriteSerial(128);

                           }

                           else

                           {

                                  break;

                           }

                    }

                    else if(ReadSerial_bytes[0] == 0xDF)

                    {

                           WriteSerial(128);

                    }

                    else if(ReadSerial_bytes[0] == 0xbb)

                    {

                           break;

                    }

             }

            

      }

      printf("|                                                                  |\n");

      printf("|              start write flash........                           |\n");

      printf("|                                                                  |\n");

 

      while(1)

      {

             if(ReadSerial())

             {

                   

                    if(ReadSerial_bytes[0] == 0xaF)

                    {

                           printf("|              end write flash!                                    |\n");     

                           break;

                    }

             }

      }

      printf("|                                                                  |\n");

      printf("|              verify flash data........                           |\n");

      printf("|                                                                  |\n");

      while(1)

      {

             if(ReadSerial())

             {

                   

                    if(ReadSerial_bytes[0] == 0xEF)

                    {

                           printf("|              verify data success!                                |\n");

                           printf("|              Program Over Success!                               |\n");     

                           printf("|------------------------------------------------------------------|\n");

                           break;

                    }

                    if(ReadSerial_bytes[0] == 0xcf)

                    {

                           printf("|              verify data err!                                    |\n");

                           printf("|------------------------------------------------------------------|\n");

                           break;

                    }

             }

      }

 

     

      fclose(fp);

      system("pause");

      return 0;

}

 

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

/*                                      打开串口(同步方式)                                     */

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

bool openport(char *portname)

{

     

      hComm = CreateFile(portname,                  //串口号

             GENERIC_READ | GENERIC_WRITE,           //允许读写

             0,                                                            //通讯设备必须以独占方式打开(串口不能共享,该参数必须置为0)

             0,                                                            //无安全属性(引用安全性属性结构,缺省值为NULL)

             OPEN_EXISTING,                                       //通讯设备已存在(创建标志,对串口操作该参数必须置为OPEN_EXISTING)

             0,                                                            //异步I/O(如何设置为0,即为同步方式;FILE_FLAG_OVERLAPPED,即为异步方式)

             0);                                                          //通讯设备不能用模板打开(对串口而言该参数必须置为NULL)

      if (hComm == INVALID_HANDLE_VALUE)

      {

             CloseHandle(hComm);

             return FALSE;

      }

      else

             return true;

}

 

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

/*                                      设置串口DCB                                                      */

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

bool setupdcb(int rate_arg)

{

      DCB  dcb;

      int rate= rate_arg;

      memset(&dcb,0,sizeof(dcb));

      if(!GetCommState(hComm,&dcb))//获取当前DCB配置

      {

             return FALSE;

      }

      // set DCB to configure the serial port

      dcb.DCBlength       = sizeof(dcb);

      /* ---------- Serial Port Config ------- */

      dcb.BaudRate        = rate;              //波特了吧

      dcb.Parity                  = NOPARITY;           //无奇偶校验

      dcb.fParity                 = 0;

      dcb.StopBits        = ONESTOPBIT;     //1位停止位

      dcb.ByteSize        = 8;                   //8位数据位

      dcb.fOutxCtsFlow    = 0;

      dcb.fOutxDsrFlow    = 0;

      dcb.fDtrControl     = DTR_CONTROL_DISABLE;

      dcb.fDsrSensitivity = 0;

      dcb.fRtsControl     = RTS_CONTROL_DISABLE;

      dcb.fOutX           = 0;

      dcb.fInX            = 0;

      /* ----------------- misc parameters ----- */

      dcb.fErrorChar      = 0;

      dcb.fBinary         = 1;

      dcb.fNull           = 0;

      dcb.fAbortOnError   = 0;

      dcb.wReserved       = 0;

      dcb.XonLim          = 2;

      dcb.XoffLim         = 4;

      dcb.XonChar         = 0x13;

      dcb.XoffChar        = 0x19;

      dcb.EvtChar         = 0;

      // set DCB

      if(!SetCommState(hComm,&dcb))

      {

        return false;

      }

      else

      {

        return true;

      }

}

 

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

/*                               设置串口超时                                                       */

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

bool setuptimeout(DWORD ReadInterval,DWORD ReadTotalMultiplier,DWORD ReadTotalconstant,DWORD WriteTotalMultiplier,DWORD WriteTotalconstant)

{

      COMMTIMEOUTS timeouts;

      timeouts.ReadIntervalTimeout=ReadInterval;

      timeouts.ReadTotalTimeoutConstant=ReadTotalconstant;

      timeouts.ReadTotalTimeoutMultiplier=ReadTotalMultiplier;

      timeouts.WriteTotalTimeoutConstant=WriteTotalconstant;

      timeouts.WriteTotalTimeoutMultiplier=WriteTotalMultiplier;

      if(!SetCommTimeouts(hComm, &timeouts))

      {

             return false;

      }

      else

      {

             return true;

      }

}

 

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

/*                               同步读串口数据                                                          */

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

bool ReadSerial(void)

{

      DWORD wCount;     //读取的字节数

      BOOL bReadStat;

      bReadStat=ReadFile(hComm,ReadSerial_bytes,1,&wCount,NULL);

      if(!bReadStat)

      {

             printf("Read Serial fail!");

             return FALSE;

      }

      PurgeComm(hComm,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

     

      //     printf("实际读取数据:%d\n",wCount);

      //     printf("实际读取数据:%x\n",ReadSerial_bytes[0]);

     

      return TRUE;

}

 

 

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

/*                                      串口发送数据                                                */

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

bool WriteSerial(int SendByteNum)

{

      DWORD wCount=SendByteNum;

      COMSTAT ComStat;

      DWORD dwErrorFlags;

      BOOL bWriteStat;

      ClearCommError(hComm,&dwErrorFlags,&ComStat);

   bWriteStat=WriteFile(hComm,ReadFile_bytes,SendByteNum,&wCount,NULL);

      if(!bWriteStat)

      {

             printf("Write Serial fail!");

             return FALSE;

      }

      PurgeComm(hComm,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

     

      return TRUE;

}

 

 

 

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

/*                               解析文件                                                               */

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

void ParseFile(char *filename)

{

      int i=0;

     

      if((fp=fopen(filename,"rb")) == NULL)//打开操作不成功     //如果不以二进制形式打开,fread读时,碰到0x1A就不读了。

      {

             printf("open file fail!");

             exit(1);//结束程序的执行

      }    

      else

      {

//           printf("open file success!\n");

      }

     

     

      fseek(fp,0L,SEEK_END);

      LenFile_Bytes = ftell(fp);

      rewind(fp);

     

      SendTime_128Bytes_shang = LenFile_Bytes/128;

      SendTime_128Bytes_yu = LenFile_Bytes%128;

//    printf("LenFile_Bytes = %d\n",LenFile_Bytes);

//    printf("SendTime_128Bytes_shang = %d\n",SendTime_128Bytes_shang);

      printf("|              The SendTime is %4d                                |\n",SendTime_128Bytes_shang);

//    printf("SendTime_128Bytes_yu = %d\n",SendTime_128Bytes_yu);

     

}

 

 

void delay(int count)

{

      int i = 0;

      for(i = 0;i < count;i++)

      {

             ;

      }

}

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值