14. CGC——时钟控制

本章配套视频介绍:

../../_images/video.png

《16-CGC时钟控制(第1节)——时钟源》

https://www.bilibili.com/video/BV1yH4y1z7PZ/

../../_images/video.png

《17-CGC时钟控制(第2节)——时钟框图配置分析》

https://www.bilibili.com/video/BV1334y1c7nd/

../../_images/video.png

《18-CGC时钟控制(第3节)——时钟配置与输出实验》

https://www.bilibili.com/video/BV1rQ4y1x7AT/

CGC(Clock Generation Circuit):时钟生成电路

14.1. CGC模块简介

CGC 全称是 Clock Generation Circuit,中文译为“时钟生成电路”,或者也可以叫它“时钟控制电路”。

14.1.1. 时钟源

我们学过《数字逻辑电路》知道,在芯片集成电路的系统中,必须要输入时钟信号进行驱动,才能使得这些逻辑电路正常工作。 那么系统所需的这些时钟信号是来源于哪里的呢?

时钟信号的来源我们称之为时钟源。RA6M5/RA4M2 的时钟源如下表所示:

RA6M5/RA4M2 时钟源

时钟源

描述

Main Clock Oscillator (MOSC)

主时钟振荡器(连接外部 8~24 MHz 高速晶振)

Sub-Clock Oscillator (SOSC)

副时钟振荡器(连接外部 32.768 kHz 低速晶振)

HOCO

高速片上振荡器

MOCO

中速片上振荡器

LOCO

低速片上振荡器

PLL

PLL输出

PLL2

PLL2输出

IWDT-dedicated clock

独立看门狗时钟

JTAG clock

JTAG (TCK) 时钟

SWD clock

SWD (SWCLK) 时钟

RA2L1 的时钟源如下表所示:

RA2L1 时钟源

时钟源

描述

Main Clock Oscillator (MOSC)

主时钟振荡器(连接外部 1~20 MHz 高速晶振)

Sub-Clock Oscillator (SOSC)

副时钟振荡器(连接外部 32.768 kHz 低速晶振)

HOCO

高速片上振荡器

MOCO

中速片上振荡器

LOCO

低速片上振荡器

IWDT-dedicated clock

独立看门狗时钟

SWD clock

SWD (SWCLK) 时钟

相关概念的详细说明:

  • Main Clock Oscillator (MOSC) :主时钟振荡器

    • RA6M5/RA4M2 连接外部 8 ~ 24 MHz 高速晶振 (连接引脚 EXTAL、XTAL);

    • RA2L1 连接外部 1 ~ 20 MHz 高速晶振 (连接引脚 EXTAL、XTAL)。

  • Sub-Clock Oscillator (SOSC) :副时钟振荡器

    • 连接外部 32.768 kHz 低速晶振 (连接引脚 XCIN、XCOUT)。

    • 32.768 kHz 的外部时钟频率一般是用于 RTC 为用户系统提供时间日历功能的。

  • Phase Locked Loop (PLL、PLL2) :PLL 即锁相环。 PLL 电路具有倍增振荡器频率的功能,可选择输入到 PLL 的时钟信号,并对其进行分频和倍频, 输入时钟源为 MOSC、HOCO,输入频率 8 MHz至 24 MHz,倍频比可在 10 到 30 之间选择(0.5步进)

    • PLL 输出频率:120 MHz ~ 200 MHz。

    • PLL2 输出频率:120 MHz ~ 240 MHz。

    • 注:RA2L1 没有 PLL,因此它的主频(48 MHz)相对比较低,而这也有利于低功耗。

  • High-speed on-chip oscillator (HOCO) :高速片上振荡器

    • 振荡频率:RA6M5/RA4M2 的为 16/18/20 MHz

    • 振荡频率:RA2L1 的为 24/32/48/64 MHz

  • Middle-speed on-chip oscillator (MOCO) :中速片上振荡器,振荡频率:8 MHz

  • Low-speed on-chip oscillator (LOCO) :低速片上振荡器,振荡频率:32.768 kHz

  • IWDT-dedicated clock (IWDTLOCO) :IWDT 专用片上振荡器,振荡频率:15 kHz

  • External clock input for JTAG (TCK) :JTAG 的外部时钟输入,振荡频率:最大 25 MHz

    • 注:RA2L1 是不支持 JTag 接口的。

  • External clock input for SWD (SWCLK) :SWD 的外部时钟输入

    • 振荡频率:RA6M5/RA4M2 的最大 25 MHz

    • 振荡频率:RA2L1 的最大 12.5 MHz

