Preface
The RISC-V development environment was built earlier. This article will talk about the SDK code framework, which is conducive to subsequent program development.
process
Finding the linker script
For embedded projects, to understand the code framework, you must first start with the link script, from here you can find the startup code, program entry and other information, and then you can understand the whole picture by peeling off the layers.
Right click on the project->Properties
See the link script as follows
D:\BOARD\SF1-FPSoC\SF1S60CG121I_SF102\SF1S60CG121I_SF102\TN810_SF102\src\mcu_ahb_to_fpga\sdk_project\bmp_image_display\anlogic_sdk\SoC\anlogic\Board\sf1_eval\Source\GCC\gcc_anlogic_work3.ld
Let’s open this file and see
You can see that there are other different ld files in this directory, which are used in projects with different working modes. The principles are the same, so just look at one.
The ld file format can be searched online for documents, so I will not go into details here and will mainly talk about the content related to this project.
First look at the storage defined earlier
MEMORY
{
flash (rxai!w): ORIGIN = 0x000E0000, LENGTH = 4M
ilm (rxai!w) : ORIGIN = 0x08000000, LENGTH = 8K
ram (wxa!ri) : ORIGIN = 0x20000000, LENGTH = 8K
}
Here you can see the storage layout.
Then we find the entrance of the program
.init :
{
*(.vtable)
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash
Here, the .vtable is placed in the flash, so the instruction here is the entry point of the program
Search for .vtable
Menu bar Serch->Search
See that this section is the startup code
Fixed interrupt vector
The fixed terminal vector table is defined at the beginning
/*** Vector Table Code Section ***/
/*
* Put the interrupt vectors in this section according to the run mode:
* FlashXIP: .vtable
* ILM: .vtable
* Flash: .vtable_ilm
*/
#if defined(DOWNLOAD_MODE) && (DOWNLOAD_MODE == DOWNLOAD_MODE_FLASH)
.section .vtable_ilm
#else
.section .vtable
#endif
.weak eclic_msip_handler
.weak eclic_mtip_handler
.weak uart0_handler
.weak i2c_handler
.weak QSPI0_handler
.weak QSPI_handler
.weak gpio0_handler
.weak gpio1_handler
.weak gpio2_handler
.weak gpio3_handler
.weak gpio4_handler
.weak gpio5_handler
.weak gpio6_handler
.weak gpio7_handler
.weak fpga0_handler
.weak fpga1_handler
.weak fpga2_handler
.weak fpga3_handler
.weak fpga4_handler
.weak fpga5_handler
.weak fpga6_handler
.weak fpga7_handler
.weak fpga8_handler
.weak fpga9_handler
.weak fpga10_handler
.weak fpga11_handler
.weak fpga12_handler
.weak fpga13_handler
.weak fpga14_handler
.weak fpga15_handler
User interrupt vector
Then the user interrupt vector entry is
.globl vector_base
vector_base:
#if defined(DOWNLOAD_MODE) && (DOWNLOAD_MODE != DOWNLOAD_MODE_FLASH)
// j _start /* 0: Reserved, Jump to _start when reset for ILM/FlashXIP mode.*/
la ra,_start // fix according to suggestion of SW
ret
.align LOG_REGBYTES /* Need to align 4 byte for RV32, 8 Byte for RV64 */
#else
DECLARE_INT_HANDLER default_intexc_handler /* 0: Reserved, default handler for Flash download mode */
DECLARE_INT_HANDLER default_intexc_handler /* 1: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 2: Reserved */
#endif
// DECLARE_INT_HANDLER default_intexc_handler /* 1: Reserved */
// DECLARE_INT_HANDLER default_intexc_handler /* 2: Reserved */
DECLARE_INT_HANDLER eclic_msip_handler /* 3: Machine software interrupt */
DECLARE_INT_HANDLER default_intexc_handler /* 4: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 5: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 6: Reserved */
DECLARE_INT_HANDLER eclic_mtip_handler /* 7: Machine timer interrupt */
DECLARE_INT_HANDLER default_intexc_handler /* 8: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 9: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 10: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 11: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 12: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 13: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 14: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 15: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 16: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 17: Reserved */
DECLARE_INT_HANDLER default_intexc_handler /* 18: Reserved */
DECLARE_INT_HANDLER uart0_handler /* 19: Interrupt 19 */
DECLARE_INT_HANDLER i2c_handler /* 21: Interrupt 21 */
DECLARE_INT_HANDLER QSPI0_handler /* 22: Interrupt 22 */
DECLARE_INT_HANDLER QSPI_handler /* 29: Interrupt 29 */
DECLARE_INT_HANDLER gpio0_handler /* 30: Interrupt 30 */
DECLARE_INT_HANDLER gpio1_handler /* 31: Interrupt 31 */
DECLARE_INT_HANDLER gpio2_handler /* 32: Interrupt 32 */
DECLARE_INT_HANDLER gpio3_handler /* 33: Interrupt 33 */
DECLARE_INT_HANDLER gpio4_handler /* 34: Interrupt 34 */
DECLARE_INT_HANDLER gpio5_handler /* 35: Interrupt 35 */
DECLARE_INT_HANDLER gpio6_handler /* 36: Interrupt 36 */
DECLARE_INT_HANDLER gpio7_handler /* 37: Interrupt 37 */
DECLARE_INT_HANDLER fpga0_handler /* 38: Interrupt 38 */
DECLARE_INT_HANDLER fpga1_handler /* 39: Interrupt 39 */
DECLARE_INT_HANDLER fpga2_handler /*40: Interrupt 40 */
DECLARE_INT_HANDLER fpga3_handler /* 41: Interrupt 41 */
DECLARE_INT_HANDLER fpga4_handler /* 42: Interrupt 42 */
DECLARE_INT_HANDLER fpga5_handler /* 43: Interrupt 43 */
DECLARE_INT_HANDLER fpga6_handler /* 44: Interrupt 44 */
DECLARE_INT_HANDLER fpga7_handler /* 45: Interrupt 45 */
DECLARE_INT_HANDLER fpga8_handler /* 43: Interrupt 43 */
DECLARE_INT_HANDLER fpga9_handler /* 44: Interrupt 44 */
DECLARE_INT_HANDLER fpga10_handler /* 45: Interrupt 45 */
DECLARE_INT_HANDLER fpga11_handler /* 44: Interrupt 44 */
DECLARE_INT_HANDLER fpga12_handler /* 45: Interrupt 45 */
DECLARE_INT_HANDLER fpga13_handler /* 44: Interrupt 44 */
DECLARE_INT_HANDLER fpga14_handler /* 45: Interrupt 45 */
DECLARE_INT_HANDLER fpga15_handler /* 45: Interrupt 45 */
Search for vector_base
It can be seen that the address is set as the user interrupt vector base address.
/*
* Initialize ECLIC vector interrupt
* base address mtvt to vector_base
*/
la t0, vector_base
csrw CSR_MTVT, t0
Startup Code
.globl vector_base
vector_base:
#if defined(DOWNLOAD_MODE) && (DOWNLOAD_MODE != DOWNLOAD_MODE_FLASH)
// j _start /* 0: Reserved, Jump to _start when reset for ILM/FlashXIP mode.*/
la ra,_start // fix according to suggestion of SW
ret
If it is DOWNLOAD_MODE mode, jump to _start
.section .init
.globl _start
.type _start,@FUNCTION
.option norvc
/**
* Reset Handler called on controller reset
*/
_start:
Corresponding to the link script, it is placed in the .init section
.init :
{
*(.vtable)
KEEP (*(SORT_NONE(.init)))
} >flash AT>flash
The following is the initialization of the interrupt stack pointer, etc., which will not be repeated here. You can refer to the RISC-V article to understand the instructions.
Later, we will focus on the loading of the code data segment and the initialization of the bss segment. Variables such as _data are all addresses defined in the link script.
1:
/* Load code section if necessary */
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
/* Load data section */
la a0, _data_lma
la a1, _data
la a2, _edata
bgeu a1, a2, 2f
1:
lw t0, (a0)
sw t0, (a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
/* Clear bss section */
la a0, __bss_start
la a1, _end
bgeu a0, a1, 2f
1:
sw zero, (a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
Then call SystemInit to initialize the systick timer
call SystemInit
Finally enter main
#ifdef RTOS_RTTHREAD
// Call entry function when using RT-Thread
call entry
#else
call main
#endif
Code Framework
Under anlogic_sdk are chip-related codes, mainly focusing on startup code, interrupt handling code, and link scripts
Under application is the user code
Summarize
The above introduces the code framework, mainly the startup process, to facilitate an overall understanding of the SDK.