软件环境:vivado 2017.4 硬件平台:XC7Z020


在实际项目中,写好的ZYNQ工程在debug测试完毕之后,固化到FLASH往往是最后一步,然而,在固化的过程中,往往并不都是一次就能成功的,而固化不成功的原因也很多,最直接的排查手段就是可以先做一下FLASH的读写测试,看下FLASH的访问是否正常。

这里以镁光N25Q128为例子,说下常规FLASH的操作和测试过程,工程这边没什么特别需要注意的,用的是之前测试uartlite的工程,接口是QSPI Flash的。

首先打开flash手册,可以看到有这么一段比较重要的说明:

可以看出,flash是从1写到0,也就是说,擦除后的flash应该是全FF,然后写数据时候,往对应bit写0即可; 总字节数16MB,包含256个sectors(每sector 64K),相当于4096个subsectors(每个subsectors 4K),或65536个page(每个page 256B)。以框图描述如下:

主要还是要记住sector有256个,包括65536个page,每个page 256B,每个地址代表1B。

搞清楚存储的结构之后,下一个要关心的就是读写等操作指令了,下面只是列举了其中一部分,不同厂商,不同容量的话,需要注意有些指令是有可能不一样的:

另外,在使用fast read时候,需要注意,上来的数据中,首先是dummy bytes:

写的话就直接按照指令+地址+数据的格式就好:

先上代码:

