【GD32F303红枫派使用手册】第二十节 SPI-SPI NAND FLASH读写实验

news2024/11/25 6:48:51

20.1 实验内容

通过本实验主要学习以下内容:

  • SPI通信协议,参考19.2.1东方红开发板使用手册 
  • GD32F303 SPI操作方式,参考19.2.2东方红开发板使用手册 
  • NAND FLASH基本原理
  • SPI NAND介绍
  • 使用GD32F303 SPI接口实现对GD5F1GQ5UEYIGY的读写操作

20.2 实验原理

20.2.1 NAND FLASH基本原理

NAND Flash和NOR Flash都是两种非易失性存储器,其读写速度、读写方式,存储区结构、成本、容量、擦写寿命都有很大区别。NAND在寿命、速度、读写方式上都不如NOR,但在成本和容量上有很大区别,故而决定了大容量数据存储是NAND的主要应用领域,而快速启动、快速数据读取等场景是NOR的主要应用领域。而SPI是目前NAND和NOR的主要通信接口形式,降低了器件体积,标准化了器件接口。

  • NAND Flash结构示例

如上图所示,以GD5F1GQ5UEYIGY为例,一个1Gb的存储结构下是由1024个block组成,每个block又64page组成,每个page是2K Main Area+Spare Area(ECC ON:64B;ECC OFF:128B)组成。

NAND的擦除单位是blocks,写入单位是page,所以寻址的方式上和nor是有本质区别的,需要按blocks、page、page字节偏移地址进行一个数据的寻址。

20.2.2 SPI NAND介绍

SPI NAND简化了NAND的接口设计和尺寸,SPI接口更是降低了主控对接口的要求,同时内置ECC。下图是GD5F1GQ5UEYIGY的命令表,常用的命令为擦除、编程、读取命令。

  • block擦除命令
  • 编程
  • 编程流程
  1. 先用数据缓存写入指令将数据写入缓冲区
  1. 然后发送写使能命令,并确认写使能成功
  1. 然后发送数据载入命令执行缓冲区数据到FLASH的写
  1. 最后查询读寄存器确认P_FAIL是否有错,OIP是否完成

注意(84h/C4h/34h) 和(FFh) 指令是不会清除缓存中的内容的,所以下次编程时要注意是否缓存区都是需要更新的数据,所以必须是一次更新整个缓冲区,不要部分更新。

编程page地址按照块的顺序

  • 数据缓存写入命令

 

  • 数据载入命令
  • 读取
  • 读取流程
  1. 读需要先通过读cache命令从FLASH中读出数据到缓存中
  1. 然后通过读cache指令从缓冲区中开始读出数据

读到2048+128后绕回从0开始继续。

20.3 硬件设计

红枫派开发板SPI——NAND FLASH的硬件设计如下:

 

从图中可以看出,本实验使用的是普通单线SPI,GD5F1GQ5UEYIGY的片选由GD32F303ZET6的PG13控制(因PG14不是SPI的NSS管脚,所以本实验用主机NSS软件模式,,通过普通IO控制片选),GD25Q32ESIGR的SO、SI和SCLK分别和GD32F303ZET6的PB4(SPI2_MISO)、PB5(SPI2_MOSI)以及PB3(SPI2_CLK)相连。

20.4 代码解析

20.4.1 SPI初始化和读写BYTE函数实现

SPI初始化配置流程可参考19.4.1东方红开发板使用手册 ;

SPI读写BYTE函数实现可参考19.4.2东方红开发板使用手册 ;

20.4.2 SPI NAND FLASH BSP驱动层实现

操作NAND FLASH的函数都定义在bsp层文件bsp_spi_nand.c中,这个文件中定义的函数都是针对NAND FLASH命令来实现的,我们选取几个函数进行介绍。

  • NOR FLASH按block擦除函数bsp_nandflash_block_erase,输入block号即可擦除;该函数流程是:使能NAND FLASH的写功能->向NOR FLASH发送block擦除指令0xD8->发送左移6位的Block NO->查询OIP标志等待完成
