4.2.5. 设计说明¶
4.2.5.1. 源码说明¶
CMU 相关 .c 和 .h 文件分别位于 luban-lite\bsp\artinchip\hal\cmu 和 luban-lite\bsp\artinchip\include\hal 目录。主要源文件说明如下:
| 文件 | 说明 | 
|---|---|
| aic_clk_id.h | 时钟 ID 以及 寄存器设置 | 
| aic_hal_clk.h | hal 层 clk api 的头文件 | 
| aic_hal_clk.c | hal 层 clk api 的实现 | 
| aic_hal_reset.h | hal 层 reset api 的头文件 | 
| aic_hal_reset.c | hal 层 reset api 的实现 | 
| aic_hal_pll_clk.c | PLL 时钟的具体实现 | 
| aic_hal_fixed_rate_clk.c | 固定频率时钟的具体实现 | 
| aic_hal_fixed_parent_clk.c | 单个父时钟的时钟的具体实现 | 
| aic_hal_multi_parent_clk.c | 多个父时钟的时钟的具体实现 | 
| aic_hal_disp_clk.c | DISP 时钟的具体实现 | 
| aic_hal_fpga_clk_def_v10.c | CMU V1.0 的 Clock 配置 | 
| aic_hal_fpga_clk_def_v11.c | CMU V1.1 的 Clock 配置 | 
| aic_hal_fpga_clk_def_v12.c | CMU V1.2 的 Clock 配置 | 
| aic_hal_reset_def_v10.c | CMU V1.0 的 Reset 配置 | 
| aic_hal_reset_def_v11.c | CMU V1.1 的 Reset 配置 | 
| aic_hal_reset_def_v12.c | CMU V1.2 的 Reset 配置 | 
4.2.5.2. 模块架构¶
 
CMU 驱动的逻辑比较简单,目前只在 HAL 层提供了 Clock 和 Reset 的 API 接口。RTOS 驱动和 Baremetal 驱动都可以直接使用。
4.2.5.2.1. Clock¶
4.2.5.2.1.1. 时钟树¶
 
