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.

[参考译文] TMS570LS1224:F021闪存 API 会在擦除或重新编程闪存扇区时导致预取条目。

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/880989/tms570ls1224-f021-flash-api-causes-prefetch-entry-when-erasing-or-reprogramming-flash-sector

器件型号:TMS570LS1224

您好!

我正在尝试实现引导加载程序应用程序。

为了开始了解如何执行引导加载、设计了一个用例。  成功完成此简单用例后、可以增强基本功能并针对外部存储器或仿真 EEPROM 进行缩放。 有各种可能性。

用例:

  1. 将 F021闪存 API 加载到 RAM 中、以获得闪存组0 (主闪存)的擦除/重新编程访问权限。
  2. 擦除闪存组0中的扇区、以验证 F021是否加载到 RAM 中。
  3. 使用 F021使用同一闪存组中另一个扇区的数据对扇区进行重新编程。

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

 

我迄今采取的步骤:

  • 链接器文件中的"sys_link.cmd"
      • 我已将 SPNU515C 用于存储器布局。 每个存储器段的原点与闪存扇区的起始地址对齐、 如 SPNU515C (第113页)中所指定、并由中的 Joe Josh 表示重要
      • F021闪存 API 位于其自己的存储器部分(FLASH_API)中。
      • 我要擦除和编程的存储器部分称为 FLASH_COPY。  
内存
{
/*扇区0 */
矢量 (x) :O=0x00000000 l=0x00001000
BOOT_LOAD (RX):o=0x00001000 l=0x00001000 //引导加载程序位于此处*/
FLASH_API (RX):o=0x00002000 l=0x00002000 // F021 API 驻留在此处*/
/*扇区1..14 */
FLASH0 (Rx):O=0x00004000 l=0x0011BFFF
/*扇区15 */
Flash_copy (RX):o=0x00120000 l=0x0001FFFF f=0x5A5A5A

堆栈 (RW):o=0x08000000 l=0x00010500
RAM (RW):o=0x08010500 l=0x0001fb00

//用户代码开始(2)*/
*用户代码结束*/
} 

 

      • 我现在将整个 F021库包含在 FLASH_API 部分中,这解决了 e2e 论坛( URL:   )上其他线程中讨论的问题。 该库适合部分。
部分
{
.intvecs:{}>向量
.text :{}>FLASH0
.const :{}>FLASH0
.cinit :{}>FLASH0
.pinit :{}>FLASH0
.bss :{}> RAM
.data :{}> RAM
sysmem :{}>RAM


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

BOOT_LDR:{sys_core_AFw.obj (.text)}> boot_load
eabi_start:{sys_startup_AFw.obj (.text)}> boot_load

FLASH_API:
{
fapi_usr_func.obj (.text)
bl_flash.obj (.text)

l F021_API_CortexR4_be_V3D16.lib (.text)
}
LOAD = FLASH_API、
运行= RAM、
LOAD_START (API_LOAD)、
RUN_START (API_RUN)、
load_size (api_size)

/*用户代码结束*/

} 
  • 在启动序列中(sys_startup.c sys_core.asm)
      • 在_coreInitRegisters_函数结束时、CPU 被切换回监控器模式。
…
;切换到未定义指令模式(M=11011)
CPS #27
MOV LR、r0
R1女士、CPSR
MSR spsr_cxsf、R1
;切换到系统模式(共享用户模式寄存器)(M = 11111)
CPS #31
MOV LR、r0
R1女士、CPSR
MSR spsr_cxsf、R1
;切换回 Supervisor 模式(M=10011)-引导加载程序
CPS #19
MOV LR、r0
R1女士、CPSR
MSR spsr_cxsf、R1

;ARM 模式- cortex R4手动 ARM DDI 0363G p.56
      •  
      • 之后、我使用 MPU 访问控制寄存器授予完全读取/写入数据权限、如 Cortex-R4F 技术参考手册第126页(ARM DDI 0363G、ID041111;第126/436页)中所述
;MPU cortex R4 ARM DDI 0363G 第184页
MRC P15、 0x00、 R2、 c1、c0、#0x02
ORR R2、 R2、 0xF00000
MCR P15、 0x00、 R2、 c1、c0、#0x02
MOV R2、 0x40000000
fmxr fpexc、R2