C
/*!
    \brief      erase the nandflash blcok
    \param[in]  block_No:the serial number of erase block
    \param[out] none
    \retval     SPI_NAND_FAIL: erase the nandflash block fail
    \retval     SPI_NAND_SUCCESS: erase the nandflash block success
*/
uint8_t bsp_spi_nandflash_block_erase(uint32_t block_No)
{
    uint8_t result = SPI_NAND_SUCCESS;

    block_No<<=6;        //block_No=block_No*64
    bsp_spi_nandflash_write_enable();
    /* select the flash: chip select low */
    bsp_spi_nand_cs_low();
    /* send "ERASE BLOCK" command */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_BLOCK_ERASE);
    /* send the address of memory */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(block_No>>16)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(block_No>>8)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,block_No&0xFF);
    /* deselect the flash: chip select high */
    bsp_spi_nand_cs_high();
    while(bsp_spi_nandflash_get_status_flag(OIP)==SPI_NAND_BUSY);
    /* check program result */        

    return result;
}
  • NOR FLASH按page写入函数bsp_nandflash_page_program,输入待写入数据指针、block号、page号;该函数流程是:
  • 写缓冲区,实现流程:向NOR FLASH发送写缓冲区指令0x02->发送写入的page偏移地址->发送待写入数据
  • 载入数据到page,实现流程:使能NAND FLASH的写功能->发送载入命令0x10->发送写入的page号
  • 查询OIP标志等待完成
C
/*!
    \brief      send the program load command,write data to cache
    \param[in]  buffer: the data of array
    \param[in]  address_in_page: the address in nandflash page
    \param[in]  byte_cnt: the number of data
    \param[out] none
    \retval     none
*/
void bsp_spi_nandflash_program_load(uint8_t *buffer,uint16_t address_in_page,uint32_t byte_cnt)
{
    uint32_t i=0;

    /* select the flash: chip select low */
    bsp_spi_nand_cs_low();
#ifdef SPI_NANDFLASH
    /* send "PAGE READ" command */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_PAGE_LOAD);
    /* send the serial number of page */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(address_in_page>>8)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,address_in_page&0xFF);
#endif 
    

    /* deselect the flash: chip select high */

        
    for(i=0;i<byte_cnt;i++){
        driver_spi_master_transmit_receive_byte(&BOARD_SPI,*buffer++);
    }
    //printf("cache program %x %x\n\r",m32record[0],m32record[1]);
        
    bsp_spi_nand_cs_high();
    qspi_disable(BOARD_SPI.spi_x);
}

/*!
    \brief      send the program excute command
    \param[in]  page_No: the serial number of nandflash page
    \param[out] none
    \retval     none
*/
void bsp_spi_nandflash_program_execute(uint32_t page_No)
{
    /* enable the write access to the flash */
    bsp_spi_nandflash_write_enable();
    /* select the flash: chip select low */
    bsp_spi_nand_cs_low();
    /* send "PAGE READ" command */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_PROGRAM_EXEC);
    /* send the serial number of page */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>16)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>8)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,page_No&0xFF);
    /* deselect the flash: chip select high */
    bsp_spi_nand_cs_high();
}

/*!
    \brief      write the data to nandflash
    \param[in]  *buffer:the data of array
    \param[in]  page_No: the serial number of nandflash page
    \param[in]  address_in_page: the address of nandflash page
    \param[in]  byte_cnt:the number of data
    \param[out] none
    \retval     SPI_NAND_FAIL,SPI_NAND_SUCCESS 
*/
uint8_t spi_nandflash_write_data(uint8_t *buffer,uint32_t page_No,uint16_t address_page,uint32_t byte_cnt)
{


    /*sned the program load command,write data to cache*/
    bsp_spi_nandflash_program_load(buffer, address_page, byte_cnt);
    /*sned the program excute command*/
    bsp_spi_nandflash_program_execute(page_No);
    /* Check program result */
    while(bsp_spi_nandflash_get_status_flag(OIP)==SPI_NAND_BUSY);

    
#ifdef WRITE_PAGE_VERIFY_EN
     spi_nandflash_read_data (tem_buffer,page_No, address_page, byte_cnt);
    if (memcmp(tem_buffer, buffer,  byte_cnt) != 0){
        return SUCCESS;
    }
#endif
    return 1;

}
  • NOR FLASH按page读取函数spi_nandflash_read_data,输入读取数据指针、page号、page内地址偏移、读取长度;该函数流程是:
  • 读page到缓冲区,实现流程:向NOR FLASH发送写缓冲区指令0x13->送要读取的page号
  • 等待OIP标志(NAND读取page到缓冲区完成)
  • 从缓冲区读取数据,实现流程:发送读cache命令0x03->发送要读取的page地址偏移->读取所需长度的数据
  • 查询是否有ecc错误
