-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GD32VF103] Jump to embedded bootloader from user code #29
Comments
Hi @KarlK90 , I also didn't know what is happening in gd32v bootrom(it is not a chip made by Nuclei, we just provided RISC-V CORE ip to Gigabyte), maybe you need to check the datasheet for more details. |
@fanghuaqi Thanks for clarification! I share my findings with you or others that maybe have the same question. Some further investigation in the disassembly of the bootloader revealed that it wasn't compiled to be position independent. E.g in the startup assembly the I tried to rewrite the startup code and vector table with the correct values and jump over the original startup assembly. See below update. ; Init gp
0x0000018c auipc gp, 0x20001
0x00000190 addi gp, gp, -684
; Bootloader running from 0x1FFFB000 gives invalid address
; 0x1FFFB18C + 0x20001000 = 0x3FFFBEE0
;
; Bootloader running from 0x0 gives valid address
; 0x0000018C + 0x20001000 = 0x20000EE0
;
; Init sp
0x00000194 auipc sp, 0x20001
0x00000198 addi sp, sp, 1644
; Bootloader running from 0x1FFFB000 gives invalid address
; 0x1FFFB194 + 0x20001000 + 1644 = 0x3FFFC800
;
; Bootloader running from 0x0 gives valid address
; 0x00000194 + 0x20001000 + 1644 = 0x20001800 rewritten startup assembly#define BOOTLOADER_ADDRESS 0x1FFFB000
#define VECTOR_TABLE_BASE 0x20001800 // Address needs 512 Byte alignment
#define VECTOR_TABLE_END (VECTOR_TABLE_BASE + (87 * 4))
#define VECTOR_TIMER2_OFFSET (0xC0 + VECTOR_TABLE_BASE)
#define VECTOR_TIMER2_ADDR (0x216C + BOOTLOADER_ADDRESS)
#define VECTOR_USART0_OFFSET (0xE0 + VECTOR_TABLE_BASE)
#define VECTOR_USART0_ADDR (0x20CC + BOOTLOADER_ADDRESS)
#define VECTOR_USART1_OFFSET (0xE4 + VECTOR_TABLE_BASE)
#define VECTOR_USART1_ADDR (0x211C + BOOTLOADER_ADDRESS)
#define VECTOR_USBFS_OFFSET (0x158 + VECTOR_TABLE_BASE)
#define VECTOR_USBFS_ADDR (0x20B4 + BOOTLOADER_ADDRESS)
/*
* Set the the NMI base mnvec to share
* with mtvec by setting CSR_MMISC_CTL
* bit 9 NMI_CAUSE_FFF to 1
*/
li t0, MMISC_CTL_NMI_CAUSE_FFF
csrs CSR_MMISC_CTL, t0
/*
* Intialize ECLIC vector interrupt
* base address mtvt to bootloader entry
*/
la t0, VECTOR_TABLE_BASE
csrw 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_handler.
*/
#define IRQ_HANDLER 0x1FFFD1C4
la t0, IRQ_HANDLER
csrw CSR_MTVT2, t0
csrs CSR_MTVT2, 0x1
/* Set the interrupt processing mode to ECLIC mode */
li t0, 0x3f
csrc CSR_MTVEC, t0
csrs CSR_MTVEC, 0x3
/* Set Exception Entry MTVEC */
#define EXCEPTION_HANDLER 0x1FFFD180
la t0, EXCEPTION_HANDLER
csrw CSR_MTVEC, t0
/* Set bootloader global pointer */
la gp, 0x20000EE0 /* 0x20001000+0x18c-684 */
/* Set bootloader stack pointer */
la sp, 0x20001800 /*0x20001000+0x194+1644*/
#define DATA_BASE 0x20000000 /* 0x20000000 + 0x1a4 - 420 */
#define DATA_END 0x20000708 /* 0x20000000 + 0x1ac + 1372 */
#define DATA_ROM 0x1FFFED14 /* 0x4000 + 0x19c - 1160 + BOOTLOADER_ADDRESS */
/* Data initialization. */
la a0, DATA_ROM
la a1, DATA_BASE
la a2, DATA_END
dloop_boot:
bge a1, a2, enddloop_boot
lw a3, 0(a0)
sw a3, 0(a1)
addi a0, a0, 4
addi a1, a1, 4
j dloop_boot
enddloop_boot:
#define BSS_BASE 0x20000708 /* 0x20000000 + 0x1c8 + 1344 */
#define BSS_END 0x20001270 /* gp + 912 = 0x20000EE0 + 912 */
/* BSS initialization. */
la a1, BSS_BASE
la a2, BSS_END
bloop_boot:
bge a1, a2, endbloop_boot
sw zero, 0(a1)
addi a1, a1, 4
j bloop_boot
endbloop_boot:
/* Reconstruct vector table. */
la a1, VECTOR_TABLE_BASE
la a2, VECTOR_TABLE_END
vloop_boot:
bge a1, a2, endvloop_boot
sw zero, 0(a1)
addi a1, a1, 4
j vloop_boot
endvloop_boot:
la a1 , VECTOR_TIMER2_OFFSET
la a2, VECTOR_TIMER2_ADDR
sw a2, 0(a1)
la a1 , VECTOR_USART0_OFFSET
la a2, VECTOR_USART0_ADDR
sw a2, 0(a1)
la a1 , VECTOR_USART1_OFFSET
la a2, VECTOR_USART1_ADDR
sw a2, 0(a1)
la a1 , VECTOR_USBFS_OFFSET
la a2, VECTOR_USBFS_ADDR
sw a2, 0(a1)
/* Jump into bootloader after inti section. */
la a0, (BOOTLOADER_ADDRESS + 0x1E2)
jr a0 |
Actually I got the numbers for the data section wrong and the vector table was outside the SRAM region... After updating the numbers the bootloader doesn't trap anymore and tries to enumerate as a USB device now. But it fails the setup, the code is caught in a loop. This is very similar to the behavior often seen when putting the device into bootloader mode via BOOT0 pin.
|
Hi @KarlK90 , sorry I can't give you more help with this issue, I didn't know too much details in side the bootrom of gd32v. |
@fanghuaqi no problem, as stated above jumping into the bootloader is not an easily accomplished. Therefore I have started to port the tinyuf2 userland bootloader for the GD32VF103. There are some problems with the USB peripheral, but when this is sorted this should solve my problems. |
I'm wondering if it is possible to jump to the embedded bootloader that is present at
0x1FFFB000
in the devices ROM without a reset and externally pulling Boot0 high?So far I have tried to jump to
0x1FFFB000
immediately after the device has been reset in the startup code. Observing the execution path with a debugger I can confirm that this indeed produced a valid jump, but the bootloader code is not executed successfully e.g. with a USB connection it doesn't show up as a USB-DFU device.I know that this is possible with STM32F103 and GD32F103, so there is a chance that this possible as well?
The text was updated successfully, but these errors were encountered: