打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SFDP – NOR Flash 的简历 | TaterLi''''s LazyBlog

JEDEC有一个针对Nor Flash的标准,当然不是所有Nor Flash都符合这个标准.比如国产GD你说兼容不兼容,我就懒得说了.

下面我说的是镁光的65nm闪存N25Q128A,支持SFDP的.此身份证总长9 DWORD.为了更准确验证,我们应该写个程序.因为不是所有Flash都支持QSPI,DSPI所以用单线的验证下.特别是有些Flash必须人工写入某寄存器才能开启QSPI的…

指令固定是0x5A,因为事先假设不知道Flash型号,然后发24bit地址,8个dummy.然后返回长度是9个DWORD,这是根据SPDF的官方手册(JEDEC)写的,9 * 4 = 36Byte,然后0x0F – 0x2F是保留不使用的,所以总长是84个字节.不排除以后出现超过9个DWORD,那么程序就得改了,因为9 DWORD后面暂时没内容,所以暂时以9 DWORD来判断.先写个获取代码.

void BSP_QSPI_Read_SPDF(uint8_t *pData){    QSPI_CommandTypeDef sCommand;    /* Initialize the read command */    sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;    sCommand.Instruction       = 0x5A;    sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;    sCommand.Address           = 0x00000000;    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;    sCommand.DataMode          = QSPI_DATA_1_LINE;    sCommand.DummyCycles       = 8;    sCommand.NbData            = 84;    sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;    sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;    sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;    /* Configure the command */    QSPI_Command(&sCommand);    /* Reception of the data */    QSPI_Receive(pData);}

pData就是返回的数据,记得不要导致内存溢出了.明显,签名字节已经获取到了.

然后我做成个结构体,这样方便我自己访问.

typedef struct{    uint32_t Signature;    uint16_t Revision;    uint8_t Number;    uint8_t RESERVED0;    uint8_t Parameter_ID;    uint8_t Parameter_Minor_Rev;    uint8_t Parameter_Major_Rev;    uint8_t Parameter_Length;    uint32_t PTP;    uint32_t dwData[9];} BSP_QSPI_SFDP_TypeDef;

dwData就是真正简历部分,要通过PTP寻址.然后我的读取函数改成.

void BSP_QSPI_Read_SPDF(BSP_QSPI_SFDP_TypeDef *pID){    QSPI_CommandTypeDef sCommand;    uint8_t *pRxBuffPtr = (uint8_t *)pID;    /* Initialize the read command */    sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;    sCommand.Instruction       = 0x5A;    sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;    sCommand.Address           = 0x00000000;    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;    sCommand.DataMode          = QSPI_DATA_1_LINE;    sCommand.DummyCycles       = 8;    sCommand.NbData            = 16;    sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;    sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;    sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;    /* Configure the command */    QSPI_Command(&sCommand);    /* Reception of the data */    QSPI_Receive(pRxBuffPtr);    pID->PTP = pID->PTP & 0xFFFFFF;    /* 此处获得对应位置指针. */    /* Initialize the read command */    sCommand.InstructionMode   = QSPI_INSTRUCTION_1_LINE;    sCommand.Instruction       = 0x5A;    sCommand.AddressMode       = QSPI_ADDRESS_1_LINE;    sCommand.AddressSize       = QSPI_ADDRESS_24_BITS;    sCommand.Address           = pID->PTP;    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;    sCommand.DataMode          = QSPI_DATA_1_LINE;    sCommand.DummyCycles       = 8;    sCommand.NbData            = 36;    sCommand.DdrMode           = QSPI_DDR_MODE_DISABLE;    sCommand.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;    sCommand.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;    /* Configure the command */    QSPI_Command(&sCommand);    /* Reception of the data */    QSPI_Receive(pRxBuffPtr + 0x10);}

读取得到.

参考解码手册:

JESD216

解码第一个WORD(其他差不多):

主要代码:

#include "N25Q128.h"#include "SEGGER_RTT.h"BSP_QSPI_ID_TypeDef pId;BSP_QSPI_SFDP_TypeDef pSFDP;void SPIFFS_Main(void){    BSP_QSPI_Init();    BSP_QSPI_RDID(&pId);    BSP_QSPI_Read_SPDF(&pSFDP);    SEGGER_RTT_printf(0, "SFDP Detect! \r\n");    if((pSFDP.dwData[0] & 0x03) == 0x01)    {        SEGGER_RTT_printf(0, "4KB Erase Support:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "4KB Erase Support:NO \r\n");    }    if((pSFDP.dwData[0] & 0x04) == 0x04)    {        SEGGER_RTT_printf(0, "64B Write Buffer:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "64B Write Buffer:NO \r\n");    }    if((pSFDP.dwData[0] & 0x08) == 0x08)    {        SEGGER_RTT_printf(0, "WRITE ENABLE command required for writing to volatile status registers:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "WRITE ENABLE command required for writing to volatile status registers:NO \r\n");    }    if((pSFDP.dwData[0] & 0x10) == 0x10)    {        SEGGER_RTT_printf(0, "WRITE ENABLE command code select for writing to volatile status register:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "WRITE ENABLE command code select for writing to volatile status register:NO \r\n");    }    if(pSFDP.dwData[0] & 0xFF00)    {        SEGGER_RTT_printf(0, "4KB ERASE command code:0x%02X \r\n", (pSFDP.dwData[0] & 0xFF00) >> 8);    }    if((pSFDP.dwData[0] & 0x10000) == 0x10000)    {        SEGGER_RTT_printf(0, "Supports 1-1-2 fast read:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "Supports 1-1-2 fast read:NO \r\n");    }    if((pSFDP.dwData[0] & 0x60000) == 0x00000)    {        SEGGER_RTT_printf(0, "Address Bytes:3 Byte \r\n");    }    else if((pSFDP.dwData[0] & 0x60000) == 0x20000)    {        SEGGER_RTT_printf(0, "Address Bytes:3 Byte + 4Byte \r\n");    }    else if((pSFDP.dwData[0] & 0x60000) == 0x40000)    {        SEGGER_RTT_printf(0, "Address Bytes:4Byte \r\n");    }    if((pSFDP.dwData[0] & 0x80000) == 0x80000)    {        SEGGER_RTT_printf(0, "Supports Double Transfer Rate (DTR) Clocking:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "Supports Double Transfer Rate (DTR) Clocking:NO \r\n");    }    if((pSFDP.dwData[0] & 0x100000) == 0x100000)    {        SEGGER_RTT_printf(0, "Supports (1-2-2) Fast Read:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "Supports (1-2-2) Fast Read:NO \r\n");    }    if((pSFDP.dwData[0] & 0x200000) == 0x200000)    {        SEGGER_RTT_printf(0, "Supports (1-4-4) Fast Read:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "Supports (1-4-4) Fast Read:NO \r\n");    }    if((pSFDP.dwData[0] & 0x400000) == 0x400000)    {        SEGGER_RTT_printf(0, "Supports (1-1-4) Fast Read:YES \r\n");    }    else    {        SEGGER_RTT_printf(0, "Supports (1-1-4) Fast Read:NO \r\n");    }    for(;;)    {        vTaskDelay(1);    }}

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
J
Segger RTT的使用
浅谈工程师的调试法宝(四)---RTT的应用
调试备忘录-J-Link RTT的使用(原理 + 教程 + 应用 + 代码)
嵌入式开发笔记——调试组件SEGGER_RTT
C语言之如何输出uint32_t和uint64_t和16进制
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服