gd32vf103 启动文件分析

/*** Reset Handler called on controller reset*/
_start:/* ===== Startup Stage 1 ===== *//* csrc是伪指令* csrc csr rs -> csrrc x0, csr, rs : Clear bits in CSR* csrrc指令格式 csrrc rd, csr, rs1* CSRRC(CSR 中的原子读取和清除位)指令读取 CSR 的值,将值零扩展到 XLEN* 位,并将其写入整数寄存器 rd。 整数寄存器 rs1 中的初始值被视为位掩码,* 指定要在 CSR 中清除的位位置。 如果 CSR 位可写,rs1 中的任何高位都会导致* CSR 中的相应位被清除。 CSR 中的其他位不受影响。 * MSTATUS_MIE MIE bit * machine状态下的全局中断控制位 1:enable 0: disable* 这里是关闭中断*/ /* Disable Global Interrupt */csrc CSR_MSTATUS, MSTATUS_MIE/* Jump to logical address first to ensure correct operation of RAM region  *//* 如果是flash启动的话,_start地址是 0x0800xxxx * 如果是ram启动,__start地址是0x2000xxxx*/la      a0, _startli      a1, 1/* 这里的值是 1<<29 = 0x20000000 就是ram的地址*/slli    a1, a1, 29/* 如果_start大于0x20000000 则说明是从ram启动* 这里跳到_start0800去执行*/bleu    a1, a0, _start0800/* 0x20000000>>2 = 0x08000000 这里对应flash的基地址 */ srli    a1, a1, 2/* 如果_start大于0x08000000,则说明是从flash启动* 同样跳到_start0800去执行*/bleu    a1, a0, _start0800/* 走到这里的话,说明_start地址是小于0x08000000的* 这是有问题的,所以强制执行 0x08000000+_start0800* 也就是定位到flash中*/la      a0, _start0800add     a0, a0, a1jr      a0  _start0800:/* Initialize GP and Stack Pointer SP */.option push.option norelax/* 将标签__global_pointer$所处的地址赋值给gp寄存器* _global_pointer在链接脚本中定义参见链接脚本*/la gp, __global_pointer$.option pop /* 设置堆栈指针* _sp在链接脚本中定义*/la sp, _sp /*  * Set the the NMI base mnvec to share* with mtvec by setting CSR_MMISC_CTL* bit 9 NMI_CAUSE_FFF to 1*/ /* #define MMISC_CTL_NMI_CAUSE_FFF     (1<<9)* #define CSR_MMISC_CTL           0x7D0* mmisc_ctl 自定义寄存器用于控制NMI的处理程序地址入口* bit 9置1后,mnvec 的值与 mtvec 一致,NMI 的 mcause.EXCCODE 为* 0xfff* mnvec 寄存器用于配置 NMI 的入口地址* mtvec 寄存器用于配置中断和异常处理程序的入口地址*/li t0, MMISC_CTL_NMI_CAUSE_FFFcsrs CSR_MMISC_CTL, t0/*  * Intialize ECLIC vector interrupt* base address mtvt to vector_base*/  /* mtvt ECLIC 中断向量表的基地址 * 填充基地址*/la t0, vector_basecsrw CSR_MTVT, t0/*  * Set ECLIC non-vector entry to be controlled* by mtvt2 CSR register.* Intialize ECLIC non-vector interrupt* base address mtvt2 to irq_entry.*//* 自定义* mtvt2 用于指定 ECLIC 非向量模式的中断 common-code 入口地址* bit2~bit31 用于存放common-code入口地址 所以改地址需要4bytes对齐* bit0:*  0: 入口地址有mtvec决定*  1: 入口地址就是设置的值*/la t0, irq_entrycsrw CSR_MTVT2, t0csrs CSR_MTVT2, 0x1 /** Set Exception Entry MTVEC to exc_entry* Due to settings above, Exception and NMI* will share common entry.*//* 异常处理程序入口地址* 同样要4bytes对齐*/la t0, exc_entrycsrw CSR_MTVEC, t0/* Set the interrupt processing mode to ECLIC mode *//* mtvee中bit0~bit5 值为3的时候,中断处理模式为ECLIC中断模式* 其他值的话则是 默认中断模式*/li t0, 0x3fcsrc CSR_MTVEC, t0csrs CSR_MTVEC, 0x3/* mtvc中记录了中断向量表的地址* 都知道有向量中断和非向量中断,两者的区别这些不多说* 下面通过寄存器说一下两者之前的区别和联系* 1. 无论中断是向量模式还是非向量模式,硬件都会通过查询中断向量表中的*    地址跳到其对应的中断服务程序中。* 2. mtvec 中记录了异常入口地址*    mtvt2 中记录了非向量中断入口地址*    这2个地址的区别?*    mtvt2中有个有个bit0*    值为0的时候,非向量中断入口地址是mtvec中的地址*    这个是异常和中断使用一个入口地址*    值为1的时候,非向量中断入口地址是mtvt2中记录的地址*    这个时候,非向量中断的入口地址是mtvt2,而异常的入口地址是mtevc*    异常和中断的入口地址是分开的* 3. 怎么设置使用向量中断和非向量中断?*    ECLIC的每个中断源均可以设置成向量或者非向量处理*   (通过寄存器clicintattr[i]的shv域)*   3.1 如果被配置成为向量处理模式 (clicintattr[i].shv==1),*        则该中断被处理器内核响应后,处理器直接跳入该中断的向量入口*       (Vector Table Entry)存储的目标地址*   3.2 如果被配置成为非向量处理模式 (clicintattr[i].shv==0),*       则该中断被处理器内核响应后,处理器直接跳入所有中断共享的入口*       地址 * 默认是非向量中断*//* __riscv_flen没有定义,所以这里不会执行 */
#ifdef __riscv_flen/* Enable FPU */li t0, MSTATUS_FScsrs mstatus, t0csrw fcsr, x0
#endif/* Enable mcycle and minstret counter */csrci CSR_MCOUNTINHIBIT, 0x5/* ===== Startup Stage 3 ===== *//** Load code section from FLASH to ILM* when code LMA is different with VMA*//* LMA: 内存装载地址*      比如程序原来是在flash中,如果可以在flash中执行,那么LMA*      就是flash地址。如果需要搬运到ram中运行,那么LMA就是ram地址* VMA: 虚拟内存地址*      一般来说启用了MMU之后,才有虚拟地址和实地址。*      这里不考虑MMU,可以认为就是实际运行的地址* _ilm_lma 和 _ilm 是在链接脚本中定义的* ld文件:* MEMORY* {*      flash (rxai!w) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE*      ram (wxa!ri) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE* }* .ilalign         :* {*      . = ALIGN(4);*   /* Create a section label as _ilm_lma which located at flash */*      PROVIDE( _ilm_lma = . );* } >flash AT>flash** .ialign         :* {*  /* Create a section label as _ilm which located at flash */*      PROVIDE( _ilm = . );* } >flash AT>flash* 语法中AT前的一个flash表示该段的运行地址,AT后的flash表示该段的物* 理地址 * 注意如果后面没有设置>ram* 则说明后面的段都是在flash中的*//* 可以看到都是在flash中,所以_ilm_lma和_ilm值一样* 跳到下一个2执行*/la a0, _ilm_lmala a1, _ilm/* If the ILM phy-address same as the logic-address, then quit */beq a0, a1, 2fla a2, _eilmbgeu a1, a2, 2f1:/* Load code section if necessary */lw t0, (a0)sw t0, (a1)addi a0, a0, 4addi a1, a1, 4bltu a1, a2, 1b
2:/* Load data section *//* _data_lma是在flash中的* _data和_edata是在ram中* a1 < a2的话,说明data段中有数据*/la a0, _data_lmala a1, _datala a2, _edatabgeu a1, a2, 2f
1:/* 下面将data段从flash中拷贝到ram */lw t0, (a0)sw t0, (a1)addi a0, a0, 4addi a1, a1, 4bltu a1, a2, 1b
2:/* Clear bss section */la a0, __bss_startla a1, _endbgeu a0, a1, 2f
1:/* 清空bss段 */sw zero, (a0)addi a0, a0, 4bltu a0, a1, 1b
2:/** Call vendor defined SystemInit to* initialize the micro-controller system*//* 调用C函数 SystemInit * 主要是初始化时钟*/call SystemInit/*__libc_fini_array 和 __libc_init_array 是库里面定义的* 主要作用就是 执行fini_array段和init_aray段中的函数*//* Call global constructors */la a0, __libc_fini_arraycall atexit/* Call C/C++ constructor start up code */call __libc_init_array/* _premain_init 这里主要是初始化 gd32vf103的外设* 比如 gpio i2c uart等等*//* do pre-init steps before main */call _premain_init/* 默认main函数无参数*//* ===== Call Main Function  ===== *//* argc = argv = 0 */li a0, 0li a1, 0/* 如果编译RTT,则入口函数是enrty* 非RTT,入口函数是main*/
#ifdef RTOS_RTTHREAD// Call entry function when using RT-Threadcall entry
#elsecall main
#endif/* 从main函数退出的话,则执行_postmain_fini *//* do post-main steps after main */call _postmain_fini/* 跳到清bss 重新执行 */
1:j 1b