C
/*!
    \brief      send the read page command
    \param[in]  page_No: the serial number of nandflash page
    \param[out] none
    \retval     none
*/
void bsp_spi_nandflash_page_read(uint32_t page_No)
{
    /* select the flash: chip select low */
    bsp_spi_nand_cs_low();
    /* send "PAGE READ" command */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_PAGE_READ);
    /* send the serial number of page */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>16)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(page_No>>8)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,page_No&0xFF);
    /* deselect the flash: chip select high */
    bsp_spi_nand_cs_high();
}

/*!
    \brief      send the read cache command
    \param[in]  buffer: a pointer to the array
    \param[in]  address_in_page: the address in nandflash page
    \param[in]  byte_cnt: the number of data
    \param[out] none
    \retval     none
*/
void bsp_spi_nandflash_read_cache(uint8_t *buffer,uint16_t address_in_page,uint32_t byte_cnt)
{
    uint32_t i=0;

    /* select the flash: chip select low */
    bsp_spi_nand_cs_low();
#ifdef SPI_NANDFLASH
    /* send "PAGE READ" command */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,SPI_NAND_READ_CACHE);
    //driver_spi_master_transmit_receive_byte(&BOARD_SPI,DUMMY_BYTE);//Q4UC ++ Q5 --
    /* send the address of page */
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,(address_in_page>>8)&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,address_in_page&0xFF);
    driver_spi_master_transmit_receive_byte(&BOARD_SPI,DUMMY_BYTE);//Q4UC -- Q5 ++
    
#endif


    
    for(i=0;i<byte_cnt;i++){
        *buffer++=driver_spi_master_transmit_receive_byte(&BOARD_SPI,DUMMY_BYTE);
    }
    
    /* deselect the flash: chip select high */
    bsp_spi_nand_cs_high();
    qspi_disable(BOARD_SPI.spi_x);
}

/*!
    \brief      read the data from nandflash
    \param[in]  *buffer:the data of array
    \param[in]  page_No: the serial number of nandflash page
    \param[in]  address_in_page: the address in nandflash page
    \param[in]  byte_cnt:the number of data
    \param[out] none
    \retval     SPI_NAND_FAIL,SPI_NAND_SUCCESS 
*/
uint8_t spi_nandflash_read_data(uint8_t *buffer,uint32_t page_No,uint32_t address_in_page,uint32_t byte_cnt)
{
    uint8_t result = SPI_NAND_SUCCESS;
    uint8_t status = 0;
    uint8_t retrycnt = 0;

    /* the capacity of page must be equal or greater than the taotal of address_in_page and byte_cnt */
    if((address_in_page+byte_cnt)>SPI_NAND_PAGE_TOTAL_SIZE){
        return SPI_NAND_FAIL;
    }
ReadRetry:
    /* send the read page command */
    bsp_spi_nandflash_page_read(page_No);
    /* wait for NANDFLASH is ready */
    while(bsp_spi_nandflash_get_status_flag(OIP)==SPI_NAND_BUSY);
    /* read data from cache */
    bsp_spi_nandflash_read_cache(buffer, address_in_page, byte_cnt);
    
    bsp_spi_nandflash_get_feature( STATUS, &status );
    if(( (status & ECCS0) == 0 )&&( (status & ECCS1) == ECCS1 )){    //UECC
        if(retrycnt < 3)
        {
            retrycnt++;

            printf("\rReadretry:%x %x\n",retrycnt,page_No); 
      
            goto ReadRetry;
        }
        else
        {
            printf("\rRead Fail %x\n",page_No);
        }      
    }             
    return result;
}

 20.4.3 main函数实现

