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.

[FAQ] PRU_ICSSG:如何在 CCS 中查看和设置 PRU 内核频率?

Other Parts Discussed in Thread: SYSCONFIG

我正在使用带有 PRU_ICSSG 的处理器(AM24xAM64xAM65x),并使用 Code Composer Studio (CCS) 连接处理器。如何查看 PRU 内核的运行频率?如何更改 PRU 内核频率?

注意:这些步骤介绍了如何使用 CCS 设置 PRU 内核频率。CCS 在开发和调试 PRU 应用时很有用。不过,在由 Linux、RTOS 或裸机内核初始化 PRU 的生产代码中,设置 PRU 时钟频率需要执行不同的步骤。

通过 Linux 设置 PRU 内核频率:参考 [常见问题解答] PRU_ICSSG:如何在 Linux 中查看和设置 PRU 内核频率?

通过 RTOS 或裸机设置 PRU 内核频率:使用 MCU+ SDK 中的 SOC 驱动程序。在 MCU+ SDK 文档中,参考“SOC 外设驱动程序”>“SOC”。在 SysConfig 的 PRU-ICSS 模块中选择特定的频率后,会添加自动生成的代码以在初始化期间调用“SOC_moduleSetClockFrequency”API。如果需要稍后在运行期间更改 PRU-ICSS 时钟频率,则可以再次使用相同的 API。请注意,用于 SDK 8.0 及更低版本的 AM24x/AM64x SysConfig 仅提供针对时钟频率 200MHz 至 250MHz 的选项。适用于 SDK 8.1 及更高版本的 AM24x/AM64x SysConfig 提供 200MHz 至 333MHz (1GHz/3) 的完整 ICSSG 时钟频率范围。

  • 答:

    此次答复将说明一般步骤,后续将给出具体示例。

    如何实现 ICSSG 内核时钟?

    有关 PRU_ICSSG 时钟如何连接处理器的信息,请参阅处理器的技术参考手册 (TRM),先查看 TRM 的“PRU_ICSSG 集成”部分、“PRU_ICSSG 电源和时钟管理”部分,再看“PRU_ICSSG 时钟”表

    ICSSG 中实际使用的 CORE_CLOCK 是通过 ICSSGn_CORE_CLK 或 ICSSGn_ICLK(250MHz,与接口时钟同步)选择的。CORE_CLOCK 通过寄存器 ICSSG_CORE_SYNC_REG、位 CORE_VBUSP_SYNC_EN 进行选择。

    ICSSGn_CORE_CLK 可从不同的系统时钟中选择,具体取决于器件。ICSSGn_CORE_CLK 通过寄存器 CTRLMMR_ICSSGx_CLKSEL、位 CORE_CLKSEL 进行选择。

    系统时钟是何时配置的?

    CCS 提供了不同的方法来初始化 EVM。本常见问题解答假定您按照[常见问题解答] AM64x/AM24x:如何使用 Code Composer Studio (CCS) 连接到 PRU_ICSSG?中所述的步骤执行。 

    对于 AM24x/AM64x SDK 8.1 及更低版本,OPSI SBL NULL 初始化二进制文件不启用 PRU 时钟。因此,必须在 CCS 连接到处理器的 DMSC 时执行的 DMSC GEL 脚本中修改 PLL 输出时钟频率。

    TODO:该方法是否适用于 AM65x 处理器?

    TODO:对于不同的处理器,是否有关于客户如何找到该 DMSC GEL 文件的通用指南?

    如何查看系统时钟频率? 

    提供了用于检查 PLL 配置的 GEL 脚本,该脚本可从 R5F0_0 或 DMSC 执行。要执行此脚本,须连接到所需的内核并执行:Scripts->PLL Configuration->Get PLL Configurations->Get_All_PLL_Configurations。GEL 脚本的输出可用于计算 PLL 输出频率。有关如何计算 PLL 输出频率的详细信息,请参阅 TRM 表“PLLTS16FFCLAFRACF 输出时钟”。

  • AM64x 示例: 

    ICSSGn_CORE_CLK 在 MAIN_PLL2_HSDIV0_CLKOUT(225MHz、300MHz)或 MAIN_PLL0_HSDIV9_CLKOUT(200MHz、250MHz、333MHz,即,1GHz/3)之间选择。

    假设我们要将 ICSSG1 配置为 250MHz。

    查看当前的 PRU 内核时钟频率

    TRM ICSSG1 集成图中显示的时钟多路复用器的设置通过以下寄存器进行配置:

    ICSSG1, CTRLMMR_ICSSG1_CLKSEL   :   4300 8044h
    
    ICSSG1, ICSSG_CORE_SYNC_REG     :   300A 603Ch

    可以在 CCS“Memory”窗口中观察或修改这些寄存器。连接到 R5 内核。如果存储器浏览器不可见,请选择“View”>“Memory Browser”将其打开。现在,您可以通过键入要查看的十六进制地址导航到不同的存储器区域。

    从 CCS“Memory”窗口:

    0x40308044 = 0x00000000 => ICSSG1_CORE_CLK
    
    0x300a603c = 0x00000000 => MAIN_PLL2_HSDIV0_CLKOUT

    因此,ICSSG1 目前正在使用 ICSSG1_CORE_CLK。ICSSG1_CORE_CLK 来自 MAIN_PLL2_HSDIV0_CLKOUT。

    从 Get_All_PLL_Configurations GEL 脚本:

    MAIN_Cortex_R5_0_0: GEL Output: Base address: 0x00680000
    MAIN_Cortex_R5_0_0: GEL Output: PLL index: 0x00000002
    MAIN_Cortex_R5_0_0: GEL Output: PLL index register base: 0x00002000
    MAIN_Cortex_R5_0_0: GEL Output: Register: 0x00000020
    MAIN_Cortex_R5_0_0: GEL Output: Reference Divider is:     1
    MAIN_Cortex_R5_0_0: GEL Output: Feedback Divider is:      72
    MAIN_Cortex_R5_0_0: GEL Output: Fractional Multiplier is: 0
    MAIN_Cortex_R5_0_0: GEL Output: Output Divider #1 is:     1
    MAIN_Cortex_R5_0_0: GEL Output: Output Divider #2 is:     1
    MAIN_Cortex_R5_0_0: GEL Output: Number of hsdivs: 10
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #0's divider value is: 6
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #0's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #1's divider value is: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #1's clkout_en: 0
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #2's divider value is: 9
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #2's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #3's divider value is: 6
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #3's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #4's divider value is: 18
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #4's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #5's divider value is: 8
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #5's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #6's divider value is: 8
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #6's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #7's divider value is: 18
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #7's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #8's divider value is: 1
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #8's clkout_en: 0
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #9's divider value is: 5
    MAIN_Cortex_R5_0_0: GEL Output: HSDIV #9's clkout_en: 1
    MAIN_Cortex_R5_0_0: GEL Output: Parsed PLL configuration information.

    OSC:25MHz

    FOUTP = (25e6/1) * (72 + 0) / (1*1) = 1.8e9

    FOUTPOSTDIV = 1.8e9/6 = 300e6,300MHz

    因此,ICSSG1 内核时钟当前设置为 300MHz。

    更改 PRU 内核时钟频率 

    GEL 文件位于何处? 

    ccs_base\emulation\gel\AM64x\AM64x.gel --> OnTargetConnect() --> 运行 Set_All_PLL_OFC1()。Set_All_PLL_OFC1() 在 ccs_base\emulation\gel\AM64x\AM64_PLL\AM64x_PLL_OFC1.gel 中定义。

    Set_All_PLL_OFC1() 运行 Setup(),后者在 ccs_base\emulation\gel\AM64x\AM64_PLL\AM64x_PLL.gel 中定义。Setup() 调用 Program_PLL()。由于 Clocking_Scheme = OFC1,因此 MAIN_PLL2_HSDIV0_CLKOUT 分频器由 MAIN_PLL2_OFC1_HSDIV0_DIV_VAL 进行设置,MAIN_PLL0_HSDIV9_CLKOUT 分频器由 MAIN_PLL0_OFC1_HSDIV9_DIV_VAL 进行设置。

    如果我们查看 ccs_base\emulation\gel\AM64x\AM64_PLL\25MHz_HFOSC\AM64x_PLL_PARAMS_OFC1.gel,我们会看到


    MAIN_PLL2_OFC1_HSDIV0_DIV_VAL = 5(除以 6)


    MAIN_PLL0_OFC1_HSDIV9_DIV_VAL = 2(除以 3)

    对于 PLL2、HSDIV0:1800MHz 除以 6 可得到 300MHz,该值与 Get_All_PLL_Configurations GEL 脚本的输出相匹配。


    如何更改 PLL 分频器? 

    假设我们要使用 MAIN_PLL2_HSDIV0_CLKOUT,但具有 225MHz 时钟,而不是 300MHz 时钟。那么我们将更新 ccs_base\emulation\gel\AM64x\AM64_PLL\25MHz_HFOSC\AM64x_PLL_PARAMS_OFC1.gel 中的 MAIN_PLL2_OFC1_HSDIV0_DIV_VAL 条目,将 1800MHz 除以 8,以获得 225MHz 的输出时钟:

    #define MAIN_PLL2_OFC1_HSDIV0_DIV_VAL    7      //8

    如何选择不同的时钟源? 

    请注意,以下是用于选择输入到 AM64x ICSSG1 内核的时钟的 ICSSG1 寄存器:

    ICSSG1, CTRLMMR_ICSSG1_CLKSEL   :   4300 8044h
    
    ICSSG1, ICSSG_CORE_SYNC_REG     :   300A 603Ch

    假设我们要选择 250MHz ICSSG1_ICLK,而不是 ICSSG1_CORE_CLK。那么,我们需要将寄存器 ICSSG_CORE_SYNC_REG 的 CORE_VBUSP_SYNC_EN 位从 0 更新为 1。

    转至存储器浏览器并导航至 0x300A603C。通过将鼠标悬停在 8 个字节上,直到您在上面悬停鼠标的地址显示出来,来验证您正在查看的 32 位地址是否为正确的存储器地址。现在,您可以通过双击该地址来编辑寄存器值。

    PRU 内核时钟现在将由 250MHz 接口时钟提供。

    如果我们要运行 PRU 内核,以便每个 PRU 时钟周期恰好有 3ns,该怎么办?我们需要由 MAIN_PLL0_HSDIV9_CLKOUT 提供 333MHz 的时钟。

    首先,检查寄存器 ICSSG_core_sync_REG 的 CORE_VBUSP_SYNC_EN 位的值是否为 0(即我们要使用 ICSSG1_CORE_CLK)。

    接下来,我们需要向 CTRLMMR_ICSSG1_CLKSEL 写入数据。不过,CTRLMMR 寄存器受写保护。为了将新值写入 CTRLMMR 寄存器,我们需要首先解锁 KICK 寄存器。有关更多信息,请参阅 TRM 中的“KICK 保护寄存器”一节。

    CCS 中有一个 GEL 脚本,可用于解锁 MCU_CTRL_MMR 寄存器。首先,确保您已连接至 R5 内核,然后转到“Scripts”->“Lock-Unlock”->“Unlock_Register”并输入要解锁的地址:0x43008044。现在,您可以在存储器浏览器中导航至 0x43008044 并更新 CORE_CLKSEL 位。在该示例中,IEP_CLKSEL 位已设置为 0,并将其保持不变。

    PRU 内核时钟现在将由 MAIN_PLL0_HSDIV9_CLKOUT 提供。默认的 GEL 脚本已根据“GEL 文件位于何处?”部分将 MAIN_PLL0_HSDIV9_CLKOUT 设置为 333MHz(1GHz/3,或恰好为 3ns),因此无需更新 GEL 脚本。如果您要使用与 MAIN_PLL0_HSDIV9_CLKOUT 不同的频率,则需要按照上述方法更新 PLL 分频器。