14.1.2. 模块输入时钟

上述内容我们知道已经有了各个时钟源的输入,那么,输入的各个时钟源是要输出时钟信号给到各个时钟线上的, 而芯片的各种模块又挂载到各个时钟线上。

系统中的每一个模块都需要不同的工作频率,对应到各个时钟线所能提供的最大时钟频率也有快有慢,而不是完全一样。 用户在使用一些外设或模块时需要特别考虑其输入时钟频率,这可以通过配置对应时钟线的时钟频率来满足不同模块的需求。

以 RA6M5 为例, 下面是系统内部主要时钟线的时钟源及其用以支持的模块和其所能提供的最高频率。

RA6M5 内部时钟说明

时钟线(时钟信号)

时钟源

模块

最大时钟频率

系统时钟 (ICLK)

MOSC/SOSC/HOCO/

MOCO/LOCO/PLL

CPU, DTC, DMAC, Flash, RAM

最大 200 MHz

外设模块时钟A (PCLKA)

MOSC/SOSC/HOCO/

MOCO/LOCO/PLL

ETHERC, EDMAC, USBHS, QSPI,

SCI, CAN-RAM, SPI, CRC, DOC,

ADC12, DAC12, SCE9, GPT bus clock

最大 100 MHz

外设模块时钟B (PCLKB)

MOSC/SOSC/HOCO/

MOCO/LOCO/PLL

CAC, ELC, I/O ports, POEG, RTC,

WDT, IWDT, AGT, IIC, CAN, USBFS,

SSIE, SDHI, CEC, TSN, CTSU,

Standby SRAM, Octal-SPI bus clock

最大 50 MHz

外设模块时钟C (PCLKC)

MOSC/SOSC/HOCO/

MOCO/LOCO/PLL

ADC12 conversion clock

最大 50 MHz

外设模块时钟D (PCLKD)

MOSC/SOSC/HOCO/

MOCO/LOCO/PLL

GPT计数时钟

最大 100 MHz

FlashIF时钟 (FCLK)

MOSC/SOSC/HOCO/

MOCO/LOCO/PLL

FlashIF

4 MHz ~ 50 MHz (P/E)

最大50 MHz (read)

外部总线时钟 (BCLK)

MOSC/SOSC/HOCO/

MOCO/LOCO/PLL

External bus (外部总线时钟)

最大 100 MHz

注意到设置时钟频率的一些限制:

  • ICLK ≥ PCLKA ≥ PCLKB, PCLKD ≥ PCLKA ≥ PCLKB

  • ICLK ≥ FCLK, ICLK ≥ BCLK

14.1.3. 时钟相关的引脚

与时钟相关的引脚及其说明如下表所示。

时钟相关的引脚

引脚

方向

说明

XTAL

Output

  • RA6M5/RA4M2 连接外部 8~24 MHz 晶振

  • RRA2L1 连接外部 1~20 MHz 晶振

EXTAL

Input

  • RA6M5/RA4M2 连接外部 8~24 MHz 晶振。时钟信号输入引脚

  • RA2L1 连接外部 1~20 MHz 晶振。时钟信号输入引脚

XCIN

Input

连接外部 32.768 kHz 晶振。时钟信号输入引脚

XCOUT

Output

连接外部 32.768 kHz 晶振

TCK/SWCLK

Input

用作 JTAG/SWD 的时钟输入。用于调试

EBCLK

Output

输出外部总线时钟信号,用以驱动外部设备。

用于为外部设备提供外部总线时钟(EBCLK)

CLKOUT

Output

输出 CLKOUT/BUZZER 时钟

14.2. CGC时钟配置框图分析

打开 FSP 配置器里的时钟配置页面,未经修改的 RA6M5/RA4M2/RA2L1 的默认时钟配置如下面三张图所示。 这样的时钟配置图实际上主要是为了方便用户进行配置,其结构是比较简单的,可以看做简化版的时钟树, 而完整的时钟树请读者参考相应的RA芯片的硬件手册第8章“Clock Generation Circuit”, 但其比较复杂,限于篇幅不便直接分析,因此比较感兴趣的读者可以一边结合手册里的完整时钟树一边阅读本章本小节内容。

