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.

[参考译文] RM57L843:如何获取调试信息? CCS &放大器;RM57 &放大器;LwIP

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/566100/rm57l843-how-to-get-debug-information-ccs-rm57-lwip

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

你(们)好。  

我使用的是 CCS 6.1.1和 HDK RM57。 我 正在开发一种应用程序、通过串行读取传感器数据并通过 TCP 发送数据。 在第二步中、我将使用 LwIP 库。

该应用程序正常工作、但每次随机运行一段时间后、应用程序都会"崩溃"。 只有在通过 TCP 发送数据时才会发生这种情况(如果我通过另一个串行端口发送调试数据而 TCP 未发送、则程序不会崩溃-至少似乎是这样、因为在该设置中它没有崩溃)。

我正在尝试弄清为什么、但在崩溃后我没有从 CCS 收到任何消息、程序在以下任一行的文件"HL_sys_intvecs.asm"处"挂起":

PrefetchEntry
b prefetchEntry
DataEntry
b DataEntry 

我还在尝试解决 LwIP 邮件列表中的问题、但我需要向他们发送一些我不知道如何从 CCS 获取的调试信息。  我不知道如何重现错误、因此我无法在某个位置放置一个唤醒点并开始步进代码。

如果这是一个亵渎性的存储器访问或类似的访问、CCS 是否认为能够告知这一点? CCS 调试 GUI 完全没有变化、CCS 没有错误消息或跟踪。 没有。

也许您知道我可以检查哪些寄存器? 我可能需要修改调试器设置?

请提供任何帮助。

此致、

