资讯详情

【联盛德W806上手笔记】三、MCU系统与时钟结构

目录

  • 总线结构
    • AHB-1 总线
    • AHB-2 总线
  • 时钟与复位
    • 主要特性
    • 时钟结构
    • 功能描述
      • 时钟门控
      • 时钟适应关闭
      • 功能复位
      • 时钟分频
      • 寄存器描述
        • 寄存器列表
        • 软件时钟门控制
        • 软件时钟掩码寄存器
        • 软件复位控制寄存器
        • 时钟分频配置寄存器
        • 调试控制寄存器
        • I2S 时钟控制寄存器
        • 复位状态寄存器
      • 调试功能控制
    • 参考时钟电路设计
    • 启动配置
  • 地址空间
  • SRAM
  • Flash
    • QFlash
    • SPI Flash
  • PSRAM
  • 库函数
    • wm_cpu.h
      • 函数
      • 参数
    • wm_gpio_ex.h:引脚复用相关
    • wm_rcc.h:时钟相关
    • wm_it.h:声明中断服务函数

Windows 10 20H2 HLK-W806-V1.0-KIT WM_SDK_W806_v0.6.0


摘自《W806 芯片设计指南 V1.0》、《W806 MCU 芯片规格书 V2.0》

总线结构

这里没找到W806,但找到了类似的W800的: W800 芯片由两级总线组成,如下图所示 在这里插入图片描述

AHB-1 总线

本级总线有四个主设备 XT804,DMA,GPSEC 以及 5 个从设备。 XT804 面向控制领域 32 高能效嵌入式 CPU 核, 采用 16/32 混合编码指令系统设计精简高效 3 级流水线。 XT804 提供硬件浮点单元、片上高速缓存等多种可配置功能DSP 加速单元、可信防护技术 IP 等等,用户可以根据应用程序的需要进行配置。此外,XT804 提供多总线接口,支持系统总线、指令总线和数据总线的灵活配置。XT804 中断响应特别加速,中断响应延迟只需要 13 个周期。 总线时钟最快工作 240MHz 频率,可配置为 240/160/120/80/40MHz,或更低。

AHB-2 总线

本条总线有 4 个主设备,3 从设备,使用 crossbar 连接结构可以同时访问不同的主设备,从而增加带宽。总线时钟工作最快 40MHz 根据需要,频率可以更低。 各主设备采用固定优先级,自上而下递减优先级。

时钟与复位

支持芯片时钟和复位系统的控制,包括时钟变频、时钟关闭和自适应门控制;复位控制包括系统和子模块的软复位控制。

主要特性

支持每个模块的时钟关闭 支持部分模块时钟自适应关闭 支持各模块软件复位 支持 CPU 频率设置 支持 ADC/DAC 回环测试 支持 I2S 时钟设置

时钟结构

这里没有找到W806,但找到了类似的W800的: W800 使用 24/40MHz 晶体作为 SoC 电影内置时钟源 1 个 DPLL 输出 480MHz,供给CPU,系统总线、数据总线和 WiFi 系统使用;片内另外内置; 32.768KHZ RC 振荡器,供 PMU 及 LCD 模块使用。如下图所示,时钟结构概括图。

功能描述

时钟门控

寄存器可以通过配置时钟门 CLK_GATE_EN 时钟关闭可以控制指定功能,从而达到关闭模块功能的目的。 时钟和复位模块系统功耗控制的灵活性,时钟和复位模块以提供固件对系统功耗控制的灵活性。当相应模块的时钟关闭时,模块的数字逻辑和时钟树将停止工作,从而降低系统的动态功耗。 每个模块的具体开关对应于寄存器 SW_CLKG_EN 详细描述。

时钟适应关闭

芯片内部某些状态的迁移,芯片自适应关闭某些功能模块的时钟。 请不要更改配置,否则配置可能会出现 PMU 系统异常是由功能引起的。

功能复位