在以下的三张时钟配置图中,我们可以看到 FSP 时钟配置页面里时钟信号生成的实际流向是沿着颜色较深的黑色箭头。 颜色较浅的灰色箭头表示的是实际未使用到的时钟路线,对应到硬件层面这部分电路是不会被配置和启用的。

FSP 配置器里 RA6M5 默认时钟配置如下图所示:

图 14‑1 e2 studio 默认的RA6M5时钟配置

在上图中顺着黑色实线箭头的流向看,XTAL 是外部高速晶振,也就是 MOSC, 查看启明6M5开发板原理图可以知道,它连接的是频率为 24 MHz 的外部晶振,因此这里的设置是正确的我们不必修改。 继续往下看,PLL 时钟源选择(PLL Src)中选择外部高速晶振(XTAL)作为 PLL 的时钟源, 然后 PLL 通过 /3 分频和 x25 倍频,即 24MHz / 3 * 25 = 200MHz,最后得到了 PLL 的输出时钟频率为 200 MHz。 继续往下,在系统时钟源选择(Clock Src)中选择 PLL 作为系统时钟源,最后再经过各自的分频器,提供给各路的时钟线及其挂载的各个外设。

FSP 配置器里 RA4M2 默认时钟配置如下图所示:

图 14‑2 e2 studio 默认的RA4M2时钟配置

上图与 RA6M5 默认时钟配置图类似,不再赘述。

FSP 配置器里 RA2L1 默认时钟配置如下图所示:

图 14‑3 e2 studio 默认的RA2L1时钟配置

在上图中也是顺着黑色实线箭头的流向看,首先是从 “HOCO 48Mhz” 开始, 也就是默认选择的是芯片内部的高速振荡器(HOCO),当然我们也可以通过更改配置选择 XTAL 作为时钟源, 不过我们需要特别注意的是,启明2L1开发板上连接的外部高速晶振频率是 8MHz,而不是上图中默认设置的 20MHz。 当选择 XTAL 作为时钟源时,如果外部高速晶振的频率设置错误,芯片是不能够工作的,因此这里的设置需要改为 “XTAL 8MHz”。 我们从 HOCO 继续往下看,系统时钟源选择(Clock Src)中选择的是片上高速振荡器(HOCO), 然后经过各自的分频器,提供给各路的时钟线及其挂载的各个外设。 注意 RA2L1 没有 PLL。

注解

注:更加详细的时钟树内容可以参考硬件手册的第8章节的图 8.1 时钟生成电路框图。

我们把以上简化版的时钟树(时钟配置图)分别简单地划分为几个区域来看待,这几个区域都已在图中用序号标注了出来, 接下来我们将一一分析这几个区域的时钟信号。

  • ①-时钟源

  • ②-锁相环

  • ③-系统时钟区域

  • ④-外设专用独立时钟区域

14.2.1. 时钟源

见图中标注 ① 处。

时钟源在本章前面部分也有讲解。

14.2.1.1. 外部振荡器时钟区域

外部振荡器包括外部高速振荡器(主时钟振荡器)和外部低速振荡器(副时钟振荡器)。

  • Main Clock Oscillator (MOSC) :主时钟振荡器

    • RA6M5/RA4M2 连接外部 8 ~ 24 MHz 高速晶振 (连接引脚 EXTAL、XTAL);

    • RA2L1 连接外部 1 ~ 20 MHz 高速晶振 (连接引脚 EXTAL、XTAL)。

  • Sub-Clock Oscillator (SOSC) :副时钟振荡器

    • 连接外部 32.768 kHz 低速晶振 (连接引脚 XCIN、XCOUT)。

    • 32.768 kHz 的外部时钟频率一般是用于 RTC 为用户系统提供时间日历功能的。

查看启明6M5和启明4M2开发板原理图, 可以发现这两块开发板用的外部高速晶振是24MHz的晶振,所以在时钟配置页面中,XTAL 要设置为 24MHz; 启明2L1开发板上用的就是8MHz的晶振,在时钟配置页面中,XTAL 应设置为 8MHz

