

沁恒 CH32V208(二): CH32V208的储存结构, 启动模式和时钟 - Milton
source link: https://www.cnblogs.com/milton/p/17367163.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

CH32V 存储容量命名方式
在介绍下面的内容前, 先看一下CH32V系列和存储相关的命名格式, 以CH32V203为例, 前面的CH32V203代表一个系列, 后面的字符分别代表了Pin脚数量, Flash大小, 封装和工作温度范围
CH32V203G6U6 |||| |||`-> Temperature range ||`--> Package: QFN |`---> Flash Size `----> Pin Count
其中的Flash大小表示为
4 = 16K6 = 32K8 = 64KB = 128KC = 256K
以及以D开头的容量表示形式(在用户手册中会出现)
D6 32KB or 64KB, Low-and-medium-density generalD8 128KB or 256KB, High-density generalD8C 128KB or 256KB, Connectivity or interconnectivityD8W 128KB or 256KB, Wireless
这些容量类型与型号的对应关系为
- CH32V20x_D6
CH32V203F6, CH32V203G6, CH32V203K6, CH32V203F8, CH32V203G8, CH32V203K8, CH32V203C6, CH32V203C8 - CH32V20x_D8
CH32V203RB - CH32V20x_D8W
CH32V208GB, CH32V208CB, CH32V208RB, CH32V208WB - CH32V30x_D8
CH32V303CB, CH32V303RB, CH32V303RC, CH32V303VC - CH32V30x_D8C
CH32V305FB, CH32V305RB, CH32V307RC, CH32V307WC, CH32V307VC
可以看到 CH32V208 全系列属于 CH32V20x_D8W 容量类型
CH32V208 的存储
数据手册中对存储部分的说明为
- 内置最大 64K 字节 SRAM 区, 用于存放数据, 掉电后数据丢失. 具体容量要对应芯片型号.
- 内置最大 480K 字节程序闪存存储区(Code FLASH), 用于用户的应用程序和常量数据存储. 其中包括零等待程序运行区域和非零等待区域.
- 内置 28K 字节系统存储区(System FLASH)用于系统引导程序存储(厂家固化自举加载程序).
- 128 字节用于系统非易失配置信息存储区, 128 字节用于用户选择字存储区
CH32V208 的存储器地址映射
下图是 CH32V208 的存储器地址映射

地址分配和 ARM Cortex M 几乎是一样的
- Flash地址从 0x0800 0000 开始
- RAM地址从 0x2000 0000 开始
- 根据 BOOT pin 的设置, 启动时将对应的地址映射到 0x0000 0000
其中 Flash 大小是 480KB, 而 RAM 是可以配置的(应该是一块总计192KB的RAM), 根据零等待Flash的大小不同, 有三种划分选项 128KF + 64KR, 144KF + 48KR, 160KF + 32KR. 当启动时, 对应大小的code从 Flash 载入到 RAM 中执行, 实现零等待.
Flash RAM 映射关系
CH32V208 的 Flash 分为三块: 最开始的128KB固定映射到RAM, 在复位后复制到RAM; 之后的32KB是可配置区域; 除了前面的160KB, 后面的320KB是固定的非零等待代码区域.
| Fixed | Dynamic || ----- | -------- | ------- | -------------------- | ------ || Flash | 128KB | 32KB | 320KB | 32KB | ------------------------------------------ └───480K 用户可擦写可执行| ----- | -------- | ------- | ------ | -------------------- || RAM | 128KB | 32KB | 32KB | -------- ------- ------ | | └─── 32K固定RAM | └───32K可配置为RAM或Flash映射 └───128K固定Flash映射, 复位后硬件拷贝
在LD文件中设置可用 Flash 大小
编辑项目中的 link.ld, 在 MEMORY 部分修改, 下面的例子将 Flash 设置为 448KB
MEMORY{ FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K}
注意 Flash 的 ORIGIN 从 0x0000 0000 开始, 不是 0x0800 0000, 因为执行时 Flash 会被映射到 0 地址, 连接时代码的地址都以0地址为偏移量.
在启动时, 通过自举引脚(BOOT0 和 BOOT1), 可以选择三种自举模式中的一种
BOOT0 | BOOT1 | 启动模式 |
---|---|---|
0 | X | 从Code Flash 启动 |
1 | 0 | 从System FLASH 启动 |
1 | 1 | 从内部 SRAM 启动 |
- BOOT0 为独立的pin
- BOOT1 为PB2
QFN28封装的 CH32V208GBU6 比较特殊, 一是没有引出 BOOT1, 默认接地, 二是 BOOT0 与 PB8 共用同一个物理PIN脚, 在手册第19页有单独说明:
BOOT0引脚引出, 但BOOT1/PB2引脚未引出的芯片, 内部BOOT1/PB2引脚将下拉到GND. 此时如果进入低功耗模式配置IO口状态时, 建议BOOT1/PB2引脚使用输入下拉模式防止产生额外电流.
BOOT0和PB8引脚合封芯片, 建议外接500K下拉电阻, 保证芯片上电稳定进入程序闪存存储器自举模式. 另外, 此PB8引脚及其复用功能只保留了输出驱动功能, 所有输入功能已被禁止.
这个500K下拉可以保证BOOT0不浮空的同时, 对PB8作为输出不造成影响.
28引脚封装芯片有许多合封引脚(至少2个IO功能引脚物理合为一个引脚), 此时驱动不要同时配置输出功能, 否则可能损坏引脚. 有功耗要求的注意引脚状态.
简单说就是合封的pin脚, 不要同时设为输出模式
CH32V208 的时钟
根据数据手册, 时钟树结构如下