main函数中实现了擦除一个block,并对该block中的page进行写入操作,然后读取后进行数据对比校验的功能。

C
/*!
* 说明     main函数
* 输入     无
* 输出     无
* 返回值   无
*/
int main(void)
{
   
    //延时、共用驱动部分初始化 
    driver_init();
          
    //初始化LED组和默认状态
    bsp_led_group_init();
    bsp_led_on(&LED0);
    bsp_led_off(&LED1);     

    //初始化UART打印
    bsp_uart_init(&BOARD_UART);

    //初始化SPI    
    bsp_spi_init(&BOARD_SPI);
    
    //初始化SPI NAND         
    bsp_spi_nand_init();
  
    printf("\n\rSPI NAND:GD5F1G configured...\n\r");

    //读取flash id    
        flash_id=bsp_spi_nandflash_read_id();
    printf("\n\rThe NAND_ID:0x%X\n\r",flash_id);  

    //比对flash id是否一致
    if(NAND_ID != flash_id)
        {
        printf("\n\r\n\rWrite to tx_buffer:\n\r\n\r");

        //准备数据
        for(uint16_t i = 0; i < BUFFER_SIZE; i ++){
            tx_buffer[i] = i;
            printf("0x%02X ",tx_buffer[i]);

            if(15 == i%16)
                printf("\n\r");
        }

        printf("\n\r\n\rRead from rx_buffer:\n\r");

        //擦除要写入的block        
        bsp_nandflash_block_erase(0);
        //写入数据         
        bsp_nandflash_page_program((uint8_t*)tx_buffer,0,0,0);

        //回读写入数据
        bsp_nandflash_page_read(rx_buffer,0,0);        

        /* printf rx_buffer value */
        for(uint16_t i = 0; i <= 255; i ++){
            printf("0x%02X ", rx_buffer[i]);
            if(15 == i%16)
                printf("\n\r");
        }

        //比较回读和写入数据        
        if(ERROR == memory_compare(tx_buffer,rx_buffer,BUFFER_SIZE)){
            printf("Err:Data Read and Write aren't Matching.\n\r");
            /* spi flash read id fail */
            printf("\n\rSPI nand: Read ID Fail!\n\r");
            
            //写入错误            
            /* turn off all leds */
            bsp_led_on(&LED0);
            /* turn off all leds */
            bsp_led_on(&LED1);           
            while(1);
        }else{
            printf("\n\rSPI-GD5F1G Test Passed!\n\r");
        }
    }else{ //ID读取错误
        /* spi flash read id fail */
        printf("\n\rSPI Nand:Read ID Fail!\n\r");
        /* turn off all leds */
        bsp_led_on(&LED0);
        /* turn off all leds */
        bsp_led_on(&LED1);           
        while(1);
    }

    while(1){
        /* turn off all leds */
        bsp_led_toggle(&LED0);
        /* turn off all leds */
        bsp_led_toggle(&LED1);        
        delay_ms(200);
    }
}

 20.5 实验结果