#include "xparameters.h"   /* SDK generated parameters */
#include "xqspips.h"      /* QSPI device driver */
#include "xil_printf.h"
#include "sleep.h"
/************************** Constant Definitions *****************************//** The following constants map to the XPAR parameters created in the* xparameters.h file. They are defined here such that a user can easily* change all the needed parameters in one place.*/
#define QSPI_DEVICE_ID      XPAR_XQSPIPS_0_DEVICE_ID/** The following constants define the commands which may be sent to the FLASH* device.*/
#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/** The following constants define the offsets within a FlashBuffer data* type for each kind of data.  Note that the read data offset is not the* same as the write data because the QSPI driver is designed to allow full* duplex transfers such that the number of bytes received is the number* sent and received.*/
#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 *//** The following constants specify the extra bytes which are sent to the* FLASH on the QSPI interface, that are not data, but control information* which includes the command and address*/
#define OVERHEAD_SIZE       4/** The following constants specify the page size, sector size, and number of* pages and sectors for the FLASH.  The page size specifies a max number of* bytes that can be written to the FLASH with a single transfer.*/
#define SECTOR_SIZE     0x10000//65536
#define NUM_SECTORS     0x100//256
#define NUM_PAGES       0x10000//65536
#define PAGE_SIZE       256/** Number of flash pages to be written.*/
#define PAGE_COUNT      65536/** Flash address to which data is ot be written.*/
#define TEST_ADDRESS        0x00000000//0x00055000
#define UNIQUE_VALUE        0x05
/** The following constants specify the max amount of data and the size of the* the buffer required to hold the data and overhead to transfer the data to* and from the FLASH.*/
#define MAX_DATA        PAGE_COUNT * PAGE_SIZE/**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************/int 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);int QspiFlashPolledExample(XQspiPs *QspiInstancePtr, u16 QspiDeviceId);/************************** Variable Definitions *****************************//** The instances to support the device drivers are global such that they* are initialized to zero each time the program runs. They could be local* but should at least be static so they are zeroed.*/
static XQspiPs QspiInstance;/** The following variable allows a test value to be added to the values that* are written to the FLASH such that unique values can be generated to* guarantee the writes to the FLASH were successful*/
int Test = 5;/** 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[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[PAGE_SIZE + DATA_OFFSET];/*****************************************************************************/
/**
*
* Main function to call the QSPI Flash example.
*
* @param   None
*
* @return  XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note        None
*
******************************************************************************/
#define FLASH_TEST_ADDRESS0         0x00000000int System_init_startup (void);
int qspi_flash_id(void);
int qspi_ease_entire_flash(void);
int Spi_Blank_Check(u32 StartAddr, u32 NoByteToRead);
int qspi_flash_write(void);
int qspi_flash_read(void);static int qspi_init_flag=0;
static u32 Address = FLASH_TEST_ADDRESS0;int main(void)
{int Status;int Cnt;int choice, exit_flag = 0;u32 SectCount=1, StartAddr, NoByteToRead;if (qspi_init_flag ==0){Status = System_init_startup();if (Status != XST_SUCCESS) {return XST_FAILURE;}elseqspi_init_flag=1;}StartAddr = FLASH_TEST_ADDRESS0;NoByteToRead = 512;SectCount = 512;while(exit_flag != 1){print("\n\r*******************************************************************\n\r");print("\n\rChoose from options below: \r\n");print("1: Read Quad SPI flash ID\r\n");print("2: Erase Quad SPI flash\r\n");print("3: Blank Check Quad SPI flash\r\n");print("4: Write Quad SPI flash\r\n");print("5: Read Quad SPI flash\r\n");print("\n\r*******************************************************************\n\r");choice = inbyte();if (isalpha(choice)) {choice = toupper(choice);}switch(choice){case '1':{print("\n\r\t Read Quad SPI flash ID\t\r\n");qspi_flash_id();}break;case '2':{print("Entire flash erase (Bulk Erase)\r\n");FlashErase(&QspiInstance, TEST_ADDRESS, MAX_DATA);print("Entire flash erase finish!\r\n");}break;case '3':{print ("\n\rQuad SPI flash Blank Check:\n\r");xil_printf("\r\n\r\nStart Address \t= 0x%08x\n\rEnd Address \t= 0x%08x\n\r", StartAddr,(TEST_ADDRESS + MAX_DATA));print ("\n\rPerforming Blank Check operation...\n\r");Status = Spi_Blank_Check(TEST_ADDRESS, MAX_DATA);if (Status != XST_SUCCESS) {print("\n\r\n\r\t\tBlank Check Operation Fail!.\r\n");}else{print("\n\r\n\rBlank Check Operation Completed without error.\r\n");}}break;case '4':{print ("\n\rWrite Quad SPI flash:\n\r");qspi_flash_write();}break;case '5':{print ("\n\rRead Quad SPI flash:\n\r");qspi_flash_read();}break;default:break;}}
}int System_init_startup (void)
{int Status;XQspiPs_Config *QspiConfig;QspiConfig = XQspiPs_LookupConfig(QSPI_DEVICE_ID);if (NULL == QspiConfig) {return XST_FAILURE;}Status = XQspiPs_CfgInitialize(&QspiInstance, QspiConfig,QspiConfig->BaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}XQspiPs_SetOptions(&QspiInstance, XQSPIPS_MANUAL_START_OPTION |XQSPIPS_FORCE_SSELECT_OPTION |XQSPIPS_HOLD_B_DRIVE_OPTION);XQspiPs_SetClkPrescaler(&QspiInstance, XQSPIPS_CLK_PRESCALE_8);XQspiPs_SetSlaveSelect(&QspiInstance);return XST_SUCCESS;
}int qspi_flash_id(void)
{int Status;if (qspi_init_flag ==0){Status = System_init_startup ();if (Status != XST_SUCCESS) {return XST_FAILURE;}elseqspi_init_flag=1;}Status = FlashReadID();if(Status != XST_SUCCESS) {return XST_FAILURE;}return XST_SUCCESS;
}int Spi_Blank_Check(u32 StartAddr, u32 NoByteToRead)
{int Status;int remaind_int, NoOfPage;u32 Index,StartOffsetAddr;StartOffsetAddr = StartAddr;if (qspi_init_flag ==0){Status = System_init_startup ();if (Status != XST_SUCCESS) {} else qspi_init_flag=1;}NoOfPage = (NoByteToRead/PAGE_SIZE);remaind_int = (NoByteToRead - ( NoOfPage * PAGE_SIZE));if (remaind_int != 0) {NoOfPage = (NoOfPage+1);}xil_printf("\n\rPerforming Blank Check Operation...\n\rStart Address\t= 0x%08x\n\rEnd Address\t= 0x%08x\n\rNumber Of Pages\t= 0x%08x\n\r", StartOffsetAddr, NoByteToRead, NoOfPage);while (NoOfPage !=0){memset(ReadBuffer, 0x00, sizeof(ReadBuffer));FlashRead(&QspiInstance, StartOffsetAddr, PAGE_SIZE, FAST_READ_CMD);xil_printf("\nStartOffsetAddr %x:",StartOffsetAddr);for(Index = 0; Index < PAGE_SIZE; Index++){if(ReadBuffer[Index + DATA_OFFSET + DUMMY_SIZE] != 0xFF){xil_printf("Blank Check Fail at Address:0x%x = 0x%x\r\n", (TEST_ADDRESS + Index), (ReadBuffer[Index + DATA_OFFSET + DUMMY_SIZE]));return XST_FAILURE;} else{xil_printf(".");}}NoOfPage--;StartOffsetAddr = (StartOffsetAddr + PAGE_SIZE);}return XST_SUCCESS;
}int qspi_flash_write(void)
{int Page;int Count;u8 UniqueValue;print ("\n\rWriteBuffer:");for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < PAGE_SIZE;Count++, UniqueValue++) {WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue);xil_printf (" 0x%x ",WriteBuffer[DATA_OFFSET + Count]);}for (Page = 0; Page < 5; Page++) {FlashWrite(&QspiInstance, (Page * PAGE_SIZE) + TEST_ADDRESS,PAGE_SIZE, WRITE_CMD);usleep(500000);}return XST_SUCCESS;
}int qspi_flash_read(void)
{int Cnt;memset(ReadBuffer, 0x00, sizeof(ReadBuffer));FlashRead(&QspiInstance, TEST_ADDRESS, (5 * PAGE_SIZE) , FAST_READ_CMD);for(Cnt = 0; Cnt < (5 * PAGE_SIZE); Cnt++){xil_printf(" 0x%x ", (ReadBuffer[Cnt + DATA_OFFSET + DUMMY_SIZE]));}return XST_SUCCESS;
}/*****************************************************************************/
/**
*
* This function writes to the  serial FLASH connected to the QSPI interface.
* All the data put into the buffer must be in the same page of the device with
* page boundaries being on 256 byte boundaries.
*
* @param   QspiPtr is a pointer to the QSPI driver component to use.
* @param   Address contains the address to write data to in the FLASH.
* @param   ByteCount contains the number of bytes to write.
* @param   Command is the command used to write data to the flash. QSPI
*       device supports only Page Program command to write data to the
*       flash.
*
* @return  None.
*
* @note        None.
*
******************************************************************************/
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;}}
}/*****************************************************************************/
/**
*
* This function reads from the  serial FLASH connected to the
* QSPI interface.
*
* @param   QspiPtr is a pointer to the QSPI driver component to use.
* @param   Address contains the address to read data from in the FLASH.
* @param   ByteCount contains the number of bytes to read.
* @param   Command is the command used to read data from the flash. QSPI
*       device supports one of the Read, Fast Read, Dual Read and Fast
*       Read commands to read data from the flash.
*
* @return  None.
*
* @note        None.
*
******************************************************************************/
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);
}/*****************************************************************************/
/**
*
* This function erases the sectors in the  serial FLASH connected to the
* QSPI interface.
*
* @param   QspiPtr is a pointer to the QSPI driver component to use.
* @param   Address contains the address of the first sector which needs to
*       be erased.
* @param   ByteCount contains the total size to be erased.
*
* @return  None.
*
* @note        None.
*
******************************************************************************/
int 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 XST_SUCCESS;}/** 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;}return XST_SUCCESS;
}/*****************************************************************************/
/**
*
* This function reads serial FLASH ID connected to the SPI interface.
*
* @param   None.
*
* @return  XST_SUCCESS if read id, otherwise XST_FAILURE.
*
* @note        None.
*
******************************************************************************/
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;}xil_printf("FlashID=0x%x 0x%x 0x%x\n\r", ReadBuffer[1], ReadBuffer[2],ReadBuffer[3]);if ( (ReadBuffer[1] == 0x20)){xil_printf("\n\rManufacturer ID:\t0x%x\t:= MICRON\n\r", ReadBuffer[1]);if ( (ReadBuffer[2] == 0xBA)){xil_printf("Memory Type:\t\t0x%x\t:= N25Q 3V0\n\r", ReadBuffer[2]);}else{if ((ReadBuffer[2] == 0xBB)){xil_printf("Memory Type:\t\t0x%x\t:= N25Q 1V8\n\r", ReadBuffer[2]);} else xil_printf("Memory Type:\t\t0x%x\t:= QSPI Data\n\r", ReadBuffer[2]);}if ((ReadBuffer[3] == 0x18)){xil_printf("Memory Capacity:\t0x%x\t:= 128Mbit\n\r", ReadBuffer[3]);}else if ( (ReadBuffer[3] == 0x19)){xil_printf("Memory Capacity:\t0x%x\t:= 256Mbit\n\r", ReadBuffer[3]);}else if ((ReadBuffer[3] == 0x20)){xil_printf("Memory Capacity:\t0x%x\t:= 512Mbit\n\r", ReadBuffer[3]);}else if ((ReadBuffer[3] == 0x21)){xil_printf("Memory Capacity:\t0x%x\t:= 1024Mbit\n\r", ReadBuffer[3]);}}else if ((ReadBuffer[1] == 0x01)){xil_printf("\n\rManufacturer ID: \tSPANSION\n\r");if ((ReadBuffer[3] == 0x18)){xil_printf("Memory Capacity\t=\t256Mbit\n\r");}else if ((ReadBuffer[3] == 0x19)){xil_printf("Memory Capacity\t=\t512Mbit\n\r");}else if ((ReadBuffer[3] == 0x20)){xil_printf("Memory Capacity\t=\t1024Mbit\n\r");}}else if ((ReadBuffer[1] == 0xEF)){xil_printf("\n\rManufacturer ID\t=\tWINBOND\n\r");if ((ReadBuffer[3] == 0x18)){xil_printf("Memory Capacity\t=\t128Mbit\n\r");}}return XST_SUCCESS;
}