CH32V208 的时钟相对于 CH32V307 的不同点: 在CH307中没有 ETH-PHY
对于 CH32F20x_D8C 和 CH32V30x_D8C, 当使用 USB 功能时,CPU 的频率必须是48MHz、96MHz 或 144MH
而在 CH32V208中, ETH-PHY 的时钟通过 HCLK 提供
CH32F20x_D8W, CH32V20x_D8 和 CH32V20x_D8W 若同时使用 USB 和 ETH 功能, 需将 USBPRE[1:0]置为 11b
对于 USBPRE[1:0] 这个寄存器值为 0B11 时的说明
5 分频, 且 PLL 的源为 HSE 二分频(适用于PLLCLK=240MHz , 仅 适 用 于 CH32V20x_D8W/ CH32F20x_D8W) 注: CH32V20x_D8W、CH32F20x_D8W 具有 11b 选项, 其余型号该选项保留
可以看到, CH32V208 如果要同时使用 USB 和 ETH, 为了同时满足 USB 的48MHz, ETH-PHY 的60MHz, 需要将 PLLCLK 升至240MHz, 5分频后输出给 USB, 而 ETH-PHY 则从 120MHz 的 HCLK 通过2分频得到 60MHz
另一个需要注意的点是, BLE的 RFCLK 时钟是由 HSE 提供的, 如果时钟树没错的话, 可以理解为只有外接时钟源才能使用 BLE.
时钟设置代码
在沁恒提供的 SDK 和代码示例中, 与时钟相关的代码主要是这两个文件
ch32v20x.h
文件中定义了外置时钟源的频率 HSE_VALUE, CH32V208 默认使用的是 32MHz, 如果使用其他频率的晶振, 需要在这里修改
#if defined(CH32V20x_D8) || defined(CH32V20x_D8W) #define HSE_VALUE ((uint32_t)32000000) /* Value of the External oscillator in Hz */#else #define HSE_VALUE ((uint32_t)8000000) /* Value of the External oscillator in Hz */#endif
而内建时钟源是固定的 8MHz
#define HSI_VALUE ((uint32_t)8000000) /* Value of the Internal oscillator in Hz */
system_ch32v20x.c
这个文件存在于每个示例项目的 User 目录下, 已经实现了常用的频率值函数, 通过修改宏配置可以切换不同的系统频率
//#define SYSCLK_FREQ_HSE HSE_VALUE//#define SYSCLK_FREQ_48MHz_HSE 48000000//#define SYSCLK_FREQ_56MHz_HSE 56000000//#define SYSCLK_FREQ_72MHz_HSE 72000000//#define SYSCLK_FREQ_96MHz_HSE 96000000//#define SYSCLK_FREQ_120MHz_HSE 120000000#define SYSCLK_FREQ_144MHz_HSE 144000000//#define SYSCLK_FREQ_HSI HSI_VALUE//#define SYSCLK_FREQ_48MHz_HSI 48000000//#define SYSCLK_FREQ_56MHz_HSI 56000000//#define SYSCLK_FREQ_72MHz_HSI 72000000//#define SYSCLK_FREQ_96MHz_HSI 96000000//#define SYSCLK_FREQ_120MHz_HSI 120000000//#define SYSCLK_FREQ_144MHz_HSI 144000000
在里面搜索(3<<22)
, 对应 RCC->CFGR0, (3<<22)
就是 USBPRE 寄存器, 可以看到在设置系统频率为 120MHz 时的特殊处理.
void SystemCoreClockUpdate (void){ uint32_t tmp = 0, pllmull = 0, pllsource = 0, Pll_6_5 = 0; tmp = RCC->CFGR0 & RCC_SWS; switch (tmp) { case 0x00: SystemCoreClock = HSI_VALUE; break; case 0x04: SystemCoreClock = HSE_VALUE; break; case 0x08: pllmull = RCC->CFGR0 & RCC_PLLMULL; pllsource = RCC->CFGR0 & RCC_PLLSRC; pllmull = ( pllmull >> 18) + 2; if(pllmull == 17) pllmull = 18; if (pllsource == 0x00) { if(EXTEN->EXTEN_CTR & EXTEN_PLL_HSI_PRE){ SystemCoreClock = HSI_VALUE * pllmull; } else{ SystemCoreClock = (HSI_VALUE >> 1) * pllmull; } } else {#if defined (CH32V20x_D8W) // 对应 CH32V208 额外的处理逻辑 if((RCC->CFGR0 & (3<<22)) == (3<<22)) // 如果 USBPRE 为 11, 仅出现在 120MHz的配置函数中 { SystemCoreClock = ((HSE_VALUE>>1)) * pllmull; // 系统时钟为 32 / 2 * 15 = 240MHz } else#endif if ((RCC->CFGR0 & RCC_PLLXTPRE) != (uint32_t)RESET) {#if defined (CH32V20x_D8) || defined (CH32V20x_D8W) SystemCoreClock = ((HSE_VALUE>>2) >> 1) * pllmull;#else SystemCoreClock = (HSE_VALUE >> 1) * pllmull;#endif } else {#if defined (CH32V20x_D8) || defined (CH32V20x_D8W) SystemCoreClock = (HSE_VALUE>>2) * pllmull;#else SystemCoreClock = HSE_VALUE * pllmull;#endif } } if(Pll_6_5 == 1) SystemCoreClock = (SystemCoreClock / 2); break; default: SystemCoreClock = HSI_VALUE; break; } tmp = AHBPrescTable[((RCC->CFGR0 & RCC_HPRE) >> 4)]; // 通过 AHBPrescTable 对应的分频系数, 降回 120MHz SystemCoreClock >>= tmp;}
AHBPrescTable 的分频系数数组为
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
在 SetSysClockTo120_HSE(void) 中, 设置了 RCC_HPRE_DIV2
RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;
而 RCC_HPRE_DIV2 的值对应的是 0x00000080, RCC_HPRE 的值是 0x000000F0
#define RCC_HPRE ((uint32_t)0x000000F0) /* HPRE[3:0] bits (AHB prescaler) */#define RCC_HPRE_0 ((uint32_t)0x00000010) /* Bit 0 */#define RCC_HPRE_1 ((uint32_t)0x00000020) /* Bit 1 */#define RCC_HPRE_2 ((uint32_t)0x00000040) /* Bit 2 */#define RCC_HPRE_3 ((uint32_t)0x00000080) /* Bit 3 */ #define RCC_HPRE_DIV1 ((uint32_t)0x00000000) /* SYSCLK not divided */#define RCC_HPRE_DIV2 ((uint32_t)0x00000080) /* SYSCLK divided by 2 */#define RCC_HPRE_DIV4 ((uint32_t)0x00000090) /* SYSCLK divided by 4 */
通过 RCC->CFGR0 & RCC_HPRE, 可以还原回 0x00000080, 再右移4位, 就变成 0x00000008, 对应 AHBPrescTable 中的第9个, 值为1, SystemCoreClock 右移1位, 相当于除以2, 值从240MHz变回120MHz.
Recommend
-
45
新浪科技讯北京时间1月15日下午消息,在经过为期一年半的价格暴涨之后,部分存储芯片的价格突然急速下滑,之后三星电子发布了一份并不乐观的2017年业绩预期,这两件事情让那些押注芯片行业的投资人陷入了深深的不安,一些投资人曾经认为芯片行业的红火
-
67
1、查看mysql提供的引擎。MariaDB [(none)]> show engines;+--------------------+---------+----------------------------------------------------------------------------+--------------+------+----
-
48
-
51
-
63
云计算 - @Jackyxiaoc - 最近接到老板的需求,要把监控视频永久储存。请问各位 v 友是否有廉价可靠的储存方案提供。测试环境情况如下:摄像头数:4摄像头每周产生的数据:550g一年数据:26.5T十年数据
-
67
概观本指南支持在Kubernetes集群中集成,部署和管理GlusterFS容器化存储节点。这使Kubernetes管理员能够为其用户提供可靠的共享存储。包括设置指南、其中包含一个示例服务器pod,它使用动态配置的GlusterFS卷进行存储。对于那些希望测试或了解有关此主题的更多信息...
-
11
CH32V003 沁恒最近推出的低价CH32V003系列, 基于青稞RISC-V2A内核, 48MHz主频, 2KB SRAM, 16KB Flash, 工作电压兼容3.3V和5V. 主要参数如下 System Clock: 48MHz SRAM: 2KB Flash: 16KB Power Suppl...
-
8
沁恒 CH32V208(一): CH32V208WBU6 评估板上手报告和Win10环境配置 CH32V208 CH32V208系列是沁恒32位RISC-V中比较新的一个系列, 基于青稞...
-
4
Milton 日常笔记, 仅供个人学习使用 随笔 - 810, 文章 - 0, 评论...
-
11
在使用MySQL数据库的时候,我们知道了它有两种物理存储结构,hash存储和B+树存储,由于hash存储使用的少,而B+树存储使用的范围就多些,如 InnoDB和MYISAM引擎都是使用的B+树作为存储结构, B+树,顾名思义,它还是树形结构,那么它是怎么演变过来的,那么就...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK