964|4

445

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

【兆易GD32H759I-EVAL】--14.OSPI Flash读写 [复制链接]

  本帖最后由 dirty 于 2024-6-15 23:46 编辑

      开发板板载64MB Nor Flash芯片GD25X512MEBIRY,该芯片支持标准SPI与OSPI(Octal-SPI interface).本篇讲述OSPI对Flash读写。

 

一.原理了解与准备
      开发板板载NorFlash芯片原理图如下。由MCU GD32H759IMK6 datasheet可查阅主控支持两个OSPI,这里用到OSPI0.OSPI有三个功能模式:间接模式、状态轮询模式、内存映射模式;支持单线、双线、四线、八线通讯。硬件上,跳线帽JP64、JP67打到OSPI侧。

图1:OSPI Flash原理图

二.代码准备
      这里主要实现单线、八线间接模式,内存映射模式对NorFlash写与读,并比较二者是否相同以判别写入是否成功。
1.OSPI初始化。这里包含引脚初始化,使能时钟与片选,OSPI外设口选择及OSPI参数初始化与使能。

/*!
    \brief      initialize OSPI/OSPIM and GPIO
    \param[in]  ospi_periph: OSPIx(x=0,1)
    \param[out] ospi_struct: OSPI parameter initialization stuct members of the structure
                             and the member values are shown as below:
                  prescaler: between 0 and 255
                  fifo_threshold: OSPI_FIFO_THRESHOLD_x (x = 1, 2, ..., 31, 32)
                  sample_shift: OSPI_SAMPLE_SHIFTING_NONE, OSPI_SAMPLE_SHIFTING_HALF_CYCLE
                  device_size: OSPI_MESZ_x_BYTES (x = 2, 4, 8, ..., 512, 1024)
                               OSPI_MESZ_x_KBS (x = 2, 4, 8, ..., 512, 1024)
                               OSPI_MESZ_x_MBS (x = 2, 4, 8, ..., 2048, 4096)
                  cs_hightime: OSPI_CS_HIGH_TIME_x_CYCLE (x = 1, 2, ..., 63, 64)
                  memory_type: OSPI_MICRON_MODE, OSPI_MACRONIX_MODE, OSPI_STANDARD_MODE
                               OSPI_MACRONIX_RAM_MODE,
                  wrap_size: OSPI_DIRECT, OSPI_WRAP_16BYTES, OSPI_WRAP_32BYTES
                             OSPI_WRAP_64BYTES, OSPI_WRAP_128BYTES
                  delay_hold_cycle: OSPI_DELAY_HOLD_NONE, OSPI_DELAY_HOLD_QUARTER_CYCLE
    \retval     none
*/
void ospi_flash_init(uint32_t ospi_periph, ospi_parameter_struct *ospi_struct)
{
    /* reset the OSPI and OSPIM peripheral */
    ospi_deinit(ospi_periph);
    ospim_deinit();
    /* enable OSPIM and GPIO clock */
    rcu_periph_clock_enable(RCU_OSPIM);
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
    rcu_periph_clock_enable(RCU_GPIOE);

    /* configure OSPIM GPIO pin:
           OSPIM_P0_IO0(PD11)
           OSPIM_P0_IO1(PC10)
           OSPIM_P0_IO2(PE2)
           OSPIM_P0_IO3(PD13)
           OSPIM_P0_IO4(PD4)
           OSPIM_P0_IO5(PD5)
           OSPIM_P0_IO6(PD6)
           OSPIM_P0_IO7(PD7)
           OSPIM_P0_CLK(PA3)
           OSPIM_P0_NCS(PB10) */

    gpio_af_set(GPIOA, GPIO_AF_12, GPIO_PIN_3);
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);

    gpio_af_set(GPIOB, GPIO_AF_9, GPIO_PIN_10);
    gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);

    gpio_af_set(GPIOC, GPIO_AF_9, GPIO_PIN_10);
    gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);

    gpio_af_set(GPIOD, GPIO_AF_10, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);

    gpio_af_set(GPIOD, GPIO_AF_9, GPIO_PIN_11 | GPIO_PIN_13);
    gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11 | GPIO_PIN_13);
    gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11 | GPIO_PIN_13);

    gpio_af_set(GPIOE, GPIO_AF_9, GPIO_PIN_2);
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_2);

    /* enable SCK, CSN, IO[3:0] and IO[7:4] for OSPIM port0 */
    ospim_port_sck_config(OSPIM_PORT0, OSPIM_PORT_SCK_ENABLE);
    ospim_port_csn_config(OSPIM_PORT0, OSPIM_PORT_CSN_ENABLE);
    ospim_port_io3_0_config(OSPIM_PORT0, OSPIM_IO_LOW_ENABLE);
    ospim_port_io7_4_config(OSPIM_PORT0, OSPIM_IO_HIGH_ENABLE);

    switch(ospi_periph) {
    case OSPI0:
        rcu_periph_clock_enable(RCU_OSPI0);
        /* configure OSPIM port0 */
        ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI0_SCK);
        ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI0_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI0_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI0_IO_HIGH);
        break;
    case OSPI1:
        rcu_periph_clock_enable(RCU_OSPI1);
        /* configure OSPIM port0 */
        ospim_port_sck_source_select(OSPIM_PORT0, OSPIM_SCK_SOURCE_OSPI1_SCK);
        ospim_port_csn_source_select(OSPIM_PORT0, OSPIM_CSN_SOURCE_OSPI1_CSN);
        ospim_port_io3_0_source_select(OSPIM_PORT0, OSPIM_SRCPLIO_OSPI1_IO_LOW);
        ospim_port_io7_4_source_select(OSPIM_PORT0, OSPIM_SRCPHIO_OSPI1_IO_HIGH);
        break;
    default:
        break;
    }

    /* initialize the parameters of OSPI struct */
    ospi_struct_init(ospi_struct);

    ospi_struct->prescaler = 9U;
    ospi_struct->sample_shift = OSPI_SAMPLE_SHIFTING_NONE;
    ospi_struct->fifo_threshold = OSPI_FIFO_THRESHOLD_5;
    ospi_struct->device_size = OSPI_MESZ_512_MBS;
    ospi_struct->wrap_size = OSPI_DIRECT;
    ospi_struct->cs_hightime          = OSPI_CS_HIGH_TIME_3_CYCLE;
    ospi_struct->memory_type = OSPI_MICRON_MODE;
    ospi_struct->delay_hold_cycle = OSPI_DELAY_HOLD_NONE;

    /* initialize OSPI parameter */
    ospi_init(ospi_periph, ospi_struct);
    /* enable OSPI */
    ospi_enable(ospi_periph);
}