下面对代码进行简要的说明:

1.代码总共包含5个功能,读ID、整片擦除、空白检测、写入数据、读取数据,通过串口进行交互

2.代码最开始#define _CMD相关的指令和OFFSET、SIZE配置等参数,需要根据实际使用的片子来进行调整,保证跟手册一致,否则有可能无法正常进行测试

3.读、写测试均测试5个page,起始地址由代码中的TEST_ADDRESS来指定

4.在System_init_startup()中完成了QSPI接口的初始化,通过XQspiPs_SetOptions()来设置参数,通过XQspiPs_SetClkPrescaler()来设置时钟的分频

5.如果待测的是1Gb那种大容量flash,一定注意要把FlashWrite()和FlashRead()函数接口中的地址长度改掉,当前使用的是3字节地址

6.不同厂商不同芯片不同读取指令,dummy bytes个数可能会不同,如果懒得查手册,最好实际读取时候打断点,来确定最开始的dummy bytes个数

7.在写flash时,注意要有小的间隔,否则有可能写入的数据完全不正确

接下来展示实测结果:

读ID:

整片擦除:

此时回读前5个page:

进行空白检测:

然后再向前5个page循环写入从5开始的递增数:

此时回读新写入后的5个page,可见:

【JokerのZYNQ7020】FLASH_TEST。相关推荐

  1. 【JokerのZYNQ7020】PS_LWIP_POLL。

    软件环境:vivado 2017.4        硬件平台:XC7Z020 说起zynq平台下PS端的lwip实现机制,有可能很多老哥跟我一样,具体并不十分清楚,我自己也是在很偶然的情况下看了一篇帖 ...

  2. 【JokerのZYNQ7020】TIMER。

    软件环境:vivado 2017.4        硬件平台:XC7Z020 手册说的很清楚呀,ZYNQ的每个CPU都有自己的私有定时器,私有定时器工作频率是CPU工作频率的一半,即ARM工作频率是6 ...

  3. 【JokerのZYNQ7020】UART。

    https://blog.csdn.net/natty715/article/details/84668564 软件环境:vivado 2017.4        硬件平台:XC7Z020 内部结构大 ...

  4. 【JokerのZYNQ7020】AXI4_FULL。

    软件环境:vivado 2017.4        硬件平台:XC7Z020 ZYNQ片内分PS端PL端,但既然都在片内,肯定不是两个独立的个体,两部分之间联系,主要是通过AXI4总线.是总线必然有总 ...

  5. 【JokerのZYNQ7020】LINUX_BRAM。

    软件环境:vivado 2019.1        硬件平台:XC7Z020 前一节说了一种冷门的PL与PS间数据交互方式,然后忽然发现,之前写的RAM和ROM方式操作block ram并不全面,作为 ...

  6. 【JokerのZYNQ7020】AXI_EMC。

    软件环境:vivado 2019.1 硬件平台:XC7Z020 赶在六月的屁股,与看见这篇文章的各位,分享一个非常非常实用模块,这就是AXI_EMC,大概平时听起来可能比较陌生,接下来结合场景举例,给 ...

  7. 【JokerのZYNQ7020】INTERRUPT(PL产生,PS处理)。

    软件环境:vivado 2017.4        硬件平台:XC7Z020 由图中可见,中断大体分为三类,包括SGI(软件中断).PPI(私有中断).SPI(共享中断). 每个CPU均有16个SGI ...

  8. 【JokerのZYNQ7020】QSPI启动。

    软件环境:vivado 2017.4        硬件平台:XC7Z020 通常来说,系统做好以后是放SD卡里,上电以后,根据boot引脚的配置,从SD卡引导系统启动.如果你像我一样,板子上还带有Q ...

  9. 【JokerのZYNQ7020】SDK程序从QSPI启动。

    软件环境:vivado 2017.4        硬件平台:XC7Z020 之前写的QSPI启动是对ZYNQ的PS装Linux系统的,如果不想搞那么麻烦或者功能要求单一,调试又想方便一些,直接写SD ...

