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.

[参考译文] UCD3138128:校验和 don't 匹配

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

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1496944/ucd3138128-checksums-don-t-match

部件号:UCD3138128
主题中讨论的其他器件:UCD3138

工具/软件:

再次大家好...

我在计算和验证闪存中的校验和时遇到问题。

以下是操作步骤。

步骤1.

我下载了应用程序并按如下方式添加了校验和:  

校验和为:0x3097B3F36D16

然后、引导加载程序成功引导程序、以便我知道添加到块1末尾的校验和正确(至少引导加载程序认为正确)。

步骤2.

我使用此处的 FUSION GUI 验证了这是正确的:

步骤3.

我在同一地址空间上运行固件校验和计算、得到了不同的结果。 这是我的代码片段。 使用的 代码来自 UCD3138编程器手册。

通过 下面包含的函数、我在固件中计算  的值为:0x18F9B3F36D16、而值融合 GUI 计算的值为   0x3097B3F36D16。

您能否验证这与引导加载程序使用的函数相同、或者是否为我提供了代码片段?

如往常一样、我们非常感谢您的任何帮助!

.e2e.ti.com/.../5556.New-Text-Document-_2800_3_2900_.txt

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

    虽然我认为下面不是问题...

    也许我的内存基址寄存器不正确?  这是 MFBAHR1和17个寄存器。  
    有人能检查这些吗? 我使用了默认值。

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

    我注意到的另一点是、GUI 计算的校验和更大。 在 GUI 计算中还包含另一个存储器块、但我的计算中未包含该存储器块。 该 GUI 计算中是否可以使用引导加载程序存储器? 我完全迷失了为什么我的计算不正确。

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

    你好、蝙蝠侠、

    感谢您的提问。 我正在调查您的查询、我将在下周提供回复。

    此致、

    Jonathan Wong

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

    我不得不解决此问题以及在固件控制下切换应用程序的固件问题...因此、我们非常感谢您提供任何快速的帮助!

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

    你好、蝙蝠侠、

    您可以尝试使用文本编辑器(如 VS Code)直接查看.map 文件、查看寄存器地址是否与存储器调试器中显示的寄存器值匹配。 我发现有时内存 调试器与.map 文件不同。 此外、请确认您在存储器调试器中选择的文件位置是正确的位置。 我假设您使用双向直流/直流固件作为起点。 该固件文件结构与典型的 UCD3138文件结构不同。

    我相信该固件也没有启用.pp 文件。 您可以在 Project Properties →Build→ Arm Compiler Advanced  Options→Parser Preprocessing Options 中找到 Parser Preprocessor (.pp)指令的设置。 选择手动模式、然后检查底部的两个选项。 确保在与.map 文件相同的文件夹中生成.pp 文件、并指向存储器调试器中的该文件夹。  

    此致、

    Jonathan Wong

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

    我可以使用存储器调试器正确地计算校验和并对其进行编程。 这是因为当我重新启动器件时、引导加载程序会验证校验和是否正确并正确引导应用程序。 但是、当我运行应用程序函数来验证校验和时、我会计算另一个结果。 我 检查了存储器映射和 pp 文件以确保没有在调试器和存储器映射之间看到任何差异。 编译时(.pp)文件也会更新。

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

    你好、蝙蝠侠、

    我将检查是否有更好的方法来计算校验和。 我会在本周结束时回复您。

    此致、

    Jonathan Wong

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

    尊敬的 Jonathan:

     在处理"unsigned long long"值时似乎存在编译器错误。

    我不得不承认,当我看到使用64位整数计算校验和的方法时,我有点生气,因为处理器只有32位 ,所以处理32位总和值的进位/溢出位,必须用 assy 代码处理。 理论上、这样做是为了"加速"校验和计算。

    这不奏效:

    void calculate_checksum (寄存器 Uint32 * start_address、寄存器 Uint32 * end_address)

      uint64 lcs = 0;
      while (start_address < end_address)
      {
        LCS = lcs +*start_address;
        LCS = lcs +*(start_address + 1);
        start_address = start_address + 2;
      }

    }

    这是可行的!! 奇怪的胡子?

    void calculate_checksum(register Uint32 *start_address, register Uint32 *end_address)
    {

       Uint64 lcs = 0; 

       while(start_address < end_address)
       {
           lcs = lcs + (Uint64)*start_address ; // MUST BE CAST HERE or addition doesnt work properly!
           start_address = start_address + 1;
        }
    }

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

    你好、蝙蝠侠、

    感谢您的输入。 我将在本周晚些时候提供详细的答复。

    此致、

    Jonathan Wong

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

    你好、蝙蝠侠、

    感谢您对的见解  calculate_checksum () 功能。 以下是我希望对您和本论坛上的任何其他人有所帮助的一些想法。

    原稿  calculate_checksum () 您可以 在 UCD3138A64/UCD3138128编程手册的第18页中找到此功能。  

    void calculate_checksum(register Uint32 *start_address, register Uint32 *end_address)
    {
        register unsigned long long lcs = long_checksum; //use local register variable for speed.
        while(start_address < end_address)
        {
            lcs = lcs + *start_address ;
            lcs = lcs + (Uint32)*(start_address + 1) ;
            start_address = start_address + 2;
        }
        long_checksum = lcs;
    }

    UCD3138x Arm 内核是32位处理器、是正确的。 所以、 START_ADDRESS 索引为32位数字。 因此、最好的方法是使用32位数字进行索引、这样每次递增 START_ADDRESS 时、都会读取接下来的4个字节的数据。 编程人员手册建议通过读取每个循环的8个字节数据来加快此过程。

    因此、我 有3种计算校验和的方法。 我在下表中重点介绍了该过程:

    1. 《编程人员手册》中一次读取2个32位的快速方法
    2. 读取1x 64位的方法  
    3. 慢速方法一次仅读取1个32位。  

     提供的编程人员手册中的解决方案应该可以使用、因此我不知道为什么代码不适用于您。 我怀疑2个可能的原因:

    • Fusion GUI 校验和会计算整个 程序闪存组的校验和(如果您选择全部4个块、则为128KB)。 您的职能可能有所不同  END_ADDRESS 这样就会在不同的位置停止计算。
    • 这可能是一个小端字节序与大端字节序问题。 您的函数可能会读取0x3322110077665544等内容、而不是准确读取0x0011223344556677。  

    calculate_checksum () 摘自程序员手册

    calculate_checksum ()函数   ↓启动(lcs) ↓start+1 (lcs) ↓START+2
    存储器地址 0x800 0x801 0x802 0x803 0x804 0x805 0x806 0x807 0x808 0x809 0x80a 0x80b 0x80c 0x80d 0x80e 0x80f
    程序数据(1字节) 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xbb 0xcc 0xdd 0xee 0xFF

    calculate_checksum ()  使用(uint64)  

    calculate_checksum ()函数   ↓启动 ↓START+1
    存储器地址 0x800 0x801 0x802 0x803 0x804 0x805 0x806 0x807 0x808 0x809 0x80a 0x80b 0x80c 0x80d 0x80e 0x80f
    程序数据(1字节) 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xbb 0xcc 0xdd 0xee 0xFF

    calculate_checksum () 仅使用(Uint32)

    calculate_checksum ()函数   ↓启动 ↓START+1
    存储器地址 0x800 0x801 0x802 0x803 0x804 0x805 0x806 0x807 0x808 0x809 0x80a 0x80b 0x80c 0x80d 0x80e 0x80f
    数据(1字节) 0x00 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88 0x99 0xAA 0xbb 0xcc 0xdd 0xee 0xFF

    我建议使用最后一种方法、即一次只需计数1倍32位。 虽然理论上速度较慢、但我认为一次计算2倍32位时不会节省太多时间、但代价是可能出现错误。 一次对1个32位进行计数的代码如下:

    void calculate_checksum(register Uint32 *start_address, register Uint32 *end_address)
    {
        register unsigned long long lcs = long_checksum; //use local register variable for speed.
        while(start_address < end_address)
        {
            lcs = lcs + *start_address ;
            start_address = start_address++;
        }
        long_checksum = lcs;
    }

    此致、

    Jonathan Wong