computer_knowledge_notes/Hardware/RISC-V/k210/系统控制器.md

16 KiB
Raw Blame History

名词解释

PLL

锁相环(Phase Locked Loop)使电路上的时钟和某一外部时钟的相位同步。PLL的主要用途是作为频率合成器产生更宽范围的频率输出。也可以用作抖动滤波器或补充时钟网络的延迟。锁相环通过由PD(Phase Detector)、LF(Loop Filter)和VCO(Voltage Controlled Oscillator)三部分组成。

APB

一个总线协议,几乎成为一种标准的片上总线结构。主要用于低带宽的外设连接。

系统控制器的寄存器

系统控制器是个外设它负责所有与系统相关的外设的设置。它的32个32位寄存器都映射在内存里。

编号 名称 描述
0 git_id Git短提交id。只读寄存器git的commit id共160位而它只能提供前32位所以叫"short commit id"。
1 clk_freq 系统时钟频率。只读寄存器。
2 pll0 PLL0控制器。可写其中clkr0,clkf0,clkod0用于计算输出频率其中clkr0,clkf0,clkod0,bwadj0用于控制输入频率其中pll_bypass0设置是否bypass pll0(1:bypass, 0:do not bypass)pll_out_en0位控制pll0的时钟使能pll_pwrd0控制pll0的启动(0:power off, 1:power on)pll_reset0用于重置pll0(0:不重置1:重置)
3 pll1 PLL1控制器。可写其中clkr1,clkf1,clkod1用于计算输出频率其中clkr1,clkf1,clkod1,bwadj1用于控制输入频率其中其中pll_bypass1设置是否bypass pll1(1:bypass, 0:do not bypass)pll_out_en1位控制pll1的时钟使能pll_pwrd1控制pll1的启动(0:power off, 1:power on)pll_reset1用于重置pll1(0:不重置1:重置)
4 pll2 PLL2控制器。可写其中clkr2,clkf2,clkod2用于计算输出频率其中clkr2,clkf2,clkod2,bwadj2用于控制输入频率其中其中pll_bypass2设置是否bypass pll2(1:bypass, 0:do not bypass)pll_out_en2位控制pll2的时钟使能其中pll_ckin_sel2将pll2设为时钟源pll_pwrd2控制pll2的启动(0:power off, 1:power on)pll_reset2用于重置pll2(0:不重置1:重置)
5 resv5 保留
6 pll_lock PLL锁测试器。其中pll_lock0~2均只读pll_lock0=3则pll0已锁pll_lock1=1则pll1已锁pll_lock2=1则pll2已锁。其中pll_lip_clear0~2用于清空对应pll的slip置1则清空对应pll的slip。
7 rom_error AXI ROM测试器
8 clk_sel0 时钟选择控制器0。可写其中aclk_sel设置aclk为时钟源(0:IN0, 1:ACLK)其中aclk_divider_sel占用2位控制aclk的分频值其中apb0~2_clk_sel分别占用3位分别控制apb0~2的分频值其中spi3_clk_sel设置spi3为时钟源其中timer0~2_clk_sel分别设置timer0~2为时钟源其它为保留位。
9 clk_sel1 时钟选择控制器1。可写仅第一位有效spi3_sample_clk_sel将spi3_sample设为时钟源。
10 clk_en_cent 中心时钟使能。可写每一位控制一个时钟使能共用6个位控制cpu, sram0~1, apb0~2其余位保留。其中apb0~2分别控制着若干外设。置1使能置0不使能。
11 clk_en_peri 外部时钟使能。可写每一位控制一个外设的时钟全能。置1使能置0不使能。
12 soft_reset 软重置。可写仅第一位有效。置1重置置0不重置。
13 peri-reset 外重置。可写每一位控制一个外设。置1重置置0不重置。
14 clk_th0 时钟分频值控制器0。可写控制分频值宽度为4的外设的分频值控制的外设有5个sram0~1, ai, dvp, rom
15 clk_th1 时钟分频值控制器1。可写控制分频值宽度为8的外设的分频值控制的外设有4个spi0~3
16 clk_th2 时钟分频值控制器2。可写控制分频值宽度为8的外设的分频值控制的外设有3个timer0~2剩余8位为保留位
17 clk_th3 时钟分频值控制器3。可写控制分频值宽度为16的外设的分频值控制的外设有2个i2s0~1_clk_threshold
18 clk_th4 时钟分频值控制器4。可写控制2个分频值宽度为8的外设的分频值i2s0~1_mclk_threshold还控制1个分频值宽度为16的外设的分频值i2s2_clk_threshold
19 clk_th5 时钟分频值控制器5。可写控制分频值宽度为8的外设的分频值控制的外设有4个i2s2_mclk_threshold, i2c0~2_clk_threshold
20 clk_th6 时钟分频值控制器6。可写控制分频值宽度为8的外设的分频值控制的外设有2个wdt0~1_clk_threshold, 剩余16位为保留位
21 misc 杂项控制器。有1个1位的sip_dvp_data_enable1为使能0为不使能
22 peri 外设控制器
23 spi_sleep SPI睡眠控制器
24 reset_status reset源的状态。wdt0~1_reset_sts和soft_reset_sts代表其各自的reset状态1为reset0为非resetreset_sts_clr如写入1则清空reset状态。其余为保留位。
25 dma_sel0 DMA握手控制器0。可写控制dma_sel0~4共5个6位宽的channel其余2位保留
26 dma_sel1 DMA握手控制器1。可写控制dma_sel5这个6位宽的channel其余26位保留
27 power_sel IO电源模式选择控制器。可写power_mode_sel0~7共8个1位的项控制8种电源模式1为使能0为不使能其余24位保留
28-31 resv28-resv31 保留

