This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] PROCESSOR-SDK-AM437X:&quot 中的软件崩溃;QSPI_BasicExample_idkAM437x_armExampleProject"

Guru**** 2589280 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/974055/processor-sdk-am437x-software-crash-in-qspi_basicexample_idkam437x_armexampleproject

器件型号:PROCESSOR-SDK-AM437X

您好!

我使用 CCS 8.3.0.9在 Processor SDK RTOS AM437x v5.3.0.7版本中运行"QSPI_BasicExample_idkAM437x_armExampleProject"。 该代码在 AM437x IDK 板上运行。 此 IDK 具有一个板载 QSPI 闪存、其中包含1024块64[KB]存储器。

我将示例代码扩展了一个位、以检查是否可以访问所有 QSPI 存储器块(从0...1023开始)。 请查看红色矩形内的以下代码:  

如果我为 QSPI 块272调用"SPI_READ_WRITE ()"函数、代码似乎会崩溃、请参阅上面和下图中的红色箭头:

  

我将在明天努力接近根本原因。 您是否可以快速检查您的侧是否看到相同的行为?

谢谢、

Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、我更深入地了解了一个爬虫程序。 这是软件崩溃的函数:

    在"QSPI_mmap_mode_write_v1"中、这是导致崩溃的代码:

    它看起来与"temp_addr"变量的计算有关、因为"*pDst"显然指向禁止的地址。

    谢谢、

    Inno

    PS:即使访问块16也不能用于我:

    RetVal = SPI_READ_WRITE (flashHandle、16、transferLength);

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Inno、

    如果您将值更改为64、它是否仍然失败?

    此问题似乎与此主题类似:

    e2e.ti.com/.../732293

    此致、

    Dillon

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Dillon、

    它确实似乎与您上面提到的那个帖子有关。 如果我调用块编号为64的函数、那么我将收到:

    CortexA9:未处理的 ADP_Stopped 异常0x80027E68

    您能否检查问题是否出现、因为我必须使用非常旧的"SDK RTOS AM437x v5.3.0.7" (我不得不临时切换到 Win 10 32位 PC、该 PC 仅适用于 CCS 版本8、因此我必须使用旧版 SDK 几周)? 该问题可能已在较新的 SDK 版本中得到解决?

    为了检查所有闪存块是否可访问、也许有必要实现一个 for 循环:

    for (i=0;i<1023;i++)//闪存有1024个块,从0...1023开始计数

      RetVal = SPI_READ_WRITE (flashHandle、I、transferLength);

    如果问题仍然存在、我可以检查较新的 SDK 版本、但如果您能告诉我、哪种 SDK 版本应该可以解决此问题、那将会很好。

    谢谢、

    Inno  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Inno、  

    目前、我无法访问 AM437x IDK、但我正在考虑获取一个。 这样、我就可以运行该代码、并查看是否在最新 SDK 上遇到相同的错误。 我将在2-3天内提供有关我是否已获得电路板的更新信息。  

    此致、

    Dillon

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Inno、  

    我找到了一位同事可以访问 AM437x IDK、因此我将了解我们是否可以在明天下午运行该测试。

    此致、

    Dillon

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Dillon、

    感谢您查看此内容。 请稍微增强测试、以便查看您可以访问1024 64KB 块中的每个块:

    for (i=0;i<1023;i++)//闪存有1024个块,从0...1023开始计数

      RetVal = SPI_READ_WRITE (flashHandle、I、transferLength);

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Inno、

    我可以确认6.3 SDK 上存在此问题。 我们能够按原样运行示例、但在测试块64时出现了您提到的错误。 我正在搜索以查看是否有解决方案、以及是否有针对此问题的现有 TT。 如果没有、我将为它提交一个 TT。

    此致、

    Dillon

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Dillon、

    非常感谢您的观看。

    您找到的相关 E2E (e2e.ti.com/.../732293 已于2018年9月/10月发布。 但当前的6.3 SDK 从2020年4月开始。 我不会期望这个话题的门票在1.5年内没有进展。 总之、希望解决这个问题不会太棘手。

    我假设该修复程序将位于 QSPI 驱动程序文件"QSPI_v1.c"中。 是否可以提前获得 SDK 版本的修复(可能需要一段时间)、并且我们可以将该修复手动合并到我们正在使用的旧 SDK 版本?

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Dillon、

    我们目前正在将 IDK 源代码合并到我们的客户开发板中、很快我们就需要能够访问每个闪存块。

    您能否提供有关此主题的更新信息? 您是否知道我们何时可以获得带有错误修复的代码(我们不需要新的 SDK 版本、只需更正驱动程序 c/h 文件中的代码)?

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Inno、

    在访问每个闪存块时、您打算使用哪种模式?

    e2e.ti.com/.../732293

    虽然 上面的 E2E 主题似乎遇到了类似的问题、但该主题确实解决了特定场景中的问题。 您是否曾尝试在该 E2E 主题中实施前面的一些建议?

    此致、

    Dillon

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Dillon、

    关于模式:

    我真的不在乎在哪种模式下访问闪存进行写入。 我还可以将模式更改为 CONFIG (而不是存储器映射)并更正我在"SF25FL_ConfigMode_Write"中找到的错误(缺少字节交换、错误的命令字节等)。

    但请注意、代码在写入期间已经崩溃、因此我尚未检查是否至少可以从所有闪存块中读取。 当然、这是我可以测试的东西。

    现在、在 E2E 帖子中、您提到的上述帖子以下列行结尾:  

    "我无法确定为什么第一个条目不正确。
    我从闪存的正面和背面读回数据、但仍然得到这个结果。
    因此、我的想法是、读数中存在错误。

    我已将相关文件与更改一起添加、因此您可以根据需要对其进行比较。

    任何有关这方面的输入都将是极好的。"


    因此、我的印象是、读取也有一个错误、因此、我认为您在以任何模式(配置或存储器映射)访问环路中的所有1024个块时、正在修复驱动程序。

    或者、我可以尝试使闪存写入访问在配置模式下工作、并交叉我的手指、至少读取在存储器映射模式下工作。 通过这种方法、我可以绕过我们的电流问题。

    我还想知道 TI 目前在处理此错误方面所做的工作、因为从2018年开始的前一份报告直到今天才处理。

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Dillon、

    我编写了一个自己的"写入闪存"函数、可以将其视为"SF25FL_ConfigMode_Write"的更正版本。 这个自己的写入函数一直在标准 SPI 模式下工作(object->rxLines = QSPI_RX_LINes_single 和 object->qspiMode = QSPI_OPER_MODE_CFG)。 通过此函数、我可以访问所有1024个闪存块。

    但是、当我尝试访问所有闪存块时、TI 驱动程序函数"SF25FL_bufferRead"也会崩溃。 因此、我必须编写自己的"从闪存读取"函数、其工作方式与"写入闪存"函数相同。

    完成后、我将与您分享代码。 同时、请告诉我、如果您为该错误创建了 TT、并将在哪个 SDK 版本中解决此问题。

    谢谢、

    Inno

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Inno、

    很高兴听到您现在能够访问所有1024个闪存块。 已  创建包含 SF25FL_ConfigMode_Write 和 SF25FL_bufferRead 错误的 TT。 我不知道哪一个、但它将在将来的版本中修复。 在您共享代码后、我将确保将其链接到 TT。

    此致、

    Dillon

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Dillon、

    借助这些读/写功能、我可以访问所有1024个闪存块。 我在 FATFS 示例项目中使用了这些函数、将应用程序二进制文件和 QSPI SBL 二进制文件从 SD 卡复制到 QSPI 闪存器件中。 在下电上电后、IDK 从 QSPI 闪存正确引导。

    请随时查看并提供反馈、因为我不保证没有其他问题。 这些功能看起来很有希望。

    / //*
    此函数是 TI 函数的一种替代方法,允许我们*/*
    访问 QSPI 闪存的1024 (0...1023) 64[KB]存储块中的每个块。 //
    //*此函数的工作方式与'25FLFlash_BlockEras'或相同 /*
    'FlashPrintId'、这意味着在标准 SPI 模式(MOSI/MISO/CLK/CS)下访问*/
    * SPI_CORE 接口。 */
    * //
    //*此函数之所以被写入,是因为在调用'SP25FL_bufferRead'时 //
    /*"(QSPI_OPER_MODE_CFG = object->qspiMode)",则函数中存在几个错误
    (例如缺少地址字节交换),如果调用'SPF25FL_bufferRead *//
    ///*当"(QSPI_OPER_MODE_MMAP = object->qspiMode)
    时,当调用'SPF25FL_bufferRead'时,*//某些闪存块(例如,当访问 QSPI_spiMode_Q64)时,*闪存驱动程序会崩溃,* //
    /*(地址0x400000)。 */
    * */
    /*另请参阅: *//*
    ---- */
    /* e2e.ti.com/.../974055                               */
    /* e2e.ti.com/.../969427                             */
    /* e2e.ti.com/.../969166                             */
    * */
    * //
    //*参数:dstOffstAddr -要访问的闪存地址(0x0...0x3FFFFFF) */
    * dstAddr -指向用于存储该数据的缓冲区的指针、即 */
    * 已从闪存读取。 */
    * length -从闪存读取的字节数 */
    * flashHandle - QSPI 闪存句柄 */
    ********* /
    bool SF25FL_ConfigMode_StandardSPI_Read_IWG (uint32_t dstOffstAddr、
    unsigned char* dstAddr、
    uint32_t 长度、
    S25FL_Handle flashHandle)
    {
    bool RetVal = true; /*返回值=成功*/
    bool retVal2 = true;//成功
    SPI_Handle handle = flashHandle->spiHandle;/* SPI handle */
    unsigned char writeVal[4]; /*要写入的数据*/
    uint32_t addrLengthInBytes = 3U; /*以字节为单位的闪存地址长度*/
    uint32_t readCmd = 0U; /*读取命令*/
    unsigned int frmLength;
    unsigned int transferType;
    uint32_t offsetValue;
    unsigned int operMode; /*用于保持模式的温度变量*/
    unsigned int rxLines; /*用于保存 Rx 行的温度变量*/
    unsigned int rxLinesArg;
    uint32_t tempAddr;
    QSPI_v1_Object *对象;
    
    /*获取对象和 hwAttrs 的指针*/
    对象=句柄->对象;
    
    
    /********* /
    /*阶段1:保存当前模式和 rxLine 配置*/
    /********* /
    operMode = object->qspiMode;
    rxLines = object->rxLines;
    
    / /
    /*第2阶段:向 QSPI 驱动程序指示如何访问'QSPI_cmd_mode_read_v1'*
    /* 读取访问时为'QSPI_CMD_MODE_WRITE_v1'、写入时为*/
    /* 访问。 *
    / /
    SPI_CONTROL (Handle、SPI_V1_CMD_SETCONFIGMODE、NULL);
    rxLinesArg = QSPI_RX_LINE_SINGLE;
    SPI_CONTROL (handle、SPI_V1_CMD_SETRXLINES、(void *)&rxLinesArg);
    
    / /
    /*第3阶段:识别地址信息的字节数、*/
    /* 正确的命令字节并设置*/的总帧长度
    /* QSPI 驱动器。 *
    / /
    
    addrLengthInBytes = 3U;
    offsetValue = dstOffstAddr;//加载要从中读取数据的闪存地址
    if (offsetValue > 0xFFFFFFF)
    {
    /*进入32位寻址模式*/
    addrLengthInBytes = 4;
    }
    
    if (offsetValue > 0xFFFFFFF)
    {
    readCmd = QSPI_LIB_CMD_READ_SINGLE_4B;
    }
    其他
    {
    readCmd = QSPI_LIB_CMD_READ_SINGLE;
    }
    
    /*以字(字节)为单位的事务帧总长度*/
    /*这将告诉 SPI 驱动程序激活 CS 信号的时间。 *
    frmLength = 1 + addrLengthInBytes + length;//命令字节+地址字节+'length'数据字节
    SPI_CONTROL (handle、SPI_V1_CMD_SETFRAMELENGTH (((void *)&frmLength));
    
    
    /********* /
    /*第4阶段:将命令字节发送到闪存*/
    /********* /
    /*写入读取命令*/
    writeVal[0]= readCmd;
    transaction.txBuf =(无符号字符*)&writeVal[0];
    transaction.rxBuf =空;
    transaction.count = 1;
    
    transferType = SPI_TRANSACTION 类型写入;
    SPI_CONTROL (handle、SPI_V1_CMD_TRANSFERMODE_RW、(void *)&transferType);
    RetVal = SPI_transfer (handle、&transaction);//此命令最终发送一个字节,该字节取自指针'transaction.txBuf'。
    if (RetVal == false)
    {
    retVal2 = RetVal;
    }
    
    /******** /
    /*第5阶段:将地址字节发送到闪存*/
    /******** /
    //此处我们执行字节交换,以便最高读取地址字节位于'tempAddr'内的最低字节
    //最低读取地址字节位于'tempAddr'内的最高字节。 预期的值
    //根据数据表首先发送的最高地址字节。
    tempAddr =((offsetValue & 0xFF000000)>> 24)|
    ((offsetValue & 0x00FF0000)>> 8)|
    ((offsetValue & 0x0000FF00)<< 8)|
    ((offsetValue & 0x000000FF)<<24);
    
    //此处删除'tempAddr'的最低字节,它是4字节地址的最高读取地址信息。
    //不应为3字节地址访问发送此最高字节(地址位 A23...A0)。
    if (addrLengthInBytes == 3)
    {
    tempAddr =(tempAddr >> 8)& 0x00FFFFFF;
    }
    
    transaction.txBuf =(unsigned char *)&tempAddr;//设置变量地址指针
    transaction.rxBuf =空;
    transaction.count = addrLengthInBytes;
    
    transferType = SPI_TRANSACTION 类型写入;
    SPI_CONTROL (handle、SPI_V1_CMD_TRANSFERMODE_RW、(void *)&transferType);
    RetVal = SPI_transfer (handle、&transaction);//此命令最终发送一个字节,该字节取自指针'transaction.txBuf'。
    if (RetVal == false)
    {
    retVal2 = RetVal;
    }
    
    /********* /
    /*阶段6:从闪存器件读取实际数据*/
    /********* /
    /*读取实际闪存数据*/
    transaction.txBuf =空;
    transaction.rxBuf =(unsigned char *) dstAddr;
    transaction.count =长度;
    
    transferType = SPI_TRANSACTION 类型读取; //告知 SPI 驱动程序我们正在将数据读取到事务 rxBuf 中
    SPI_CONTROL (handle、SPI_V1_CMD_TRANSFERMODE_RW、(void *)&transferType);//告知 SPI 驱动程序我们正在将数据读取到事务中。rxBuf
    RetVal = SPI_transfer (handle、&transaction);//此命令最终发送电报并从闪存中读出数据。
    if (RetVal == false)
    {
    retVal2 = RetVal;
    }
    
    /********* /
    /*阶段7:恢复运行模式和 Rx 线路设置。 *
    /********* /
    object->qspiMode = operMode;//在这里,我们直接恢复运行模式,而不涉及"SPI_CONTRAINE",这是允许的。
    SPI_CONTROL (handle、SPI_V1_CMD_SETRXLINES、(void *)&rxLines);
    
    RetVal = retVal2;
    返回值
    ;}
    
    
    /********* //*
    此函数是 TI 函数的一种替代方法,允许我们*/*
    访问 QSPI 闪存的1024 (0...1023) 64[KB]存储块中的每个块。 //
    //*此函数的工作方式与'25FLFlash_BlockEras'或相同 /*
    'FlashPrintId'、这意味着在标准 SPI 模式(MOSI/MISO/CLK/CS)下访问*/
    * SPI_CORE 接口。 */
    * //
    //*此函数之所以被写入,是因为在调用'SP25FL_bufferWrite'时 //
    /*"(QSPI_OPER_MODE_CFG = object->qspiMode)",则在*/
    *函数'SPF25FL_ConfigMode_Write'中存在几个错误,如果在*/
    /*"(QSPI_OPER_MODE_MMAP = object->SPI_Write)时调用'SPF25FL_bufferWrite',则在
    访问某些闪存块时*/*像 Q64一样崩溃(QSPI_spi_mode_mcblock 地址) */
    /* 0x400000)。 */
    * */
    /*另请参阅: *//*
    ---- */
    /* e2e.ti.com/.../974055                              */
    /* e2e.ti.com/.../969427                            */
    /* e2e.ti.com/.../969166                            */
    * //
    //*参数:dstOffstAddr -要访问的闪存地址(0x0...0x3FFFFFF) */
    * dstAddr -指向我们想要的数据缓冲区的指针 */
    * 写入闪存。 */
    * length -从闪存读取的字节数 */
    * flashHandle - QSPI 闪存句柄 */
    ********* /
    bool SF25FL_ConfigMode_StandardSPI_Write_IWG (uint32_t dstOffstAddr、
    unsigned char* srcAddr、
    uint32_t 长度、
    S25FL_Handle flashHandle)
    {
    bool RetVal = true; /*返回值=成功*/
    bool retVal2 = true;//成功
    SPI_Handle handle = flashHandle->spiHandle;/* SPI handle */
    uint32_t addrLengthInBytes = 3U; /*闪存 addr 长度(以字节为单位)*/
    unsigned int frmLength;
    unsigned char writeVal[4]; /*要写入 QSPI 的数据*/
    unsigned int transferType;
    uint32_t offsetValue;
    uint32_t tempAddr;
    uint32_t localIndex = 0;
    unsigned int operMode; /*用于保持模式的温度变量*/
    unsigned int rxLines; /*用于保存 Rx 行的温度变量*/
    unsigned int rxLinesArg;
    QSPI_v1_Object *对象;
    uint32_t bytesLeft = length;
    uint32_t dataBytesPerFrame;
    
    /*获取对象和 hwAttrs 的指针*/
    对象=句柄->对象;
    
    //
    //在这里,我们只为一页256[字节]编程尽可能多的字节。
    //我们这样做是为了保护用户意外过 A
    // 256[字节]页边界。
    //
    //示例
    //----
    // dstOffstAddr = 12且 length=256、
    //-如果我们将数据写入一个电报中,我们将在处写入字节0...243
    // 地址12...255和字节244...255至地址0...11。
    //-但由于我们标识了页中的空间,所以我们将字节0...255写入
    // 地址12...267
    //
    while (bytesLeft >0)
    {
    / /
    /*阶段1:确定要写入的地址和要发送的地址字节数。 *
    / /
    addrLengthInBytes = 3U; /*以字节为单位的闪存地址长度*/
    offsetValue = dstOffstAddr + localIndex;
    /*从闪存的目的地址中提取地址字长度 offst addr*/
    if (offsetValue > 0xFFFFFFF)
    {
    /*进入32位寻址模式*/
    addrLengthInBytes = 4;
    }
    
    / /
    /*第2阶段:根据闪存地址确定可以写入页面的字节数。 *
    / /
    dataBytesPerFrame = 256 -(offsetValue%256);
    if (dataBytesPerFrame > bytesLeft)
    {
    dataBytesPerFrame = bytesLeft;
    }
    
    / /
    /*第3阶段:将闪存设备设置为接受页面程序请求的状态。 *
    / /
    /*写入启用*/
    S25FLFlash_WriteEnable (flashHandle);//将闪存设置为写入使能模式、页面写入的前提条件
    
    /********* /
    /*第4阶段:保存当前模式和 rxLine 配置*/
    /********* /
    operMode = object->qspiMode;
    rxLines = object->rxLines;
    
    / /
    /*第5阶段:向 QSPI 驱动程序指示如何访问'QSPI_cmd_mode_read_v1'*
    /* 读取访问时为'QSPI_CMD_MODE_WRITE_v1'、写入时为*/
    /* 访问。 *
    / /
    SPI_CONTROL (Handle、SPI_V1_CMD_SETCONFIGMODE、NULL);
    rxLinesArg = QSPI_RX_LINE_SINGLE;
    SPI_CONTROL (handle、SPI_V1_CMD_SETRXLINES、(void *)&rxLinesArg);
    
    
    /********* /
    /*第6阶段:设置 QSPI 驱动器的总帧长度。 *
    /********* /
    /*事务帧的总长度(以字节数表示)。 *
    /*这将告诉 SPI 驱动程序激活 CS 信号的时间。 *
    frmLength = 1 + addrLengthInBytes + dataBytesPerFrame;//命令字节加上地址字节加上数据字节数据字节的数量
    SPI_CONTROL (handle、SPI_V1_CMD_SETFRAMELENGTH (((void *)&frmLength));
    
    /********* /
    /*第7阶段:发送闪存写入命令字节*/
    /********* /
    writeVal[0]= QSPI_LIB_CMD_PAGE_PRG;//闪存写入命令
    //将闪存命令字节更改为4字节页访问
    if (addrLengthInBytes == 4)
    {
    writeVal[0]= QSPI_LIB_CMD_PAGE_PRG_4B;
    }
    
    transaction.txBuf =(无符号字符*)&writeVal[0];
    transaction.rxBuf =空;
    transaction.count = 1U;
    
    transferType = SPI_TRANSACTION 类型写入;
    SPI_CONTROL (Handle、SPI_V1_CMD_TRANSFERMODE_RW、(void *)&transferType);//将驱动程序设置为写入模式
    RetVal = SPI_transfer (handle、&transaction);
    if (RetVal == false)
    {
    retVal2 = RetVal;
    }
    
    /******** /
    /*第8阶段:发送必须写入数据的闪存地址。 *
    /******** /
    //此处我们执行字节交换,以便最高写入地址字节位于'tempAddr'内的最低字节
    //并且最低写入地址字节位于'tempAddr'内的最高字节。 预期的值
    //根据数据表首先发送的最高地址字节。
    tempAddr =((offsetValue & 0xFF000000)>> 24)|
    ((offsetValue & 0x00FF0000)>> 8)|
    ((offsetValue & 0x0000FF00)<< 8)|
    ((offsetValue & 0x000000FF)<<24);
    
    //此处删除'tempAddr'的最低字节,它是4字节地址的最高写入地址信息。
    //不应为3字节地址访问发送此最高字节(地址位 A23...A0)。
    if (addrLengthInBytes == 3)
    {
    tempAddr =(tempAddr >> 8)& 0x00FFFFFF;
    }
    
    transaction.txBuf =(unsigned char *)&tempAddr;//设置变量地址指针
    transaction.rxBuf =空;
    transaction.count = addrLengthInBytes;
    
    transferType = SPI_TRANSACTION 类型写入;
    SPI_CONTROL (Handle、SPI_V1_CMD_TRANSFERMODE_RW、(void *)&transferType);//将驱动程序设置为写入模式
    RetVal = SPI_transfer (handle、&transaction);
    if (RetVal == false)
    {
    retVal2 = RetVal;
    }
    
    /******** /
    /*第9阶段:将数据字节写入闪存*/
    /******** /
    transaction.txBuf =(unsigned char *)&srcAddr[localIndex];
    transaction.rxBuf =空;
    transaction.count = dataBytesPerFrame;
    
    transferType = SPI_TRANSACTION 类型写入;
    SPI_CONTROL (Handle、SPI_V1_CMD_TRANSFERMODE_RW、(void *)&transferType);//将驱动程序设置为写入模式
    RetVal = SPI_transfer (handle、&transaction);
    if (RetVal == false)
    {
    retVal2 = RetVal;
    }
    
    / /
    /*阶段10:恢复 QSPI 驱动器内的原始操作模式和 Rx 线路。 *
    / /
    object->qspiMode = operMode;//在这里,我们直接恢复运行模式,而不涉及"SPI_CONTRAINE",这是允许的。
    SPI_CONTROL (handle、SPI_V1_CMD_SETRXLINES、(void *)&rxLines);
    
    / /
    /*阶段11:等待闪存状态寄存器中的 BUSY 位(位0)为 true。 *
    / /
    /*检查闪存状态是否完成写入*/
    while ((FlashStatus (flashHandle)& 0x1U));
    
    / /
    /*阶段12:等待闪存状态寄存器中的 BUSY 位(位0)为 true。 *
    / /
    localIndex += dataBytesPerFrame;
    bytesLeft-= dataBytesPerFrame;
    
    } // while (字节左> 0)
    
    RetVal = retVal2;
    返回 RetVal;
    }
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Inno、

    很高兴听到您的一切工作都在进行。 感谢您分享代码并进行深入记录。 我已经对它进行了审阅、对我来说一切都很好。 我将确保它也与 TT 相关联。  

    谢谢、

    Dillon