启明6M5开发板外部晶振部分原理图如下图所示:

图

启明4M2开发板外部晶振部分原理图如下图所示:

图

启明2L1开发板外部晶振部分原理图如下图所示:

图

14.2.1.2. 内部振荡器时钟区域

内部振荡器或者叫片上振荡器,相当于芯片内置了晶振。 在一些应用场景下,为了满足设计需求和节省硬件成本,可以去掉外部晶振, 仅使用内部晶振为芯片提供主要时钟信号。

  • High-speed on-chip oscillator (HOCO) :高速片上振荡器

    • 振荡频率:RA6M5/RA4M2 的为 16/18/20 MHz

    • 振荡频率:RA2L1 的为 24/32/48/64 MHz

  • Middle-speed on-chip oscillator (MOCO) :中速片上振荡器,振荡频率:8 MHz

  • Low-speed on-chip oscillator (LOCO) :低速片上振荡器,振荡频率:32.768 kHz

RA MCU 的内部振荡器主要包括 HOCO、MOCO 和 LOCO,区分了高速、中速和低速,功能齐全, 用户在启用内部振荡器时可以非常灵活地去选择。

FSP 时钟配置页面和时钟树上的内部振荡器部分:

图

14.2.2. 锁相环

见图中标注 ② 处。

  • Phase Locked Loop (PLL、PLL2) :PLL 即锁相环。 PLL 电路具有倍增振荡器频率的功能,可选择输入到 PLL 的时钟信号,并对其进行分频和倍频, 输入时钟源为 MOSC、HOCO,输入频率 8 MHz至 24 MHz,倍频比可在 10 到 30 之间选择(0.5步进)

    • PLL 输出频率:120 MHz ~ 200 MHz。

    • PLL2 输出频率:120 MHz ~ 240 MHz。

    • 注:RA2L1 没有 PLL,因此它的主频(48 MHz)相对比较低,而这也有利于低功耗。

14.2.2.1. PLL锁相环

PLL 输出时钟信号一般是用于系统时钟(ICLK)、内部Flash时钟(FCLK)以及外设模块时钟(PCLKA/B/C/D)等。 RA6M5/RA4M2 时钟配置图中的默认设置为 PLLCLK = MOSC(24MHz) / 3 * 25 = 200MHz。

FSP 配置器的时钟视图和对应的时钟树PLL部分:

图 14‑4 SP 配置器的时钟视图和时钟树PLL部分

14.2.2.2. PLL2锁相环

PLL 输出主要用于系统时钟(ICLK)等,而 PLL2 主要用于一些重要的外设,为其单独提供稳定的时钟。 这里我们没有使用到 PLL2。

FSP 时钟配置图中的 PLL2 部分:

图 14‑5 SP 配置器的时钟视图和时钟树PLL部分

14.2.3. 系统时钟区域

见图中标注 ③ 处。

系统时钟指的是 ICLK。系统时钟(ICLK)是 CPU、DMAC、DTC、Flash 和 SRAM 的工作时钟。 ICLK 的时钟源可以指定选择 MOSC、SOSC、HOCO、MOCO、LOCO、XTAL、PLL(不包括PLL2)。 我们只需要配置时钟配置图中的 “Clock Src” 即可进行选择。

对于不同的启明开发板,我们一般参考主芯片的主频来设置系统时钟:

  • RA6M5 主频为 200MHz,因此一般设置其 ICLK 为 200MHz

  • RA4M2 主频为 100MHz,因此一般设置其 ICLK 为 100MHz

  • RA2L1 主频为 48MHz,因此一般设置其 ICLK 为 48MHz

注意我们在设置系统时钟时,是不可以超过芯片手册所规定的频率范围的, 如果超出,会使芯片工作不稳定,容易发热、程序跑飞等等。

当然,这部分区域不只有系统时钟(ICLK),还包括其他的一些内部总线时钟:

  • 外设模块时钟:PCLKA, PCLKB, PCLKC, PCLKD

  • FlashIF 时钟:FCLK

  • 外部总线时钟:BCLK

这个需要根据具体芯片具体分析,比如 RA4M2 和 RA2L1 没有 BCLK。

14.2.4. 外设专用独立时钟区域

见图中标注 ④ 处。

