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.

[参考译文] CCS/TMS570LC4357:Fapi EEPROM 编程

Guru**** 2229420 points
Other Parts Discussed in Thread: TMS570LC4357, HALCOGEN
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/712491/ccs-tms570lc4357-fapi-eeprom-programing

器件型号:TMS570LC4357
主题中讨论的其他器件: HALCOGEN

工具/软件:Code Composer Studio

我正在使用 TI 提供的示例引导加载程序代码。

为了测试功能、我尝试验证 EEPROM 功能是否正确编程 EEPROM

我有一个32字节的测试模式、我正在尝试编程到地址0x8000中。

我正在使用以下实用程序:

oReturnCheck = Fapi_BlockProgram (0、0x8000、(无符号长整型)&g_pulUpdateSuccessess、g_ulUpdateBufferSize);

并测试了以下内容(似乎正常工作)

Size = BLInternalFlashFirstSectorSizeGet ();   返回0x4000

size = BLInternalFlashSizeGet ();   返回0x400000

Check = BLInternalFlashStartAddrCheck (0x8000、32);    返回0 -(它在包含引导加载程序和应用程序的组0中)

我还尝试了 Fapi_doVerify()测试,该测试正确识别了失败的编程并正确提供了正确的坏字节。

 

实用程序会识别出它正在无误地正确处理请求、但 Code Composer 存储器视图显示 EEPROM 尚未修改。

 

