zynq中mgtx应用_ZYNQ开发(六)ZYNQ的UART加载

 

加载方法

fd8c5103726041c892a01c5bdc9533e8.png fd8c5103726041c892a01c5bdc9533e8.png

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

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

        串口交互形式

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        交互流程如图1所示。

62303327b0c52a291eade45123605580.png

UART与QSPI读写函数的设计

fd8c5103726041c892a01c5bdc9533e8.png fd8c5103726041c892a01c5bdc9533e8.png

        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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值