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.

[参考译文] RM44L520:通过 FIQ 的 SCI RX 中断导致预取中止

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025217/rm44l520-sci-rx-interrupt-via-fiq-causes-prefetch-abort

器件型号:RM44L520
主题中讨论的其他器件:HALCOGENSEGGER

大家好!

我们的应用需要降低 SCI RX 中断的中断延迟。 因此、我尝试通过 FIQ 进行路由、FIQ 在调试编译中部分起作用、但在版本编译中不起作用。 据我所见、在调试构建中、处理器始终在0x0000000C 停止、这向我说明了一个指令预取中止。

我执行了以下操作来找出根本原因:

  • 项目是使用 HALCoGen 4.7.01设计的、并使用带有 MPU 的 FreeRTOS
  • 该工程是使用 CCS 10.2.0.9和 TI 编译器 v20.2.1.LTS 编译的
  • 如果所有 SCI 中断均通过 IRQ 处理、则代码运行良好
  • 将 RX 中断从低电平更改为高电平(在 HALCoGen 的 SCI 页面上)、启用 VIM 上的新通道并将其分配给 FIQ
  • HALCoGen 现在在 sci.c 中生成一个带有"#pragma INTERRUPT (linHighLevelInterrupt、FIQ)"修饰的中断处理程序
  • 在 RAM 设置中、我为 IRQ 和 FIQ 堆栈长度分配了0x200
  • 如果我在 FIQ 处理程序(在 switch (VEC)语句中、除了"default"子句之外、不执行任何操作、代码仍然会崩溃
  • 使用一些调试引脚、我感觉处理器永远不会达到 sci.c 中的 FIQ 处理程序函数
  • 如果我让代码从 IRQ 电平上的 SCI RX 开始、并在其他 SCI 中断之一中将其切换至 FIQ、则代码在切换后崩溃。

是否可以、添加这个"#paragma interrupt (..、FIQ)"来获得一个有效的 FIQ 处理程序就可以完成更多的工作? 我在这里还缺少其他东西吗? 我们非常感谢您提供的任何提示。

1月

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="155627" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025217/rm44l520-sci-rx-interrupt-via-fiq-causes-prefetch-abort "]部分在调试构建中工作的 FIQ

    在调试构建中、代码是否在中断发生时跳转 FIQ 处理程序?

    是否通过清除 CPSR 寄存器的 F 位来启用 FIQ?

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

    您好、QJ Wang!

    非常感谢您的回复!

    在调试构建中、代码几乎按预期工作。 FIQ 处理程序也会被调用、SCI 通知也会被调用。 一段时间后、在未知条件下、代码停止在0x0000000C。 这似乎与发布版本中的签名相同。当代码停止时(实际上是 HALCoGen 生成的一个死锁、它会分支到自身)、Abort_Registers -> R14_ABT 为0x10、Cp15 -> CP15_DATA_FAULT_STATUS 为0xD、CP15_instruction_FAULT_STATUS 0x10、CP15_AULT_ADDRESS_0x0000_ADDRESS 0x15、CP15_ADDRESS_AULT_ADDRESS 0x000_ADDRESS_0_ADDRESS 0x15、CP15_AULT_ADDRESS_AULT_ADDRESS_0_ADDRESS 0x15、CP15_ADDRESS_0_ R13_FIQ 仍然指向 HALCoGen 中配置的0x08000C00。

    在版本构建中、我无法看到对 SCI FIQ 处理程序的单次调用(我在处理程序中放置了调试 IO、它从未更改其级别)。

    通过比较调试 IO (在 FIQ 处理程序中)和触发 FIQ 的外部信号、我认为代码在尝试执行 FIQ 时会消失。

    为了确保在我的设置中不连接它、我将使用 SPNA190中的修改后的引导加载程序代码(用于 Hercules RM48x MCU 的 USART 引导加载程序)。 复位矢量表不变:主应用程序中的复位分支进入引导加载程序、未定义、软件以及两个中止中断分支。 IRQ 和 FIQ 都使用"寄存器矢量中断"架构。 主应用基于 HALCoGens RM44L520APE_FreeRTOS。

    1月

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

    您好、Jan、

    DFSR 的值(0xD) 表示问题是由存储器访问权限引起的。 MPU 决定所有内存访问的访问权限。

    我不明白为什么代码在调试模式下工作、但在释放模式下失败。  

    BTW、从调试构建切换到发布构建时、需要重新定义项目属性。 是否在您的版本中构建了代码优化?  

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

    您好、QJ Wang!

    访问许可、这是一个好消息、现在我"只"需要知道在哪里以及为什么...

    我的调试构建没有用于简化调试的优化。 版本编译具有级别4 (整个程序优化)。

    我的问题似乎更奇怪:今天我尝试添加预取处理程序来检查在外部信号方面发生崩溃的位置。 在调试构建中、不执行预取处理程序。 MCU 在0xc 停止、在我执行单步执行一条汇编器指令之前不会继续。 我还注意到、在一半的时间里、0x0处的矢量部分仅显示了存储器窗口中所有矢量的0xd0d0d0d0d0d0。 在该状态下、我甚至不能单步执行。 (我使用 Segger J-Link 作为 JTAG 探针、不确定是否存在故障、更新驱动程序、无变化) BMMCR 始终为0xA。 我的闪存设置也应该正常、对于180MHz HCLK、FRDCNTL = 0x311。

    重复一遍:我的代码动态地将 SCI RX 中断从 IRQ 切换到 FIQ 级别。 如果 RX 中断完全在 IRQ 中处理、那么一切都很正常。 如果处于 FIQ、则会随机发生上述问题。 除了切换中断级别之外、代码的其他部分也不会更改。

    接收器本身基本上会等待一个中断。 中断在 IRQ 级别执行、将之前的数据写入 FreeRTOS 队列并从第二个队列请求内存。 (某些 FreeRTOS 功能可从 IRQ 级别安全调用。 我假设永远不能从 FIQ 级别安全调用它们、因为 FIQ 不能被阻止。) 指向这个内存的指针作为静态存储在 IRQ 处理程序中。 然后、RX 中断在 FIQ 级别调用相同的处理程序、并将新数据写入存储器。 我假定(并由调试 IO 验证)中断在第一个 RX 中断之前已经被处理好。 因此、我假设、如果 RX 中断在 FIQ 处执行、则存储器指针有效。 我添加了指针不应为 NULL 的基本验证。 我还假设 RM44是一个32位计算机、并且在静态变量中存储我的内存指针 是原子的。

    1月

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="155627" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025217/rm44l520-sci-rx-interrupt-via-fiq-causes-prefetch-abort/3795232 #3795232"]只需重复一遍:我的代码会将 SCI RX 中断从 IRQ 动态切换至 FIQ 级别。

    如何动态地将中断从 IRQ 切换到 FIQ?

    #pragma INTERRUPT (LIN1HighLevelInterrupt、FIQ) ---- 电流

    #pragma INTERRUPT (LIN1HighLevelInterrupt、IRQ) ---- 用于 IRQ

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

    代码优化可能会影响代码执行。 您是否会尝试不进行代码优化?

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

    不完全是这样。 我将使用从 SCI 到 VIM 的两条中断线作为

    #pragma INTERRUPT (LIN1HighLevelInterrupt、FIQ) ---- 电流

    #pragma INTERRUPT (lin1LowLevelInterrupt、IRQ) ---- 用于 IRQ

    要更改 RX 中断优先级、请使用 SCI 的中断级别寄存器。 在这两个函数中、我调用相同的处理程序函数(它不调用 SCI_RX_INT 路径中的任何 FreeRTOS 函数)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="45190" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025217/rm44l520-sci-rx-interrupt-via-fiq-causes-prefetch-abort/3795616 #3795616")代码优化可能会影响代码执行。 您是否会在没有代码优化的情况下尝试?

    是的、这很简单。

     具有"整个程序优化"的调试编译(如版本编译)的行为与未进行优化的情况相同:它在数据帧中间经过一段随机时间后终止、该数据帧中已经接收了一些字节。

    没有优化的 Release 编译的行为与调试编译相同:它们会在随机时间后死亡、与调试编译一样、我的预取处理程序不会执行(即使没有连接调试器)。

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

    您好、Jan、

    我不熟悉 FreeRTOS。 进入临界区时、FreeRTOS 是否禁用了 FIQ?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="45190" url="~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025217/rm44l520-sci-rx-interrupt-via-fiq-causes-prefetch-abort/3796548 #3796548">我不熟悉 FreeRTOS。 进入临界区时、FreeRTOS 是否禁用了 FIQ?  [/报价]

    根据 TRM (15.2.2节中的注释)、FIQ 是 Cortex-R4F 中的一个不可屏蔽中断、因此它不能被禁用。 我非常小心、不要调用任何肯定会破坏内核的 FreeRTOS 函数。

    我仅将接收到的数据写入先前分配的存储器。 我认为,这应该是"允许的"。 Cortex-R4中是否有任何非原子指令、或者如果被 FIQ 中断、可能会损坏?

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

    今天我进行了另一项测试:除了读取接收数据缓冲区以确认中断之外、我几乎从 FIQ 处理程序中删除了所有内容。 这是反汇编:

     953          scilinREG->RD;
              linHighLevelInterrupt():
    00042460:   E59F802C            ldr        r8, [pc, #0x2c]
    00042464:   E5988000            ldr        r8, [r8]
    1033      }
    00042468:   E25EF004            subs       pc, r14, #4
    [...]
              $C$CON52:
    00042494:   FFF7E434           .word       0xfff7e434
    

    如您所见、它加载寄存器地址并对其进行读取。 知道 R8在 FIQ 中分组、无需任何序言或结语。 此外、不涉及堆栈操作、因此 FIQ 堆栈设置不重要。

    但是、这个代码也会在一段时间后以相同的签名消失:CPU 在0xc 停止、并且不执行连接在该处的预取处理程序。

    我能俯瞰这里的风景吗?

    闻起来越来越像硅虫。 谁会解决这个问题?

    1月  

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

    你是对的。  Cortex-R4F 中的 FIQ 是不可屏蔽的。  

    您看到的预取中止可能是由于代码或部分代码缺少 ECC。 您是否会尝试使用链接器 cmd 文件生成 ECC? 因此、您可以生成 ECC、包括空穴。  

    以下是 RM44Lx 器件的链接器 cmd 文件示例。 它将为整个闪存生成 ECC。

    /*------------------ *
    /*用户代码开始(0)*/
    /*用户代码结束*/


    /*------------------ *
    /*链接器设置*/

    --retain="*(.intvecs)"

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

    /*------------------ *
    /*内存映射*/

    存储器

    引导程序(X):origin=0x00000000 length=0x00000020 vfill =0xFFFF
    FLASH0 (RX):origin=0x00000020 length=0x000BFFE0 vfill = 0xffffffff
    SRAM (RW):origin=0x08002000 length=0x0001EB00
    栈(RW):origin=0x08000000 length=0x00001500
    /*用户代码开始(2)*/
    #if 1.
    ECC_VEC (R):origin=(0xf0400000 +(start (vectors)>> 3))
    length=(size (vectors)>> 3)
    ecc={algoL2R4F021、input_range=vectors}

    ECC_FLA0 (R):origin=(0xf0400000 +(开始(FLASH0)>> 3))
    length=(size (FLASH0)>> 3)
    ecc={algoL2R4F021、input_range=FLASH0}
    #endif
    /*用户代码结束*/

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

    algoL2R4F021:address_mask = 0xfffffff8 //地址位31:3 */
    汉明_mask = R4 /*使用掩码中的 R4/R5构建*/
    奇偶校验掩码= 0x0c //设置哪些 ECC 位是偶校验和奇校验*/
    镜像= F021 //* RM57Lx 和 TMS570LCx 在 F021中编译

    /*用户代码结束*/

    /*------------------ *
    /*段配置*/


    部分

    .intvecs:{}>向量

    .text:{}> FLASH0
    .const:{}>FLASH0
    .cinit:{}> FLASH0
    .pinit:{}> FLASH0
    .data :{}> SRAM
    .bss:{}> SRAM
    .sysmem:{}>SRAM

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

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

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

    如果您在不使用 FreeRTOS 的情况下运行代码(SCI RX 和 FIQ)、代码是否会生成相同的异常? 您是否会通过注释掉 "vTaskStartScheduler()"来进行快速测试?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="45190" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025217/rm44l520-sci-rx-interrupt-via-fiq-causes-prefetch-abort/3798046 #3798046"]是否尝试使用链接器 cmd 文件生成 ECC?

    很抱歉、这不会改变情况。 一段时间后、MCU 仍在0xc 停止。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="45190" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1025217/rm44l520-sci-rx-interrupt-via-fiq-causes-prefetch-abort/3798048 #3798048"]如果您在不使用 FreeRTOS 的情况下运行代码(具有 FIQ 的 SCI RX),代码是否会生成相同的异常?

    不、 我在过去半小时内没有看到例外情况。 通常在几秒钟后发生。

    我尝试逐个禁用/重新启用所有任务、似乎异常是由上下文切换触发的:如果启用任务、每20ms 读取一些 IO、无论任务是否实际读取 IO、我都可以再次看到异常。 这与之前的观察结果是同步的,调用操作系统函数(xQueueSend(),它可能而且通常会触发上下文切换)使异常更有可能被触发。

    如果我设置一个只延迟1ms 的任务、我可以轻松地触发异常。 我的外部信号每秒生成约5k 个 FIQ 我正在使用支持 MPU 的 FreeRTOS。

    似乎没有支持 MPU 的 R4F 官方 FreeRTOS 端口。 至少我在 GitHub 上没有找到它。 您有什么提示要继续吗?

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

    我做了更多的调查、并将 Cortex-R4F 的特定于端口的代码与 Cortex-M4的官方代码进行了比较。 看起来、HalCoGen 为 OS_portasm.asm 中的 portRESTORE_CONTEXT 提供代码、但在重新配置 MPU 之前未能禁用 MPU。 我复制了同一文件中的 prvMpuDisable 和 prvMpuEnable 代码、但未再次看到异常。 即使重新启用了我的所有代码并且恢复了链接器脚本中的 ECC 生成、我仍然看不到异常。

    如何就此问题提交错误报告?