通过设置各子系统的软复位功能,芯片 SW_RST_CTRL 相应 BIT 为 0 子系统复位可以实现。 但复位状态不会自动清除,需要恢复正常工作 SW_RST_CTRL 相应 BIT 位置 1。 软复位功能不复位 CPU 及 WatchDog。 寄存器,对 APB/BUS1/BUS2(对应 APB 不推荐总线、系统总线和数据总线的复位操作,会导致系统访问设备异常。

时钟分频

W800 系统采用 40MHz/24MHz 晶体内置为系统时钟源 DPLL,固定输出 480MHz 时钟是整个系统的时钟源(如下图所示)。 时钟与系统总线 CPU 时钟一致,数据总线的时钟固定为 WLAN 根时钟的 1/4。 WLA 根时钟同时也是整个 WLAN 系统的时钟源头。        此模块中提供了设定 CPU 时钟与 WLAN 根时钟的功能,供固件调节系统性能及功耗使用。        设置 SYS_CLK_DIV 寄存器的 BIT[7:0]可以调整 CPU 时钟分频系数。CPU 时钟分频的源时钟为 DPLL 的输出,固定为 480MHz。CPU 时钟分频系数默认值为 6,即 CPU 默认工作频率为 480MHz 的 6 分频,即 80MHz。当需要调整 CPU 所需时钟时,可以重新配置本参数。        CLK_PERI 时钟提供 SoC 系统中加密模块的运行时钟的根时钟,以及某些接口的运行时钟的根时钟,比如 PWM 接口,I2S 接口,Flash 接口时钟。此时钟也由 DPLL 输出的 480MHz 分频得出。正常工作情况下应固定为 3 分频,得到 CLK_PERI 根时钟 160MHz。由 CLK_PERI 根时钟进行 2 分频,4 分频得到80MHz 和 40MHz,提供给加密模块和接口模块使用。        设置 SYS_CLK_DIV 寄存器的 BIT[15:8]可以调整 WLAN 时钟分频系数。默认分频因子为 3,即对 DPLL的 480MHz 输出 3 分频,得到 160MHz 时钟,作为根节点时钟送给 WLAN(WLAN 再继续分频得到更为详细的低频时钟供 WLAN 系统使用。        注意:如果希望 WLAN 系统正常工作,WLAN 根时钟需要保持在 160MHz,否则 WLAN 系统将失效。        当不需要 WLAN 系统工作的时候,可以将 WLAN 根时钟降低,降低系统动态功耗。        在改变系统时钟配置的时候,需要注意:系统总线与数据总线的比例需要维持在 M:1,其中 M 为整数,最小为 1。在改变系统时钟配置时,也需要同时更新寄存器 SYS_CLK_DIV 的 BIT [23:16], 设置正确的比例系数。否则,访问数据总线将得到异常数据。        SYS_CLK_SEL 的[15:8]提供了设置 SAR_ADC 工作频率的分频因子,以 40M 为时钟源进行分频。分频系数即为所配分频值。        SYS_CLK_SEL 的 BIT[4]为配置 RSA 模块核心运算的时钟频率选择,可以选择 80MHz 或者 160MHz。        BIT[5]为配置 GPSEC 模块核心运算的时钟频率选择,可以选择 80MHz 或者 160MHz。        BIT[6]为配置 FLASH 模块对外总线的时钟频率选择,可以选择 40MHz 或者 80MHz。        当需要重新配置 cpu_clk_divider,wlan_clk_divider,bus2_syncdn_factor,sdadc_fdiv 时,需要置位 SYS_CLK_DIV 的 BIT[31],硬件自动更新上述四个参数到分频器,然后清零 BIT[31]。        I2S_CLK_CTRL 提供了 I2S 模块的时钟配置功能。

寄存器描述

寄存器列表

软件时钟门控使能寄存器

软件时钟掩码寄存器

软件复位控制寄存器

时钟分频配置寄存器

调试控制寄存器

I2S 时钟控制寄存器

复位状态寄存器

调试功能控制

       用户可以通过设置 DEBUG_CTRL 的值(SYS_CLK_SEL- BIT[16])来达到使能和禁用 JTAG 功能的目的。

参考时钟电路设计

       芯片参考时钟选用 40MHz 频率,用户根据实际产品需求选用不同温度等级、稳定度、负载电容值的晶体。晶体两端所接负载电容根据不同厂家晶体及频偏情况需要调整。        晶体摆放尽量靠近芯片,走线尽量短,并且远离干扰源,时钟周围多地孔隔离。时钟下面各层禁止其它走线穿过,防止干扰时钟源。

启动配置

       W800 芯片上电后,CPU 会启动执行 ROM 中的固件,加载 Flash 中指定地址的用户 Image。ROM 固件在开始运行时会读取 BootMode(PA0)引脚,根据引脚的信号判断进入启动状态:        通常,BootMode 引脚应该用于生产或者调试阶段。在生产阶段,用户通过将 BootMode 引脚持续拉低 30ms 以上,进入功能模式,可以快速进行烧录 Flash 工作。        在产品返工或者维修的场景中,在芯片未进入“最高安全等级”(关于安全等级的描述请参考《WM_W800_ROM 功能简述》)时,可以通过该引脚进入功能模式,擦除旧的 Image,写入新的Image。        在调试阶段,无论固件出现任何故障,都可以通过将 BootMode 引脚持续拉低 30ms 以上,进入串口下载功能,烧录新的固件。

地址空间

       这里没有找到W806的,不过找到了与之差不多的W800的:        XT804 支持 4G 存储空间,如上图所示分为 6 个 block,分别为代码区,内存区,片上外设,片外存储区,片外外设和系统外设区。根据需求,w800 片内存储空间如图三所示映射到前三区。

SRAM

       W800 内置 288KB SRAM。其中 160KB 挂载一级 AHB 总线上,128KB 挂载在二级 AHB 总线上。CPU等一级总线设备可以访问所有内存区域,但是二级总线上的设备只能访问二级总线上 128KB 的内存。

Flash

QFlash

       W800 内部集成 2MBytes QFlash。通过芯片内部集成 32KB cache 实现 XIP 方式在 QFlash 上执行程序。 程序运行过程中,CPU 首先从 Cache 中读取指令,当不能获取指令时,以 8Bytes 一行的方式从QFlash 读取指令,存入 Cache 内。因此,当持续运行代码大小小于 32K 时,CPU 将无需从 QFlash 读取指令,此时 CPU 可以运行在更高的频率。上述方式为读取指令操作方式,整个 Image 的 RO 段都会以这种方式操作。此过程用户无需干预。        QFlash 也可以存储数据,当用户程序需要读写 QFlash 内数据时,需要通过内置的 QFlash 控制器进行操作,QFlash 提供了相应的地址、指令等寄存器来协助实现用户想要的操作。        用户需要注意的是,程序进行读取或者写入数据时,无需进行状态判断、等待等操作,因为 QFlash 控制器本身会进行判断。当 QFlash 控制器返回时,表明读取或者写入已经完成。

SPI Flash

       W800 芯片除了支持 6PIN 的 QFlash 接口之外(内置 PIN,未封装),还支持低速 SPI 接口访问。该 SPI接口的最高工作频率可达 20MHz,支持主从功能。

PSRAM

       W800 内置 SPI/QSPI 接口的 PSRAM 控制器,支持外置最大容量 64Mb 的 PSRAM 设备访问,提供总线方式的 PSRAM 读写擦操作。最高读写速度 80MHz。当存储容量需要扩充时,可以使用片外 PSRAM 扩充代码存储空间或者数据存储空间。PSRAM 同样支持 XIP 方式执行程序,CPU Cache 同样支持缓存PSRAM 中数据。

库函数

wm_cpu.h

函数

       打开wm_cpu.h,有如下的函数声明:

void SystemClock_Config(uint32_t clk);
//该函数用于设置CPU时钟,如SystemClock_Config(CPU_CLK_160M);
void SystemClock_Get(wm_sys_clk *sysclk);
//这个函数用来获取CPU时钟

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority);
void HAL_IncTick(void);
uint32_t HAL_GetTick(void);
void HAL_Delay(uint32_t Delay);

void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t Priority);
//设定中断优先级,Priority为0~15的值,值越小,优先级越高。如HAL_NVIC_SetPriority(GPIOA_IRQn, 0);
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
//使能中断通道,如HAL_NVIC_EnableIRQ(GPIOA_IRQn);
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn);
//失能中断通道

