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.

[参考译文] J721EXSOMXEVM:J721E:通过远程处理器停止/启动后、UART 中断在 MCU3_0/MCU3_1 上无法正常工作

Guru**** 2941480 points

Other Parts Discussed in Thread: J721EXSOMXEVM

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1653113/j721exsomxevm-j721e-uart-interrupts-not-working-on-mcu3_0-mcu3_1-after-stop-start-via-remoteproc

器件型号: J721EXSOMXEVM

你好。

在 R5F 内核 MCU3_0 和 MCU3_1 上启动应用程序后、我遇到 UART 中断根本无法正常工作的问题。 相同的应用程序可在 MCU2_0 和 MCU2_1 上正常运行。 支持 TT 的几个信息:

-首次运行时应用程序和 UART 工作正常。
-使用的是 WKUP_UART0。
-按照示例正确实施通过 RPMessage 正常关闭。
-我已经重写了 UART 驱动程序,因为 SDK 中的驱动程序不适合我们的用例。
-电路板初始化按照以下代码完成:

void BOARD_init(void)
{

    Sciclient_ConfigPrms_t config;

    Sciclient_configPrmsInit(&config);
    Sciclient_init(&config);

    /* Disable clocks first to ensure a clean state in case the board is coming from a reset */
    Board_moduleClockDeinitMcu();
    Board_moduleClockDeinitMain();

    Board_moduleClockInitMcu();
    Board_moduleClockInitMain();

    Ipc_loadResourceTable((void*)&ti_ipc_remoteproc_ResourceTable);

    OS_init();
}