2.复位OSPI Flash。这里对SPI模式和OSPI模式进行同时处理。

/* reset ospi flash */
    ospi_flash_reset_enable(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
    ospi_flash_reset_memory(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
    ospi_flash_reset_enable(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
    ospi_flash_reset_memory(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);


3.读取flash ID.这里使用SPI模式读出。在读出正确的情况下对Flash进行写、读后比较。

 /* read flash ID */
    flashid = ospi_flash_read_id(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
    
    if(GD25X512ME_ID == flashid) 
    {
        printf("\n\rThe device ID is 0x%X\n\r", flashid);
    }
    else
    {
        printf("\n\rFailed to read device ID\n\r");
        while(1){
    }

4.单线间接模式写、读后比较

/* 1 line in indirect mode read/write */
        printf("\n\rThe data written with 1 line in indirect mode to flash is:");
        printf("\n%s\n\r", tx_buffer1);
        
        /* erase specified address */
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        ospi_flash_block_erase(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, FLASH_WRITE_ADDRESS_1, GD25X512ME_ERASE_4K);
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        
        /* write data of tx_buffer1 to flash */
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        ospi_flash_page_program(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, tx_buffer1, FLASH_WRITE_ADDRESS_1, buffersize1);
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        
        /* read data from flash */
        ospi_flash_read(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, rx_buffer1, FLASH_WRITE_ADDRESS_1, buffersize1);
        
        if(ERROR != memory_compare(tx_buffer1, rx_buffer1, buffersize1)) {
            printf("The data read with 1 line in indirect mode from flash is:");
            printf("\n%s\n", tx_buffer1);
            printf("OSPI read/write with 1 line in indirect test success!\r\n");
        } else {
            printf("OSPI read/write with 1 line in indirect test failed!\r\n");
            while(1){
            }
        }


5.八线间接模式写、读后比较

 
        /* 8 lines in indirect mode read/write */
        printf("\n\rThe data written with 8 lines in indirect mode to flash is:\n");

        printf("\n%s\n\r", tx_buffer2);
        
        /* configure OSPI FLASH dummy cycles */
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        ospi_flash_write_volatilecfg_register(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, GD25X512ME_CFG_REG1_ADDR, GD25X512ME_CFG_16_DUMMY_CYCLES);
        
        /* configure OSPI FLASH enter STR OSPI mode */
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, SPI_MODE);
        ospi_flash_write_volatilecfg_register(OSPI_INTERFACE, &ospi_struct, SPI_MODE, GD25X512ME_3BYTES_SIZE, GD25X512ME_CFG_REG0_ADDR, GD25X512ME_CFG_OCTAL_STR_WO);
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        
        /* erase specified address */
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_block_erase(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE, FLASH_WRITE_ADDRESS_2, GD25X512ME_ERASE_4K);
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        
        /* write data of tx_buffer to flash */
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_page_program(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE, tx_buffer2, FLASH_WRITE_ADDRESS_2, buffersize2);
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        
        /* read data from flash */
        ospi_flash_read(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE, rx_buffer2, FLASH_WRITE_ADDRESS_2, buffersize2);
        
        if(ERROR != memory_compare(tx_buffer2, rx_buffer2, buffersize2)) {
             printf("\n\rThe data read with 8 lines in indirect mode from flash is:\n");
             for(i = 0; i < buffersize2; i++) {
                printf("%c", rx_buffer2[i]);
             }
             printf("\r\n");
             printf("OSPI read/write with 8 lines in indirect test success!\r\n");
        } else {
            printf("OSPI read/write with 8 lines in indirect test failed!\r\n");
            while(1){
            }
        }


6.内存映射模式模式写、读后比较

 
        /* memory mapped mode read/write */
        printf("\n\rThe data written in indirect mode to flash is:\n");
        for(i = 0; i < buffersize3; i++){
            printf("%c", tx_buffer3[i]);
        }
        /* erase specified address */
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_block_erase(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE, 0x400000, GD25X512ME_ERASE_4K);
        
        /* write data of tx_buffer to flash */
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_write_enbale(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);
        ospi_flash_memory_map_mode_wrap_enable(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE);
        ospi_flash_page_program(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE, tx_buffer3, 0x400000, buffersize3);
        ospi_flash_autopolling_mem_ready(OSPI_INTERFACE, &ospi_struct, OSPI_MODE);

        ospi_flash_memory_map_mode_wrap_enable(OSPI_INTERFACE, &ospi_struct, OSPI_MODE, GD25X512ME_3BYTES_SIZE);
        memory_mapped_read(rx_buffer3, FLASH_WRITE_ADDRESS_3, buffersize3);
        
        if(ERROR != memory_compare(tx_buffer3, rx_buffer3, buffersize3)) {
            printf("\n\rThe data read in memory mapped mode from flash is:\n");
            for(i = 0; i < buffersize3; i++) {
               printf("%c", rx_buffer3[i]);
            }
            printf("\r\n");
            printf("OSPI read in memory mapped mode test success!\r\n");
        } else {
            printf("OSPI read in memory mapped mode test failed!\r\n");
            while(1){
            }
        }

 

三.测验
      编译烧录后,复位查看日志,可看到三种模式均成功写入与读出,且数据正确。

图2:OSPI Flash读写

      至此,实现OSPI对Nor Flash的读写功能。

最新回复

三种模式均成功写入与读出OSPI Flash读写看起来都差不多吧   详情 回复 发表于 2024-6-20 07:29
点赞 关注
 
 

回复
举报

6841

帖子

11

TA的资源

版主

沙发
 
他这个可以搞文件系统吗?比如放升级固件,或者从这里启动。

点评

是具有可行性,感兴趣有时间可以弄一弄。  详情 回复 发表于 2024-6-22 14:37
 
 
 

回复

6587

帖子

0

TA的资源

五彩晶圆(高级)

板凳
 

三种模式均成功写入与读出OSPI Flash读写看起来都差不多吧

点评

方式不同,结果都是读写成功的  详情 回复 发表于 2024-6-22 14:38
 
 
 

回复

445

帖子

0

TA的资源

纯净的硅(初级)

4
 
lugl4313820 发表于 2024-6-20 07:29 他这个可以搞文件系统吗?比如放升级固件,或者从这里启动。

是具有可行性,感兴趣有时间可以弄一弄。

 
 
 

回复

445

帖子

0

TA的资源

纯净的硅(初级)

5
 
Jacktang 发表于 2024-6-20 07:29 三种模式均成功写入与读出OSPI Flash读写看起来都差不多吧

方式不同,结果都是读写成功的

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表