以上汇编代码可以借鉴
https://www.nucleisys.com/product/n100/6_sdk/

1.2 nuclei sdk gd32vf03 启动文件分析相关推荐

  1. STM32启动过程解析-2.02固件库启动文件分析

    源:STM32启动过程解析-2.02固件库启动文件分析 转载于:https://www.cnblogs.com/LittleTiger/p/9205372.html

  2. startup_LPC17XX.s 启动文件分析

    startup_LPC17XX.s 启动文件分析 工程中startup_LPC17XX.s是M3的启动文件,启动文件由汇编语言写的,它的作用一般是下面这几个: 1)堆和栈的初始化 2)中断向量表定义 ...

  3. Cortex-M3 .s 启动文件分析

    Cortex-M3 .s启动文件分析 arm 中常见的汇编指令和伪指令 下面是startup_.s文件的源代码, 该文件主要完成三项工作:堆栈以及堆的初始化.定位中断向量表.调用Reset Handl ...

  4. STM32F4XX启动文件分析

    STM32F4XX启动文件分析 - STM32F4XX启动文件下载地址 导读:STM32F4XX启动文件的作用 初始化设置SP,即栈指针 初始化设置PC指针指向复位中断处理函数,即PC = Reset ...

  5. 二、IAR for ARM中STM32项目创建及其启动文件分析

    IAR for ARM STM32F10X官方固件库: 链接: https://pan.baidu.com/s/1U6vfGqp9IhhkvVuDXcxTtQ 提取码: 9mcx IAR for AR ...

  6. STM32启动文件分析

    相对于ARM上一代的主流ARM7/ARM9内核架构,新一代Cortex内核架构的启动方式有了比较大的变化. ARM7/ARM9内核的控制器在复位后,CPU会从存储空间的绝对地址0x000000取出第一 ...

  7. 秉火429笔记之四启动文件分析

    名为"startup_stm32f429_439xx.s"的文件,它里边使用汇编语言写好了基本程序,当STM32芯片上电启动的时候,首先会执行这里的汇编程序,从而建立起C语言的运行 ...

  8. or1k启动文件分析

    or1k从spi flash启动文件spi_uimage_loader.S内容如下: /* Assembly program to go into the boot ROM *//* For use ...

  9. startup_stm32f10x_hd.s启动文件分析

    ;* 文件名          : startup_stm32f10x_hd.s ;* 库版本           : V3.5.0 ;* 说明:             此文件为STM32F10x高 ...

最新文章

  1. linux格式化文件,无需格式化就可以转换文件系统
  2. Facebook 对前端工程师的要求是啥?一起来看看
  3. 了解计算机指令和汇编指令
  4. 用Unity3D实现智能巡逻兵游戏
  5. USACO 1.5.4 Checker Challenge
  6. linux软件工程师笔试题,C/C++软件工程师笔试题
  7. Qt/C++工作笔记-对vector与QVector中erase操作的进一步认识(区别与联系)
  8. Code Project - Your First C# Web Service
  9. 一个敏捷教练成长必备的8项技能
  10. php5.4全局变量,PHP 5 全局变量 - 超全局变量
  11. python是什么意思啊-星号*在Python中是什么意思?
  12. Chromedriver和Chrome浏览器版本
  13. 怎样建自己的网站?如何建立一个网站?建网站的步骤?
  14. RK3399 制作更新logo.img
  15. vue页面背景颜色修改
  16. 卡券、直充下单接口文档
  17. 去哪儿网2015年春季校园招聘技术笔试题
  18. 撕开帝国裂缝的互联网+饮料公司——元气森林是如何做的?
  19. 老师助手为什么总是服务器错误,【家长助手】孩子在校总犯错 解决内因最关键...
  20. 12月27日刷题总结

热门文章

  1. Linux进行syn攻击的代码,Linux遭受SYN洪水攻击设置
  2. python麻将和牌算法
  3. 盘点:物联网产业的六大特征
  4. ios端h5页面双击页面会发生滚动问题解决办法
  5. GUI 剖析之 控件篇1)按钮控件
  6. python基础list_python基础学习之列表list
  7. 连通图存在欧拉回路,等价于每个节点的度为偶数
  8. 嵌入式设备和固件中的自动漏洞检测(三):静态分析技术
  9. java对接移动物联网onenet平台实现接收设备上报数据命令下发
  10. win8连接wifi成功但受限制_必看丨“格力+”手机APP,智能WiFi连接教程。(含AI语音连接教程)...