这部分区域主要包含一些比较重要的外设的专用时钟, 比如USB外设时钟(UCLK)、OSPI外设时钟(OCTASPICLK)、还有CANFD外设时钟(CANFDCLK)等。 有部分 RA 芯片不支持这些外设的情况下,一般也不会有对应外设的专用时钟。

除了外设专用时钟,还有一个 CLKOUT,一般 MCU 都会有这个时钟信号。 CLKOUT 是时钟信号输出,可以将内部的时钟信号输出到对应的外部引脚, 这样可以为外部其他电路模块提供时钟驱动信号。 有时候我们也可以利用这个 CLKOUT 通过示波器测量它的时钟频率, 再根据一些时钟分频的配置,进而可以计算出芯片目前的运行主频。

14.3. 设置系统时钟库函数

上面说讲述的时钟树,对应的配置函数如下,该函数截取自FSP库文件 ./ra/fsp/src/bsp/mcu/all/bsp_clocks.c 。 为了方便阅读,本章已把一些暂时用不上的、选择编译的代码删掉,把英文注释翻译成了中文。 该函数是直接操作寄存器的,有关寄存器部分请参考数据手册的 “8. Clock Generation Circuit” 章节的寄存器描述部分。

代码清单 14‑1 bsp_clock_init 时钟配置库函数
 /*******************************************************************************************************************//**
  * Initializes system clocks.  Makes no assumptions about current register settings.
  **********************************************************************************************************************/
 void bsp_clock_init (void)
 {
     /* 解锁CGC和LPM保护寄存器。 */
     R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_UNLOCK;

     /* 启用闪存缓存,在从闪存运行时不要禁用它。在这些MCU上,调整工作电源模式时不需要禁用闪存缓存。 */
     R_BSP_FlashCacheEnable();

     /* 初始化变量以存储系统时钟频率。 */
     //存放比如:g_clock_freq[BSP_CLOCKS_SOURCE_CLOCK_MAIN_OSC] = BSP_CFG_XTAL_HZ;
     bsp_clock_freq_var_init();  //主要宏来自 bsp_clock_cfg.h

     /* 配置主振荡器驱动器。 */
     R_SYSTEM->MOMCR = BSP_PRV_MOMCR;

     /* 设置主振荡器等待时间。 */
     R_SYSTEM->MOSCWTCR = (uint8_t) BSP_CLOCK_CFG_MAIN_OSC_WAIT;

     /* 如果子时钟振荡器在重置时启动,请在配置子时钟驱动器之前停止。 */
     if (0U == R_SYSTEM->SOSCCR)
     {
         /* 停止子时钟振荡器以更新SOMCR寄存器。 */
         R_SYSTEM->SOSCCR = 1U;

         /* 在配置驱动容量和重新启动子时钟振荡器之前,允许至少5个SOSC时钟周期的停止间隔。 */
         R_BSP_SoftwareDelay(BSP_PRV_SUBCLOCK_STOP_INTERVAL_US, BSP_DELAY_UNITS_MICROSECONDS);
     }

     /* 在子时钟未运行时配置子时钟驱动。 */
     R_SYSTEM->SOMCR = ((BSP_CLOCK_CFG_SUBCLOCK_DRIVE << BSP_FEATURE_CGC_SODRV_SHIFT) & BSP_FEATURE_CGC_SODRV_MASK);

     /* 重新启动子时钟振荡器。 */
     R_SYSTEM->SOSCCR = 0U;

     /* 首先启动其他时钟使用的所有时钟。 */
     R_SYSTEM->HOCOCR = 0U;

     R_SYSTEM->MOSCCR = 0U;

     /* 等待主振荡器稳定。 */
     FSP_HARDWARE_REGISTER_WAIT(R_SYSTEM->OSCSF_b.MOSCSF, 1U);

     /* 启动需要其他时钟的时钟。在这一点上,如果需要,所有相关时钟都在运行和稳定。 */

     /* 配置PLL寄存器。 */
     R_SYSTEM->PLLCCR = (uint16_t) BSP_PRV_PLLCCR;  // PLL的 分频系数 和 倍频系数

     R_SYSTEM->PLLCR = 0U;

     /* 等待PLL稳定。 */
     FSP_HARDWARE_REGISTER_WAIT(R_SYSTEM->OSCSF_b.PLLSF, 1U);

     /* 设置源时钟和分频器。 */
     bsp_prv_clock_set_hard_reset();  //系统时钟源选择,其他时钟的分频系数选择

     /* 配置BCLK(如果它存在于MCU上)。 */
     R_SYSTEM->BCKCR   = BSP_CFG_BCLK_OUTPUT - 1U;
     R_SYSTEM->EBCKOCR = 1U;


     /* 配置CLKOUT。 */
     uint8_t ckocr = BSP_CFG_CLKOUT_SOURCE | (BSP_CFG_CLKOUT_DIV << BSP_PRV_CKOCR_CKODIV_BIT);
     R_SYSTEM->CKOCR = ckocr;
     ckocr          |= (1U << BSP_PRV_CKOCR_CKOEN_BIT);
     R_SYSTEM->CKOCR = ckocr;

     /* 锁定CGC和LPM保护寄存器。 */
     R_SYSTEM->PRCR = (uint16_t) BSP_PRV_PRCR_LOCK;
 }

