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.

[参考译文] AM6442:Endat2.2:Loadshare 编码器硬件连接

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

https://e2e.ti.com/support/motor-drivers-group/motor-drivers/f/motor-drivers-forum/1593875/am6442-endat2-2-loadshare-encoder-hardware-connectivity

器件型号: AM6442

尊敬的专家

使用 endat 诊断多通道负载共享、 我注意到以下行为

image.png

一旦我配置 syscofing 使用通道 0 , 1. 驱动程序层似乎期望两个通道都连接到发件人。

 

我收到以下错误

EnDat 固件 :1.0.4(发行版)


 已选择通道 0 1


错误:EnDat 初始化失败-

    无法在通道中检测到编码器   
由于固件初始化失败而退出 endat_main

 

 

当中只有 1 个通道连接到实际编码器时。

 

 

我是否可以通过任何方式配置/修改驱动程序层以转换到下面的用例

1-我有 2 个编码器通道、通道 0 和通道 1

2-并非所有通道都必须连接到物理编码器。 编码器控制器应能够检测已连接的通道

3 - I 应该能够基于连接的编码器通道继续操作。 例如、如果仅连接了通道 1、 我应该能够读取通道 1 上的位置

 

如果可以、请告诉我

 

谢谢

Alan I

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

    您好 Alan、

    当前设计要求在初始化期间检测所有选定的通道。 如果任何选定通道无法初始化、驱动程序将返回错误、应用程序将无法运行。

    它支持、并且我们尚未测试如果仅存在所选通道之一、则必须继续应用的工作流程。 当前的应用流程为:

    • 设置信道掩码
    • 加载固件
    • 等待检测所有通道(固件加载函数内部的 endat_wait_initialization)
    • 如果在超时内未检测到任何选定通道、初始化将失败

    您可以进行的建议更改

    • 修改 endat_wait_initialization、以便在检测到所需的通道(例如通道 1)时返回成功结果。
    • 之后、再次更新信道掩码并调用 endat_config_multi_channel_mask、以便驱动程序仅针对检测到的信道运行。

    您能否分享“部分“通道运行的预期用例?

    稍作澄清将有助于我们决定是否添加 SDK 支持、并确定理想方法。

    BR、

    Achala Ram

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

    嗨、Achala

    感谢您的建议,我设法实现了部分成功的建议。

    使用案例

    1 — 构建具有 2 个物理编码器通道的系统

    2-用户可以将一个或两个通道连接到编码器通道、或者不将一个通道连接到编码器通道

      可能的组合

      ch0:已连接 ch1:未连接 (NC)

      ch0:已连接 ch1:已连接

      ch0:NC ch1 :已连接

       ch0: NC ch1 :nc.

    3-系统将需要自动检测 带编码器连接的通道、并 根据连接的编码器继续运行。

    从固件的角度来看、我们将拥有一个能够处理上述所有场景的单个固件

    4-我需要在 Endat、BISS 和 HDSL 协议上启用上述功能

    当前状态

    1 — 我将   endat_wait_initialization 修改为 endat_wait_initialization  、其中返回值已更改为以下值

    0 — 无连接

    1 — 仅连接 CH0

    2 — 仅连接 CH1

    3 - CH0 和 CH1 均已连接

    似乎较低层能够处理案例 1 和 3、但当 CH0 未连接到物理编码器时、必须在 CH1 上检测编码器(案例 2)。

    如果您需要更多信息、请告诉我。

    Alan I

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

    e2e.ti.com/.../endat_5F00_diagnostic_5F00_multi_5F00_channel_5F00_load_5F00_share_5F00_am243x_2D00_evm_5F00_r5fss0_2D00_0_5F00_freertos_5F00_ti_2D00_arm_2D00_clang.zip

    附件是我修改后的代码。 它能够检测并继续检测 CH0 和 CH1 是否已连接或仅连接 CH0。 它无法检测是否仅连接 CH1

    谢谢

    Alan I

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

    嗨、Achala

    我已经通过检查 numClkPulse 来检测对 CH0 或 CH 的编码

          情形 3       /*通道 0 或 1 已连接*/

              if (pruss_xchg->ch[0].numClkPulse != 0 )
                 返回 1

              if (pruss_xchg->ch[1].numClkPulse != 0 )
                 返回 2


              休息
    我的下一个问题是在 endat_config_multi_channel_mask 上启动的
    当 gEndat_multi_ch_MASK = 2 时、Endat 诊断现在会卡住
    如果您对解决此问题有任何想法、请告诉我
    谢谢
    Alan I
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Alan、

    两个内核之间存在相关性、这可能会导致出现以下问题:

    并行运行多个编码器通道时、固件相关性至关重要。 具体情况如下:

    1. 对于所有 3 个通道、都有一个全局配置、需要由一个内核或一个通道完成

    2. 由于这种共享配置、两个固件实例都需要同步运行。 固件包含同步逻辑、以保持两个通道并行运行。

    3. 当一个编码器断开连接时、连接的通道将进入等待状态、期望另一个编码器响应。 这可能会导致固件卡住。

    建议:  要解决此问题、请 使用不同的配置运行固件加载功能两次。

    1. 在调用通道编号之前、请将通道编号作为参数提供给固件加载函数。
    2. 添加 if-else 条件以启用正确的内核并加载当前通道的固件。
    3. 在在固件加载函数内调用 endat_wait_initialization 之前、更新通道掩码设置。

    此方法将确保两个通道按顺序初始化、一旦固件加载和初始化完成、您可以使用更新的掩码运行连接通道的应用。

    这样可以解决您遇到的通信问题。

    此致、

    Achala Ram

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

    嗨、Achala  

    感谢您对使用正确配置重新加载固件的建议。

    我目前在重新加载步骤后遇到 endat 固件问题。  重新加载后、endat 固件无法持续检测编码器。

    我必须多次重新加载 固件才能再次检测编码器。 在大多数情况下、重载从 1 到 10 不等。 在固件重新加载中是否有建议的步骤可确保重新加载后编码器固件功能一致。

    我当前的重新加载步骤

    -->

    endat_pre_init();

    icssClk = ICSS_PRU_CORE_Clock;

    /*3 通道串行时钟配置*/
    endat_clk_config.PRU_CLOCK = icssClk;
    endat_clk_config.PRU_UART_CLOCK = ENDAT_INPUT_CLOCK_UART_FREQUENCY;
    endat_clk_config.rx_clock_source = CONFIG_ENDAT0_TX_RX_FIFO_CLOCK_SOURCE;
    endat_clk_config.tx_clock_source = CONFIG_ENDAT0_TX_RX_FIFO_CLOCK_SOURCE;



    #if (PRUICSS_SLICEx == 1)
    priv = endat_init (struct endat_pruss_xchg *)((PRUICSS_HwAttrs *)(
    gPruIcssXHandle->hwAttrs))->pru1DramBase、&gEndatChInfo、gEndatChInfoGlobalAddr、pruicss_cfg、pruicss_IEP PRUICSS_SLICEx、&endat_clk_config);

    #else
    priv = endat_init (struct endat_pruss_xchg *)((PRUICSS_HwAttrs *)(
    gPruIcssXHandle->hwAttrs))->pru0DramBase、&gEndatChInfo、gEndatChInfoGlobalAddr、pruicss_cfg、pruicss_IEP PRUICSS_SLICEx、&endat_clk_config);
    #endif

    endat_config_multi_channel_mask (priv、gEndat_multi_ch_MASK、gEndat_is_load_share_mode);
    endat_config_host_trigger (priv);

    // powercycle_encoder ();

    /*根据 ICSSG 频率配置延迟*/
    /*计数=((所需的延迟* icssClk)/1000)*/
    priv->pruss_xchg->endat_delay_125ns =((icssClk*125)/1000000);
    priv->pruss_xchg->endat_delay_51us =((icssClk*51)/1000000 );
    priv->pruss_xchg->endat_delay_5us =((icssClk*5)/1000000 );
    priv->pruss_xchg->endat_delay_1ms =((icssClk/1000)* 1);
    priv->pruss_xchg->endat_delay_2ms =((icssClk/1000)* 2);
    priv->pruss_xchg->endat_delay_12ms =((icssClk/1000)* 12);
    priv->pruss_xchg->endat_delay_50ms =((icssClk/1000)* 50);
    priv->pruss_xchg->endat_delay_380ms =((icssClk/1000)* 380);
    priv->pruss_xchg->endat_delay_900ms =((icssClk/1000)* 900);
    priv->pruss_xchg->icssg_clk = icssClk;


    gI2 = endat_pruicss_load_run_fw (priv);

    -->

    谢谢你

    Alan I

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

    您好 Alan、

    您能分享完整的代码吗? 此外、在第二次加载固件之前、请确保正在更新 gEndat_multi_ch_MASK。

    谢谢、此致

    Achala Ram  

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

    Alan

    我必须多次重新加载 固件才能再次检测编码器。 在大多数情况下、它在 1 到 10 之间变化重新加载

    此外、您是否详细介绍了未检测到编码器时会发生什么故障? TX 不工作或 RX 不工作? 或任何其他观察?

    此致

    Dhaval

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

    您好 Dhaval

    我 回到了最基本的 endat_diagnostic_single_channel ,编码器在 CH0 上执行固件重新加载.  我特意强制使用 相同的 编码器配置重新加载(继续重新加载,直到通过)while 循环内 endat_pruicss_load_run_fw 上的重新加载始终失败

    ...
    .
      i = endat_pruicss_load_run_fw (priv);

      if (i < 0)
      {
        DebugP_log(“\rexit %s、由于固件初始化失败\n“、__func__);
        返回


      }
      i =–1
      whid( i ==–1 ){

       DebugP_log(“\rrestart PRU 代码-\n\n“)
       endat_pre_init()

       icssClk = ICSS_PRU_CORE_Clock;

        /*3 通道串行时钟配置*/
        endat_clk_config.PRU_CLOCK = icssClk;
        endat_clk_config.PRU_UART_CLOCK = ENDAT_INPUT_CLOCK_UART_FREQUENCY;
        endat_clk_config.rx_clock_source = CONFIG_ENDAT0_TX_RX_FIFO_CLOCK_SOURCE;
        endat_clk_config.tx_clock_source = CONFIG_ENDAT0_TX_RX_FIFO_CLOCK_SOURCE;

        
        
        #if (PRUICSS_SLICEx == 1)
          priv = endat_init (struct endat_pruss_xchg *)((PRUICSS_HwAttrs *)(
                   gPruIcssXHandle->hwAttrs))->pru1DramBase、&gEndatChInfo、gEndatChInfoGlobalAddr、pruicss_cfg、pruicss_IEP PRUICSS_SLICEx、&endat_clk_config);

        #else
          priv = endat_init (struct endat_pruss_xchg *)((PRUICSS_HwAttrs *)(
                   gPruIcssXHandle->hwAttrs))->pru0DramBase、&gEndatChInfo、gEndatChInfoGlobalAddr、 pruicss_cfg、pruicss_IEP PRUICSS_SLICEx、&endat_clk_config);
        #endif     
        
        //endat_config_channel (priv、i);
        endat_config_channel (priv、1);
        endat_config_host_trigger (priv);

        priv->pruss_xchg->endat_delay_125ns =((icssClk*125)/1000000);
        priv->pruss_xchg->endat_delay_51us =((icssClk*51)/1000000 );
        priv->pruss_xchg->endat_delay_5us =((icssClk*5)/1000000 );
        priv->pruss_xchg->endat_delay_1ms =((icssClk/1000)* 1);
        priv->pruss_xchg->endat_delay_2ms =((icssClk/1000)* 2);
        priv->pruss_xchg->endat_delay_12ms =((icssClk/1000)* 12);
        priv->pruss_xchg->endat_delay_50ms =((icssClk/1000)* 50);
        priv->pruss_xchg->endat_delay_380ms =((icssClk/1000)* 380);
        priv->pruss_xchg->endat_delay_900ms =((icssClk/1000)* 900);
        priv->pruss_xchg->icssg_clk = icssClk;


        i = endat_pruicss_load_run_fw (priv);


      }


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

    我在代码上发现了一个错误(单通道)

    >>   endat_config_channel (priv、 1); //错误地设置为 ch1

    更正了

     endat_config_channel (priv、 0);// 设置为 CH0

    修复后、重新启动仍需要 2 次重新启动才能看到重新连接到编码器

    回到负载共享模式我发现,如果原来的 Endat PRU 加载共享代码设置为 CH0 和 ch1 ,

    仅使用 CH0 配置 重新启动似乎在 2 次重新启动后重新连接

    在 2 次重新启动后、CH0 和 CH1CONFIGURE 似乎重新连接

    仅以 CH1 重新启动并不一致。  可能需要多达 12 次重新启动、有时无法完全重新连接

    我仍然不明白为什么编码器需要多次重新启动才能重新连接

    Alan I

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

    您好 Alan、

    您是否 gEndat_is_multi_ch  endat_pruicss_load_run_fw 第二次致电之前更新了?

    此外、请确保在每次调用时加载 PRU 固件并为正确的通道启用 PRU 内核  endat_pruicss_load_run_fw ?

    [引述 userid=“544168" url="“ url="~“~/support/motor-drivers-group/motor-drivers/f/motor-drivers-forum/1593875/am6442-endat2-2-loadshare-encoder-hardware-connectivity/6155684

    建议:  要解决此问题、请 使用不同的配置运行固件加载功能两次。

    1. 在调用通道编号之前、请将通道编号作为参数提供给固件加载函数。
    2. 添加 if-else 条件以启用正确的内核并加载当前通道的固件。
    3. 在在固件加载函数内调用 endat_wait_initialization 之前、更新通道掩码设置
    [/报价]

    修改了 endat_pruicss_load_run_fw 以允许为单个通道加载和运行固件:   

    uint32_t endat_pruicss_load_run_fw(struct endat_priv *priv, uint8_t channel)
    {
        uint32_t status = SystemP_FAILURE;
        uint32_t mask =  1 << channel; 
    
    #if CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_MULTI_PRU
        /* Process only the specified channel */
        if (channel == 0) {
            /*validate binary size*/
            if((sizeof(EnDatFirmwareMultiMakeRTU_0)) > RTUPRU_IRAM_SIZE) {
                DebugP_log("ERROR: Firmware binary size (%d) exceeds available IRAM size (%d)\n", 
                          sizeof(EnDatFirmwareMultiMakeRTU_0), RTUPRU_IRAM_SIZE);
            }
            
            status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_RTUPRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_RTU_PRU(PRUICSS_SLICEx),
                                        0, (uint32_t *) EnDatFirmwareMultiMakeRTU_0,
                                        sizeof(EnDatFirmwareMultiMakeRTU_0));
            DebugP_assert(0 != status);
            status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_RTUPRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_RTUPRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            
            
        }
        else if (channel == 1) {
            /*validate binary size*/
            if((sizeof(EnDatFirmwareMultiMakePRU_0)) > PRU_IRAM_SIZE) {
                DebugP_log("ERROR: Firmware binary size (%d) exceeds available IRAM size (%d)\n", 
                          sizeof(EnDatFirmwareMultiMakePRU_0), PRU_IRAM_SIZE);
            }
            
            status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_PRU(PRUICSS_SLICEx),
                                        0, (uint32_t *) EnDatFirmwareMultiMakePRU_0,
                                        sizeof(EnDatFirmwareMultiMakePRU_0));
            DebugP_assert(0 != status);
            status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_PRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_PRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            
        }
        else if (channel == 2) {
            /*validate binary size*/
            if((sizeof(EnDatFirmwareMultiMakeTXPRU_0)) > TXPRU_IRAM_SIZE) {
                DebugP_log("ERROR: Firmware binary size (%d) exceeds available IRAM size (%d)\n", 
                          sizeof(EnDatFirmwareMultiMakeTXPRU_0), TXPRU_IRAM_SIZE);
            }
            
            status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_TXPRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            status = PRUICSS_writeMemory(gPruIcssXHandle, PRUICSS_IRAM_TX_PRU(PRUICSS_SLICEx),
                                        0, (uint32_t *) EnDatFirmwareMultiMakeTXPRU_0,
                                        sizeof(EnDatFirmwareMultiMakeTXPRU_0));
            DebugP_assert(0 != status);
            status = PRUICSS_resetCore(gPruIcssXHandle, PRUICSS_TXPRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            status = PRUICSS_enableCore(gPruIcssXHandle, PRUICSS_TXPRUx);
            DebugP_assert(SystemP_SUCCESS == status);
            
        }
    
        /* Only wait for initialization after all specified channels are loaded */
        status = endat_wait_initialization(priv, WAIT_5_SECOND, mask);
    
    #else
        /* Original single channel code */
        status = PRUICSS_disableCore(gPruIcssXHandle, PRUICSS_PRUx);
        DebugP_assert(SystemP_SUCCESS == status);
    
    #if(CONFIG_ENDAT0_MODE == ENDAT_MODE_MULTI_CHANNEL_SINGLE_PRU)
        /* Existing code for multi-channel single PRU mode */
        /* ... */
    #endif
        /* Rest of the original function */
    #endif
    
        return status;
    }

     在 endat_main 中为两个通道调用 endat_pruicss_load_run_fw 两次

    endat_main()
    {
     /* Rest of the original code */
    /* Load firmware for channel 0 */
    status = endat_pruicss_load_run_fw(priv, 0);
    if (status == SystemP_SUCCESS) {
        /* Update mask only if successful */
        gEndat_multi_ch_mask |= ENDAT_MULTI_CH0;
    } else {
        /* Handle error */
        DebugP_log("ERROR: Failed to initialize ENDat channel 0\n");
    }
    
    /* Load firmware for channel 1 */
    status = endat_pruicss_load_run_fw(priv, 1);
    if (status == SystemP_SUCCESS) {
        /* Update mask only if successful */
        gEndat_multi_ch_mask |= ENDAT_MULTI_CH1;
    } else {
        /* Handle error */
        DebugP_log("ERROR: Failed to initialize ENDat channel 1\n");
    }
    
     /* Rest of the original */
     
     }
    BR、
    Achala Ram