gd32vf103-hal 0.0.6

Hardware abstract layer (HAL) for RISC-V microcontroller GD32VF103
Documentation
/* author:  Luo Jia <luojia65@hust.edu.cn> 2019-11-29 */
.section .vectors, "ax"
.globl _gd32vf103_vectors
_gd32vf103_vectors:
/* source: Firmware\RISCV\env_Eclipse\start.S */
    .weak  eclic_msip_handler
    .weak  eclic_mtip_handler
    .weak  eclic_bwei_handler
    .weak  eclic_pmovi_handler
    .weak  WWDGT_IRQHandler
    .weak  LVD_IRQHandler
    .weak  TAMPER_IRQHandler
    .weak  RTC_IRQHandler
    .weak  FMC_IRQHandler
    .weak  RCU_IRQHandler
    .weak  EXTI0_IRQHandler
    .weak  EXTI1_IRQHandler
    .weak  EXTI2_IRQHandler
    .weak  EXTI3_IRQHandler
    .weak  EXTI4_IRQHandler
    .weak  DMA0_Channel0_IRQHandler
    .weak  DMA0_Channel1_IRQHandler
    .weak  DMA0_Channel2_IRQHandler
    .weak  DMA0_Channel3_IRQHandler
    .weak  DMA0_Channel4_IRQHandler
    .weak  DMA0_Channel5_IRQHandler
    .weak  DMA0_Channel6_IRQHandler
    .weak  ADC0_1_IRQHandler
    .weak  CAN0_TX_IRQHandler
    .weak  CAN0_RX0_IRQHandler
    .weak  CAN0_RX1_IRQHandler
    .weak  CAN0_EWMC_IRQHandler
    .weak  EXTI5_9_IRQHandler
    .weak  TIMER0_BRK_IRQHandler
    .weak  TIMER0_UP_IRQHandler
    .weak  TIMER0_TRG_CMT_IRQHandler
    .weak  TIMER0_Channel_IRQHandler
    .weak  TIMER1_IRQHandler
    .weak  TIMER2_IRQHandler
    .weak  TIMER3_IRQHandler
    .weak  I2C0_EV_IRQHandler
    .weak  I2C0_ER_IRQHandler
    .weak  I2C1_EV_IRQHandler
    .weak  I2C1_ER_IRQHandler
    .weak  SPI0_IRQHandler
    .weak  SPI1_IRQHandler
    .weak  USART0_IRQHandler
    .weak  USART1_IRQHandler
    .weak  USART2_IRQHandler
    .weak  EXTI10_15_IRQHandler
    .weak  RTC_Alarm_IRQHandler
    .weak  USBFS_WKUP_IRQHandler
    .weak  EXMC_IRQHandler
    .weak  TIMER4_IRQHandler
    .weak  SPI2_IRQHandler
    .weak  UART3_IRQHandler
    .weak  UART4_IRQHandler
    .weak  TIMER5_IRQHandler
    .weak  TIMER6_IRQHandler
    .weak  DMA1_Channel0_IRQHandler
    .weak  DMA1_Channel1_IRQHandler
    .weak  DMA1_Channel2_IRQHandler
    .weak  DMA1_Channel3_IRQHandler
    .weak  DMA1_Channel4_IRQHandler
    .weak  CAN1_TX_IRQHandler
    .weak  CAN1_RX0_IRQHandler
    .weak  CAN1_RX1_IRQHandler
    .weak  CAN1_EWMC_IRQHandler
    .weak  USBFS_IRQHandler
    jal x0, _start_logical_addr
    .word     0
    .word     0
    .word     eclic_msip_handler
    .word     0
    .word     0
    .word  	  0
    .word  	  eclic_mtip_handler
    .word  	  0
    .word  	  0
    .word  	  0
    .word  	  0
    .word  	  0
    .word  	  0
    .word  	  0
    .word 	  0
    .word  	  0
    .word  	  eclic_bwei_handler
    .word  	  eclic_pmovi_handler
    .word  	  WWDGT_IRQHandler
	.word     LVD_IRQHandler
	.word     TAMPER_IRQHandler
	.word     RTC_IRQHandler
	.word     FMC_IRQHandler
	.word     RCU_IRQHandler
	.word     EXTI0_IRQHandler
	.word     EXTI1_IRQHandler
	.word     EXTI2_IRQHandler
	.word     EXTI3_IRQHandler
	.word     EXTI4_IRQHandler
	.word     DMA0_Channel0_IRQHandler
	.word     DMA0_Channel1_IRQHandler
	.word     DMA0_Channel2_IRQHandler
	.word     DMA0_Channel3_IRQHandler
	.word     DMA0_Channel4_IRQHandler
	.word     DMA0_Channel5_IRQHandler
	.word     DMA0_Channel6_IRQHandler
	.word     ADC0_1_IRQHandler
	.word     CAN0_TX_IRQHandler
	.word     CAN0_RX0_IRQHandler
	.word     CAN0_RX1_IRQHandler
	.word     CAN0_EWMC_IRQHandler
	.word     EXTI5_9_IRQHandler
	.word     TIMER0_BRK_IRQHandler
	.word     TIMER0_UP_IRQHandler
	.word     TIMER0_TRG_CMT_IRQHandler
	.word     TIMER0_Channel_IRQHandler
	.word     TIMER1_IRQHandler
	.word     TIMER2_IRQHandler
	.word     TIMER3_IRQHandler
	.word     I2C0_EV_IRQHandler
	.word     I2C0_ER_IRQHandler
	.word     I2C1_EV_IRQHandler
	.word     I2C1_ER_IRQHandler
	.word     SPI0_IRQHandler
	.word     SPI1_IRQHandler
	.word     USART0_IRQHandler
	.word     USART1_IRQHandler
	.word     USART2_IRQHandler
	.word     EXTI10_15_IRQHandler
	.word     RTC_Alarm_IRQHandler
	.word     USBFS_WKUP_IRQHandler
    .word     0
    .word     0
    .word     0
    .word     0
	.word     0
	.word     EXMC_IRQHandler
	.word     0
	.word     TIMER4_IRQHandler
	.word     SPI2_IRQHandler
	.word     UART3_IRQHandler
	.word     UART4_IRQHandler
	.word     TIMER5_IRQHandler
	.word     TIMER6_IRQHandler
	.word     DMA1_Channel0_IRQHandler
	.word     DMA1_Channel1_IRQHandler
	.word     DMA1_Channel2_IRQHandler
	.word     DMA1_Channel3_IRQHandler
	.word     DMA1_Channel4_IRQHandler
    .word     0
    .word     0
	.word     CAN1_TX_IRQHandler
	.word     CAN1_RX0_IRQHandler
	.word     CAN1_RX1_IRQHandler
	.word     CAN1_EWMC_IRQHandler
	.word     USBFS_IRQHandler