参数

enum CPU_CLK{ 
        
	CPU_CLK_240M = 2,
	CPU_CLK_160M = 3,
	CPU_CLK_80M  = 6,
	CPU_CLK_40M  = 12,
	CPU_CLK_2M  = 240,		
};

typedef union { 
        
    struct { 
        
        uint32_t CPU: 8;                     /*!< bit: 0.. 7 cpu clock divider */
        uint32_t WLAN: 8;                    /*!< bit: 8.. 15 Wlan clock divider */
        uint32_t BUS2: 8;                    /*!< bit: 16.. 23 clock dividing ratio of bus2 & bus1 */
        uint32_t PD: 4;                      /*!< bit: 24.. 27 peripheral divider */
        uint32_t RSV: 3;                     /*!< bit: 28.. 30 Reserved */
        uint32_t DIV_EN: 1;                  /*!< bit: 31 divide frequency enable */
    } b;
    uint32_t w;
} clk_div_reg;

typedef struct{ 
        
	uint32_t apbclk;
	uint32_t cpuclk;
	uint32_t wlanclk;
}wm_sys_clk;

typedef enum
{ 
        
	HAL_TICK_FREQ_10HZ         = 10,
	HAL_TICK_FREQ_100HZ        = 100,
	HAL_TICK_FREQ_1KHZ         = 1000,
	HAL_TICK_FREQ_DEFAULT      = HAL_TICK_FREQ_1KHZ
} HAL_TickFreqTypeDef;

