打印
[活动专区]

【AT-START-F437测评】QPI-FLASH测试

[复制链接]
502|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aple0807|  楼主 | 2022-12-28 15:38 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 aple0807 于 2022-12-28 17:42 编辑

QPI是很多高性能MCU的标配,AT32F437也不例外,今天来测试一下板载QPI-FLASH的读写性能如何。

QPI初始化代码如下:
void bsp_qpi_init(void)
{
        intx_alloc();

        intx_disable();

        /* enable the qspi clock */
        crm_periph_clock_enable(CRM_QSPI1_PERIPH_CLOCK, TRUE);
        crm_periph_reset(CRM_QSPI1_PERIPH_RESET, TRUE);
        crm_periph_reset(CRM_QSPI1_PERIPH_RESET, FALSE);

        intx_enable();

        /* switch to cmd port */
        qspi_xip_enable(QPIX, FALSE);

        /* set sclk , AHB / 4*/
        qspi_clk_division_set(QPIX, QSPI_CLK_DIV_4);

        /* set sck idle mode 0 */
        qspi_sck_mode_set(QPIX, QSPI_SCK_MODE_0);

        /* set wip in bit 0 */
        qspi_busy_config(QPIX, QSPI_BUSY_OFFSET_0);

        cmd_cfg.pe_mode_enable = FALSE;
        cmd_cfg.pe_mode_operate_code = 0;
        cmd_cfg.instruction_length = QSPI_CMD_INSLEN_1_BYTE;
        cmd_cfg.read_status_config = QSPI_RSTSC_HW_AUTO;
        cmd_cfg.read_status_enable = FALSE;
}
该接口为AHB外设,时钟设定4分频,即72MHz。
AT32的QPI接口是基于命令处理的,用户配置好命令、时序等内容启动后,硬件自动按照指定的位宽发送/接收数据。
本测试读写均采用DMA方式,这样可以最大限度的发挥QPI的执行速度,特别是读操作。
void qspi_dma_set(dma_dir_type dir, uint8_t *buf, uint32_t length)
{
        dma_init_type dma_init_struct;
        dma_reset(DMA2_CHANNEL1);
        dma_default_para_init(&dma_init_struct);
        dma_init_struct.buffer_size = (length + 3) >> 2; /* using word unit */
        dma_init_struct.loop_mode_enable = FALSE;
        dma_init_struct.direction = dir;
        dma_init_struct.memory_base_addr = (uint32_t)buf;
        dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_WORD;
        dma_init_struct.memory_inc_enable = TRUE;
        dma_init_struct.peripheral_base_addr = (uint32_t)(&(QPIX->dt));
        dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_WORD;
        dma_init_struct.peripheral_inc_enable = FALSE;
        dma_init_struct.priority = DMA_PRIORITY_HIGH;

        dma_init(DMA2_CHANNEL1, &dma_init_struct);

        dmamux_init(DMA2MUX_CHANNEL1, DMAMUX_DMAREQ_ID_QSPI1);
        dmamux_enable(DMA2, TRUE);

        dma_channel_enable(DMA2_CHANNEL1, TRUE);
}
应用层测试代码如下:
 if (1 == nortst.check_req || nortst.chk_keep)

        {

                uint32_t amount = nortst.amount;

                uint32_t ticks;



                // 写入数据

                uint32_t dats = nortst.dat = nortst.dat_first;



                flash_dbg_print("fix spi mode check : start : R/W : %dMB\n", amount / (1024 * 1024));

                ticks = app_tick_get();

                for (nortst.addr = nortst.addr_start; nortst.addr < amount + nortst.addr_start; nortst.addr += SPI_NOR_PAGE_SIZE)

                {

                        if (nortst.addr % SPI_NOR_SECTOR_SIZE == 0)

                        {

                                bsp_snor_sector_erase(nortst.addr);

                        }



                        for (int index = 0; index < SPI_NOR_PAGE_SIZE / 4; index++)

                        {

                                nortst.buff[index].uVal = nortst.dat++;

                        }



                        // 写入一页数据

                        bsp_snor_write(nortst.addr, SPI_NOR_PAGE_SIZE, nortst.buff[0].v);



                        if (0 == (nortst.addr & 0x03FFFF))

                        {

                                flash_dbg_print("fix spi mode check write data: %d %% \n", (nortst.addr - nortst.addr_start) * 100 / amount);

                        }

                }

                flash_dbg_print("fix spi write end: time : %d ms \n", app_tick_get() - ticks);



                // 读回校验

                ticks = app_tick_get();

                nortst.dat = dats;

                for (nortst.addr = nortst.addr_start; nortst.addr < amount + nortst.addr_start; nortst.addr += SPI_NOR_PAGE_SIZE)

                {

                        if (nortst.addr % SPI_NOR_SECTOR_SIZE == 0)

                        {

                                // 读取一扇区数据

                                bsp_snor_read(nortst.addr, SPI_NOR_SECTOR_SIZE, nortst.buff[0].v);



                                for (int index = 0; index < SPI_NOR_SECTOR_SIZE / 4; index++)

                                {

                                        if (nortst.buff[index].uVal != nortst.dat)

                                        {

                                                nortst.err++;

                                        }

                                        nortst.dat++;

                                }



                                if (nortst.err)

                                {

                                        flash_dbg_print("fix spi mode check err: %d [url=home.php?mod=space&uid=72445]@[/url] %x \n", nortst.err, nortst.addr);

                                        nortst.err = 0;

                                }

                        }

                }



                nortst.check_req = 0;

                flash_dbg_print("fix qpi mode read and check end : time : %d ms\n", app_tick_get() - ticks);



                set_u32(nortst.buff, 0, 4096 / 4);



                nortst.chk_cnt++;

                if (nortst.err)

                        nortst.chk_err_cnt++;

        }





先写入FLASH一定量的数据,然后读回验证。
在串口终端 输入 : nor check 4 启动测试,测试FLASH容量4MB,测试结果如下图所示:

4MB,写46s,读156ms。可以算得Flash写入速度大约87KB/s,读取并验证速度大约25.6MB/s。 写速度受FLASH擦写特性影响等待操作比较耗时。而读操作是无延时的,速度十分感人,这样读取16MB数据也只需要0.7s,比访问内置FLASH也差不了多少了。
QPI暂时测到这里,后面就可以给它加文件系统存储数据了。

代码托管在GITEE,后面评测会一直用这个仓库更新。
https://gitee.com/aple_sun/atf437-start


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

70

主题

314

帖子

2

粉丝