系统控制器的功能

外设时钟的使能或取消使能

sysctl_clock_[enable | disable]

共有三条总线(apb0, apb1, apb2),所有外设都分配在这三条总线上。在clk_en_cent寄存器上有3位分别控制这三条总线时钟的使能或取消使能。

共有三种类型的外设。一种外设是PLL它们的时钟使能由各自的寄存器控制(pll0, pll1, pll2)一种连在内部总线上它们是CPU、内存和外部总线它们的时钟使能由寄存器clk_en_cent控制;其它外设连在外部总线上,它们的时钟使能由clk_en_peri控制。

对于PLL或连在内部总线上的设备只要该外设对应的时钟使能位置1即可使能该设备对于连接在外部总线apb上的设备则需要先使能该外设所在的apb总线的时钟再使能该外设的时钟。

设备要取消使能只要将该设备的使能位置0即可。

对应时钟分频值的设置与获取

sysctl_clock_[set | get]_threshold

不同的外设其分频值位宽是不一样的共有2、3、4、8、16五种情况。其中aclk_divider(2位)、apb0~2(各3位)由寄存器clk_sel0控制。其中sram0~1、ai、dvp、rom的分频值均为4位由寄存器clk_th0控制。其中spi0~3的分频值为8位由寄存器clk_th1控制。其中timer0~2的分频值为8位由寄存器clk_th2控制。其中i2s0~1的分频值为16位由寄存器clk_th3控制。其中i2s2的分频值为16位i2s0~1_mclk的分频值为8位由寄存器clk_th4控制。其中i2s2_mclki2c0~2的分频值为8位由寄存器clk_th5控制。其中wdt0~1的分频值为8位由寄存器clk_th6控制。

设置外设的时钟分频值就是向相应的位写入数据,获取外设的时钟分频值就是从相应的位读取数据。

时钟对应时钟源的设置与获取

sysctl_clock_[set | get]_clock_select

时钟 时钟源 意义
pll0~2->pll_bypass0~2 0, 1 1绕过对应pll0不绕过对应pll
pll2->pll_ckin_sel2 0, 1, 2 0IN01PLL02PLL1
clk_sel0寄存器的aclk, spi3, timer0~2 0, 1 1设置对应设备为时钟源0不设置对应设备为时钟源
clk_sel1->spi3_sample_clk_sel 0, 1 1设置spi3_sample为时钟源0不设置spi3_sample为时钟源

时钟源的设置就是为如上寄存器的相关位指定时钟源。

时钟源的获取就是从如上寄存器中的相应位获取对应的值。

获取PLL的频率

sysctl_pll_get_freq

FOUT = FIN / NR * NF /OD	# 输出频率 = 输入频率 / R分频器 * N计数器 / od
	# nr = pll.clkr + 1
	# nf = pll.clkf + 1
	# od = pll.clkod + 1
	# FIN : 如PLL0~1则为26000000UL如PLL2则从pll2.pll_ckin_sel2获取对应时钟源(可能是SOURCE_IN0, SOURCE_PLL0, SOURCE_PLL1)如SOURCE_IN0则为26000000UL,如SOURCE_PLL0~1则按上述公式再算一遍。
获取各种设备的基本时钟频率

sysctl_clock_get_freq

