基于TISDK中qspiflash驱动库的Flash读写

前言:

前一篇文章【GPIO模拟SPI时序】记录了如何利用模拟IO来驱动Flash,这一篇内容将在此基础上利用TI驱动库来实现Flash的读写操作

硬件介绍:

开发平台:AWR1843EVM
嵌入式平台:CCS
Flash芯片:MX25V1635F

TI-QSPIFlash驱动库的应用

驱动库的介绍

TI的SDK中包含了部分Flash的驱动程序,具体如下图所示,如果Flash的型号不在内则需要按要求进行驱动库的更新修改。
在这里插入图片描述

基于TI驱动库的Flash读写操作

Step 1. 硬件引脚配置

    Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINR12_PADAP, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
    Pinmux_Set_FuncSel(SOC_XWR18XX_PINR12_PADAP, SOC_XWR18XX_PINR12_PADAP_QSPI_CLK);

    Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINP11_PADAQ, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
    Pinmux_Set_FuncSel(SOC_XWR18XX_PINP11_PADAQ, SOC_XWR18XX_PINP11_PADAQ_QSPI_CSN);

    Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINR13_PADAL, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
    Pinmux_Set_FuncSel(SOC_XWR18XX_PINR13_PADAL, SOC_XWR18XX_PINR13_PADAL_QSPI_D0);

    Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINN12_PADAM, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
    Pinmux_Set_FuncSel(SOC_XWR18XX_PINN12_PADAM, SOC_XWR18XX_PINN12_PADAM_QSPI_D1);

    Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINR14_PADAN, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
    Pinmux_Set_FuncSel(SOC_XWR18XX_PINR14_PADAN, SOC_XWR18XX_PINR14_PADAN_QSPI_D2);

    Pinmux_Set_OverrideCtrl(SOC_XWR18XX_PINP12_PADAO, PINMUX_OUTEN_RETAIN_HW_CTRL, PINMUX_INPEN_RETAIN_HW_CTRL);
    Pinmux_Set_FuncSel(SOC_XWR18XX_PINP12_PADAO, SOC_XWR18XX_PINP12_PADAO_QSPI_D3);

注:对照AWR1843芯片手册查看引脚并配置相应功能,例如R12引脚可以用来配置为QSPI-Flash的时钟信号线
Step 2. Flash初始化

typedef struct mmwDemo_Flash_t
{
    /*! @brief   QSPI driver handle */
    QSPI_Handle        QSPIHandle;

    /*! @brief   QSPI flash driver handle */
    QSPIFlash_Handle   QSPIFlashHandle;

    uint32_t           flashAddr;

    /*! @brief   Module initialized flag */
    bool               initialized;
}mmwDemo_Flash;

/**
 * @brief
 *  Global Variable for tracking information required by the mmw Demo
 */
mmwDemo_Flash         gMmwDemoFlash;

/**
 *  @b Description
 *  @n
 *      The function is used to initialize QSPI and Flash interface.
 *
 *
 *  @retval
 *      Success -   0
 *  @retval
 *      Error   -   <0
 */
static int32_t init_qspiflash(void)
{
    QSPI_Params      QSPIParams;
    int32_t          retVal = 0;

    memset((void *)&gMmwDemoFlash, 0, sizeof(mmwDemo_Flash));

    /* Initialize the QSPI Driver */
    QSPI_init();

    /* Initialize the QSPI Flash */
    QSPIFlash_init();

    /* Open QSPI driver */
    QSPI_Params_init(&QSPIParams);

    /* Set the QSPI peripheral clock to 200MHz  */
    QSPIParams.qspiClk = 200 * 1000000U;

    QSPIParams.clkMode = QSPI_CLOCK_MODE_0;

    /* Running at 40MHz QSPI bit rate
     * QSPI bit clock rate derives from QSPI peripheral clock(qspiClk)
       and divide clock internally down to bit clock rate
       BitClockRate = qspiClk/divisor(=5, setup by QSPI driver internally)
     */
    QSPIParams.bitRate = 40 * 1000000U;

    gMmwDemoFlash.QSPIHandle = QSPI_open(&QSPIParams, &retVal);
    if(gMmwDemoFlash.QSPIHandle == NULL)
    {
        System_printf("Error: Unable to open the QSPI Instance\n");
        retVal = -1;
        goto exit;
    }

    /* Open the QSPI Instance */
    gMmwDemoFlash.QSPIFlashHandle = QSPIFlash_open(gMmwDemoFlash.QSPIHandle, &retVal);
    if (gMmwDemoFlash.QSPIFlashHandle == NULL )
    {
        System_printf("Error: Unable to open the QSPIflash Instance\n");
        retVal = -1;
        goto exit;
    }
    gMmwDemoFlash.initialized = true;
    gMmwDemoFlash.flashAddr   = QSPIFlash_getExtFlashAddr(gMmwDemoFlash.QSPIFlashHandle);


exit:
    return retVal;
}

