GD32VF103 Bootstrap指南(二)

GD32VF103 引导代码和中断原理分析(二)

作者:水银
Email:athieka@hotmail.com
龙眼Longan RV技术交流群: 816177882
转载请注明作者和出处

_start代码分析

    .globl _start           // 定义全局_start符号
	.type _start,@function  // 指定_start类型为function

    _start:

	csrc CSR_MSTATUS, MSTATUS_MIE   // csr寄存器mstatus的mie位清零,关全局中断
	/* Jump to logical address first to ensure correct operation   of RAM region  */
    la		a0,	_start      	// 把_start地址载入到a0,根据启动位置的不同,_start可能在ram地址中也可能在flash中
    li		a1,	1           	// a1 = 1
	slli	a1,	a1, 29      // a1 = a1 << 29  (a1=0x20000000,ram起始地址)
    bleu	a1, a0, _start0800  // if (a1 <= a0) goto _start0800检 测是否在ram中运行,如果在ram中运行,_start地址将会大于 0x20000000
    srli	a1,	a1, 2           // a1 = a1 >> 2  (a1=0x08000000 flash起始地址)
    bleu	a1, a0, _start0800  // if (a1 <= a0) goto _start0800
    la		a0,	_start0800      // a0 =_start0800 程序地址不正确
    add		a0, a0, a1          // a0 = a0+0x08000000 (把程序地址重新定位到flash中)
	jr      a0                  // 跳转到a0所存的地址

_start0800:

    /* Set the the NMI base to share with mtvec by setting CSR_MMISC_CTL */
    li t0, 0x200					// t0 = 0x200
    csrs CSR_MMISC_CTL, t0	// mmisc_ctl = 0x200 ECLIC寄存器mmisc_ctl用于控制NMI中断向量表,这里设置成和mtvec一致

	/* Intial the mtvt*/
    la t0, vector_base	// t0 = vector_base
    csrw CSR_MTVT, t0	// mtvt寄存器设置为vector_base地址

	/* Intial the mtvt2 and enable it*/
    la t0, irq_entry				// t0=irq_entry,irq_entry是一个中断处理入口函数,位于entry.S
    csrw CSR_MTVT2, t0	// mtvt2寄存器设置为irq_entry
    csrs CSR_MTVT2, 0x1	// mtvt2[0] = 1 mtvt2[0]为0时,中断入口使用mtvec寄存器,mtvt2[0]为1时,中断入口为mtvt2[31:2]

    /* Intial the CSR MTVEC for the Trap ane NMI base addr*/
    la t0, trap_entry			// t0 = trap_entry,trap_entry是异常处理入口函数,位于entry.S
    csrw CSR_MTVEC, t0	// mtvec寄存器设置为trap_entry

#ifdef __riscv_flen		// 未使用代码
	/* Enable FPU */
	li t0, MSTATUS_FS
	csrs mstatus, t0
	csrw fcsr, x0
#endif						// 未使用代码

.option push		// 保存编译设置
.option norelax	// 禁用相对寻址
	la gp, __global_pointer$	// gp = __global_pointer$,__global_pointer$在ld脚本中定义,一般指向.sdata段,用于快速相对寻址优化。
.option pop		// 恢复设置
	la sp, _sp		// sp = _sp,_sp为堆栈顶部,在ld脚本中定义

	/* Load data section */
	la a0, _data_lma	// a0= _data_lma,_data_lma指向.data段在flash中的地址,在ld脚本中定义
	la a1, _data			// a1= _data,_data指向.data段在ram中的加载地址,在ld脚本中定义
	la a2, _edata		// a2 = _edata,_edata指向.data段在ram中的结束地址,在ld脚本中定义
	bgeu a1, a2, 2f	// if (a1 >= a2) goto 2f,2f表示后一个为2的标号
1:
	lw t0, (a0)			// t0 = *a0,从a0指向的地址中4个字节到t0
	sw t0, (a1)			// *a1 = t0,将t0保存到a1指向的地址
	addi a0, a0, 4		// a0+=4
	addi a1, a1, 4		// a1+=4
	bltu a1, a2, 1b		// if (a1 < _edata) goto 1b,1b表示前一个为1的标号
2:
	/* Clear bss section */
	la a0, __bss_start	// a0 = __bss_start,__bss_start指向.bss段在ram中的地址,在ld脚本中定义
	la a1, _end				// a1 = _end,_end指向.bss段在ram中的结束地址,在ld脚本中定义
	bgeu a0, a1, 2f		// if (a0 >= a1) goto 2f,2f表示后一个为2的标号
1:
	sw zero, (a0)			// *a0=0,将a0指向的地址置位0
	addi a0, a0, 4			// a0+= 4
	bltu a0, a1, 1b			// if (a0 < _end) goto 1b,1b表示前一个为1的标号
2:
	/*enable mcycle_minstret*/
    csrci CSR_MCOUNTINHIBIT, 0x5 	// mcountinhibit.IR被清零,minstret计数开启, mcountinhibit.CY被清零,mcycle计数开启
	/* Call global constructors */
	la a0, __libc_fini_array		// 初始化libc
	call atexit								
	call __libc_init_array


	/* argc = argv = 0 */
	li a0, 0			// a0=0
	li a1, 0			// a1=0
	call main		// 进入main
	tail exit

1:
	j 1b

risc-v 的la是一条伪指令,编译器会根据情况编译成不同的代码。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值