CMU 驱动将时钟树中的时钟分为五种类型:
- fixed rate clock包含 OSC24M、RC1M、OSC32K 三个时钟,这种时钟频率固定,不能调节频率,不能打开或关闭。
- fixed parent module clock实现只有一个父时钟源的时钟驱动,主要是各个外设模块的时钟,该类型时钟可以改变时钟频率,打开或关闭时钟,获取父时钟源参数,但不能设置或改变父时钟源。
- multiple parent module clock实现有多个父时钟源的时钟驱动,主要是各种总线时钟,该类型的时钟最为复杂,可以打开或关闭时钟,调节频率,获取或改变父时钟源。
- display module clock实现了几个与显示模块相关的时钟驱动,由于显示模块除了自身的模块时钟外,还有一个像素时钟,相应的底层寄存器的设计也不同,所以将显示相关的几个时钟重新设计了底层驱动。
- pll clock实现了 CMU 的 pll 时钟驱动。
| 类型 | 时钟 | 
|---|---|
| fixed rate clock | OSC24M | 
| OSC32K | |
| RC1M | |
| fixed parent clock | CLK_DMA | 
| CLK_CE | |
| CLK_USBD | |
| CLK_USBH0-1 | |
| CLK_USB_PHY0-1 | |
| CLK_GMAC0-1 | |
| CLK_SPI0-1 | |
| CLK_SDMMC0-2 | |
| CLK_SYSCON | |
| CLK_RTC | |
| CLK_I2S0-1 | |
| CLK_ADDA | |
| CLK_DE | |
| CLK_GE | |
| CLK_VE | |
| CLK_WDOG | |
| CLK_SID | |
| CLK_GTC | |
| CLK_GPIO | |
| CLK_UART0-7 | |
| CLK_I2C0-3 | |
| CLK_CAN0-1 | |
| CLK_PWM | |
| CLK_ADCIM | |
| CLK_GPADC | |
| CLK_RTP | |
| CLK_TSEN | |
| CLK_CIR | |
| CLK_RGB | |
| CLK_LVDS | |
| CLK_MIPIDSI | |
| multi parent clock | CLK_CPU | 
| CLK_AHB0 | |
| CLK_APB0 | |
| CLK_APB1 | |
| CLK_AXI0 | |
| CLK_OUT0 | |
| CLK_OUT1 | |
| CLK_OUT2 | |
| CLK_OUT3 | |
| pll clock | CLK_PLL_INT0 | 
| CLK_PLL_INT1 | |
| CLK_PLL_FRA0 | |
| CLK_PLL_FRA1 | |
| CLK_PLL_FRA2 | |
| disp clock | CLK_PIX | 
| CLK_SCLK | 
4.2.5.2.2. Reset¶
CMU 在提供 Clock 控制的同时,也提供了 Reset 控制功能。但是相对时钟树来说,并不是每一级的时钟都对应有 Reset 控制,只有终端模块才会有 Reset 控制的需求。对应上一节五种类型的时钟,只有 fixed parent clock 同时拥有 Reset 功能。
4.2.5.3. 关键流程设计¶
4.2.5.4. 数据结构设计¶
CMU 模块关键结构体定义如下:
4.2.5.4.1. aic_clk_fixed_parent_cfg¶
struct aic_clk_fixed_parent_cfg {
    struct aic_clk_comm_cfg comm;   // 时钟操作的函数集合
    u32 offset_reg;                 // 寄存器偏移地址
    s8 bus_gate_bit;                // 总线使能位偏移
    s8 mod_gate_bit;                // 模块使能位偏移
    u8 div_bit;                     // 分频系数位偏移
    u8 div_mask;                    // 分频系数 Mask
    u8 id;                          // 时钟 id
    u8 type;                        // 时钟类型
    u8 parent_id;                   // 父时钟 id
    u8 flag;
};
4.2.5.4.2. aic_clk_multi_parent_cfg¶
struct aic_clk_multi_parent_cfg {
    struct aic_clk_comm_cfg comm;   // 时钟操作的函数集合
    u32 offset_reg;                 // 寄存器偏移地址
    s32 gate_bit;                   // 时钟使能位偏移
    u8 mux_bit;                     // 父时钟源选择位的bit偏移
    u8 mux_mask;                    // 父时钟源选择位 Mask
    u8 div0_bit;                    // 分频系数位偏移
    u8 div0_mask;                   // 分频系数 Mask
    u8 id;                          // 时钟 id
    u8 num_parents;                 // 父时钟个数
    const u8 *parent_ids;           // 父时钟数组
};
4.2.5.4.3. aic_clk_pll_cfg¶
struct aic_clk_pll_cfg {
    struct aic_clk_comm_cfg comm;   // 时钟操作的函数集合
    u32 offset_gen;                 // 整数分频寄存器的偏移
    u32 offset_fra;                 // 小数分频寄存器的偏移
    u32 offset_sdm;                 // 展频寄存器的偏移
    u8 id;                          // 时钟 id
    u8 type;                        // 时钟类型
    u8 parent_id;                   // 父时钟 id
    u8 flag;
};
4.2.5.4.4. aic_clk_disp_cfg¶
struct aic_clk_disp_cfg {
    struct aic_clk_comm_cfg comm;   // 时钟操作的函数集合
    u32 offset_reg;                 // 寄存器偏移地址
    u8 divn_bit;                    // 分频系数 N 位偏移
    u8 divn_mask;                   // 分频系数 N 位 Mask
    u8 divm_bit;                    // 分频系数 M 位偏移
    u8 divm_mask;                   // 分频系数 M 位 Mask
    u8 divl_bit;                    // 分频系数 L 位偏移
    u8 divl_mask;                   // 分频系数 L 位 Mask
    u8 pix_divsel_bit;              // pix 分频系数位偏移
    u8 pix_divsel_mask;             // pix 分频系数位 Mask
    u8 id;                          // 时钟 id
    u8 parent_id;                   // 父时钟 id
};
4.2.5.5. 接口设计¶
4.2.5.5.1. Clock API¶
CMU 驱动提供了 Clock API 接口函数,不同类型时钟支持的 API 接口函数如下表:
| API 函数 | 功能描述 | fixed rate clock | fixed parent clock | multi parent clock | disp clock | pll clock | 
|---|---|---|---|---|---|---|
| hal_clk_enable() | 使能时钟 | √ | √ | √ | ||
| hal_clk_disable() | 关闭时钟 | √ | √ | √ | ||
| hal_clk_enable_deassertrst() | 使能时钟的同时放开复位 | √ | ||||
| hal_clk_disable_assertrst() | 关闭时钟的同时使能复位 | √ | ||||
| hal_clk_enable_iter() | 迭代的使能时钟及其父时钟 | √ | √ | √ | ||
| hal_clk_enable_deassertrst_iter() | 迭代的使能时钟及其父时钟 同时放开复位 | √ | ||||
| hal_clk_get_freq() | 获取时钟频率 | √ | √ | √ | √ | √ | 
| hal_clk_set_freq() | 设置时钟频率 | √ | √ | √ | √ | |
| hal_clk_get_parent() | 获取父时钟 id | √ | √ | √ | ||
| hal_clk_set_parent() | 设置父时钟 id | √ | 
4.2.5.5.1.1. hal_clk_enable¶
| 函数原型 | int hal_clk_enable(uint32_t clk_id) | 
|---|---|
| 功能说明 | 使能时钟 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.1.2. hal_clk_disable¶
| 函数原型 | int hal_clk_disable(uint32_t clk_id) | 
|---|---|
| 功能说明 | 关闭时钟 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.1.3. hal_clk_enable_deassertrst¶
| 函数原型 | int hal_clk_enable_deassertrst(uint32_t clk_id) | 
|---|---|
| 功能说明 | 使能时钟的同时放开复位 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.1.4. hal_clk_disable_assertrst¶
| 函数原型 | int hal_clk_disable_assertrst(uint32_t clk_id) | 
|---|---|
| 功能说明 | 关闭时钟的同时使能复位 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.1.5. hal_clk_enable_iter¶
| 函数原型 | int hal_clk_enable_iter(uint32_t clk_id) | 
|---|---|
| 功能说明 | 迭代的使能时钟及其父时钟 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.1.6. hal_clk_enable_deassertrst_iter¶
| 函数原型 | int hal_clk_enable_deassertrst_iter(uint32_t clk_id) | 
|---|---|
| 功能说明 | 迭代的使能时钟及其父时钟,同时放开复位 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.1.7. hal_clk_get_freq¶
| 函数原型 | unsigned long hal_clk_get_freq(uint32_t clk_id) | 
|---|---|
| 功能说明 | 获取时钟频率 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 时钟频率,单位为 Hz | 
| 注意事项 | 
4.2.5.5.1.8. hal_clk_set_freq¶
| 函数原型 | int hal_clk_set_freq(uint32_t clk_id, unsigned long freq) | 
|---|---|
| 功能说明 | 设置时钟频率 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) freq:时钟频率,单位为 Hz | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.1.9. hal_clk_get_parent¶
| 函数原型 | unsigned int hal_clk_get_parent(uint32_t clk_id) | 
|---|---|
| 功能说明 | 获取时钟频率 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) | 
| 返回值 | 父时钟 ID | 
| 注意事项 | 
4.2.5.5.1.10. hal_clk_set_parent¶
| 函数原型 | int hal_clk_set_parent(uint32_t clk_id, unsigned int parent_clk_id) | 
|---|---|
| 功能说明 | 设置时钟频率 | 
| 参数定义 | clk_id:时钟 ID (CLK_xxxx 格式定义的宏) parent_clk_id:父时钟 ID | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.2. Reset API¶
CMU 驱动提供了 Reset API 接口函数:
| API 函数 | 功能描述 | 
|---|---|
| hal_reset_assert() | 使能复位 | 
| hal_reset_deassert() | 放开复位 | 
| hal_reset_status() | 获取复位状态 | 
4.2.5.5.2.1. hal_reset_assert¶
| 函数原型 | int hal_reset_assert(uint32_t rst_id) | 
|---|---|
| 功能说明 | 使能复位 | 
| 参数定义 | rst_id:Reset ID (RESET_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.2.2. hal_reset_deassert¶
| 函数原型 | int hal_reset_deassert(uint32_t rst_id) | 
|---|---|
| 功能说明 | 放开复位 | 
| 参数定义 | rst_id:Reset ID (RESET_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=OK, other=Error) | 
| 注意事项 | 
4.2.5.5.2.3. hal_reset_status¶
| 函数原型 | int hal_reset_status(uint32_t rst_id) | 
|---|---|
| 功能说明 | 查看复位状态 | 
| 参数定义 | rst_id:Reset ID (RESET_xxxx 格式定义的宏) | 
| 返回值 | 操作是否成功 (0=复位有效, 1=复位无效) | 
| 注意事项 |