14.4. 实验1:配置系统时钟实验

简单地讲一下思路: 使用不同频率的系统时钟,会导致CPU执行简单软件延时函数的时间不一样,就会形成不同的延时效果,这可以通过LED闪烁的频率来判断。 其中的简单软件延时函数由用户自己编写,后面会给出。

14.4.1. 硬件设计

本实验需要使用 LED 灯,通过 LED 闪烁的快慢来进行简单判断时钟频率的修改是否生效。

野火启明6M5、启明4M2、启明2L1开发板 LED 灯电路图的讲解可参考前面的点亮LED灯章节,这里不再赘述。

14.4.2. 软件设计

14.4.2.1. 新建工程

对于 e2 studio 开发环境:

拷贝一份我们之前的 e2s 工程 “11_GPIO_LED”, 然后将工程文件夹重命名为 “14_CGC”,最后再将它导入到我们的 e2 studio 工作空间中。

对于 Keil 开发环境:

拷贝一份我们之前的 Keil 工程 “11_GPIO_LED”, 然后将工程文件夹重命名为 “14_CGC”,并进入该文件夹里面双击 Keil 工程文件,打开该工程。

工程拷贝完成之后,在工程根目录的 “src” 文件夹已包含有 “led” 文件夹以及LED驱动程序文件,我们不必重复添加。

14.4.2.2. FSP 配置

然后打开该工程的 FSP 配置界面,在时钟配置页面我们可以修改MCU主频或其他总线的时钟频率。 在更改MCU主频后,也可通过观察LED闪烁频率来简单判断CPU主频是否修改成功。

配置CPU以默认的200MHz频率运行

打开 FSP 的 Clock 配置页面,RA6M5 的默认时钟配置如下图所示。 外部晶振(XTAL)频率已默认设置为 24MHz,与启明6M5开发板的晶振频率一致,如果不对的话需要修改。 这里我们不做任何变更,所有配置都按照默认的时钟频率配置,MCU的主频(ICLK)为默认的 200 MHz。

图 14‑9 RA6M5 时钟配置页面,配置时钟

配置完成后,点击右上角的 “Generate Project Content” 生成项目内容图标,让软件生成新的代码内容。

实际上在 bsp_clock_cfg.h 文件当中,可以看到具体的一些时钟配置相关的宏。