最新文章

  1. VC++ 常见编译错误
  2. 基本数据类型与引用数据类型的不同
  3. 使用Spring Boot和Vue进行有益的开发
  4. Android Demo---如何敲出圆角的Button+圆角头像
  5. sublime3打开多个窗口
  6. 3 深入解析controlfile
  7. mac硬盘空间怎么清理?这样也能清理出上10G的磁盘空间
  8. 将软件代码从Delphi 7迁移升级到Delphi 10.4.1等现代化新版本的注意事项
  9. 【SketchUp插件】10款吊炸天的SU插件,拿走不谢!
  10. Android系统中SD卡各文件夹名称功能详解
  11. ubuntu18.04 Nvidia 显卡的风扇调速及startx的后果 --转载
  12. 外国同行看中国互联网“微创新”
  13. [蓝桥杯]java实现第39级台阶
  14. 19.flowable 任务委派
  15. hbuilder运行uniapp,微信开发者工具打开但没有运行项目
  16. Minecraft多人联机服务器配置
  17. 基于FPGA的电子密码锁
  18. DLT698.45之数据类型(RSD)
  19. 计算机主机干什么,电脑硬盘是干什么用的
  20. [仅ESP32] BT AT命令

热门文章

  1. 2011-12-24
  2. 联想与戴尔台式计算机比较,戴尔台式机和联想台式机哪个好用
  3. 主板四大厂_(【四大品牌主板真假图片对比之技嘉】- 中关村在线)
  4. NumPy 基础教程
  5. 『正睿OI 2019SC Day3』
  6. Greenplum初始化gpinitsystem报错解决
  7. 家族关系查询系统程序设计算法思路_数据结构课程设计(家族关系查询系统)
  8. Vue手把手带你入门(一) nodejs安装配置以及vue-cli脚手架创建第一个vue项目(超级详细)
  9. 如何使DFC实现跨平台
  10. 云计算介绍 tcp/ip协议介绍及配置