;读/写完全访问 ARM DDI 0363G 第126页
MRC P15、 0x00、 R2、 C6、C1、#0x04
MOV R2、 0x03
MCR P15、 0x00、 R2、 C6、C1、#0x04
MOV R2、 0x40000000
fmxr fpexc、R2

      • 闪存在管线模式中被初始化以实现160MHz 的读取/写入(SPNU515C;第288页)。
/**-设置闪存读取模式、地址等待状态和数据等待状态*/
flashWREG->FRDCNTL = 0x000000000000
|(UINT32)((UINT32) 3U << 8U)
|(uint32)((uint32) 1U <<4U)
| 1U; 

      • 在 sys_startup.c 中为 RAM 启用 ECC (_coreEnableRamEcc_();函数)
      • 按照中的 Charles Tsai 的建议、在 CCS 中选中 Auto-ECC 选项   。
      • 看门狗未启用。
  • "引导加载程序"
      • 要在 RAM 中复制闪存 API、我选择了 C 函数而不是汇编语言。 我们公司的 CI 管道可以分析 C 代码、但不能分析汇编代码。 我在另一个 E2E 主题上找到的代码、我没有记下它!
      • 我使用 SPNU118W 之后的链接器符号、第8.6.1节 在 C/C++应用中使用链接器符号
      • 我在每次函数调用后刷新流水线、即使这不是必需的。
      •  

extern uint8_t api_load;
extern uint8_t api_run;
extern uint8_t api_size;

// f021 API 以 u32字表示的大小*/
#define API_U32_word_count (uint32_t)((uint32_t)(&api_size)/ sizeof (uint32_word_)*

要
定义闪存地址/#int32_t)*要定义的地址 0x00120000
#define ADDR_FLASH_API 0x00002000

/*闪存-组0、EEPROM -组7 */
#define Bank_0 0U
#define Bank_7 7U

#define Bank_0_Sector_15 0x8000U

void fn_copy_api_to_ram (uint8_t * p_load、uint8_t * p_start、uint32_t u32_size)
{

操作
{
*p_start =*p_load;
P_START++;
P_LOAD++;
} while (--u32_size);

return;
}