clock divider 频率
IN0 源频率是26000000UL结果频率与源频率相等
directly under PLL时钟域(PLL0~2) gated 源频率是对应PLL的频率结果频率与源频率相等
directly under ACLK时钟域(CPU, DMA, FFT, ACLK, HCLK) 从寄存器clk_sel0的aclk位取对应的值如为0表示没有选择aclk则源频率为IN0的频率如为1表示选择了aclk则源频率的算法为(PLL0的频率)/(2ULL << ACLK的时钟分频值)。结果频率与源频率相等
under ACLK时钟域(SRAM0~1, ROM, DVP) gated 源频率是ACLK的时钟频率结果频率的算法为(源频率)/(设备对应的分频值 + 1)
under ACLK时钟域(ABP0~2) even 源频率是ACLK的时钟频率结果频率的算法为(源频率)/(设备对应的分频值 + 1)
under AI时钟域 gated 源频率是PLL1的时钟频率结果频率的算法为(源频率)/(AI的分频值 + 1)
under I2S时钟域(I2S0~2) even 源频率是PLL2的时钟频率结果频率的算法为(源频率)/(对应设备的分频值 + 1)/2
under WDT时钟域(WDT0~1) even 源频率是IN0的时钟频率结果频率的算法为(源频率)/(对应设备的分频值 + 1)/2
under PLL0时钟域(SPI0~2, I2C0~2) even 源频率是PLL0的时钟频率结果频率的算法为(源频率)/(对应设备的分频值 + 1)/2
under PLL0_SEL时钟域(SPI3, TIMER0~2) even 从寄存器clk_sel0相应的位获取对应的值如为0表示没有选择对应设备的时钟则源频率为IN0的频率如为1表示选择了对应设备的时钟其源频率为PLL0的频率。对于SPI3结果频率的算法是(源频率)/(SPI3的分频值 + 1)/2对于TIMER0~2结果频率的算法是(源频率)/(TIMER2的分频值 + 1)/2
under MISC时钟域 even 无代码,仅注释,目前无任何意义
under APB0时钟域(GPIO, UART1~3, FPIOA, SHA) even 源频率为APB0的时钟频率结果频率与源频率相等
under APB1时钟域(AES, OTP, RTC) even 如为AES或OTP则源频率是APB1的时钟频率如为RTC则源频率是IN0的时钟频率。结果频率与源频率相等
under APB2时钟域 even Do nothing即源频率和结果频率均为0
设备重置与获取重置状态

sysctl_reset, sysctl_get_reset_status

重置的过程就是将寄存器soft_restperi_rest中对应的位置1再置0。

获取重置状态就是从寄存器reset_status中依次读取相应的位如某一位为1则表明该位对应的外设被重置了。可以获取重置状态的外设有wdt1, wdt2, soft。最后应该是通过给reset_sts_clr位置1来清空外设的重置状态。

PLL的使能与禁用

sysctl_pll_[enable | disable]

寄存器pll0~2分别控制相应PLL的使能与禁用。

使能的过程:

sysctl->pll.pll_bypass = 0		// 不绕过pll
sysctl->pll.pll_pwd = 1			// 开启pll

// 重置pll
sysctl->pll.pll_reset = 0
sysctl->pll.pll_reset = 1
asm volatile("nop; nop");
sysctl->pll.pll_reset = 0

禁用的过程:

sysctl->pll.pll_bypass = 1		// 绕过pll
sysctl->pll.pll_pwrd = 0		// 关闭pll
选择外设DMA通道握手信号

sysctl_dma_select

DMA一共有6个通道每个通道占6位。前5个通道在寄存器dma_sel0第6个通道在寄存器dma_sel1。每个通道可选择的外设有SSI, I2C, UART, AES, SHA, AI, FFT, I2S。

设置spi0和dvp数据

sysctl_set_spi0_dvp_data

寄存器misc的spi_dvp_data_enable位置1则使能置0则不使能。

设置FPIOA电源模式

sysctl_set_power_mode

电源模式共有两种3.3V和1.8V。寄存器power_sel共可选择8种power bank(即IO电源域编号)如电源模式选择1.8V则相应的power bank位置1如电源模式选择3.3V则相应的power bank位置0。

CPU频率的获取与设置

sysctl_cpu_[get | set]_freq

获取CPU频率固定为390000000.

设置CPU的频率实际上就是设置PLL0的频率以IN0为源频率(clk_sel0->aclk_divider_sel + 1) * 2 * freq为结果频率计算出对应的pll寄存器相关位的值并进行设置。

设置PLL的频率

sysctl_pll_set_freq

  1. 如为PLL0则设置寄存器clk_sel0的aclk_sel位为0目的是为了让CPU时钟变为XTAL
  2. 设置对应pll寄存器的pll_out_en位为0目的是使对应pll输出失效
  3. 设置对应pll寄存器的pll_pwrd位为0目的是关闭对应的pll
  4. 设置pll的新值如为pll2则以pll2->pll_ckin_sel为源计算结果频率如为其它pll则以IN0为源计算结果频率
  5. 设置对应pll寄存器的pll_pwrd位为1目的是开启对应的pll
  6. 设置对应pll寄存器的pll_reset位为1目的是重置对应的pll
  7. 设置寄存器pll_lock里与pll对应的pll_slip_clear位为1清空对应pll的slip
  8. 设置对应pll寄存器的pll_out_en位为1目的是开启对应pll的输出
  9. 如为PLL0则设置寄存器clk_sel0的aclk_sel位为1目的是为了让CPU时钟变为PLL
  10. 最终return第4步算出的结果频率。
中断的使能与取消使能

sysctl_[enable | disable]_irq

通过设置miemstatus相应的位实现。

获取从启动到现在所用的时间

sysctl_get_time_us

mcycle获取CPU周期数sysctl_clock_get_freq()获取CPU频率两者相除即为启动到现在所过的时间。

待解决的问题

  • 不知道PLL的具体作用。

  • 不知道时钟的threshold的具体作用。

    threshold在kendryte的编程指南里翻译为分频值似乎不是词典里翻译的阈值的意思。

  • 外设重置可以理解为重置外设的寄存器,那么软重置是什么意思呢?

  • 为什么重置状态寄存器只记录wdt0~1和soft的重置呢其它外设为什么不记录呢