代码清单 14‑2 bsp_clock_cfg.h 时钟配置相关宏
 /* generated configuration header file - do not edit */
 #ifndef BSP_CLOCK_CFG_H_
 #define BSP_CLOCK_CFG_H_
 #define BSP_CFG_CLOCKS_SECURE (0)
 #define BSP_CFG_CLOCKS_OVERRIDE (0)
 #define BSP_CFG_XTAL_HZ (24000000) /* XTAL 24000000Hz */
 #define BSP_CFG_HOCO_FREQUENCY (2) /* HOCO 20MHz */
 #define BSP_CFG_PLL_SOURCE (BSP_CLOCKS_SOURCE_CLOCK_MAIN_OSC) /* PLL Src: XTAL */
 #define BSP_CFG_PLL_DIV (BSP_CLOCKS_PLL_DIV_3) /* PLL Div /3 */
 #define BSP_CFG_PLL_MUL BSP_CLOCKS_PLL_MUL_25_0 /* PLL Mul x25.0 */
 #define BSP_CFG_PLL2_SOURCE (BSP_CLOCKS_CLOCK_DISABLED) /* PLL2 Disabled */
 #define BSP_CFG_PLL2_DIV (BSP_CLOCKS_PLL_DIV_2) /* PLL2 Div /2 */
 #define BSP_CFG_PLL2_MUL BSP_CLOCKS_PLL_MUL_20_0 /* PLL2 Mul x20.0 */
 #define BSP_CFG_CLOCK_SOURCE (BSP_CLOCKS_SOURCE_CLOCK_PLL) /* Clock Src: PLL */
 #define BSP_CFG_CLKOUT_SOURCE (BSP_CLOCKS_CLOCK_DISABLED) /* CLKOUT Disabled */
 #define BSP_CFG_UCK_SOURCE (BSP_CLOCKS_CLOCK_DISABLED) /* UCLK Disabled */
 #define BSP_CFG_OCTA_SOURCE (BSP_CLOCKS_CLOCK_DISABLED) /* OCTASPICLK Disabled */
 #define BSP_CFG_CANFDCLK_SOURCE (BSP_CLOCKS_CLOCK_DISABLED) /* CANFDCLK Disabled */
 #define BSP_CFG_ICLK_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_1) /* ICLK Div /1 */
 #define BSP_CFG_PCLKA_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_2) /* PCLKA Div /2 */
 #define BSP_CFG_PCLKB_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_4) /* PCLKB Div /4 */
 #define BSP_CFG_PCLKC_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_4) /* PCLKC Div /4 */
 #define BSP_CFG_PCLKD_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_2) /* PCLKD Div /2 */
 #define BSP_CFG_BCLK_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_2) /* BCLK Div /2 */
 #define BSP_CFG_BCLK_OUTPUT (2) /* BCLK/2 */
 #define BSP_CFG_FCLK_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_4) /* FCLK Div /4 */
 #define BSP_CFG_CLKOUT_DIV (BSP_CLOCKS_SYS_CLOCK_DIV_1) /* CLKOUT Div /1 */
 #define BSP_CFG_UCK_DIV (BSP_CLOCKS_USB_CLOCK_DIV_5) /* UCLK Div /5 */
 #define BSP_CFG_OCTA_DIV (BSP_CLOCKS_OCTA_CLOCK_DIV_1) /* OCTASPICLK Div /1 */
 #define BSP_CFG_CANFDCLK_DIV (BSP_CLOCKS_CANFD_CLOCK_DIV_6) /* CANFDCLK Div /6 */
 #endif /* BSP_CLOCK_CFG_H_ */

RA4M2 的时钟配置页面如下图所示:

图 14‑9a RA4M2 时钟配置页面,配置时钟

RA2L1 的时钟配置页面如下图所示:

图 14‑9b RA2L1 时钟配置页面,配置时钟

注意:上图 RA2L1 时钟配置的 XTAL 外部晶振频率与启明2L1开发板上的晶振频率(8 MHz)不一致, 因此,若用户需要使用外部晶振提供时钟输入,图中“XTAL 20MHz”需更改为“XTAL 8MHz”。

首先让我们以一个简单的软件延时函数来测试主频为 200 MHz时的LED闪烁效果。 请读者跳到“hal_entry入口函数”小节继续阅读。

配置CPU以100MHz频率运行

打开 RA6M5 的 Clock 时钟配置页面,如下图所示,修改 PLL Mul 为 x12.5,即 PLL 倍频系数由原来的 25 倍频改为 12.5 倍频。 此时主频变为 100 MHz。

图 14‑10a RA6M5 时钟配置页面,配置时钟2

打开 RA4M2 的 Clock 时钟配置页面,按照如下图所示修改。

图 14‑10b RA4M2 时钟配置页面,配置时钟2

打开 RA2L1 的 Clock 时钟配置页面,按照如下图所示修改。

图 14‑10c RA2L1 时钟配置页面,配置时钟2

14.4.2.3. 简单软件延时函数

代码清单 14-3:简单软件延时函数
/* 简单的软件延时函数
   使用不同的系统时钟,延时不一样
*/
void Delay(__IO uint32_t nCount)
{
   for(; nCount != 0; nCount--);
}