/**BASE PLL CLOCK*/
#define W805_PLL_CLK_MHZ (480)

#define UNIT_MHZ (1000000)

#define IS_NVIC_DEVICE_IRQ(IRQ) ((IRQ) >= (IRQn_Type)0x00U)

wm_gpio_ex.h:引脚复用相关

#define __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__) do{ 
           \ SET_BIT(__HANDLE__->AF_SEL, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->AF_S1, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->AF_S0, __IOPOSITION__); \ }while (0)
												
#define __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__) do{ 
           \ SET_BIT(__HANDLE__->AF_SEL, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->AF_S1, __IOPOSITION__); \ SET_BIT(__HANDLE__->AF_S0, __IOPOSITION__); \ }while (0)
												
#define __AFIO_REMAP_SET_OPT3(__HANDLE__, __IOPOSITION__) do{ 
           \ SET_BIT(__HANDLE__->AF_SEL, __IOPOSITION__); \ SET_BIT(__HANDLE__->AF_S1, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->AF_S0, __IOPOSITION__); \ }while (0)
												
#define __AFIO_REMAP_SET_OPT4(__HANDLE__, __IOPOSITION__) do{ 
           \ SET_BIT(__HANDLE__->AF_SEL, __IOPOSITION__); \ SET_BIT(__HANDLE__->AF_S1, __IOPOSITION__); \ SET_BIT(__HANDLE__->AF_S0, __IOPOSITION__); \ }while (0)
												
#define __AFIO_REMAP_SET_OPT5(__HANDLE__, __IOPOSITION__) do{ 
           \ CLEAR_BIT(__HANDLE__->AF_SEL, __IOPOSITION__); \ }while (0)
												
#define __AFIO_REMAP_SET_OPT6(__HANDLE__, __IOPOSITION__) do{ 
           \ CLEAR_BIT(__HANDLE__->AF_SEL, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->DIR, __IOPOSITION__); \ SET_BIT(__HANDLE__->PULLUP_EN, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->PULLDOWN_EN, __IOPOSITION__); \ }while (0)
												
#define __AFIO_REMAP_SET_OPT7(__HANDLE__, __IOPOSITION__) do{ 
           \ CLEAR_BIT(__HANDLE__->AF_SEL, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->DIR, __IOPOSITION__); \ SET_BIT(__HANDLE__->PULLUP_EN, __IOPOSITION__); \ CLEAR_BIT(__HANDLE__->PULLDOWN_EN, __IOPOSITION__); \ }while (0)

#define __HAL_AFIO_REMAP_SPI_CLK(__HANDLE__, __IOPOSITION__) do{ 
           \ if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_1)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_2)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_15)) \ { 
           \ __AFIO_REMAP_SET_OPT3(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_24)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ }while (0) 

#define __HAL_AFIO_REMAP_SPI_CS(__HANDLE__, __IOPOSITION__) do{ 
           \ if ((__HANDLE__ == GPIOA) && (__IOPOSITION__ == GPIO_PIN_0)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_4)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_14)) \ { 
           \ __AFIO_REMAP_SET_OPT3(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_23)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ }while (0) 
												
#define __HAL_AFIO_REMAP_SPI_MISO(__HANDLE__, __IOPOSITION__) do{ 
           \ if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_0)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_3)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_16)) \ { 
           \ __AFIO_REMAP_SET_OPT3(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_25)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ }while (0) 

#define __HAL_AFIO_REMAP_SPI_MOSI(__HANDLE__, __IOPOSITION__) do{ 
           \ if ((__HANDLE__ == GPIOA) && (__IOPOSITION__ == GPIO_PIN_7)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_5)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_17)) \ { 
           \ __AFIO_REMAP_SET_OPT3(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_26)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ }while (0) 
												
#define __HAL_AFIO_REMAP_UART0_TX(__HANDLE__, __IOPOSITION__) do{ 
           \ if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_19)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_27)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); \ } \ }while (0)

#define __HAL_AFIO_REMAP_UART0_RX(__HANDLE__, __IOPOSITION__) do{ 
           \ if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_20)) \ { 
           \ __AFIO_REMAP_SET_OPT1(__HANDLE__, __IOPOSITION__); \ } \ else if ((__HANDLE__ == GPIOB) && (__IOPOSITION__ == GPIO_PIN_28)) \ { 
           \ __AFIO_REMAP_SET_OPT2(__HANDLE__, __IOPOSITION__); 
        标签: 电容器kit50

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台