注: 需要添加对应的头文件:#include <ti/drivers/qspiflash/qspiflash.h>和#include <ti/demo/utils/mmwdemo_flash.h>
如果编译报错就根据报错内容添加对应文件即可
上述代码可以成功开启Flash并读取到Flash的首地址,如果无法读取到gMmwDemoFlash相关信息,一般考虑是Flash的QE位没有置1,如果需要修改,我这边采用的思路是用模拟IO写状态寄存器来配置QE位(模拟IO的思路见文章【GPIO模拟SPI时序】
在这里插入图片描述
下面是可以用于参考的MX25V1635F的写状态寄存器相关的核心代码

int32_t SPI_WriteSR_Debug(void)   //写状态寄存器
{
   int32_t   retVal = 0;
   SPI_Start();
   SPI_WriteByte(Command_WRSR);
   SPI_WriteByte(0x64);   //0100 0000
   SPI_WriteByte(0x00);   //0000 0000

   SPI_Stop();

   retVal++;
   return retVal;
}

下面简单展示一下MX25V1635F的寄存器配置相关的部分内容,更多的请参考芯片手册
在这里插入图片描述
在这里插入图片描述
基于Flash的芯片手册,可以将状态寄存器设置为0100 0000,配置寄存器设置为0000 0000,这样就可以将QE位设置为1。由于Flash是掉电非易失的,因此只需设置一次即可。设置完成后可以通过读状态寄存器和读配置寄存器来进行结果的验证。
如果在QE位已经置1的情况下,还是无法成功读取到无法读取到gMmwDemoFlash相关信息,就进行其余问题的排除。

Step 3. 基于驱动库的Flash读写操作

int32_t QSPI_debug(void)
{
    init_qspiflash();

    int32_t            retVal;
    SPIFLASH_devID     devId;

    /**************************************************************************
     * Test: Read ID API test
     **************************************************************************/
    /* Get SPI Flash id */
    QSPIFlash_getDeviceID(gMmwDemoFlash.QSPIFlashHandle, &devId);    //发送指令0x9F,具体定义在qspiflash_internal.h和qspiflash.c

    if(devId.Manufacture == SPANSION_DEV)
    {
        System_printf("SPANSION \n");
    }
    else if (devId.Manufacture == MACRONIX_DEV)    //即MX25R1635F,
    {
        System_printf("MACRONIX \n");
    }
    else
    {
        System_printf("UNKNOWN \n");
    }

    /**************************************************************************
      * Test: single write, single read
      **************************************************************************/
    /* Generate data */
    FlashCfg_fixed.flash_dfeDataOutputMode              = 1;

    FlashCfg_fixed.flash_channelCfg.rxChannelEn         = 15;
    FlashCfg_fixed.flash_channelCfg.txChannelEn         = 7;
    FlashCfg_fixed.flash_channelCfg.cascading           = 0;

    FlashCfg_fixed.flash_adcCfg.adcOutputFmt            = 2;
    FlashCfg_fixed.flash_adcCfg.numADCBits              = 1;


     /* Set flash address for  the test */
    gMmwDemoFlash.flashAddr = gMmwDemoFlash.flashAddr + 0x10000U;

    QSPIFlash_singleRead(gMmwDemoFlash.QSPIFlashHandle, gMmwDemoFlash.flashAddr, sizeof(MmDemo_fixCfg_Struct), (uint8_t *)&readFixDataArray);

    System_printf("Debug \n");

    QSPIFlash_sectorErase(gMmwDemoFlash.QSPIFlashHandle, gMmwDemoFlash.flashAddr);    // Erase a sector for test
    QSPIFlash_singleWrite(gMmwDemoFlash.QSPIFlashHandle, gMmwDemoFlash.flashAddr, sizeof(MmDemo_fixCfg_Struct), (uint8_t *)&FlashCfg_fixed);

    QSPIFlash_singleRead(gMmwDemoFlash.QSPIFlashHandle, gMmwDemoFlash.flashAddr, sizeof(MmDemo_fixCfg_Struct), (uint8_t *)&readFixDataArray);

    System_printf("Debug \n");

    /* Check data */
    if(readFixDataArray.flash_dfeDataOutputMode == 1 & readFixDataArray.flash_channelCfg.cascading == 0 & readFixDataArray.flash_adcCfg.adcOutputFmt == 2)
    {
        System_printf ("QSPIFlash single write /single read API / Success \n");
    }
    else
    {
        System_printf ("QSPIFlash single write /single read API / Fail \n");
    }

    retVal = 0;
    return retVal;
}

上述代码可以用于验证Flash读写是否成功,最好再Debug模式下运行,可以方便查找各个变量的值。

欢迎大家批评指正!

  • 19
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值