# RISC-V defined CSR registers
.equ mstatus, 0x300
.equ mie, 0x304
.equ mtvec, 0x305
# Bumblebee core defined CSR registers
.equ mtvt, 0x307
.equ msubm, 0x7c4
.equ mtvt2, 0x7ec
.equ jalmnxti, 0x7ed
.equ pushmcause, 0x7ee
.equ pushmepc, 0x7ef
.equ pushmsubm, 0x7eb
# Constants
.equ REGBYTES,4
.equ MSTATUS_MIE, 0x00000008

.section .init, "ax"
.globl _start_logical_addr

_start_logical_addr:
    la		a0,	_start_logical_addr
    li		a1,	1
	slli	a1,	a1, 29
    bleu	a1, a0, _start_bootstrap
    srli	a1,	a1, 2
    bleu	a1, a0, _start_bootstrap
    la		a0,	_start_bootstrap
    add		a0, a0, a1
	jr      a0

_start_bootstrap:
# Initialize mtvt
    la t0, _gd32vf103_vectors
    csrw mtvt, t0
# Initialize and enable mtvt2
    la t0, _gd32vf103_irq_entry
    csrw mtvt2, t0
    csrs mtvt2, 0x1
# Initialize mtvec for trap & NMI base addr
    la t0, _gd32vf103_trap_entry
    csrw mtvec, t0 # todo: conflict with riscv-rt?
# Start riscv-rt Rust entry which would check hart id,
# allocate stack, clear bss section 
    j _start

