Merge pull request #12276 from kenrabold/pr-fe310_intr_cleanup
cpu/fe310: interrupt handling cleanup
This commit is contained in:
commit
1543a8c438
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 JP Bonn
|
||||
* Copyright (C) 2017, 2019 JP Bonn, Ken Rabold
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -40,8 +40,6 @@ static void check_context_switch_frame_alignment(void)
|
||||
"Stack pointer should be 16 byte aligned");
|
||||
_Static_assert(sizeof(struct context_switch_frame) == CONTEXT_FRAME_SIZE,
|
||||
"context_switch_frame size mismatch");
|
||||
CHECK_OFFSET(pad);
|
||||
CHECK_OFFSET(pc);
|
||||
CHECK_OFFSET(s0);
|
||||
CHECK_OFFSET(s1);
|
||||
CHECK_OFFSET(s2);
|
||||
@ -55,7 +53,6 @@ static void check_context_switch_frame_alignment(void)
|
||||
CHECK_OFFSET(s10);
|
||||
CHECK_OFFSET(s11);
|
||||
CHECK_OFFSET(ra);
|
||||
CHECK_OFFSET(tp);
|
||||
CHECK_OFFSET(t0);
|
||||
CHECK_OFFSET(t1);
|
||||
CHECK_OFFSET(t2);
|
||||
@ -71,6 +68,8 @@ static void check_context_switch_frame_alignment(void)
|
||||
CHECK_OFFSET(a5);
|
||||
CHECK_OFFSET(a6);
|
||||
CHECK_OFFSET(a7);
|
||||
CHECK_OFFSET(pc);
|
||||
CHECK_OFFSET(pad);
|
||||
|
||||
/*
|
||||
* also check the SP offset in the _frame structure
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Ken Rabold, JP Bonn
|
||||
* Copyright (C) 2017, 2019 Ken Rabold, JP Bonn
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "thread.h"
|
||||
@ -39,8 +40,8 @@
|
||||
|
||||
volatile int __in_isr = 0;
|
||||
|
||||
/* ISR trap vector */
|
||||
void trap_entry(void);
|
||||
void thread_start(void);
|
||||
|
||||
/* PLIC external ISR function list */
|
||||
static external_isr_ptr_t _ext_isrs[PLIC_NUM_INTERRUPTS];
|
||||
@ -160,8 +161,12 @@ void external_isr(void)
|
||||
/**
|
||||
* @brief Global trap and interrupt handler
|
||||
*/
|
||||
void handle_trap(unsigned int mcause)
|
||||
void handle_trap(unsigned int mcause, unsigned int mepc, unsigned int mtval)
|
||||
{
|
||||
#ifndef DEVELHELP
|
||||
(void) mepc;
|
||||
(void) mtval;
|
||||
#endif
|
||||
/* Tell RIOT to set sched_context_switch_request instead of
|
||||
* calling thread_yield(). */
|
||||
__in_isr = 1;
|
||||
@ -170,6 +175,12 @@ void handle_trap(unsigned int mcause)
|
||||
if ((mcause & MCAUSE_INT) == MCAUSE_INT) {
|
||||
/* Cause is an interrupt - determine type */
|
||||
switch (mcause & MCAUSE_CAUSE) {
|
||||
case IRQ_M_SOFT:
|
||||
/* Handle software interrupt - flag for context switch */
|
||||
sched_context_switch_request = 1;
|
||||
CLINT_REG(0) = 0;
|
||||
break;
|
||||
|
||||
#ifdef MODULE_PERIPH_TIMER
|
||||
case IRQ_M_TIMER:
|
||||
/* Handle timer interrupt */
|
||||
@ -188,10 +199,21 @@ void handle_trap(unsigned int mcause)
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef DEVELHELP
|
||||
printf("Unhandled trap:\n");
|
||||
printf(" mcause: 0x%08x\n", mcause);
|
||||
printf(" mepc: 0x%08x\n", mepc);
|
||||
printf(" mtval: 0x%08x\n", mtval);
|
||||
#endif
|
||||
/* Unknown trap */
|
||||
core_panic(PANIC_GENERAL_ERROR, "Unhandled trap");
|
||||
}
|
||||
|
||||
/* Check if context change was requested */
|
||||
if (sched_context_switch_request) {
|
||||
sched_run();
|
||||
}
|
||||
|
||||
/* ISR done - no more changes to thread states */
|
||||
__in_isr = 0;
|
||||
}
|
||||
@ -253,7 +275,6 @@ char *thread_stack_init(thread_task_func_t task_func,
|
||||
int stack_size)
|
||||
{
|
||||
struct context_switch_frame *sf;
|
||||
uint32_t *reg;
|
||||
uint32_t *stk_top;
|
||||
|
||||
/* calculate the top of the stack */
|
||||
@ -275,11 +296,10 @@ char *thread_stack_init(thread_task_func_t task_func,
|
||||
/* populate the stack frame with default values for starting the thread. */
|
||||
sf = (struct context_switch_frame *) stk_top;
|
||||
|
||||
/* a7 is register with highest memory address in frame */
|
||||
reg = &sf->a7;
|
||||
while (reg != &sf->pc) {
|
||||
*reg-- = 0;
|
||||
}
|
||||
/* Clear stack frame */
|
||||
memset(sf, 0, sizeof(*sf));
|
||||
|
||||
/* set initial reg values */
|
||||
sf->pc = (uint32_t) task_func;
|
||||
sf->a0 = (uint32_t) arg;
|
||||
|
||||
@ -292,7 +312,11 @@ char *thread_stack_init(thread_task_func_t task_func,
|
||||
void thread_print_stack(void)
|
||||
{
|
||||
int count = 0;
|
||||
uint32_t *sp = (uint32_t *) sched_active_thread->sp;
|
||||
uint32_t *sp = (uint32_t *) ((sched_active_thread) ? sched_active_thread->sp : NULL);
|
||||
|
||||
if (sp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf("printing the current stack of thread %" PRIkernel_pid "\n",
|
||||
thread_getpid());
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 JP Bonn
|
||||
* Copyright (C) 2017, 2019 JP Bonn, Ken Rabold
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -40,8 +40,6 @@ extern "C" {
|
||||
*
|
||||
*/
|
||||
struct context_switch_frame {
|
||||
uint32_t pad[2]; /**< padding to maintain 16 byte alignment */
|
||||
uint32_t pc; /**< program counter */
|
||||
/* Callee saved registers */
|
||||
uint32_t s0; /**< s0 register */
|
||||
uint32_t s1; /**< s1 register */
|
||||
@ -57,7 +55,6 @@ struct context_switch_frame {
|
||||
uint32_t s11; /**< s11 register */
|
||||
/* Caller saved registers */
|
||||
uint32_t ra; /**< ra register */
|
||||
uint32_t tp; /**< tp register */
|
||||
uint32_t t0; /**< t0 register */
|
||||
uint32_t t1; /**< t1 register */
|
||||
uint32_t t2; /**< t2 register */
|
||||
@ -73,6 +70,9 @@ struct context_switch_frame {
|
||||
uint32_t a5; /**< a5 register */
|
||||
uint32_t a6; /**< a6 register */
|
||||
uint32_t a7; /**< a7 register */
|
||||
/* Saved PC for return from ISR */
|
||||
uint32_t pc; /**< program counter */
|
||||
uint32_t pad[3]; /**< padding to maintain 16 byte alignment */
|
||||
};
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
@ -83,43 +83,42 @@ struct context_switch_frame {
|
||||
* @{
|
||||
*/
|
||||
/* These values are checked for correctness in context_frame.c */
|
||||
#define pad_OFFSET 0
|
||||
#define pc_OFFSET 8
|
||||
#define s0_OFFSET 12
|
||||
#define s1_OFFSET 16
|
||||
#define s2_OFFSET 20
|
||||
#define s3_OFFSET 24
|
||||
#define s4_OFFSET 28
|
||||
#define s5_OFFSET 32
|
||||
#define s6_OFFSET 36
|
||||
#define s7_OFFSET 40
|
||||
#define s8_OFFSET 44
|
||||
#define s9_OFFSET 48
|
||||
#define s10_OFFSET 52
|
||||
#define s11_OFFSET 56
|
||||
#define ra_OFFSET 60
|
||||
#define tp_OFFSET 64
|
||||
#define t0_OFFSET 68
|
||||
#define t1_OFFSET 72
|
||||
#define t2_OFFSET 76
|
||||
#define t3_OFFSET 80
|
||||
#define t4_OFFSET 84
|
||||
#define t5_OFFSET 88
|
||||
#define t6_OFFSET 92
|
||||
#define a0_OFFSET 96
|
||||
#define a1_OFFSET 100
|
||||
#define a2_OFFSET 104
|
||||
#define a3_OFFSET 108
|
||||
#define a4_OFFSET 112
|
||||
#define a5_OFFSET 116
|
||||
#define a6_OFFSET 120
|
||||
#define a7_OFFSET 124
|
||||
#define s0_OFFSET 0
|
||||
#define s1_OFFSET 4
|
||||
#define s2_OFFSET 8
|
||||
#define s3_OFFSET 12
|
||||
#define s4_OFFSET 16
|
||||
#define s5_OFFSET 20
|
||||
#define s6_OFFSET 24
|
||||
#define s7_OFFSET 28
|
||||
#define s8_OFFSET 32
|
||||
#define s9_OFFSET 36
|
||||
#define s10_OFFSET 40
|
||||
#define s11_OFFSET 44
|
||||
#define ra_OFFSET 48
|
||||
#define t0_OFFSET 52
|
||||
#define t1_OFFSET 56
|
||||
#define t2_OFFSET 60
|
||||
#define t3_OFFSET 64
|
||||
#define t4_OFFSET 68
|
||||
#define t5_OFFSET 72
|
||||
#define t6_OFFSET 76
|
||||
#define a0_OFFSET 80
|
||||
#define a1_OFFSET 84
|
||||
#define a2_OFFSET 88
|
||||
#define a3_OFFSET 92
|
||||
#define a4_OFFSET 96
|
||||
#define a5_OFFSET 100
|
||||
#define a6_OFFSET 104
|
||||
#define a7_OFFSET 108
|
||||
#define pc_OFFSET 112
|
||||
#define pad_OFFSET 116
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Size of context switch frame
|
||||
*/
|
||||
#define CONTEXT_FRAME_SIZE (a7_OFFSET + 4)
|
||||
#define CONTEXT_FRAME_SIZE (pad_OFFSET + 12)
|
||||
|
||||
/**
|
||||
* @brief Offset of stack pointer in struct _thread
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 JP Bonn
|
||||
* Copyright (C) 2017, 2019 JP Bonn, Ken Rabold
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -9,22 +9,12 @@
|
||||
#include "vendor/encoding.h"
|
||||
#include "context_frame.h"
|
||||
|
||||
/* from platform.h TODO:fix this hard code.... */
|
||||
CLINT_CTRL_ADDR = 0x02000000
|
||||
|
||||
.section .text.entry
|
||||
.align 2
|
||||
.global trap_entry
|
||||
|
||||
trap_entry:
|
||||
/*
|
||||
* Save all regs on the currently active stack.
|
||||
* This coule be the active thread's stack,
|
||||
* or if no thread is active, it is saved on ISR stack
|
||||
* (if initial startup) or on the deactivated threads
|
||||
* stack (in the case of thread exit). In the latter
|
||||
* two cases the stack is just abandoned.
|
||||
*/
|
||||
/* Save registers to stack */
|
||||
addi sp, sp, -CONTEXT_FRAME_SIZE
|
||||
|
||||
sw s0, s0_OFFSET(sp)
|
||||
@ -40,7 +30,6 @@ trap_entry:
|
||||
sw s10, s10_OFFSET(sp)
|
||||
sw s11, s11_OFFSET(sp)
|
||||
sw ra, ra_OFFSET(sp)
|
||||
sw tp, tp_OFFSET(sp)
|
||||
sw t0, t0_OFFSET(sp)
|
||||
sw t1, t1_OFFSET(sp)
|
||||
sw t2, t2_OFFSET(sp)
|
||||
@ -58,33 +47,40 @@ trap_entry:
|
||||
sw a7, a7_OFFSET(sp)
|
||||
|
||||
|
||||
/* Get the interrupt cause */
|
||||
/* Get the interrupt cause, PC, and address */
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
csrr a2, mtval
|
||||
|
||||
/* Save active thread stack pointer in a callee save register */
|
||||
mv s1, sp
|
||||
/* Save return PC in stack frame */
|
||||
sw a1, pc_OFFSET(sp)
|
||||
|
||||
/* Get the active thread (could be NULL) */
|
||||
lw tp, sched_active_thread
|
||||
beqz tp, null_thread
|
||||
|
||||
/* Save stack pointer of current thread */
|
||||
sw sp, SP_OFFSET_IN_THREAD(tp)
|
||||
|
||||
null_thread:
|
||||
/* Switch to ISR stack. Interrupts are not nested so use fixed
|
||||
* starting address and just abandon stack when finished. */
|
||||
la sp, _sp
|
||||
addi sp, sp, -4
|
||||
|
||||
/* Is it a software interrupt? */
|
||||
li t0, 0x80000003
|
||||
beq a0, t0, context_switch
|
||||
/* Call handle_trap with MCAUSE and MEPC register value as args */
|
||||
call handle_trap
|
||||
|
||||
/* Call handle_trap with MCAUSE register value as arg */
|
||||
jal handle_trap
|
||||
/* Get the active thread (guaranteed to be non NULL) */
|
||||
lw tp, sched_active_thread
|
||||
|
||||
/* See if a context switch was requested by the ISR */
|
||||
lw a0, sched_context_switch_request
|
||||
bnez a0, context_switch
|
||||
/* Load the thread SP of scheduled thread */
|
||||
lw sp, SP_OFFSET_IN_THREAD(tp)
|
||||
|
||||
/* Restore active thread stack pointer */
|
||||
mv sp, s1
|
||||
/* Set return PC */
|
||||
lw a1, pc_OFFSET(sp)
|
||||
csrw mepc, a1
|
||||
|
||||
/* Restore remaining registers */
|
||||
trap_exit:
|
||||
/* Restore registers from stack */
|
||||
lw s0, s0_OFFSET(sp)
|
||||
lw s1, s1_OFFSET(sp)
|
||||
lw s2, s2_OFFSET(sp)
|
||||
@ -98,7 +94,6 @@ trap_exit:
|
||||
lw s10, s10_OFFSET(sp)
|
||||
lw s11, s11_OFFSET(sp)
|
||||
lw ra, ra_OFFSET(sp)
|
||||
lw tp, tp_OFFSET(sp)
|
||||
lw t0, t0_OFFSET(sp)
|
||||
lw t1, t1_OFFSET(sp)
|
||||
lw t2, t2_OFFSET(sp)
|
||||
@ -117,35 +112,3 @@ trap_exit:
|
||||
|
||||
addi sp, sp, CONTEXT_FRAME_SIZE
|
||||
mret
|
||||
|
||||
|
||||
context_switch:
|
||||
/* clear the software interrupt */
|
||||
li t0, CLINT_CTRL_ADDR
|
||||
sw zero, (t0)
|
||||
|
||||
/* save the active thread's PC prior to interrupt on the stack */
|
||||
csrr a0, mepc
|
||||
sw a0, pc_OFFSET(s1)
|
||||
|
||||
/* get the active thread - it may be 0 if none currently active */
|
||||
lw t0, sched_active_thread
|
||||
/* was there a previously running thread? */
|
||||
beqz t0, no_sp_save
|
||||
/* if so, save the thread's SP in the _thread structure */
|
||||
sw s1,SP_OFFSET_IN_THREAD(t0)
|
||||
|
||||
no_sp_save:
|
||||
/* all current thread state is saved - schedule a new thread */
|
||||
call sched_run
|
||||
lw tp, sched_active_thread
|
||||
|
||||
/* set the threads SP from the newly scheduled thread
|
||||
* and abandon ISR stack. */
|
||||
lw sp, SP_OFFSET_IN_THREAD(tp)
|
||||
|
||||
/* restore the PC */
|
||||
lw a0, pc_OFFSET(sp)
|
||||
csrw mepc, a0
|
||||
|
||||
j trap_exit
|
||||
|
||||
177
cpu/fe310/ldscripts/fe310_base.ld
Normal file
177
cpu/fe310/ldscripts/fe310_base.ld
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2017, 2019 Ken Rabold
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup cpu_fe310
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Common linker directives for the SiFive FE310
|
||||
*
|
||||
* @author Ken Rabold
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
ENTRY( _start )
|
||||
|
||||
PHDRS
|
||||
{
|
||||
flash PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 256;
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data = . );
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.ramfunc .ramfunc.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _edata = . );
|
||||
PROVIDE( edata = . );
|
||||
|
||||
PROVIDE( _fbss = . );
|
||||
PROVIDE( __bss_start = . );
|
||||
.bss :
|
||||
{
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>ram :ram
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
PROVIDE( _heap_start = . );
|
||||
|
||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
|
||||
{
|
||||
PROVIDE( _heap_end = . );
|
||||
. = __stack_size;
|
||||
PROVIDE( _sp = . );
|
||||
} >ram AT>ram :ram
|
||||
}
|
||||
@ -18,10 +18,6 @@
|
||||
* @}
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
ENTRY( _start )
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rxai!w) : ORIGIN = 0x20400000, LENGTH = 0x1fc00000
|
||||
@ -29,156 +25,4 @@ MEMORY
|
||||
itim (wxa!ri) : ORIGIN = 0x08000000, LENGTH = 0x00002000
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
flash PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data = . );
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.ramfunc .ramfunc.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _edata = . );
|
||||
PROVIDE( edata = . );
|
||||
|
||||
PROVIDE( _fbss = . );
|
||||
PROVIDE( __bss_start = . );
|
||||
.bss :
|
||||
{
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>ram :ram
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
PROVIDE( _heap_start = . );
|
||||
|
||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
|
||||
{
|
||||
PROVIDE( _heap_end = . );
|
||||
. = __stack_size;
|
||||
PROVIDE( _sp = . );
|
||||
} >ram AT>ram :ram
|
||||
}
|
||||
INCLUDE fe310_base.ld
|
||||
@ -18,10 +18,6 @@
|
||||
* @}
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
ENTRY( _start )
|
||||
|
||||
MEMORY
|
||||
{
|
||||
flash (rxai!w) : ORIGIN = 0x20010000, LENGTH = 0x0006a120
|
||||
@ -29,156 +25,4 @@ MEMORY
|
||||
itim (wxa!ri) : ORIGIN = 0x08000000, LENGTH = 0x00002000
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
flash PT_LOAD;
|
||||
ram_init PT_LOAD;
|
||||
ram PT_NULL;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
__stack_size = DEFINED(__stack_size) ? __stack_size : 1K;
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.init)))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text .text.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(SORT_NONE(.fini)))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rdata)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
} >flash AT>flash :flash
|
||||
|
||||
. = ALIGN(4);
|
||||
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*crtbegin?.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*crtbegin?.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.lalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data_lma = . );
|
||||
} >flash AT>flash :flash
|
||||
|
||||
.dalign :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _data = . );
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.ramfunc .ramfunc.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE( __global_pointer$ = . + 0x800 );
|
||||
*(.sdata .sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
. = ALIGN(8);
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata .srodata.*)
|
||||
} >ram AT>flash :ram_init
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE( _edata = . );
|
||||
PROVIDE( edata = . );
|
||||
|
||||
PROVIDE( _fbss = . );
|
||||
PROVIDE( __bss_start = . );
|
||||
.bss :
|
||||
{
|
||||
*(.sbss*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
} >ram AT>ram :ram
|
||||
|
||||
. = ALIGN(8);
|
||||
PROVIDE( _end = . );
|
||||
PROVIDE( end = . );
|
||||
PROVIDE( _heap_start = . );
|
||||
|
||||
.stack ORIGIN(ram) + LENGTH(ram) - __stack_size :
|
||||
{
|
||||
PROVIDE( _heap_end = . );
|
||||
. = __stack_size;
|
||||
PROVIDE( _sp = . );
|
||||
} >ram AT>ram :ram
|
||||
}
|
||||
INCLUDE fe310_base.ld
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user