【CPKCOR-RA8D1B核心板】8、 QSPI读取外部Flash

[复制链接]
4467|0
 楼主| qintian0303 发表于 2024-12-17 10:35 | 显示全部楼层 |阅读模式
本帖最后由 qintian0303 于 2024-12-17 10:38 编辑

       QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI 是一种专用的通信接口,连接单、双或四(条数据线) SPI Flash 存储介质。QSPI是一个内存控制器,用于连接具有SPI兼容接口的串行ROM(非易失性存储器。
       我们看一下核心板上的外扩Flash:
   

       外扩的Flash的型号是AT25SF128B。
       QSPI 使用 6 个信号连接Flash,分别是四个数据线QIO0~QIO3,一个时钟输出CLK,一个片选输出(低电平有效)QSSL,它们的作用介绍如下:
              QSSL:片选输出(低电平有效),适用于 FLASH 1。如果 QSPI 始终在双闪存模式下工作,则其也可用于 FLASH 2从设备选择信号线。QSPI通讯以QSSL线置低电平为开始信号,以QSSL线被拉高作为结束信号。
              CLK:时钟输出,适用于两个存储器,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率, 不同的设备支持的最高时钟频率不一样,两个设备之间通讯时,通讯速率受限于低速设备。
              QIO0QIO0~QIO3:四线模式中为双向 IO。
接下来进行软件配置:
       添加OSPI功能模块:
   

       接下来我们配置一下引脚:
   

       一共是6个引脚,接下来配置模块信息:
   

       下面是部分Flash的命令,我们可以初始化这些内容:
   

       接下来我们代码测试一下QSPI的功能,我们定义了一些基础功能测试:
  1. uint8_t g_read_data [OSPI_B_APP_DATA_SIZE]  = {RESET_VALUE};
  2. uint8_t g_write_data [OSPI_B_APP_DATA_SIZE] = {
  3.     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
  4.     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
  5.     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
  6.     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  7. };

  8. spi_flash_direct_transfer_t g_ospi_b_direct_transfer [OSPI_B_TRANSFER_MAX] =
  9. {
  10. /* Transfer structure for SPI mode */
  11.     [OSPI_B_TRANSFER_WRITE_ENABLE_SPI] =
  12.     {
  13.         .command        = OSPI_B_COMMAND_WRITE_ENABLE_SPI,
  14.         .address        = OSPI_B_ADDRESS_DUMMY,
  15.         .data           = OSPI_B_DATA_DUMMY,
  16.         .command_length = OSPI_B_COMMAND_LENGTH_SPI,
  17.         .address_length = OSPI_B_ADDRESS_LENGTH_ZERO,
  18.         .data_length    = OSPI_B_DATA_LENGTH_ZERO,
  19.         .dummy_cycles   = OSPI_B_DUMMY_CYCLE_WRITE_SPI
  20.     },
  21.     [OSPI_B_TRANSFER_READ_STATUS_SPI] =
  22.     {
  23.         .command        = OSPI_B_COMMAND_READ_STATUS_SPI,
  24.         .address        = OSPI_B_ADDRESS_DUMMY,
  25.         .data           = OSPI_B_DATA_DUMMY,
  26.         .command_length = OSPI_B_COMMAND_LENGTH_SPI,
  27.         .address_length = OSPI_B_ADDRESS_LENGTH_ZERO,
  28.         .data_length    = OSPI_B_DATA_LENGTH_ONE,
  29.         .dummy_cycles   = OSPI_B_DUMMY_CYCLE_READ_STATUS_SPI
  30.     },
  31.     [OSPI_B_TRANSFER_READ_DEVICE_ID_SPI] =
  32.     {
  33.         .command        = OSPI_B_COMMAND_READ_DEVICE_ID_SPI,     //0x9f
  34.         .address        = OSPI_B_ADDRESS_DUMMY,                  //0
  35.         .data           = OSPI_B_DATA_DUMMY,                     //0
  36.         .command_length = OSPI_B_COMMAND_LENGTH_SPI,             //1
  37.         .address_length = OSPI_B_ADDRESS_LENGTH_ZERO,            //0
  38.         .data_length    = OSPI_B_DATA_LENGTH_FOUR,               //4
  39.         .dummy_cycles   = OSPI_B_DUMMY_CYCLE_READ_STATUS_SPI     //0
  40.     }
  41. };

  42. fsp_err_t ospi_b_read_device_id (uint32_t * const p_id)
  43. {
  44.     fsp_err_t                   err             = FSP_SUCCESS;
  45.     spi_flash_direct_transfer_t transfer        = {RESET_VALUE};

  46.     /* Read and check flash device ID */
  47.     transfer = g_ospi_b_direct_transfer[OSPI_B_TRANSFER_READ_DEVICE_ID_SPI];
  48.     err = R_OSPI_B_DirectTransfer(&g_qspi0_flash_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ);

  49.     if(err!=FSP_SUCCESS)
  50.         {
  51.                 printf("R_OSPI_B_DirectTransfer API FAILED \r\n");
  52.         }
  53.     /* Get flash device ID */
  54.     *p_id = transfer.data;

  55.     return err;
  56. }

  57. static fsp_err_t ospi_b_write_enable (void)
  58. {
  59.     fsp_err_t                   err             = FSP_SUCCESS;
  60.     spi_flash_direct_transfer_t transfer        = {RESET_VALUE};

  61.     /* Transfer write enable command */
  62.     transfer = g_ospi_b_direct_transfer[OSPI_B_TRANSFER_WRITE_ENABLE_SPI];
  63.     err = R_OSPI_B_DirectTransfer(&g_qspi0_flash_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_WRITE);
  64.     assert(FSP_SUCCESS == err);

  65.     /* Read Status Register */
  66.     transfer = g_ospi_b_direct_transfer[OSPI_B_TRANSFER_READ_STATUS_SPI];
  67.     err = R_OSPI_B_DirectTransfer(&g_qspi0_flash_ctrl, &transfer, SPI_FLASH_DIRECT_TRANSFER_DIR_READ);
  68.     assert(FSP_SUCCESS == err);

  69.     /* Check Write Enable bit in Status Register */
  70.     if(OSPI_B_WEN_BIT_MASK != (transfer.data & OSPI_B_WEN_BIT_MASK))
  71.     {
  72.         printf("Write enable FAILED\r\n");
  73.     }
  74.     return err;
  75. }

  76. static fsp_err_t ospi_b_wait_operation (uint32_t timeout)
  77. {
  78.     fsp_err_t          err    = FSP_SUCCESS;
  79.     spi_flash_status_t status = {RESET_VALUE};

  80.     status.write_in_progress = true;
  81.     while (status.write_in_progress)
  82.     {
  83.         /* Get device status */
  84.         R_OSPI_B_StatusGet(&g_qspi0_flash_ctrl, &status);
  85.         if(RESET_VALUE == timeout)
  86.         {
  87.             printf("OSPI time out occurred\r\n");
  88.         }
  89.         R_BSP_SoftwareDelay(1, OSPI_B_TIME_UNIT);
  90.         timeout --;
  91.     }
  92.     return err;
  93. }

  94. static fsp_err_t ospi_b_erase_operation (uint8_t * const p_address)
  95. {
  96.     fsp_err_t   err             = FSP_SUCCESS;
  97.     uint32_t    sector_size     = RESET_VALUE;
  98.     uint32_t    erase_timeout   = RESET_VALUE;

  99.     /* Check sector size according to input address pointer,
  100.         described in S28HS512T data sheet
  101.     */
  102.     if(OSPI_B_SECTOR_4K_END_ADDRESS < (uint32_t)p_address)
  103.     {
  104.         sector_size = OSPI_B_SECTOR_SIZE_256K;
  105.         erase_timeout = OSPI_B_TIME_ERASE_256K;
  106.     }
  107.     else
  108.     {
  109.         sector_size = OSPI_B_SECTOR_SIZE_4K;
  110.         erase_timeout = OSPI_B_TIME_ERASE_4K;
  111.     }

  112.     /* Performs erase sector */
  113.     err = R_OSPI_B_Erase(&g_qspi0_flash_ctrl, p_address, sector_size);

  114.     /* Wait till operation completes */
  115.     err = ospi_b_wait_operation(erase_timeout);

  116.     return err;
  117. }

  118. static fsp_err_t ospi_b_write_operation (uint8_t * const p_address,
  119.                                         uint8_t *pdata, uint16_t len)
  120. {
  121.     fsp_err_t   err         = FSP_SUCCESS;

  122.     /* Erase sector before write data to flash device */
  123.     err = ospi_b_erase_operation(p_address);

  124.     /* Write data to flash device */
  125.     err = R_OSPI_B_Write(&g_qspi0_flash_ctrl, pdata, p_address, len);

  126.     /* Wait until write operation completes */
  127.     err = ospi_b_wait_operation(OSPI_B_TIME_WRITE);

  128.     return err;
  129. }


  130. static fsp_err_t ospi_b_read_operation (uint8_t * const p_address,uint8_t *pdata, uint16_t len)
  131. {
  132.     fsp_err_t err = FSP_SUCCESS;

  133.     /* Clean read buffer */
  134.     memset(pdata, RESET_VALUE, len);

  135.     /* Read data from flash device */
  136.     memcpy(pdata, p_address, len);

  137.     return err;
  138. }
       在main中我们需要先初始化:
  1. void qspi_FlashInit( void )
  2. {
  3.   /* Open the OSPI instance. */
  4.     fsp_err_t err = R_OSPI_B_Open(&g_qspi0_flash_ctrl, &g_qspi0_flash_cfg);
  5.     assert(FSP_SUCCESS == err);

  6.     /* Switch OSPI module to 1S-1S-1S mode to configure flash device */
  7.     err = R_OSPI_B_SpiProtocolSet(&g_qspi0_flash_ctrl, SPI_FLASH_PROTOCOL_EXTENDED_SPI);
  8.     assert(FSP_SUCCESS == err);

  9.     /* Reset flash device by driving OM_RESET pin */
  10.     R_XSPI->LIOCTL_b.RSTCS0 = 0;
  11.     R_BSP_SoftwareDelay(OSPI_B_TIME_RESET_PULSE, OSPI_B_TIME_UNIT);
  12.     R_XSPI->LIOCTL_b.RSTCS1 = 1;
  13.     R_BSP_SoftwareDelay(OSPI_B_TIME_RESET_SETUP, OSPI_B_TIME_UNIT);

  14.     ospi_b_write_enable();

  15. }
       然后直接初始化阶段测试QSPI,我们写入一页数据,但是之读取其中的16个,并通过串口打印:
  1. fsp_err_t ospi_b_Testoperation (uint8_t * p_address)
  2. {
  3.     fsp_err_t       err                         = FSP_SUCCESS;
  4.     uint16_t i = 0;

  5.     err = ospi_b_erase_operation(p_address);
  6.     err = ospi_b_write_operation (p_address,g_write_data,OSPI_B_APP_DATA_SIZE);

  7.     if(err==FSP_SUCCESS)
  8.     {
  9.         /* Print execution time */
  10.         printf("Write %d bytes completed successfully\r\n", (int)(OSPI_B_APP_DATA_SIZE));
  11.     }
  12.     else
  13.     {
  14.         printf("Write operation failure\r\n");
  15.     }
  16.     printf("Write Data:\r\n");
  17.     for(i=0;i<=OSPI_B_APP_DATA_SIZE-1;i++)
  18.     {
  19.         printf("%d ",g_write_data[i]);
  20.     }

  21.     err = ospi_b_read_operation (p_address,g_read_data,16);
  22.     if(err==FSP_SUCCESS)
  23.     {
  24.         /* Print execution time */
  25.         printf("\r\nRead %d bytes completed successfully\r\n", (int)(OSPI_B_APP_DATA_SIZE));
  26.     }
  27.     else
  28.     {
  29.         printf("\r\nRead operation failure\r\n");
  30.     }
  31.     printf("Read Data:\r\n");
  32.     for(i=0;i<=sizeof(g_read_data)-1;i++)
  33.     {
  34.         printf("%d ",g_read_data[i]);
  35.     }
  36.     /* Compare data read and date written */
  37.     if(RESET_VALUE == memcmp(&g_read_data, &g_write_data, (size_t)16))
  38.     {
  39.         printf("\r\nData read matched data written\r\n");
  40.         printf("flash读写数据成功\r\n");
  41.     }
  42.     else
  43.     {
  44.         printf("\r\nData read does not match data written\r\n");
  45.         printf("flash读写数据失败\r\n");
  46.     }

  47.     /* Performs OSPI erase operation */
  48.     err = ospi_b_erase_operation(p_address);
  49.     if(err==FSP_SUCCESS)
  50.     {
  51.         /* Print execution time */
  52.         printf("Erase sector completed successfully\r\n");
  53.     }
  54.     else
  55.     {
  56.         printf("erase operation failure\r\n");
  57.     }
  58.     return err;
  59. }
       串口打印结果如下:
   



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

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

本版积分规则

认证:硬件工程师
简介:有着多年硬件开发经验的专业人员,专注于医疗电子领域,热衷于对新鲜事物的探索,喜欢DIY!

602

主题

2899

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部