nand读取到正确ID后开始擦写读流程,如果ID读取错误或者数据比对不通过点亮LED0,熄灭LED1,如果比对通过则交替闪烁LED0和LED1,通过USB转串口可以看到打印结果。

 由聚沃科技原创,来源于【红枫派开发板】第二十讲 SPI-SPI NAND FLASH读写实验 - 苏州聚沃电子科技有限公司 (gd32bbs.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1846050.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习 --- stanford cs231学习笔记四(训练神经网络的几个重要组成部分之一,激活函数)

训练神经网络的几个重要组成部分 一 1&#xff0c;激活函数&#xff08;activation functions&#xff09; 激活函数是神经网络之于线性分类器的最大进步&#xff0c;最大贡献&#xff0c;即&#xff0c;引入了非线性。这些非线性函数可以被分成两大类&#xff0c;饱和非线性函…

Nacos 2.x 系列【17】健康保护阈值

文章目录 1. 概述2. 案例演示2.1 设置阈值2.2 未触发2.3 触发 1. 概述 Nacos 支持通过配置健康保护阈值&#xff08;ProtectThreshold&#xff09;防止因过多实例故障&#xff0c;导致所有流量全部流入剩余实例&#xff0c;继而造成流量压力将剩余实例被压垮形成的雪崩效应。 …

神经网络模型的量化简介(工程版)

1.量化简介 模型量化&#xff08;Model Quantization&#xff09;是深度学习中一种优化技术&#xff0c;旨在减少模型的计算和存储需求&#xff0c;同时尽量保持模型的性能。具体来说&#xff0c;模型量化通过将模型的权重和激活值从高精度&#xff08;通常是32位浮点数&#…

昇思25天学习打卡营第3天 | 数据集

内容介绍&#xff1a;数据是深度学习的基础&#xff0c;高质量的数据输入将在整个深度神经网络中起到积极作用。MindSpore提供基于Pipeline的数据引擎&#xff0c;通过数据集&#xff08;Dataset&#xff09;实现高效的数据预处理。其中Dataset是Pipeline的起始&#xff0c;用于…

一些使用注意(XPTable控件使用说明十)

当XPTABLE放到线程中&#xff0c;列数据很多&#xff0c;不出现滚动条的解决代码&#xff1a; /// 这里神奇的代码&#xff0c;解决线程中XPTABLE 不出滚动条问题 , 执行UI相关的操作this.Invoke(new Action(() >{ // 列头&#xff0c;一行空的&#xff0c;这里列头设置…

AI全栈之logo生成:执文,描摹,妙哉~

前言 前几日体验了国产的AI-Agents产品coze 它是一种能够自主执行任务、与环境进行交互并根据所获取的信息做出决策和采取行动的软件程序 并且可以自己去创建属于自己的AIBot&#xff0c;还是很有意思的&#xff0c;大家可以去体验体验 在体验过程中&#xff0c;我发现在创…

echarts+vue2实战(一)

目录 一、项目准备 二、(横向分页)柱状图 2.1、动态刷新 2.2、UI调整 2.3、分辨率适配 三、(竖向平移)柱状图 3.1、平移动画 3.2、不同数值显示不同颜色 四、(下拉切换)折线图 4.1、切换图表和分辨率适配 4.2、UI调整 五、(三级分类)饼图 5.1、数据切换 六、圆环…

基于卷积神经网络的目标检测

卷积神经网络基础知识 1.什么是filter 通常一个6x6的灰度图像&#xff0c;构造一个3*3的矩阵&#xff0c;在卷积神经网络中称之为filter,对&#xff16;x6的图像进行卷积运算。 2.什么是padding 假设输出图像大小为nn与过滤器大小为ff&#xff0c;输出图像大小则为(n−f1)∗(…

qt经典界面框架

目的 其实就是一个简单的界面显示&#xff0c;是很常用的形式。 说起来简单也是简单&#xff0c;但当初&#xff0c;刚开始做时&#xff0c;感觉非常的复杂&#xff0c;不知如何下手。 现在感觉简单多了。 这个框架利用了QT的现成的MainWindow与QDockWidget&#xff0c;这样就…

Android SurfaceFlinger——SF与HWC交互流程(六)

在上一篇 HWC2On1Adapter 初始化完成后&#xff0c;调用 initWithDevice() 实例化 HwcHal 对象&#xff0c;然后创建高级接口&#xff08;IComposer&#xff09;&#xff0c;使得调用者能够通过这个接口与硬件进行交互。这里我们就来看一下 HwcHal 和 IComposer 的初始化流程。…

超级ai 必须有个,超级大的词表,必须是个向量库 faiss is all you need

说明优点图像表示流程代码实现如下全部代码 说明 使用极其庞大的词表在模型压缩和图像token化方面带来了显著优势。由于词表巨大&#xff0c;我们不得不利用向量数据库对词表进行搜索&#xff0c;以找到最匹配的token。预测出的token会再次通过嵌入矩阵&#xff08;em&#xf…

短剧片源授权,类目丰富优惠多,抢先一步更新你的短剧系统片库!

前言 如今的短剧作为一种新兴的视听艺术形式&#xff0c;正以其独特的魅力迅速占领市场高地。为了满足广大短剧爱好者和从业者的需求&#xff0c;我们提供短剧片源授权服务&#xff0c;凭借剧场独家提供的丰富片源&#xff0c;助力您轻松更新短剧系统片库&#xff0c;抢占市场…

不见五陵高管墓,无花无酒锄做田

不见五陵高管墓&#xff0c;无花无酒锄做田 Golang 通用代码生成器仙童 2.4.0 电音仙女尝鲜版七已发布&#xff0c;此版本测试修复了 PostgreSQL 数据库自动反射功能。此版本更新修复了前端代码生成器&#xff0c;并修复了前端多对多界面的缺陷。PostgreSQL 的数据库反射功能刚…

安装TensorFlow报错问题ERROR: Failed building wheel for h5py解决

安装TensorFlow报错问题&#xff1a; 安装命令: pip install tensorflow2.12.0 -i https://pypi.tuna.tsinghua.edu.cn/simple Building wheel for h5py (PEP 517) ... error ERROR: Command errored out with exit status 1: command: /usr/bin/python3 /tmp/tmpz0y9yg…

代码生成器技术乱弹五十三,人工智能和通用代码生成器的共同点:Token

代码生成器技术乱弹五十三&#xff0c;人工智能和通用代码生成器的共同点&#xff1a;Token 现在&#xff0c;随着人工智能的快速发展&#xff0c;特别是生成式人工智能的爆火&#xff0c;大家逐渐熟悉了一个概念&#xff0c;Token。我称之为字牌。在生成式人工智能的语境下&a…

【每日刷题】Day72

【每日刷题】Day72 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 1287. 有序数组中出现次数超过25%的元素 - 力扣&#xff08;LeetCode&#xff09; 2. 993. 二叉树的…

视创云展为企业虚拟展厅搭建,提供哪些功能?

在当下数字化浪潮中&#xff0c;如何为用户创造更富生动性和真实感的展示体验&#xff0c;已成为企业营销策略的核心。借助视创云展的线上虚拟3D企业展厅搭建服务&#xff0c;利用3D空间漫游和VR技术的融合&#xff0c;可以为用户呈现出一个既真实又充满想象力的全景图或三维模…

中央空调水系统安装

冷热水管&#xff1a; 空调冷热水管道的材质应由业主或使用方明确&#xff1a; 1、普通焊接钢管&#xff1b; 2、无缝钢管&#xff1b; 3、镀锌钢管&#xff1b; 4、PP-R管&#xff1b; 5、紫铜管&#xff1b; 6、水管内外表面应光洁、无疵孔、裂缝、结疤、层裂或气泡。…

Python12 列表推导式

1.什么是列表推导式 Python的列表推导式&#xff08;list comprehension&#xff09;是一种简洁的构建列表&#xff08;list&#xff09;的方法&#xff0c;它可以从一个现有的列表中根据某种指定的规则快速创建一个新列表。这种方法不仅代码更加简洁&#xff0c;执行效率也很…

【总线】AXI4第四课时:信号描述

大家好,欢迎来到今天的总线学习时间!如果你对电子设计、特别是FPGA和SoC设计感兴趣&#xff0c;那你绝对不能错过我们今天的主角——AXI4总线。作为ARM公司AMBA总线家族中的佼佼者&#xff0c;AXI4以其高性能和高度可扩展性&#xff0c;成为了现代电子系统中不可或缺的通信桥梁…