是否需要执行任何其他步骤或实用程序才能写入 EEPROM (抱歉、闪存程序存储器)?



 

 

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

    您好、John、

    EEPROM 是闪存组7、请使用7作为组号:

    oReturnCheck = Fapi_BlockProgram (7、0x8000、(无符号 长整型)&g_pulUpdateSuccessess、g_ulUpdateBufferSize);

    BLInternalFlashStartAddrCheck (..) 用于检查程序闪存(bank0和 bank1)的大小。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、发现我应该已经说过闪存的信息...

    我正在尝试对组0和1中的代码空间进行编程。

    提供的示例无法对闪存进行编程。 所有其他功能似乎都正常工作。 我将使用"TMS570LC4357_UART_Boot"示例。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    尊敬的 John:

    我在另一篇文章中发布的示例仅供参考。 该示例将应用程序编程到 Bank1而不是 Bank0。 如果要擦除组0中的扇区、则需要将 API 相关代码复制到 SRAM 并从 SRAM 执行这些代码。 请参阅 TI.com 上的引导加载程序:

    1.更改 cmd 文件:

    存储器

    引导程序(X):origin=0x00000000 length=0x00000020
    Flash_API (RX):origin=0x00000020 length=0x000014E0 //为与闪存操作相关的对象创建一个区域
    FLASH0 (Rx):origin=0x00001500 length=0x002FEB00 //LS31x 且 RM48闪存大小为0x300000
    SRAM (RW):origin=0x08002000 length=0x0002D000
    堆栈 (RW):origin=0x08000000 length=0x00002000

    部分

    .intvecs:{}>向量

    /*放置 outputsection“flashAPI”。 它由以下输入段组成:*/
    /* Fapi_UserDefinedFuncions.obj、BL_FLASH.obj 和 F021_API_CortexR4_be.lib *
    /*它有两个不同的分配。 它分配给 FLASH_API 进行加载、并分配给 SRAM 进行运行。 *
    /*此输出段放置在输出文件中,以便在加载程序时,*/
    /*它在 FLASH_API 存储器范围内。 在系统执行期间的某个时间、在使用 flashAPI 中的任何内容之前、*/
    /*应用程序将其从 FLASH_API 复制到 SRAM。 请注意、此副本不会自动完成。 *
    /*必须在应用程序代码中获取 I。 使用 flashAPI 的任何其他段(调用其函数或*/
    /*是指其数据)的行为就像闪存 API 已经在 SRAM 中一样。 load_start 等语句会建立符号*/
    /*用于实现副本。 符号 API_LOAD 的值是起始加载地址。 *
    /*同样、API_END 具有结束加载地址、API_RUN 具有开始运行地址。 *
    /* api_size 是大小*/
    闪存 API:

    fapi_UserDefinedFunctions.obj (.text)
    bl_flash.obj (.text)
    --library=.\lib\f021_API_CortexR4_be.lib (.text)
    }load = flash_API、run = SRAM、load_start (api_load)、load_end (api_end)、run_start (api_run)、 大小(API_SIZE)

    .text > FLASH0
    .const > FLASH0
    .cinit > FLASH0
    .pinit > FLASH0
    .data > SRAM
    .bss > SRAM


    2.添加将 flashAPI 段复制到 SRAM 的代码:
    ;------------------------------------------------------------------

    ;将闪存 API 从闪存复制到 SRAM。


    .def copyAPI 2RAM_
    asmfunc

    copyAPI 2RAM_

    .ref API_load
    FLASH_LOAD .word API_LOAD
    .ref API_run
    FLASH_run .word API_run
    .ref API_size
    FLASH_SIZE .word API_SIZE

    LDR r0、FLASH_LOAD
    LDR R1、FLASH_RUN
    LDR R2、FLASH_SIZE
    添加 R2、R1、R2
    COPY_Loop1:
    LDR r3、[r0]、#4
    结构 R3、[R1]、#4
    CMP R1、R2
    BLT COPY_LOOP1
    BX LR

    endasmfunc
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我希望通过将引导加载程序加载到组0 (0x8000)和程序加载到组1 (0x200000)来保持简单。

    该示例也没有更改组1。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    好的、该示例使用组1作为应用。 它擦除/编程组1中的扇区。

    如果要擦除组1中的扇区、并将代码编程到组1、则不必从 SRAM 执行代码。

    但代码使用0x8000作为起始地址、它位于组0中。

    oReturnCheck = Fapi_BlockErase (1、0x200000、g_ulUpdateBufferSize);//将擦除整个扇区
    oReturnCheck = Fapi_BlockProgram (1、0x200000、(无符号长整型)&g_pulUpdateSuccessess、g_ulUpdateBufferSize);
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我进行了另一项测试、以查看是否可以对组1进行编程

    oReturnCheck = Fapi_BlockProgram (1、0x20000、(无符号长整型)&g_pulUpdateSuccessess、g_ulUpdateBufferSize);

    有趣的结果:

    来源: 5A5A5A5A
    目的:1A5A4A

    似乎没有正确处理第一个字节。。。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    组1的起始地址为0x200000而不是0x20000。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢 QJ、这是一个艰难的过程。 (是的、这是一个拼写错误)。

    在昨天晚上做了更多的努力之后、我能够可靠地重新创建"错误"-下面是一个测试和结果:

    从头开始加载应用程序

    -> CC 在 main()中打开中断

            -> 0x200000处的内存不正确

    从中断开始运行应用程序、

          ->查看内存浏览器、发现内存正确-我没有执行代码来对闪存进行编程

    按 UART 上的键启动闪存编程序列

    CC 在执行要编程的代码之前中断

         ->内存浏览器具有正确代码的旧视图(自动更新)

    我从制动点手动刷新存储器浏览器

         ->它显示的代码不正确

    我逐步完成编程  

     -> 内存浏览器显示的值不正确(即使手动刷新也是如此)

    我让 code composer 运行(无断点)

       ->并刷新内存浏览器-显示正确的值

    我暂停 CC

       ->内存浏览器显示的值不正确

    我继续 CC 并刷新内存浏览器

       -> 显示正确的值

    我暂停 CC

       ->内存浏览器显示的值不正确

    我继续 CC 并刷新内存浏览器

       -> 显示正确的值

    你有什么想法?

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

    如果启用了高速缓存、窗口浏览器中的数据来自高速缓存、这可能与内存中的数据不同。 请禁用高速缓存、或使用高速缓存直写属性。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这些功能在 CC 中的什么位置? 我的内存浏览器上没有"启用/禁用高速缓存颜色"图标、"内存视图首选项"显示 GUI 选项? 我使用的是 XDS110 USB 调试探针。

    我尝试了另一项测试。 在运行并在存储器浏览器中显示正确的值时、我会通过编程方式读取地址、并将其与良好和不良值进行比较、如果在调试模式下没有单步执行操作的情况下发现错误值、则会放置一个断点。 通过编程方式、即使内存浏览器同时显示了良好的值、它也会看到错误的值...

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

    启用高速缓存:
    _cacheEnable_();

    您可以通过调用"_CacheDisable_();"in main.c 来禁用高速缓存
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    e2e.ti.com/.../2502.halcogen-FEE-config.docxHere是 HALCoGEN 的配置。 它们是默认设置。 您是否发现任何问题?

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

    我根据您的建议输入_cacheDisable_()。  
     
    没有变化... 仍然可以看到两种不同的视图。

    您是否发现 HALCogen FEE 配置有问题?

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

    这是我在示例中使用的代码


    uint32_t g_pulUpdateSuccesss[]={0x00000000、0x11111111、0x22222222、0x333333、0x444444、 0x555555、0x66666666、0x777777、0x88888888、0x9999990xAAAAAAAAAA、0xBBBBBBBBBB、0xCCCCCCCC、0xDDDDDDDD、0xEEEEEEEE、0xFFFFFFFF};
    uint32_t 大小;

    大小= BLInternalFlashFirstSectorSizeGet ();
    大小= BLInternalFlashSizeGet ();
    大小= BLInternalFlashStartAddrCheck (0x200000、64);
    uint16_t oReturnCheck;
    oReturnCheck = Fapi_BlockProgram (1、0x200000、(无符号长整型)&g_pulUpdateSuccessess、64);

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

    尊敬的 John:

    您可以使用 F021闪存 API 对组7 (EEPROM)进行擦除和编程、而不是对 FEE 驱动器进行编程。 如果您想使用组7存储数据。 我建议您使用 FEE 驱动器。

    您的文档中的 FEE 配置对我来说很好。 将数据写入 FEE 并从 FEE 读取数据的示例代码:

    /*用户代码开始(0)*/

    #include "ti_fee.h"

    /*用户代码结束*/

    /*包含文件*/

    #include "hL_sys_common.h"

    /*用户代码开始(1)*/

    uint16 u16JobResult,状态;

    STD_ReturnType oResult=E_OK;

    unsigned char read_data[100]={0};

    uint8 SpecialRamBlock[100];

    unsigned char 模式;

    uint16 u16writecounter;

    unsigned int FeeVirtualSectorNumber;

    unsigned char VsState、u8EEPIndex;

    unsigned char u8VirtualSector;

    uint8 Test_Recovery;

    uint8 Test_Cancel;

    空延迟(空)

    unsigned int dummycnt=0x0000FFU;

    操作

    哑人----

    while (dummycnt>0);

    /*用户代码结束*/

    /**@fn void main (void)

    * @应用程序主函数简介

    * @请注意、默认情况下、此函数为空。

    *

    * 此函数在启动后调用。

    * 用户可以使用此函数来实现应用程序。

    *

    /*用户代码开始(2)*/

    /*用户代码结束*/

    void main (void)

    /*用户代码开始(3)*/

    unsigned int BlockNumber;

    unsigned int BlockOffset、Length;

    unsigned char * read_ptr=read_data;

    unsigned int loop;

    /*初始化 RAM 阵列。*/

    for (loop=0;loop<100;loop++) SpecialRamBlock[loop]= loop;

    /*初始化费用。 这将创建虚拟扇区、初始化全局变量等。*/

    TI_FEE ();

    操作

    TI_fee_MainFunction();

    delay();

    STATUS=TI_FEE _GetStatus (0);

    while (Status!= IDLE);

    /*将块异步写入 EEP。 块大小在 ti_fee_cfg.c 文件中配置。 默认块大小为

     8字节*/

    BlockNumber=0x1;

    TI_fee_WriteAsync (BlockNumber、&SpecialRamBlock[0]);

    操作

    TI_fee_MainFunction();

    delay();

    STATUS=TI_FEE _GetStatus (0);

    while (状态!=空闲);

    /*同步将块写入 EEP。 写入将不会发生、因为数据是相同的。 *

    TI_fee_WriteSync (BlockNumber、&SpecialRamBlock[0]);

    /*读取长度未知的块*/

    BlockOffset = 0;

    长度= 0xFFFF;

    oResult=TI_fee_read (BlockNumber、BlockOffset、READ_PTR、Length);

    操作

    TI_fee_MainFunction();

    delay();

    STATUS=TI_FEE _GetStatus (0);

    while (状态!=空闲);

    /*使写入的块无效 */

    TI_FEE 验证块(BlockNumber);

    操作

    TI_fee_MainFunction();

    delay();

    STATUS=TI_FEE _GetStatus (0);

    while (状态!=空闲);

    /*设置组7的格式*/

    TI_FEE 格式(0xA5A5A5A5U);

      while (1);

    /*用户代码结束*/

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

    我正在尝试写入组1中的程序存储器来编辑闪存、而不是组7 (请参阅存储器地址0x200000)。

    哪个接口正确? "块"是否与"组"相同、如果不是、我如何在它们之间进行转换?

    编程也似乎是间歇性的、有时是成功的、有时是失败的。

    我可以可靠地生成一个条件、在这个条件下、Code Composer 提供了两个不同的存储器视图。

    我知道某些配置可能不正确、但这 是 CC 错误、需要升级。

    除了引导加载程序示例代码之外、还有一些简单的代码限制、我们可以尝试查看您的硬件和我的硬件是否正常运行?

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

    您好、John、

    文档中的图表显示了 FEE 配置。 我认为您已经转到了存储数据的费用。 在 FEE 驱动器中、该块是一组数据。

    如果您对组0和组1进行擦除/编程、则需要使用 F021 API、但 FEE 驱动器仅用于组7 (用作仿真 EEPROM)。

    您的代码看起来很好:

    uint32_t g_pulUpdateSuccesss[]={0x00000000、0x11111111、0x22222222、0x333333、0x444444、 0x555555、0x66666666、0x777777、0x88888888、0x9999990xAAAAAAAAAA、0xBBBBBBBBBB、0xCCCCCCCC、0xDDDDDDDD、0xEEEEEEEE、0xFFFFFFFF};

    uint32_t 大小;

    大小= BLInternalFlashFirstSectorSizeGet ();

    大小= BLInternalFlashSizeGet ();

    大小= BLInternalFlashStartAddrCheck (0x200000、64);

    uint16_t oReturnCheck;

    oReturnCheck = Fapi_BlockProgram (1、0x200000、(无符号长整型)&g_pulUpdateSuccessess、64);

    但是、在将数据编程到该扇区之前、您需要先擦除该扇区。

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

    我添加了擦除、编程中仍有错误。

    我已经尝试过另一个具有相同结果的 Hercules TMS570LC43x 电路板。

    以下是一些可能有用的信息。 我在以下代码行有一个断点:

    fapi_issueProgrammingCommand ((uint32_t *) dst、(uint8_t *) src、(uint32_t) bytes、0、0、fapi_DataOnly);//fapi_AutoEccGeneration);

    当我对64字节(每个调用32个)进行编程时、该行执行两次。 首次单步执行代码行时、Code Composer 会正确移动到下一行代码。 第二次单步执行该行时、Code Composer  不会返回。 如果我按下"pause"按钮、代码将在键输入循环中执行。 这可以可靠地重复。

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

    以下是 code.e2e.ti.com/.../7382.Errors-in-flash-step-sequence.docx 建议行的结果

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

    我将编写一个简单的项目、使用 F021 API 将数据编程到闪存中、并为您提供参考。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、John、

    请使用"Fapi_AutoEccGeneration"替换"Fapi_DataOnly"。 否则、您编程到闪存的数据会出现 ECC 错误。 ECC 校正算法将在您读取数据时对其进行校正。 这就是您在 CCS 存储器浏览器中看到错误数据的原因。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我们正在变得越来越近...

    我已将 Fapi_issueProgrammingCommand 从:Fapi_DataOnly 修改为:Fapi_AutoEccGeneration

    我还放入了测试代码以执行以下操作:

    -在写入之前、查看该位置的值是否正确(@ 0x200000)

    -执行写操作(@ 0x200000)

    -写入测试后、该值可查看其是否正确(@ 0x200000)

    -在不同的位置发出第二次写入(@ 0x200120)

    -再次测试原始位置(@ 0x200000)

    以下是结果(每次单步执行 一行代码):

    首次测试时位置不正确

    当执行第1次擦除/写入时、所有64 个位置(@ 0x200000)的内存呈现现在都是正确的

    第2次擦除/写入在另一个位置执行、存储器呈现正确(0x200120)、但现在损坏(0x200000)-现在未清除擦除-只是混乱

    我注释掉了第二个擦除 并重新运行了代码

    输入时内存不正确、第一次写入时正确、第二次写入时保持正确

    我已注释掉两个 Fapi_BlockErase 请求-两个位置的两个存储器都保持正确

    此外 、Fapi_issueProgrammingCommand 的第二次执行不再会使 Code Composer 步骤过程混乱。

    仔细看、虽然对0x200000进行了调用、但擦除的第一次执行(针对0x200000)会破坏第二个存储器位置(在0x200120上)。。。

    下面是使用的测试代码:

      uint32_t * src;

      src = 0x200000;

      状态=* src;

      如果(status ==0xea0004bd )

       SRC++;

      其他

       src-;

      uint32_t 成功[]={0xea0004bd、0x00000000、

      0x00000000、0x00000000、

      0x00000000、0x00000000、

      0x00000000、0x00000000、

      0x4605b538、0x2d06460c、

      0x2d08d005、0x2d0ed003、

      0x2005bf18、0x2010d108、

      0xfa34f000、0x60044803};

      状态= Fapi_BlockErase (1、0x200000、0x2000);

      STATUS = Fapi_BlockProgram (1、0x200000、(无符号长整型)&Success、64);

            src = 0x200000;

            状态=* src;

            如果(status ==0xea0004bd )

              SRC++;

            其他

              src-;

      int16_t i;

      (i=0;i<64;i++)

        pData[i]= 0xFFFFFFFF;

      uint16_t oReturnCheck;

      //oReturnCheck = Fapi_BlockErase (1、0x200120、64);   <--正在破坏0x200000)

      oReturnCheck = Fapi_BlockProgram (1、0x200120、(无符号长整型)&pData、64);

            src = 0x200000;

            状态=* src;

            如果(status ==0xea0004bd )

              SRC++;

            其他

              src-;

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

    Fapi_BlockErase (..) 用于扇区擦除。 它不能擦除扇区的一部分。

    Fapi_BlockErase (1、0x200120、64):0x200120位于组1的第1个扇区中、0x200120+64也位于扇区1中、因此仅重新读取第1个扇区。

    如果大小为0x20000、0x200120 + 0x20000位于第2个扇区、那么第1个扇区和第2个扇区将被擦除。

    因此在第二次写入之前,您无需调用 Fapi_BlockEras(),否则第一次写入的内容将被擦除。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    块清除的预期结果是什么(因为它与清除的数据模式相关 -即全0或1)?

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

    扇区中的内容将被擦除、并且所有数据位都变为1。 数据模式应为0xFFFFFFFF。

    对于 TMS570LC43x 器件、ECC 在默认情况下处于启用状态、无法禁用。 擦除闪存时、ECC 空间也会被擦除、这两个空间都将成为0xFFFFFFF。 当您读取闪存内容时、会出现 ECC 错误、您读取的数据不是0xFFFFFFF。 ECC 错误校正后、一些位发生了变化。