Julio

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

    在 prefetchEntry 或 DataEntry 挂起的 PC 意味着存在内存冲突。 如果在 prefetchEntry、则是由取指令引起的;如果在 DataEntry、则是由取数据引起的。 有关更多信息、请查看 CP15寄存器。 ARM Cortex R5 TRM 第4.3.2节对此进行了说明。 您可以在 CCS 寄存器选项卡中看到这些寄存器的内容:

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

    感谢你的帮助。 我真的很感谢。

    等待程序崩溃近2小时后,问题似乎是无效的数据获取。 CP15_DATA_FAULT_STATUS = 0x000008000、这意味着写入(SW = 1)导致了具有"后台"源(状态= 0x00)的中止。 背景在这方面意味着什么?

    通过 CP15_DATA_FAULT_ADDRESS (0x08080000)、我知道程序尝试在 RAM 之外写入(来自 HL_SYS_LINK_cmd:RAM (RW):origin=0x08001500 length=0x0007EB00 -> 0x08001500 + 0x0007EB00 = 0x08080000)。

    如何找到尝试写入该地址的语句(行和/或文件)?

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

    我能够在一个文件中包含一些来自 LwIP 的调试代码、我认为这与崩溃有关。 发生崩溃时、它在前面提到的预取 Entry 行停止、但 CP15_instruction_FAULT_STATUS 为0x00000000。 但是、CP15_instruction_FAULT_address 是0x3F606890。 这对您来说有道理吗? 当尝试从具有"背景"状态(状态0x00)的地址读取指令时、这是否是内存违例?

    如果这是有道理的、我如何继续调试(找到该指令)?

    提前感谢。

    此致、
    Julio
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    由于您的指令故障状态为0、我认为指令故障地址没有任何意义。 0x08080000的数据故障地址有意义。 这是 RAM 顶部之外的第一个位置。 后台源只是意味着其他 MPU 区都不会应用于该存储器位置、因此后台 MPU 设置(0)适用。 通常情况下、后台设置不是读取或写入。

    以下是两种确定代码尝试写入 RAM 顶部的原因的方法。 第一个只是代码分析。 是否有任何 RAM 初始化或检查例程可能索引到超过 RAM 顶部? RAM 的顶部用于堆、堆栈或堆? (如果使用 HALCoGen 创建的链接器文件、堆栈位于 RAM 的低位地址并向下增长。 堆栈溢出会产生相同的故障、但位于地址0x07FFFFFC。) 查看由链接器生成的.map 文件、查看存储器顶部的位置。

    第二种方法是查看用户 LR (链接寄存器)中的地址。 CPU 将处于中止模式、因此当前 LR 不可用、但 R14_USER 包含导致非法存储器写入的指令数之外的指令的地址。 (假设 CPU 当时处于用户或系统模式。) 查看反汇编并返回到代码中、找到可能导致写入的 STR 或 STM。 您可能必须返回到子例程中。 如果您幸运、您甚至可以在索引寄存器中看到0x08080000地址。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、Bob、

    再次感谢您的帮助。

    方法1.

    /*------------------ */
    /*内存映射 */
    
    MEMORY
    {
    * USER CODE BEGIN (2)*/
    * USER CODE END */
    引导程序(X):origin=0x00000000 length=0x00000020
    FLASH0 (RX):origin=0x00000020 length=0x001FFFE0
    FLASH1 (RX):origin=0x00200000 length=0x00200000
    堆栈(RW):origin=0x08000000 length=0x00001500
    RAM (RW):origin=0x08001500 length=0x0007EB00
    
    //用户代码开始(3)*/
    //*用户代码结束*/
    } 

    正如您所说(使用 HALCoGen)、堆栈位于 RAM 的低位地址、这意味着我有一个堆溢出错误?

    我没有使用任何 malloc、alloc 或类似函数来分配代码中的堆内存。 我只是使用一些指向(全局)栈中定义的数组的指针。 例如、作为双缓冲器:

    typedef struct Buffer
    {
    uint8 data[大小];
    }
    
    静态缓冲器 buffer_container_[2];
    静态缓冲器* current_buffer_;
    静态缓冲器* next 缓冲器_;
    
    void se_init_function ()
    {
    Current_buffer_=&buffer_container_[0];
    next 缓冲区=&buffer_container_[1];
    } 

    但是、LwIP 库需要使用其自己的 malloc 函数来动态分配内存。 我想他们会正确地处理释放内存的问题。 但可能有一个错误。

    您让我查看.map 文件、看看存储器顶部的位置是什么。 我找到了该文件、但我不明白将什么放在哪里。 我应该在哪里查找它?

     

    方法2.

    R14_USER 包含多条指令以外的指令的地址如果它是错误前的指令、会更好吗? 据我了解、反汇编不会按执行顺序显示指令。 它只是显示了将所有 c 文件放入一个文件中的每个 c 文件的汇编代码。 对吧? 我发现很难知道 R14_user 指令之前的内容、因为来自 TCP 服务器和接收串行接口的异步调用。 或者、我看到它不对吗?

    您还提到、我可以在索引寄存器中看到故障地址(0x08080000)。 在哪里可以找到索引寄存器? 我找不到。

    它是否告诉您错误发生真的需要很长时间? 我只想动态分配的指针、它需要很少的字节、并且不会被释放、最终会导致堆溢出。 还有其他原因吗?

    再次提前感谢您的帮助。

    Julio

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

    它可能是堆大小的溢出。 让我向您演示一个.map 文件示例、然后您可以检查是否可以增加堆大小以及这是否有助于解决问题。

    在映射文件的顶部、是对每个存储器类型使用量的摘要:

    存储器配置
    
    名称 原点长度 已使用 未使用的属性填充
    --- ---- ------ ---- ---- --------
    矢量 00000000 00000020 00000020 00000000 x
    FLASH0 00000020 001fffe0 0005a228 001a5db8 R X
    FLASH1 00200000 00200000 00000000 00200000 R X
    堆栈 08000000 00001500 00000000 00001500 RW
    RAM 08001500 0007eb00 0001326a 0006b896 RW
    

    在本例中、我没有使用0x6b896字节的 RAM。 如果我在映射文件中搜索单词"heap"、我会在这里找到它:

    .bss 08001500 000130c6 未初始化
    08001500 00007814 lwiplib.obj (.bss:ram_heap)
    08008d14 00007594 lwiplib.obj (.bss:memp_memory)
    080102a8 00003b24 hL_emac.obj (.bss:pbuf_array)
    08013dcc 00000400 https://obj (.bss:https://req_Buf)
    

    在我的情况下、堆不在 RAM 区域的末尾附近。 但是、如果堆溢出、则会损坏存储器管理例程使用的 RAM。 结果是不可预测的、但可能会导致代码无法取消分配堆内存、最终导致 内存中止。 由于我有很多可用的 RAM、我可以轻松地增大堆大小以查看这是否会产生影响。 LWIP 会创建自己的堆、而不是使用 TI 库中的堆。 大小由 lwipopts.h 文件的第68行设置:

    #define MEM_SIZE (30 * 1024)/* 30K */ 

    关于第二种方法、是的、如果我们可以捕获导致中止的指令的确切地址、这会很好、但为了实现高性能、Cortex R5在继续获取指令之前不会等待写入完成。 因此、当 CPU 被告知写入到一个无效位置时、PC 已经通过该指令递增。 通常、您可以在反汇编过程中向后工作、并识别导致中止的指令或至少是哪个函数。

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

    您好!

    再次感谢。 你是我唯一的希望 xD

    是的、我忘记告诉大家、我意识到我有很多未使用的 RAM (0x00058b7b)、这就是为什么我认为"需要这么长的时间才能发生错误的原因"。  我将 MEM_SIZE 设置为50k。 我的内存分配视图显示、正在使用29%的 RAM。

    我有新信息:

    我使用内部串行接口(连接到 USB 探针电缆进行调试)发送调试信息。 我增加了调试数据的数量、错误的速度要快得多(5到10分钟)。 这是什么意思? 提醒一下:我正在使用 sci3从传感器和 TCP 接收数据、以便(重新)将其发送到 PC。 LR_ABT 寄存器始终指向来自 sci3的接收函数。 我知道、此函数不需要是生成错误的函数、但它确实意味着错误总是出现在同一个点/时间/指令上。 lr_user 还始终指向相同的函数!

    我注意到的另一件事是、电流和下一个缓冲器(来自我之前的帖子)指向的地址从当前位置开始、但当错误发生时、它们是错误的(0x089B089B、 0xC308C308、0xD608CC08)。 这些缓冲器是 sci3接口的接收缓冲器、与 LR_ABT 指向的接口相同。 但是 、CP15_DATA_FAULT_ADDRESS 始终为0x08080000!!  

    我不知道以这种方式破坏指针的原因。

    此致。

    Julio

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这表明该问题与 SCI3接收缓冲器有关。 如果您从传感器接收数据的速度快于发送速度、那么接收缓冲区内容是否会继续增长? 添加额外的诊断消息以添加到 CPU 负载、并使问题更快发生。 接收缓冲区是否可以溢出并破坏指针?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、Bob、

    我进行了2次测试以排除一个接口。

    1. TCP 关闭、在 SCI 3 (传感器)上接收、在 SCI 1上发送(调试)。 我增加了调试数据的数量和发送频率、而不是 SCI 1。 程序未崩溃
    2. TCP 打开、 在 SCI 3 (传感器)上接收、在 SCI 1上发送关闭。 程序崩溃

    我还检查了时间:我每隔67ms 接收一次传感器数据(这就是它的预期方式)、TCP 接口大约需要2ms 来发送它。  

    发生了一些情况、并且 SCI 3的缓冲器连续损坏、但我认为问题的触发器不是来自 SCI 3 (其他情况也可能被卷曲、但我没有注意到)。 也许"这件事"与 LwIP 有关。 可能是我未正确配置它、或者我的代码有错误。 但我仍然没有看到它。

    我可以向您发送我的代码的简化版本吗?

    此致、

    Julio

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    简化的代码是否可以在没有硬件的情况下运行?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bob:

    由于它依赖于硬件、因此很难制作此版本的简化版。  

    我还制作了一些八位位组:

    • 我将程序与 TCP 服务器一起运行了一整天、使用一个初始化一次且从未更改的静态缓冲区。 连接到传感器的串行接口未激活。 调试串行接口处于活动状态、但会在一段时间内发送一次数据。 程序未崩溃。
    • 我将程序与 TCP 服务器一起运行了4个小时、并使用双静态缓冲区、该缓冲区每60ms 使用虚拟值更新一次。 连接到传感器的串行接口未激活。 调试串行接口处于活动状态、但会在一段时间内发送一次数据。 程序未崩溃。 (我这样做是为了测试我的复制功能是否有故障)。
    • 我尝试同时运行 TCP 服务器和传感器串行接口、但没有将串行缓冲区复制到 TCP 缓冲区。 TCP 服务器在一个测试中发送了从未更改的单个静态缓冲区、在另一个测试中发送了双静态缓冲区(每60ms 使用虚拟值更新一次)。   在这两 个测试中、程序 都崩溃

    此外、我注意到 PC 上的 TCP 客户端实际上是一个显示我的传感器数据的 GUI。 连接后、传感器数据的"图像"每~2秒"跳跃"一次。 数据错误。 我认为这可能是串行缓冲区到 TCP 缓冲区的复制错误。 但是、在电路板通过 TCP 发送数据之前、它会对数据进行处理并检查数据是否错误或损坏。 如果是、它会发送多个错误信号(LED 和串行调试数据)。 当 GUI 中的图像跳转时、我还会从板上获取错误信号(这意味着数据实际上是错误的)。 当服务器未连接到 GUI 时、我会从电路板上获得这些错误信号。

    这似乎是 TCP 服务器以某种方式影响串行接口(或同一存储器区域?)的中断例程 (并以某种方式破坏其缓冲器?)。 因此、我在我的端口(我从有关 LwIP 的德州仪器(TI)教程和我正在使用的电路板上获得)中看到、由于 SYS_PRICE_PROT = 1、下面的函数会被一直调用。 我觉得串行接口在它的中断被如此快速地启用和禁用时可能不喜欢它。

    sys_prot_t
    sys_arch_protect (void)
    {
    sys_prot_t status;
    status =(IntMasterStatusGet ()& 0xFF);
    
    IntMasterIRQDisable ();
    return status;
    }
    void
    sys_arch_unprotect (sys_prot_t lev)
    {
    //仅当中断最初在匹配时开启时才会重新开启
    发出了 SYS_ARCH_PROTECT()调用。 //
    if (((lev & 0x80)==0){
    IntMasterIRQEnable();
    }
    
    void IntMasterIRQEnable (void)
    {
    _enable_IRQ ();
    return;
    }
    
    void IntMasterIRQDisable (void)
    {
    disable_IRQ ();
    返回;
    } 

    然后、我将该定义更改为 SYS_Lighting_PROT = 0。 此函数未再次调用、但程序仍会崩溃。

    我不知道如何对此进行更深入的调查。 我还可以检查什么? 我的端口可能不正确? 您(或某人)是否有一个可供我比较的 HDK RM57端口?  

    此致、

    Julio