14.4.2.4. hal_entry入口函数

hal_entry.c 文件内容修改如下,修改完后即可阅读下一小节“下载验证”,编译和下载程序后观察实际效果。

代码清单 14-4 hal_entry 函数
/* 用户头文件包含 */
#include "led/bsp_led.h"

void hal_entry(void)
{
   /* TODO: add your own code here */

   LED_Init(); // LED 初始化

   while(1)
   {
      LED1_ON; // LED1亮
      LED2_ON; // LED2亮
      LED3_ON; // LED3亮
      //R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //延时1秒
      Delay(0x05FFFFF); //不精确延时,延时时间会随系统时钟变化

      LED1_OFF; // LED1灭
      LED2_OFF; // LED2灭
      LED3_OFF; // LED3灭
      //R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_SECONDS); //延时1秒
      Delay(0x05FFFFF); //不精确延时,延时时间会随系统时钟变化
   }


#if BSP_TZ_SECURE_BUILD
   /* Enter non-secure code */
   R_BSP_NonSecureEnter();
#endif
}

这里使用的是一个自定义的 Delay 函数进行延时。 在该函数内,对参数 nCount 进行自减操作,直到 nCount 减为 0 为止。 由于当 CPU 频率不同时,执行该函数(传入参数相同)所需要的时间不同,因此 LED 闪烁的快慢亦不同。

14.4.3. 下载验证

先按照默认的CPU主频(200MHz)运行一遍,观察LED灯闪烁的频率。

再修改CPU主频为 100 MHz,下载程序重新运行一遍,再次观察LED灯闪烁的频率。

对比两个程序执行时,LED灯闪烁的频率有较为明显的不同,这说明CPU时钟频率经过我们设置之后确实发生了改变。

14.5. 实验2:时钟信号输出实验

利用 CLKOUT 引脚输出时钟信号。

14.5.1. 软件设计

14.5.1.1. 新建工程

对于 e2 studio 开发环境:

拷贝一份我们之前的 e2s 工程 “11_GPIO_LED”, 然后将工程文件夹重命名为 “14_CGC_CLKOUT”,最后再将它导入到我们的 e2 studio 工作空间中。

对于 Keil 开发环境:

拷贝一份我们之前的 Keil 工程 “11_GPIO_LED”, 然后将工程文件夹重命名为 “14_CGC_CLKOUT”,并进入该文件夹里面双击 Keil 工程文件,打开该工程。

14.5.1.2. FSP 配置

打开工程 FSP 配置中的 “Clocks” 时钟配置页面。

RA6M5 的 Clock 时钟配置,如下图所示:

图 14‑11 clkout配置 大图

上图中,设置 RA6M5 的 CLKOUT 时钟线,设置时钟源(CLKOUT Src)为 XTAL,分频系数(CLKOUT Div)为“/16”, 最后会得到 CLKOUT 的时钟频率为 1500kHz(1.5 MHz)。

RA4M2 的 Clock 时钟配置,如下图所示:

图 14‑11b clkout配置 大图

RA2L1 的 Clock 时钟配置,如下图所示:

图 14‑11c clkout配置 大图

最后还需要切换到 “Pins” 页面设置引脚。时钟信号需要通过一个引脚进行输出, 因此对于 RA6M5 选用 P611 引脚来作为 CLKOUT 引脚输出时钟,如下图所示。

图 14‑13 选择 clkout 引脚 p611

对于 RA4M2 选用 P600 引脚来作为 CLKOUT 引脚输出时钟,如下图所示。

图 14‑13b 选择 clkout 引脚 p600

对于 RA2L1 选用 P109 引脚来作为 CLKOUT 引脚输出时钟,如下图所示。

图 14‑13c 选择 clkout 引脚 p109

配置完成之后,按下快捷键 “Ctrl + S” 保存,点右上角的 “Generate Project Content” 图标, 让软件根据我们的设置自动生成配置代码即可。接下来就可以编译和下载运行程序了。

14.5.2. 下载验证

使用示波器观察现象,将示波器探头一端接地,一端接 CLKOUT 引脚, 可以看到,示波器上显示的频率为 1.506MHz , 和我们的理论配置值 1500kHz(1.5MHz) 基本一致。

图 14‑14 示波器观察现象