.macro SAVE_CONTEXT
	sw ra, 0*REGBYTES(sp)
    sw tp, 1*REGBYTES(sp)
    sw t0, 2*REGBYTES(sp)
    sw t1, 3*REGBYTES(sp)
    sw t2, 4*REGBYTES(sp)
    sw t3, 5*REGBYTES(sp)
    sw t4, 6*REGBYTES(sp)
    sw t5, 7*REGBYTES(sp)
    sw t6, 8*REGBYTES(sp)
    sw a0, 9*REGBYTES(sp)
    sw a1, 10*REGBYTES(sp)
    sw a2, 11*REGBYTES(sp)
    sw a3, 12*REGBYTES(sp)
    sw a4, 13*REGBYTES(sp)
    sw a5, 14*REGBYTES(sp)
    sw a6, 15*REGBYTES(sp)
    sw a7, 16*REGBYTES(sp)
.endm

.macro RESTORE_CONTEXT
	lw ra, 0*REGBYTES(sp)
    lw tp, 1*REGBYTES(sp)
    lw t0, 2*REGBYTES(sp)
    lw t1, 3*REGBYTES(sp)
    lw t2, 4*REGBYTES(sp)
    lw t3, 5*REGBYTES(sp)
    lw t4, 6*REGBYTES(sp)
    lw t5, 7*REGBYTES(sp)
    lw t6, 8*REGBYTES(sp)
    lw a0, 9*REGBYTES(sp)
    lw a1, 10*REGBYTES(sp)
    lw a2, 11*REGBYTES(sp)
    lw a3, 12*REGBYTES(sp)
    lw a4, 13*REGBYTES(sp)
    lw a5, 14*REGBYTES(sp)
    lw a6, 15*REGBYTES(sp)
    lw a7, 16*REGBYTES(sp)
.endm

.section .trap, "ax"
.p2align 6 # 4-byte aligned
.globl _gd32vf103_trap_entry
.weak _gd32vf103_trap_entry
_gd32vf103_trap_entry:
; .globl _start_trap
; _start_trap: # todo: verify
# Allocate stack space
	addi sp, sp, -19*REGBYTES
# Save ra, tp, t*, a* registers
	SAVE_CONTEXT # save 17 registers
# Store mcause, mepc and msubm into memory
	csrrwi  zero, pushmcause, 17
	csrrwi  zero, pushmepc, 18
	csrrwi	zero, pushmsubm, 19
# Set the function argument of trap handler
	mv a0, sp
# Calls the trap handler (defined in riscv-rt)
# extern "C" fn start_trap_rust(trap_frame: *const TrapFrame)
	jal ra, _start_trap_rust
# Restore mcause, mepc and msubm
	lw a0, 19*REGBYTES(sp)
	csrw msubm, a0
	lw a0, 18*REGBYTES(sp)
	csrw mepc, a0
	lw a0, 17*REGBYTES(sp)
	csrw mcause, a0
# Restore ra, tp, t*, a* registers
	RESTORE_CONTEXT # restore 17 registers
# Free stack space
	addi sp, sp, 20*REGBYTES
	mret

.section .trap, "ax"
.align 2
.globl _gd32vf103_irq_entry
.weak _gd32vf103_irq_entry
_gd32vf103_irq_entry:
# Adjust stack pointer to allocate stack space
	addi sp, sp, -20*REGBYTES
# Save ra, tp, t*, a* registers
	SAVE_CONTEXT # save 17 registers
# These are special CSR read operations
# which actually uses mcause, mepc and msubm as operand 
# to directly store it to memory (stack)
	csrrwi  zero, pushmcause, 17
	csrrwi  zero, pushmepc, 18
	csrrwi	zero, pushmsubm, 19
# This special CSR read/write operation
# It claims the CLIC to find its pending highest ID.
# If the ID is not 0, then _automatically enable 
# the mstatus.MIE_, and jump to its vector-entry-label, 
# and update the link register.
# This design targets to speed up biting tail interrupts.
	csrrw ra, jalmnxti, ra 
# Disable interrupts
	csrc mstatus, MSTATUS_MIE
# Restore mcause, mepc and msubm
	lw a0, 19*REGBYTES(sp)
	csrw msubm, a0
	lw a0, 18*REGBYTES(sp)
	csrw mepc, a0
	lw a0, 17*REGBYTES(sp)
	csrw mcause, a0
# Restore ra, tp, t*, a* registers
	RESTORE_CONTEXT # restore 17 registers
# Free stack space
	addi sp, sp, 20*REGBYTES
	mret