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.

[参考译文] TMS320F28069:闪存 API 编程在不由 CCS 直接编程时失败

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/591021/tms320f28069-flash-api-programming-fails-when-not-directly-programmed-by-ccs

器件型号:TMS320F28069
Thread 中讨论的其他器件:controlSUITE

你好

我正在处理需要从闪存独立加载的项目、我必须将数据保存到闪存。 基于 SPRA958L、我实现了在启动时将程序代码、.econst 和.switch 符号复制到 RAM 的功能。 我使用 SPRAB60在一个闪存扇区中实现 EEPROM 仿真、并使用2806x_BootROM_API_TABLE_Symbols_fpu32.lib

如果我使用 CCS 对器件进行编程、则可以正常工作。 我的代码按应有的方式运行、我能够写入闪存。 如果我复位器件并让它从闪存启动、代码也会工作、但我无法写入闪存。我已经知道、API 的 Flash_Program 函数被调用、但返回错误代码30、这意味着程序失败。

我想知道为什么它在从 CCS 加载而不是从闪存加载时起作用。 我已在下面附加了我的链接器 cmd 文件。 从闪存引导时、初始化是否有什么不同?

谢谢、致以诚挚的问候

Andri

MEMORY
{
PAGE 0:/* Program Memory */
/*内存(RAM/FLASH/OTP)块可被移动到第1页进行数据分配*/
RAMM0 :origin = 0x000050、length = 0x0003B0 /*片上 RAM 块 M0 */
RAML0 :origin = 0x008000、length = 0x000800 /*片上 RAM 块 L0 */
RAML3 :origin = 0x009000、length = 0x001000//片上 RAM 块 L3 */
OTP :origin = 0x3D7800,length = 0x000400 /*片上 OTP */

FLASHG :origin = 0x3DC000、length = 0x004000 /*片上闪存*/
FLASHF :origin = 0x3E0000、length = 0x004000 /*片上闪存*/
FLASHE :origin = 0x3E4000,length = 0x004000 /*片上闪存*/
FLASHD :origin = 0x3E8000、length = 0x004000 /*片上闪存*/
FLASHC :origin = 0x3EC000、length = 0x004000 /*片上闪存*/
FLASHA :origin = 0x3F4000,length = 0x003F80 //片上闪存*/
csm_RSVD:origin = 0x3F7F80,length = 0x000076 /* FLASHA 的一部分。 当 CSM 正在使用时、使用所有0x0000进行编程。 */
开始 :origin = 0x3F7FF6,length = 0x000002 /* FLASHA 的一部分。 用于"引导至闪存"引导加载程序模式。 //
csm_PWL_P0:origin = 0x3F7FF8,length = 0x000008 /* FLASHA 的一部分。 FLASHA */

FPUTABLES 中的 CSM 密码位置:origin = 0x3FD860,length = 0x0006A0//引导 ROM 中的 FPU 表*/
IQTABLES:origin = 0x3FDF00,length = 0x000B50 /*引导 ROM 中的 IQMath 表*/
IQTABLES2:origin = 0x3FEA50,length = 0x00008C /*引导 ROM 中的 IQMath 表*/
IQTABLES3:origin = 0x3FEADC,length = 0x0000AA/*引导 ROM 中的 IQMath 表*/

ROM :origin = 0x3FF3B0,length = 0x000C10 /*引导 ROM */
重置 :origin = 0x3FFFC0,length = 0x000002 引导 ROM 的/*部分*/
向量 :origin = 0x3FFFC2,length = 0x00003E /*部分引导 ROM */

第1页:/*数据存储器*/
/*内存(RAM/FLASK/OTP)块可被移动至 PAGE0以进行程序分配*/
/*寄存器保留在第1页上 //

boot_RSVD:origin = 0x000000,length = 0x000050 // M0的一部分,引导 ROM 将此用于栈*/
RAMM1 :origin = 0x000400、length = 0x000400 /*片上 RAM 块 M1 */
RAML1 :origin = 0x008800,length = 0x000400 /*片上 RAM 块 L1 */
RAML2 :origin = 0x008C00,length = 0x000400 /*片上 RAM 块 L2 */
RAML4 :origin = 0x00A000、length = 0x002000 /*片上 RAM 块 L4 */
RAML5 :origin = 0x00C000、length = 0x002000 /*片上 RAM 块 L5 */
RAML6 :origin = 0x00E000、length = 0x002000 /*片上 RAM 块 L6 */
RAML7 :origin = 0x010000,length = 0x002000 /*片上 RAM 块 L7 */
RAML8 :origin = 0x012000、length = 0x002000 /*片上 RAM 块 L8 */
USB_RAM :origin = 0x040000、length = 0x000800 /* USB RAM*/
FLASHH :origin = 0x3D8000,length = 0x004000 /*片上闪存*/
FLASHB :origin = 0x3F0000、length = 0x004000 /*片上闪存*/
}/*

将段分配给内存块。
注:
DSP28_CodeStartBranch.asm 中用于重定向代码的 codestart 用户定义段
闪存时执行
ramfuncs 用户定义的段、用于存储将从闪存复制到 RAM
中的函数*


/段
{
.cinit :> FLASHA、 PAGE = 0.Pinit
:> FLASHA、 PAGE = 0.text
:> FLASHA、 PAGE = 0
codestart :>开始, PAGE = 0
ramfuncs :LOAD = FLASHD,
运行= RAML3、
load_start (_RamfuncsLoadStart)、
load_end (_RamfuncsLoadEnd)、
run_start (_RamfuncsRunStart)、
load_size (_RamfuncsLoadSize)、
PAGE = 0

csmpasswds :>csm_PWL_P0、page = 0
csm_rsvd :>csm_RSVD,page = 0

/*分配未初始化的数据段:*/
.stack :> RAMM1, PAGE = 1.ebss
:> RAML4, PAGE = 1
.esysmem :> RAML2, PAGE = 1