void fn_updateer_util (void)
{
/*首先将闪存 API 复制到 RAM
**以便写入闪存组0 */
fn_copy_api_to_ram ((uint8_t*)&api_load、(uint8_t*)&api_run、(uint32_t)&api_size);

uint32_t u32_fapi_res =(uint32_t) 0U;

u32_fapi_res = Fapi_initializeFlashBanks (SYS_CLK_FREQ);

u32_fapi_res = Fapi_setActiveFlashBank (Bank_0);

u32_fapi_res = Fapi_enableMainBankSecors (Bank_0_Secto_15);

while (fapi_check_FSM_ready_busy!= fapi_Status_FsmReady);
while (fapi_get_FSM_status!= fapi_Status_Success);

u32_fapi_res = Fapi_issue19 CommandWithAddress (Fapi_EraseSector、(uint32_t*) ADDR_FLASH_COPY);
fapi_flushPipeline();

while (fapi_check_FSM_ready_busy =fapi_Status_FsmBusy);
while (fapi_get_FSM_status!= fapi_Status_Success);

u32_fapi_res = fapi_get_FSM_status;

u32_fapi_res = Fapi_initializeFlashBanks (SYS_CLK_FREQ);
u32_fapi_res = Fapi_setActiveFlashBank (Bank_0);
u32_fapi_res = Fapi_enableMainBankSecors (Bank_0_Secto_15);
while (fapi_check_FSM_ready_busy!= fapi_Status_FsmReady);
while (fapi_get_FSM_status!= fapi_Status_Success);

uint8_t u8_dum_buff [4]={0xBA、0xD0、0xBA、0xD0};

u32_fapi_res = fapi_issueProgrammingCommand (((uint32_t *) ADDR_FLASH_COPY、
u8_dum_buff [0]、
4、
0U、
0U、
Fapi_AutoEccGeneration);


while (fapi_check_FSM_ready_busy =fapi_Status_FsmBusy);

u32_fapi_res = fapi_get_FSM_status;


返回;
} 

我面临的问题:  

使用调试器时,如果我单步执行 Fapi_issuedCommandWithAddress()函数,它将正常工作,并且我可以在内存浏览器中看到已擦除的闪存。 如果我在函数之后设置一个断点、并在程序开始时按 Resume Execution、则会导致预取尝试。

2.当我单步执行 fapi_issueProgrammingCommand()的汇编代码时,它可以正常工作,并且重新编程新擦除的闪存! 当我尝试单步执行函数时、它会导致预取。

 

我不知道如何继续下去,这证明是一个阻挡者。 提前感谢您!

 

此致、

米哈伊尔

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

    为了进一步澄清、 SYS_CLK_FREQ 被设定为160

    //
    //
    //用于为微控制器计时的晶体的频率(MHz)。
    //
    //这定义了运行
    //引导加载程序的微控制器所使用的晶振频率。
    //
    //取决于:无
    //不包括:无
    //要求:无
    //
    //*********
    #define CRYSTICL_FREQ 16. //MHz
    
    #define SYS_CLK_FREQ 160 //MHz 

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

    您好!

    fn_updater_util() should be executed from SRAM too,

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

    大家好、感谢大家的回答。 我相信该函数也是从 RAM 运行的!

    从 sys_startup.c 中摘录:

    /*配置系统对发送给 ESM 组1的错误条件的响应*/
    /*可以从 HALCoGen 的"ESM"选项卡配置此函数*/
    esmInit();
    /*初始化复制表*/
    __TI_auto_init();
    
    //用户代码开始(75)*/
    //用户代码结束*/
    
    /*调用应用程序*/*SAFETYMCUSW
    296 S MR:8.6 "启动代码(块范围内的库函数)"*/
    /* SAFETYMCUSW 326 S MR:8.2 "startup code (Declaration for main in library)"*/
    /* SAFETYMCUSW 60 D MR:8.8 "启动代码(库中 main 的声明;仅为相同操作 extern)"*/
    fn_updateer_util();
    
    //用户代码开始(76)*//
    //*用户代码结束*//
    *SAFETYMCUSW 122 S MR:20.11 "启动代码(需要存在 EXIT 和 ABORT)"*/
    EXIT (0);
    
    /*用户代码开始(77)*/
    /*用户代码结束*/
    } 

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

    您好!

     fn_updateer_util() fapi_usr_func()? 我在 链接器命令文件中找不到 fn_updateer_util()。

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

    再好一次!

    我已修改链接器文件以包括 fn_updateer_util()函数所驻留的文件。 它是 bl_main.obj

    BOOT_LDR:{sys_core_AFw.obj (.text)}> boot_load
    eabi_start:{sys_startup_AFw.obj (.text)}> boot_load
    
    /*链接器将段分配到单个存储器范围以便运行、
    但不同的加载存储器范围。
    *
    FLASH_API:
    {
    fapi_usr_func.obj (.text)
    bl_flash.obj (.text)
    bl_main.obj (.text)
    
    l F021_API_CortexR4_be_V3D16.lib (.text)
    }
    LOAD = FLASH_API、 /*在何处加载段*/
    运行= RAM、 /*运行段的位置*/
    load_start (api_load)、/* api_load 保存 flashAPI 段的 load addr *
    run_start (api_run)、/* api_run 保存 flashAPI 段的运行地址*/
    load_size (api_size) /* api_size 保存 flashAPI 段的大小*/
    /* api_load、api_run、api_size 可从复制表中引用。 * 

    现在、我将直接在 sys_startup.c 中调用函数 fn_copy_api_to_ram ()、如 TI 引导加载程序示例中所示。 从 sys_startup.c 中摘录

    /*用户代码开始(74)*/
    /*用户代码结束*/
    
    /*配置系统对发送给 ESM 组1的错误条件的响应*/
    /*可以从 HALCoGen 的"ESM"选项卡配置此函数*/
    esmInit();
    /*初始化复制表*/
    __TI_auto_init();
    
    //用户代码开始(75)*/
    //用户代码结束*/
    
    /*调用应用程序*/*SAFETYMCUSW
    296 S MR:8.6 "启动代码(块范围内的库函数)"*/
    /* SAFETYMCUSW 326 S MR:8.2 "startup code (Declaration for main in library)"*/
    /* SAFETYMCUSW 60 D MR:8.8 "启动代码(库中 main 的声明;仅为相同操作 extern)"*/
    fn_copy_api_to_ram ((uint8_t*)&api_load、(uint8_t*)&api_run、(uint32_t)&api_size);
    
    fn_updateer_util();
    
    //用户代码开始(76)*//
    //*用户代码结束*//
    *SAFETYMCUSW 122 S MR:20.11 "启动代码(需要存在 EXIT 和 ABORT)"*/
    EXIT (0);
    
    /*用户代码开始(77)*/
    /*用户代码结束*/
    } 

    现在我可以单步执行两个函数(Fapi_issueCommandAppoAddress()和 Fapi_issueProgrammingCommand()),它们不会生成预取指令。

    如果我在 fn_updateer_util()函数的末尾设置了一个断点,并在系统复位后按 Resume 键,它将进入 prefetchEntry!

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

    我似乎偶然发现了本主题中讨论的确切问题:


    我们的微控制器未启用中断、因为我们的架构未预见到这一点!

     

    此致、

    米哈伊尔

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

    在这个主题中所作的回答:

     

    您能否解释一下在提供的引导加载程序示例中、在 sys_intvecs.asm 中、应用程序映像的中断分支为何? 从 TI 引导加载程序示例中从 sys_intvecs.asm 中摘录:

    ;------------------------------------------------------------------
    ;中断矢量
    ;请更改#0x??? 在 bl_config.h 中定义的指定图像位置
    
    b _c_int00 ;0x00
    b #0x1FFF8 ;0x04
    b #0x1FFF8 ;0x08、软件中断
    b #0x1FFF8 ;0x0C,中止(预取)
    b #0x1FFF8 ;0x10,中止(数据)
    保留尝试
    b 保留尝试 ;0x14
    LDR PC、[PC、#-0x1b0] ;0x18
    LDR PC、[PC、#-0x1b0] ;0x1C 

    我相信解决方案即将推出、但 TI 团队的帮助将不胜感激!

     

     

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

    我将使用此平台记录我的调查结果、以便任何面临类似问题的人都可以参阅我为解决此问题而采取的步骤。

    查看我在上面的注释( )中引用的论坛线程后、我在中断矢量表(sys_intvecs.asm)的 prefetchEntry 处设置一个断点、并恢复应用程序、使其导致中止。

    已达到断点、我可以使用 CCS 中的"Register"视图观察 MCU 的寄存器。 在本例中、需要关注的是 CP15_instruction_FAULT_STATUS。 指出了这一点(链接: 2015年6月1日晚上10:41)

    使用 CortexR4F 技术参考手册(ARM DDI 0363G ID041111)在第4-47页的表4-27中、CP15_instruction_FAULT_STATUS 的位[10、3-0]的值建议为"同步奇偶校验/ECC 错误"

    使用_coreDisableRamEcc_()禁用 RAM ECC;使用 disableParity ()禁用奇偶校验;也无法解决问题。

    将中断矢量设置为与引导加载程序示例中的中断矢量相同并不是最佳选择、因为检查 TCRAMM ECC 的函数会生成数据中止(DABT)、这会导致跳转到中断矢量。


     

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

    我在 本地克隆了 Hercules 示例 git 存储库(),并签出了名为"qjwang_Hercules _examples"的分支(提交哈希:2ec9e6f9f8a09932f1d6455ab3c101c6efa27711)。

    在此存储库中、我发现 sys_link.cmd 链接器文件与 TI 网页上提供的引导加载程序示例非常不同。 我相应地修改了链接器文件。 现在针对链接器文件中的每个闪存区域调用 ECC 生成。

    在引导加载程序示例的 readme.txt 中、我找到了以下内容(在"新功能"主题下):"使用链接器 CMD 文件生成闪存 ECC 以避免推测取 ECC 错误。"

    在 readme.txt 的"Linker CMD file to generate Flash ECC"主题中对此进行了进一步讨论。 我遵循了指出的所有步骤:

    (从 readme.txt 中摘录)
    请执行闪存设置下的以下更改。 CCS 项目属性-->调试-->闪存设置:
    1.检查"连接时系统复位"
    2.取消选中"Auto ECC Generation"
    3.选中"将程序段与64位内存区域对齐"
    4.为“Flash 验证设置”选择“无”
    5.取消选中"程序加载前执行空白检查"
    6.按“应用”保存更改!

     

    所有这些操作也完成后、我仍然会获得预取终止!

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

    我真的很难解决这个问题、因此我们非常感谢您的帮助!

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

    米哈伊尔

    您是否解决了此问题?

    我遇到了一个微笑问题。

    Rob

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

    您好、 Mihail、

    您能否发布您的项目、以便我可以在电路板上进行检查?

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

    您好!

    您是否已解决此问题?

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

    QJ、

    我没有解决所有闪存问题,尽管我现在已经解决了这个特定问题。

    新用户的陷阱是推测分支。  

    我在擦除的某个扇区中有一段测试代码、在固件更新期间、我将不会访问测试代码。  

    事实证明、情况并非如此、CPU 必须不时访问已擦除的部分以进行 推测分支、从而得出不一致的结果。  

    我现在已将测试代码移出此区域、这会导致代码空间不足的另一个问题。

    因此、我想我现在已经开始讨论这个问题了。

    我现在还有一个问题需要解决、但我认为最好启动一个新线程、因为它与写入闪存失败相关。 我处于另一个调试会话的中间,如果我在太长的时间内无法解析,我将创建一个新线程。

    感谢你的帮助。

    此致

    Robert

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

    您好!

    很抱歉、我的回复延迟了、我不在办公室、无法访问源代码!

    这是源代码。 这是一个展示我仍面临的问题的最低工作示例!

     

    提前感谢您!

     

    e2e.ti.com/.../5127.tms570ls_5F00_bootloader.zip

     

     

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

    您好!

    请您发布新主题的参考链接!

    此致

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

    您好、Mihail、

    Fapi_flushPipeline()用于刷新 FMC 管道缓冲区。 请在状态检查后调用此函数。 但您在状态检查之前调用它。

    void fn_updateer_util (void)

    uint32_t u32_fapi_res =(uint32_t) 0U;

    u32_fapi_res = Fapi_initializeFlashBanks (SYS_CLK_FREQ);
    fapi_flushPipeline();

    if (((Fapi_initiatalizeFlashBanks ((uint32_t) SYS_CLK_FREQ))= Fapi_Status_Success)

    (空) Fapi_setActiveFlashBank (((Fapi_FlashBankType) Bank_0);
    (空) Fapi_enableMainBankSectors (0xFFFF);

    其他

    返回;

    while (fapi_check_FSM_ready_busy!= fapi_Status_FsmReady);
    while (fapi_get_FSM_status!= fapi_Status_Success);

    u32_fapi_res = Fapi_issue19 CommandWithAddress (Fapi_EraseSector、(uint32_t*) ADDR_FLASH_COPY);
    // fapi_flushPipeline();

    while (fapi_check_FSM_ready_busy =fapi_Status_FsmBusy);
    while (fapi_get_FSM_status!= fapi_Status_Success);

    fapi_flushPipeline();

    u32_fapi_res = fapi_get_FSM_status;

    while (fapi_check_FSM_ready_busy!= fapi_Status_FsmReady);
    while (fapi_get_FSM_status!= fapi_Status_Success);

    uint8_t u8_dum_buff [4]={0xBA、0xD0、0xBA、0xD0};

    u32_fapi_res = fapi_issueProgrammingCommand (((uint32_t *) ADDR_FLASH_COPY、
    u8_dum_buff [0]、
    4、
    0U、
    0U、
    Fapi_AutoEccGeneration);

    //fapi_flushPipeline();

    while (fapi_check_FSM_ready_busy =fapi_Status_FsmBusy);

    fapi_flushPipeline();

    u32_fapi_res = fapi_get_FSM_status;

    返回;

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

    另一项建议是、

    请使用 vfill 而不是填入链接器 cmd 文件。

    请参阅 http://www.ti.com/lit/ug/spnu118y/spnu118y.pdf

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

    非常感谢、

    这完全解决了问题!

    应用软件不再跳转到中断矢量!

    此致、

    米哈伊尔