前文:最近使用瑞萨MCU搭建了一个最小单片机系统,一下子梦回到最初学习单片机的那堂课,当时是在老师的指导下完成了小灯的闪烁,但是还是不理解整个系统的运行的方式与原理,后面随着做的项目的增多,对于单片机系统有了一个越来越清晰的理解。正好趁着这个机会系统的介绍一下一个MCU最小系统的启动方式与流程。
目录
1,最小系统搭建背景
2,MCU最小系统概述
(1)电源电路
(2)复位电路
(3)时钟电路
(4)下载调试电路
3,基于最小系统理解启动流程
3.1 硬件上电
3.2 复位释放与启动模式采样
3.3 CPU 进入复位向量
3.4 启动代码与运行环境初始化
3.5 MCU 基础硬件初始化
3.6 软件框架初始化
3.7 应用程序运行
4,汇编代码附录
1,最小系统搭建背景
最近遇到了一个MCU板端的问题,发现在系统板子上面芯片无法进行正常的烧录,怀疑是产品板出现了问题,于是将芯片放到了一个最小系统板上面进行测试,果然可以进行正常的烧录。话说回来这个就引出了最小系统是如何工作的问题。
下面的这些烧录测试的截图:当Operation completed出现的时候就表示着整个MCU最小系统的搭建完成。
2,MCU最小系统概述
基本的最小系统的开发板的形式如图所示:一面由可以拆卸的芯片固定器,一面是一个最小系统电路。
对于单片机最小系统而言,我们都知道其是由电源电路,复位电路,时钟电路与下载调试电路组成。
可以说只要一个单片机加上任何以上的电路就可以正常运行,下面就基于本篇文章的F1KMS1来一一介绍一下每一个组成部分与设计依据。
(1)电源电路
将一个芯片上面所有的EVCC与REGVCC与AWOVCL都接上一个5V或者3.3V的电源,然后并上一个电容到地,电容的大小一般是100nf左右,然后将所有的EVSS与AWOVSS等一些接地引脚接地
为什么需要电容?
MCU 在运行过程中,CPU、Flash、外设模块会产生动态电流变化。如果电源网络阻抗较大,就可能产生电压波动。
去耦电容主要承担两个作用:
滤除电源上的高频噪声。
在 MCU 瞬间需要较大电流时提供局部电荷
另外如果要用到模拟功能的话,也需要将对应参考电源与模拟接地都连上
(2)复位电路
这是一个典型的 RC 复位电路。其工作原理:
【第一阶段:上电】电源 VDD_5V 上升,电容 C11 开始充电。由于电容两端电压不能瞬间变化,RESET 节点在上电初期会受到 RC 网络影响。
【第二阶段:复位释放】随着 C11 充电,RESET 节点逐渐上升,达到 MCU 复位释放所要求的电平后,MCU 退出复位状态。
(3)时钟电路
时钟电路的作用是给 MCU 提供时钟基准。MCU 内部的 CPU、定时器、通信外设等模块都需要时钟信号才能正常工作。这张图采用的是外部晶振方案。
芯片复位启动时会先使用高速内部振荡器。 外部晶振并不是上电后自动接管时钟,而是需要软件启动 MainOSC,并按照时钟切换流程配置时钟选择器。因此,如果你不使用外部晶振,通常可以让系统继续使用 HS IntOSC,或者根据需求使用内部时钟作为 PLL 输入
内部时钟启动流程
MCU 上电 / 复位释放
芯片使用默认的内部高速振荡器启动。
确认 HS IntOSC 状态
读取
ROSCS,确认内部振荡器处于正常工作状态。配置 PLL(可选)
如果 CPU 需要高于内部振荡器的工作频率,按照手册配置 PLL 输入源、倍频参数和稳定时间。
配置时钟选择器
配置 CPU 时钟域、外设时钟域对应的
CKSC寄存器。确认时钟切换状态
按照寄存器规定的写保护解锁、切换、状态确认流程执行。
初始化外设
根据最终外设时钟频率配置 CAN、LIN、SPI、ADC、定时器等。
一般的MCU系统都是使用外部晶振
为什么需要两个电容?
因为晶振需要满足一定的负载电容条件才能稳定起振。
实际负载电容不仅取决于 C17、C18,还需要考虑 PCB 走线和 MCU 引脚的寄生电容。
另外,MCU 也可能支持内部高速振荡器,因此是否必须使用外部晶振,需要结合系统时钟精度、通信波特率和应用要求判断。
(4)下载调试电路
下载调试电路顾名思义主要是两个功能,主要是下载固件与DEBUG调试的作用,具体的连接还是需要查询对应的调试器使用手册根据选择的不同的模式进行连线。
瑞萨的基本下载调试电路组成接口如下:
RESET:复位信号。
FLMD0:Flash 编程模式控制相关引脚。
JP0_1~JP0_5:相关通信或调试信号。
VDD_5V:目标板参考电压。
GND:地。
这个接口主要用于:
通过瑞萨调试器连接 MCU。
下载用户程序。
在线调试和断点调试。
查看寄存器和 RAM 数据。
进行 Flash 编程及擦除。
3,基于最小系统理解启动流程
3.1 硬件上电
VCC / EVCC 等电源建立,电源监控确认电压条件
【外部电源建立】结合前面搭建的最小系统板,外部电源从VDD_5V进入电路,为 MCU 的相关电源域供电。RH850/F1KM 系列包含多个电源域,不同电源域分别负责不同的内部功能。
【内部 POC 检测电源】RH850 内部具有 POC(Power-on Clear)电路。POC 的主要作用是监控上电过程中的电源状态,在电源条件尚未满足要求时,使 MCU 内部保持复位状态。
3.2 复位释放与启动模式采样
RESET、MODE、FLMD 等相关引脚及启动条件
【外部 RESET 电路工作】刚上电时,C11 尚未充电,RESET 节点电压较低。随后,VDD_5V 通过 R13 给 C11 充电,RESET 电压逐渐升高
【启动模式采样】正常上电运行时,FLMD0 应处于低电平对应的正常运行模式条件。而使用编程器进入 Flash 编程模式时,需要由编程器按照规定时序控制 FLMD0、FLMD1 等模式
FLMD0 | FLMD1(P10_8) | 其他模式引脚 | 工作模式 |
|---|---|---|---|
0 | X | X | Normal operating mode |
1 | 0 | X | Flash programming mode |
1 | 1 | MODE0=0、MODE1=1 | Boundary scan |
1 | 1 | MODE0=1、MODE1=1、MODE2=1 | User boot mode |
3.3 CPU 进入复位向量
取指、执行启动代码;具体入口和启动路径取决于芯片及配置
【CPU 退出内部复位】CPU 在复位期间,其正常指令执行流程受到复位控制。
【CPU内部状态初始化】复位释放后,CPU 内部状态按照架构规定进行初始化,包括:
CPU 控制寄存器进入复位状态;
程序计数器等关键执行状态初始化;
异常和中断相关控制状态进入规定的初始状态;
CPU 开始执行复位入口处的指令。
3.4 启动代码与运行环境初始化
堆栈、全局变量、RAM、异常/中断基础环境等
【初始化 CPU 运行环境】
【初始化 RAM】程序运行过程中会使用 RAM 保存变量、堆栈和运行数据
RAM 段 | 主要作用 | 启动处理 |
|---|---|---|
| 已初始化的全局变量和静态变量 | 将初始值从 ROM/Flash 拷贝到 RAM |
| 未初始化的全局变量和静态变量 | 清零 |
| 函数调用、中断等使用的栈空间 | 设置栈区域 |
| 动态内存分配 | 按工程配置建立 |
【初始化异常和中断向量】
【C 语言运行环境初始化】典型操作包括:
初始化
.data。清零
.bss。初始化运行库所需的内部状态。
根据工程配置执行 C/C++ 全局对象初始化。
调用
main()。
3.5 MCU 基础硬件初始化
裸机进入 main();时钟、保护寄存器、端口、看门狗、外设和中断控制器
进入这一阶段之后,软件已经可以执行 C 代码,开始初始化 MCU 内部硬件资源。
对于 RH850/F1KM,重点是:时钟;端口;模块保护;定时器;ADC;CAN;LIN;SPI;中断控制器。
3.6 软件框架初始化
AUTOSAR 工程进入 EcuM / OS 等启动流程
3.7 应用程序运行
周期任务、中断、通信、诊断、控制逻辑开始工作
4,汇编代码附录
启动代码 sc_boot.asm
; Copyright(c) 2018 Renesas Electronics Corporation ; RENESAS ELECTRONICS CONFIDENTIAL AND PROPRIETARY. ; This program must be used solely for the purpose for which ; it was furnished by Renesas Electronics Corporation. No part of this ; program may be reproduced or disclosed to others, in any ; form, without the prior written permission of Renesas Electronics ; Corporation. ; NOTE : THIS IS A TYPICAL EXAMPLE for SC for RH850/F1KM. ; DATE : Thu, Apr 12, 2018 ; if using eiint as table reference method, ; enable next line's macro. USE_TABLE_REFERENCE_METHOD .set 1 ;----------------------------------------------------------------------------- ; exception vector table ;----------------------------------------------------------------------------- .section "RESET", text .align 512 jr32 __start ; RESET .align 16 syncp jr32 _Dummy ; SYSERR .align 16 jr32 _Dummy .align 16 jr32 _Dummy ; FETRAP .align 16 jr32 _Dummy_EI ; TRAP0 .align 16 jr32 _Dummy_EI ; TRAP1 .align 16 jr32 _Dummy ; RIE .align 16 syncp jr32 _Dummy_EI ; FPP/FPI .align 16 jr32 _Dummy ; UCPOP .align 16 jr32 _Dummy ; MIP/MDP .align 16 jr32 _Dummy ; PIE .align 16 jr32 _Dummy .align 16 jr32 _Dummy ; MAE .align 16 jr32 _Dummy .align 16 syncp jr32 _Dummy ; FENMI .align 16 syncp jr32 _Dummy ; FEINT .align 16 syncp jr32 _Dummy_EI ; INTn(priority0) .align 16 syncp jr32 _Dummy_EI ; INTn(priority1) .align 16 syncp jr32 _Dummy_EI ; INTn(priority2) .align 16 syncp jr32 _Dummy_EI ; INTn(priority3) .align 16 syncp jr32 _Dummy_EI ; INTn(priority4) .align 16 syncp jr32 _Dummy_EI ; INTn(priority5) .align 16 syncp jr32 _Dummy_EI ; INTn(priority6) .align 16 syncp jr32 _Dummy_EI ; INTn(priority7) .align 16 syncp jr32 _Dummy_EI ; INTn(priority8) .align 16 syncp jr32 _Dummy_EI ; INTn(priority9) .align 16 syncp jr32 _Dummy_EI ; INTn(priority10) .align 16 syncp jr32 _Dummy_EI ; INTn(priority11) .align 16 syncp jr32 _Dummy_EI ; INTn(priority12) .align 16 syncp jr32 _Dummy_EI ; INTn(priority13) .align 16 syncp jr32 _Dummy_EI ; INTn(priority14) .align 16 syncp jr32 _Dummy_EI ; INTn(priority15) ; .section "EIINTTBL", const ; .align 512 ; .dw #_Dummy_EI ; INT0 ; .dw #_Dummy_EI ; INT1 ; .dw #_Dummy_EI ; INT2 ; .rept 512 - 3 ; .dw #_Dummy_EI ; INTn ; .endm .section ".text", text .align 2 _Dummy: br _Dummy _Dummy_EI: br _Dummy_EI ;----------------------------------------------------------------------------- ; startup ;----------------------------------------------------------------------------- .section ".text", text .align 2 __start: $if 1 ; initialize register $nowarning mov r0, r1 $warning mov r0, r2 mov r0, r3 mov r0, r4 mov r0, r5 mov r0, r6 mov r0, r7 mov r0, r8 mov r0, r9 mov r0, r10 mov r0, r11 mov r0, r12 mov r0, r13 mov r0, r14 mov r0, r15 mov r0, r16 mov r0, r17 mov r0, r18 mov r0, r19 mov r0, r20 mov r0, r21 mov r0, r22 mov r0, r23 mov r0, r24 mov r0, r25 mov r0, r26 mov r0, r27 mov r0, r28 mov r0, r29 mov r0, r30 mov r0, r31 ldsr r0, 0, 0 ; EIPC ldsr r0, 16, 0 ; CTPC $endif jarl _hdwinit, lp ; initialize hardware $ifdef USE_TABLE_REFERENCE_METHOD mov #__sEIINTTBL.const, r6 jarl _set_table_reference_method, lp ; set table reference method $endif jr32 __cstart ;----------------------------------------------------------------------------- ; hdwinit ; Specify RAM addresses suitable to your system if needed. ;----------------------------------------------------------------------------- GLOBAL_RAM_ADDR .set 0 GLOBAL_RAM_END .set 0 LOCAL_RAM_ADDR .set 0 LOCAL_RAM_END .set 0 .align 2 _hdwinit: mov lp, r14 ; save return address ; clear Global RAM mov GLOBAL_RAM_ADDR, r6 mov GLOBAL_RAM_END, r7 jarl _zeroclr4, lp ; clear Local RAM mov LOCAL_RAM_ADDR, r6 mov LOCAL_RAM_END, r7 jarl _zeroclr4, lp mov r14, lp jmp [lp] ;----------------------------------------------------------------------------- ; zeroclr4 ;----------------------------------------------------------------------------- .align 2 _zeroclr4: br .L.zeroclr4.2 .L.zeroclr4.1: st.w r0, [r6] add 4, r6 .L.zeroclr4.2: cmp r6, r7 bh .L.zeroclr4.1 jmp [lp] $ifdef USE_TABLE_REFERENCE_METHOD ;----------------------------------------------------------------------------- ; set table reference method ;----------------------------------------------------------------------------- ; interrupt control register address ICBASE .set 0xfffeea00 .align 2 _set_table_reference_method: ldsr r6, 4, 1 ; set INTBP ; Some interrupt channels use the table reference method. ; mov ICBASE, r10 ; get interrupt control register address ; set1 6, 0[r10] ; set INT0 as table reference ; set1 6, 2[r10] ; set INT1 as table reference ; set1 6, 4[r10] ; set INT2 as table reference jmp [lp] $endif ;-------------------- end of start up module -------------------;sc_cstart.asm
; Copyright(c) 2013, 2016 Renesas Electronics Corporation ; RENESAS ELECTRONICS CONFIDENTIAL AND PROPRIETARY. ; This program must be used solely for the purpose for which ; it was furnished by Renesas Electronics Corporation. No part of this ; program may be reproduced or disclosed to others, in any ; form, without the prior written permission of Renesas Electronics ; Corporation. ; NOTE : THIS IS A TYPICAL EXAMPLE. ; DATE : Mon, Oct 24, 2016 ;----------------------------------------------------------------------------- ; system stack ;----------------------------------------------------------------------------- STACKSIZE .set 0x200 .section ".stack.bss", bss .align 4 .ds (STACKSIZE) .align 4 _stacktop: ;----------------------------------------------------------------------------- ; section initialize table ;----------------------------------------------------------------------------- .section ".INIT_DSEC.const", const .align 4 .dw #__s.data, #__e.data, #__s.data.R .section ".INIT_BSEC.const", const .align 4 .dw #__s.bss, #__e.bss ;----------------------------------------------------------------------------- ; startup ;----------------------------------------------------------------------------- .section ".text", text .public __cstart .align 2 __cstart: mov #_stacktop, sp ; set sp register mov #__gp_data, gp ; set gp register mov #__ep_data, ep ; set ep register mov #__s.INIT_DSEC.const, r6 mov #__e.INIT_DSEC.const, r7 mov #__s.INIT_BSEC.const, r8 mov #__e.INIT_BSEC.const, r9 jarl32 __INITSCT_RH, lp ; initialize RAM area ; enable FPU $if 1 ; disable this block when not using FPU stsr 6, r10, 1 ; r10 <- PID shl 21, r10 shr 30, r10 bz .L1 ; detecting FPU stsr 5, r10, 0 ; r10 <- PSW movhi 0x0001, r0, r11 or r11, r10 ldsr r10, 5, 0 ; enable FPU movhi 0x0002, r0, r11 ldsr r11, 6, 0 ; initialize FPSR ldsr r0, 7, 0 ; initialize FPEPC .L1: $endif ; set various flags to PSW via FEPSW stsr 5, r10, 0 ; r10 <- PSW ;xori 0x0020, r10, r10 ; enable interrupt ;movhi 0x4000, r0, r11 ;or r11, r10 ; supervisor mode -> user mode ldsr r10, 3, 0 ; FEPSW <- r10 mov #_exit, lp ; lp <- #_exit mov #_main, r10 ldsr r10, 2, 0 ; FEPC <- #_main ; apply PSW and PC to start user mode feret _exit: br _exit ; end of program ;----------------------------------------------------------------------------- ; dummy section ;----------------------------------------------------------------------------- .section ".data", data .L.dummy.data: .section ".bss", bss .L.dummy.bss: .section ".const", const .L.dummy.const: .section ".text", text .L.dummy.text: ;-------------------- end of start up module -------------------;完结。。。