/*初始化段要进入闪存*/
/*要使 SDFlash 对这些段进行编程、必须将它们分配到 PAGE 0 */
.econst :LOAD = FLASHB、
运行= RAML6、
Load_start (_EconstLoadStart)、
RUN_START (_EconstRunStart)、
load_size (_EconstLoadSize)、
PAGE = 1.switch
:load = FLASHA,
运行= RAMM0、
Load_start (_SwitchLoadStart)、
RUN_START (_SwitchRunStart)、
load_size (_SwitchLoadSize)、
PAGE = 0

/*为寄存器映射分配存储器:*/
.register :> RAML1, PAGE = 1

/*分配 IQ 数学区域:*/
IQmath :> FLASHA、 PAGE = 0 /*数学代码*/
IQmathTables :> IQTABLES,page = 0,type = NoLoad

//分配 FPU 数学区域:*/
FPUmathTables :> FPUTABLES,page = 0,type = NoLoad

//如果调用 IQNexp()或 IQexp(),请取消注释以下部分
库中的函数、以便利用
引导 ROM 中的相关 IQ Math 表(这可以节省空间和引导 ROM
1个等待状态)。 如果此部分未注释、则为 IQmathTables2
将被加载到其他存储器(SARAM、闪存等)中并将采用
上行空间、但0等待状态是可能的。
//
/*
IQmathTables2:> IQTABLES2,page = 0,type = NoLoad
{

IQMath.lib (IQmathTablesRam)

}
*/
/*如果调用 IQNasin ()或 IQasin (),请取消注释以下部分
库中的函数、以便利用
引导 ROM 中的相关 IQ Math 表(这可以节省空间和引导 ROM
1个等待状态)。 如果此部分未注释、则为 IQmathTables2
将被加载到其他存储器(SARAM、闪存等)中并将采用
上行空间、但0等待状态是可能的。
*
/*
IQmathTables3:> IQTABLES3,PAGE = 0,TYPE = NOLOAD
{

IQMath.lib (IQmathTablesRam)

}
//

/*.reset 是编译器使用的标准段。 它包含
用于 C 代码的_c_int00起始地址的*//*。 /*
/*使用引导 ROM 时
,不需要此部分和 CPU 矢量*//*表。 因此,默认类型设置为*/
/* DSECT */
.reset :>重置, PAGE = 0、TYPE = DSECT
向量 :>引导程序,页= 0,类型= DSECT

} 

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

    这些是我要检查的内容:-

    1) 1)您是否确定了尝试编程擦除条件中的哪个地址以开头。

    2) 2)您是否确保您的 PLL 设置与 Flash2806x_API_Config.h 中提到的 CPU_RATE 定义相匹配

    3) 3)检查 CLKOUT 以确保运行配置的频率

    4) 4)您是否在不同的地址看到了问题?

    5) 5)是否在多个器件上观察到此问题?

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

    尊敬的 Manoj:

    我检查了地址和时钟配置、一切看起来都很好。 正如我提到过的、代码在直接从 CCS 加载时工作。 我还使用了另一个闪存扇区和另一个器件、问题仍然存在。

    我想从闪存启动器件时出现问题、可能是将部分代码复制到 RAM 时出现问题。

    我知道闪存 API 函数存储在引导 Rom 中、因此我不必将其复制到 RAM 中。 但是、我是否必须在链接器 cmd 文件中指定它们、就像针对 FPUTABLES 或 IQTABLES 所做的那样?

    CodeSecurityModule 是否存在问题? 该文档指出、如果从不安全的部分进行访问、则需要解锁。 我假设闪存 API 访问闪存的引导 ROM 不安全、因此我尝试使用虚拟读取解锁 CSM (请参阅以下代码)、如文档中所述。 或者它是否按默认值解锁?

    此致

    Andri

    PAGE_POINTER =(uint16 *) 0x3F7FF8;//针对
    (i=0;i<8;i++){
    dummy =*(Page_pointer++);
    }的 PWL 寄存器地址 

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

    您的设备是否已锁定? 如果已锁定、则无法通过从非安全存储器(BootROM)中运行闪存 API 函数来对闪存进行编程/擦除。 您必须先解锁它。

    您可以使用 F2806x_SYSCTRL.C.中的 CsmUnlock 函数 此外、如果您已经查看过 libs\utilities\flash_api\2806x\v100a\example_Flash2806x_api_FPU 示例。 请这样做。

    uint16 CsmUnlock()

    易失性 uint16温度;

    //使用当前密码加载密钥寄存器。 0xFFFF 是虚拟的
    //密码。 用户应将其替换为正确的 DSP 密码。

    EALLOW;
    CsmRegs.KEY0 = 0xFFFF;
    CsmRegs.key1 = 0xFFFF;
    CsmRegs.key2 = 0xFFFF;
    CsmRegs.key3 = 0xFFFF;
    CsmRegs.KEY4=0xFFFF;
    CsmRegs.KEY5=0xFFFF;
    CsmRegs.KEY6 = 0xFFFF;
    CsmRegs.KEY7=0xFFFF;
    EDIS;

    //执行密码位置的虚拟读取
    //如果它们与密钥值匹配,CSM 将解锁

    temp = CsmPwl.PSWD0;
    temp = CsmPwl.PSWD1;
    temp = CsmPwl.PSWD2;
    temp = CsmPwl.PSWD3;
    temp = CsmPwl.PSWD4;
    temp = CsmPwl.PSWD5;
    temp = CsmPwl.PSWD6;
    temp = CsmPwl.PSWD7;

    //如果 CSM 未锁定,则返回成功,否则返回
    //失败。
    if (CsmRegs.CSMSCR.bit.SECURE_=0)返回 STATUS_SUCCESS;
    否则返回 STATUS_FAIL;



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

    曼诺伊

    我添加了解锁器件的代码、并通过读取特定位对其进行验证。 我的设备已解锁、但未解决问题。

    使用 CCS 对器件进行编程后、我可以通过断开连接并重新连接目标来重现错误。 编程后、我能够写入闪存、但在重新连接后、API 函数 Flash_Program 因错误代码#30而永久失败。

    我检查了输出的.map 文件、闪存相关符号映射如下:

    1      00000d02 _Flash_CallbackPtr     
    1    00000d04 _Flash_CPUScaleFactor
    ABS  003ffebb _Flash2806x_Program    
    abs  003ffebd _Flash2806x_Erase  

    我找不到任何 Ressource 来检查它们是否正确、但在我的理解中、断开连接和重新连接目标不应更改映射中的任何内容。

    谢谢你
    Andri

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

    是的、断开并重新连接目标不应更改映射中的任何内容。

    在此阶段、我将比较您的代码与 controlSUITE 示例实现。 我只想强调一点、您不需要使用软件闪存 API 库、因为 BootROM 中已经提供了 API。

    此致、
    曼诺伊
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    仅供参考... 如果您不知道存在这样的示例...
    controlSUITE 中提供的示例项目展示了如何在项目中集成软件闪存 API 和 ROM 闪存 API。

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

    曼诺伊

    根据您的建议、我将我的代码与示例进行了比较、可以解决该问题。

    Unitl 现在我使用了库部分中的"Flash_API_Example"。 今天、我还检查了特定于器件的文件夹中的"Example_2806xFlashProgramming"、并意识到我必须将 EALLOW/EDIS 放在换算系数和回调 PTR 初始化周围。

     EALLOW;

     Flash_CPUScaleFactor = scale_factor;

     Flash_CallbackPtr = 0;

     EDIS;

    出于某种原因、在 Flash_API 库中的示例中未完成此操作。 感谢您帮助解决我的问题。

    Andri