我是否应该考虑任何特定要点、以便研究为什么问题仅发生在内核 MCU3_0 和 MCU3_1 上? 您是否需要更多信息来帮助我解决此问题?

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

    尊敬的 Anderson:

    我需要有关您所使用的 SDK 及其版本的详细信息。

    此致、

    Vinit

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

    您好、

    我正在使用 PSDK  11.01.00.17。

    在我可以找出问题的平均时间。 在 MCU3_0 和 MCU3_1 上、  在远程处理停止/启动后、在 UART 初始化中调用 configSockIntrPath () 返回错误。 而 MCU2_0/2_1 上不会发生这种情况。

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

    尊敬的 Anderson:

    如果可能、您可以共享驱动程序代码、或者至少共享处理 close/deinit 的代码片段。

    这似乎是仅关闭的问题、这就是为什么当您再次重新启动时它会失败的原因。 因此、关闭可能不正确。

      在 UART 初始化中调用 configSocIntrPath ()

    此错误是在名为 uart_open_v1() 的函数(或自定义驱动程序代码中的任何等效函数)中发现的。

    另外、使用 MCU2_0/MCU2_1 时、使用的 UART 实例是什么?

    此致、

    Vinit

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

    您好、Vinit。 请 在消息末尾找到我们的 UART 驱动程序打开/关闭功能。 此外、请注意以下重要事项:

    • 在 MCU2_0/MCU2_1 上运行时、我不需要关闭驱动器。 即使我跳过呼叫关闭、停止/启动也可以正常工作。
    • 我对 UART5 运行测试、行为相同。 我想排除 WKUP_UART0 作为问题。
    • 昨天、我花了一些时间来深入调试这个问题、并设法找到了至少看起来是根本原因的问题。 请您看一下我在下面找到的详细信息并对此进行评论。

    这是直到我发现不一致为止的整个路径:

    configSocIntrPath ()-> Sciclient_rmIrqRelease ()-> Sciclient_rmClearInterruptRoute ()-> Sciclient_rmIrqGetRoute ()-> Sciclient_rmIrqGetNode ()

    文件 ti\drv\sciclient\sciclient\sciclient\sciclient_rm_irq.c 中的 Sciclient_rmIrqGetNode() src 分支 2196 行: Sciclient_rmIrqGetNode(Cfg->s_id、&cur_n)
    此时、在 MCU3_0 上运行时、cfg->s_id = 287
    Sciclient_rmIrqGetNode 内部、将指向**found_n的指针分配给“gRmIrqTree“内的匹配结构。 匹配的结构为: tisci_IRQ_WKUP_UART0。 匹配结构如下所示:

    const struct Sciclient_rmIrqIf *const tisc_if_WKUP_UART0[]={
      &WKUP_UART0_USART_IRQ_0_0_TO_R5FSS0_INTROUTER0_IN_159_159、
      &WKUP_UART0_USART_IRQ_0_0_TO_R5FSS1_INTROUTER0_IN_159_159、
    };
    静态常量结构 Sciclient_rmIrqNode tisc_irq_WKUP_UART0 ={
      .id = TISCI_WKUP_UART0、
      .n_if = 2、
      .p_if =&tisc_if_WKUP_UART0[0]、
    };

    我们可以看到、 .p_if 被硬编码为 &tisc_if_WKUP_UART0[0]、其中保存了 R5FSS0 集群结构的地址。 我对 它的工作原理感到困惑。 在某种程度上、首次运行应用程序时、UART IRQ 被正确配置、但在尝试停止和/或启动时、它不再起作用、通过查看 tisci_IRQ_WKUP_UART0 结构、它似乎根本不起作用。 正确的 IRQ 路径应指向第二个 R5 集群的结构“WKUP_UART0_USAR_IRQ_0_0_TO_R5FSS1_INTROUTER0_IN_159_159“、它位于“tisci_if_WKUP_UART0“中的索引 1。 我在这一假设中是正确的吗? 因为如果我 将.p_if 硬编码为[1]、则问题在 MCU3_0 上得到解决。 这对我来说看起来很奇怪、您能说明它是如何工作的吗? 硬编码阵列项目第一次如何工作? 是否还有其他一些代码可以调整我丢失的索引?


    UART drv 打开/关闭:

    static UART_Handle openUart(uint32_t uartInstance, const UART_Params *pParams)
    {
        UART_Handle hUart = (UART_Handle)&(UART_config[uartInstance]);
        UART_V1_Object *pObject = (UART_V1_Object*)hUart->object;
        UART_HwAttrs const *pHwAttrs = (UART_HwAttrs const*)hUart->hwAttrs;
    
        /* Disbale HW interrupts to check if UART is already open */
        uintptr_t intState = UART_osalHardwareIntDisable();
    
        if (1 == pObject->isOpen)
        {
            UART_osalHardwareIntRestore(intState);
            return NULL;
        }
    
        pObject->isOpen = 1;
        UART_osalHardwareIntRestore(intState);
    
        /* Set UART object variables to defaults */
        pObject->params = *pParams;
        pObject->writeBuf = NULL;
        pObject->readBuf = NULL;
        pObject->writeCount = 0u;
        pObject->readCount = 0u;
        pObject->writeSize = 0u;
        pObject->readSize = 0u;
        pObject->writeCR = 0u;
        pObject->readTrans = NULL;
        pObject->writeTrans = NULL;
    
        /* Clean start */
        int32_t disable = pHwAttrs->configSocIntrPath((const void *)pHwAttrs, false);
        UARTIntDisable(pHwAttrs->baseAddr, UART_INT_RHR_CTI | UART_INT_THR | UART_INT_LINE_STAT);
        UARTInt2Disable(pHwAttrs->baseAddr, UART_INT2_TX_EMPTY | UART_INT2_RX_EMPTY);
        UART_osalHardwareIntDestruct(pObject->hwi, pHwAttrs->eventId);
    
        /* Setup the interrupts router path via DMSC */
        int32_t enable = pHwAttrs->configSocIntrPath((const void*)pHwAttrs, true);
    
        /* Interrupts setup */
        OsalRegisterIntrParams_t interruptRegParams;
    
        Osal_RegisterInterrupt_initParams(&interruptRegParams);
        interruptRegParams.corepacConfig.arg = (uintptr_t)hUart;
        interruptRegParams.corepacConfig.name = NULL;
        interruptRegParams.corepacConfig.isrRoutine = uartIsr;
        /** @TODO: Check if this interrupt priority can be improved */
        interruptRegParams.corepacConfig.priority = 0x08u; /**< UART interrupt priority as suggested by TI's PDK drivers for R5F cores */
        interruptRegParams.corepacConfig.corepacEventNum = pHwAttrs->eventId;
        interruptRegParams.corepacConfig.intVecNum = pHwAttrs->intNum;
    
        UART_osalRegisterInterrupt(&interruptRegParams, &(pObject->hwi));
        if (NULL == pObject->hwi)
        {
            return NULL;
        }
    
        uint32_t fifoRegValue = UART_FIFO_CONFIG(UART_TRIG_LVL_GRANULARITY_4, UART_TRIG_LVL_GRANULARITY_4,
                                                 UART_FCR_TX_TRIG_LVL_56, UART_FCR_RX_TRIG_LVL_8, 1u, 1u,
                                                 UART_DMA_EN_PATH_FCR, UART_DMA_MODE_0_ENABLE);
        UARTFIFOConfig(pHwAttrs->baseAddr, fifoRegValue);
    
        /* Compute the divisor value for params.baudRate */
        uint32_t divisorValue = UARTDivisorValCompute(pHwAttrs->frequency, pObject->params.baudRate, pHwAttrs->operMode,
                                                      UART_MIR_OVERSAMPLING_RATE_42);
        /* Configure baud rate settings */
        UARTDivisorLatchWrite(pHwAttrs->baseAddr, divisorValue);
    
        /* Configure UART line characteristics */
        uint32_t wLenStbFlag;
        uint32_t parityType = getParityRegValue(pObject->params.parityType);
        getWLenStbFlag(pObject->params.dataLength, pObject->params.stopBits, &wLenStbFlag);
        UARTLineCharacConfig(pHwAttrs->baseAddr, wLenStbFlag, parityType);
    
        /* Disable write access to Divisor Latches. */
        UARTDivisorLatchDisable(pHwAttrs->baseAddr);
    
        /* Set operating mode */
        UARTOperatingModeSelect(pHwAttrs->baseAddr, pHwAttrs->operMode);
    
        /** @TODO: Add RX timeout control */
    
        /* Disable unused settings */
        UARTBreakCtl(pHwAttrs->baseAddr, UART_BREAK_COND_DISABLE);
        UARTLoopbackModeControl(pHwAttrs->baseAddr, UART_LOOPBACK_MODE_DISABLE);
        UARTDirEnControl(pHwAttrs->baseAddr, UART_DIRECTION_CONTROL_DISABLE);
        UARTHardwareFlowCtrlOptSet(pHwAttrs->baseAddr, UART_NO_HARDWARE_FLOW_CONTROL);
    
        /* Enable RX interrupts */
        UARTIntEnable(pHwAttrs->baseAddr, UART_INT_RHR_CTI | UART_INT_LINE_STAT);
    
        return hUart;
    }
    
    static void closeUart(UART_Handle handle)
    {
        UART_V1_Object *pObject = (UART_V1_Object*)handle->object;
        UART_HwAttrs const *pHwAttrs = (UART_HwAttrs const *)handle->hwAttrs;
        uintptr_t interruptsState;
    
        /* Disable preemption while checking if the UART is open. */
        interruptsState = UART_osalHardwareIntDisable();
    
        if (0 == pObject->isOpen)
        {
            UART_osalHardwareIntRestore(interruptsState);
            return;
        }
    
        UART_osalHardwareIntRestore(interruptsState);
    
        /* Wait until FIFO is empty */
        while (UARTIsTransmitterEmpty(pHwAttrs->baseAddr) == 0)
    
        /* Disable UART and interrupts. */
        UARTIntDisable(pHwAttrs->baseAddr, UART_INT_RHR_CTI | UART_INT_THR | UART_INT_LINE_STAT);
        UARTInt2Disable(pHwAttrs->baseAddr, UART_INT2_TX_EMPTY);
        UARTOperatingModeSelect(pHwAttrs->baseAddr, UART_DISABLED_MODE);
        pHwAttrs->configSocIntrPath((const void *)pHwAttrs, false);
        UART_osalHardwareIntDestruct(pObject->hwi, pHwAttrs->eventId);
    
        pObject->isOpen = 0;
    }

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

    尊敬的 Anderson:

    感谢这次调试。 我明白了。

    在得出任何结论之前、我想用我们现有的驱动器在我们这边重现这一点。

    您能告诉我您遵循了哪些步骤吗? 此外、如何停止和启动应用程序? 您认为重现此问题需要哪些其他详细信息?

    此致、

    Vinit

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

    您好、



    因此,为了得到这个结果,我从正常关闭例程调用 uartClose (),并在  close 函数的 configSocIntrPath () 处添加一个断点。 该应用在 FreeRTOS 上运行。

    开始: echo start > /sys/class/remoteproc/remoteprocX/state
    要停止: echo stop > /sys/class/remoteproc/remoteprocX/state

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

    尊敬的 Anderson:

    我需要更多步骤、这些步骤仅用于启动和停止固件。

    我的意思是什么引导介质,什么应用程序,如何引导 Linux 等.. 我需要在我们这边重现您所执行步骤的所有详细信息。

    此致、

    Vinit

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

    好的、我明白了。 我在两个不同的硬件上测试了场景、结果相同:

    1.J721EXSOMXEVM :microSD 卡上的 Linux FS。 Linux 从 U-Boot 引导->引导 期间 R5 上不加载应用程序-> 通过 Remoteproc 手动加载应用程序。
    2. 我们公司的自定义硬件(严重基于 J721EXSOMXEVM) :U-Boot 存储在 SerialNOR 闪存中-> Linux FS 存储在 eMMC 中-> Linux 启动 会在所有 R5 内核上加载虚拟应用程序->通过 remoteproc 停止虚拟应用程序->启动我的应用程序。

    这有什么用吗? 如果您需要更多信息、请告诉我。

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

    尊敬的 Anderson:

    我  在应用程序中只使用 configSocIntrPath(,BFALSE)和 configSocIntrPath(,BTRUE)就重现了这个问题。 如果我们将.p_if  从&tisci_if_WKUP_UART0[0]更改为&tisci_if_WKUP_UART0[1]、它的确有效、但这会导致 MCU2_0 出现错误。

    因此、我将与 Dev 团队交谈、并尝试通过一些具体的解决方案来解决此问题。

    我将对此进行更新。

    此致、

    Vinit

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

    尊敬的 Anderson:

    同时,我为您提供了进行此工作的解决方案,我已更新内部开发团队以验证以下解决方案 — 如果这是一个实际的错误,需要修复,则将在下一个版本中修复。

    这解决了我们方面目前的问题。

    我强调了位置、需要添加代码。

    因此,我们认为问题是关于 API 调用 Sciclient_rmIrqGetRoute (),  在这个函数中,当它没有找到通过 IR0 配置到 mcu3_0 的路径时,搜索循环被中断,然后它不会进入 IR1 ,因为它会中断 for 循环。

    因此,第一次这是因为它是一个新的开始,当你停止应用程序,它用于释放路径,但由于这个错误,它无法删除,最终当你再次启动应用程序时,资源已被占用,它在配置路径时会收到错误。

    当您将.p_if 更改为&tisc_if_WKUP_UART0[1]时、它是有效的、因为它只能在第一次搜索中释放中断路径、因为第一个接口是 Ir1、并且仅在第一次搜索中它就获得了通过 IR1 到 mcu3_0 的路由。 这是有效的。 但这未来会导致 MCU2_0 出现问题、因为第二个接口不是 IR0。

    因此,当我们将图片中给出的代码添加到正确的位置时,如果第一个接口没有成功,它不会中断搜索循环,它也会用于以后的接口。 因此它可以正确解决问题。

    此致、

    Vinit

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

    感谢建议的修补程序修复了该问题。

     如果可能、请使此主题保持最新、以了解有关此问题的更多信息(修复程序,版本等)。

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

    尊敬的 Anderson:

    感谢建议的修补程序解决了这个问题。

    很高兴这个问题解决了。

    请 尽可能更新此主题、以了解有关此问题的更多信息(修复,发布等)。

    没问题。

    此致、

    Vinit