From d3d4e77c4218377d9aad9a3ac5d71461274bbc1e Mon Sep 17 00:00:00 2001 From: Jiri Gaisler Date: Fri, 18 Jan 2019 12:37:55 +0100 Subject: riscv: add griscv bsp Update #3678. --- bsps/riscv/griscv/clock/clockdrv.c | 202 ++++++++++++ bsps/riscv/griscv/config/griscv.cfg | 9 + bsps/riscv/griscv/console/console.c | 162 ++++++++++ bsps/riscv/griscv/console/printk_support.c | 126 ++++++++ bsps/riscv/griscv/headers.am | 11 + bsps/riscv/griscv/include/amba.h | 143 +++++++++ bsps/riscv/griscv/include/bsp.h | 66 ++++ bsps/riscv/griscv/include/bsp/irq.h | 73 +++++ bsps/riscv/griscv/include/tm27.h | 1 + bsps/riscv/griscv/irq/irq.c | 144 +++++++++ bsps/riscv/griscv/start/amba.c | 115 +++++++ bsps/riscv/griscv/start/bsp_fatal_halt.c | 36 +++ bsps/riscv/griscv/start/bsp_specs | 9 + bsps/riscv/griscv/start/bspsmp.c | 97 ++++++ bsps/riscv/griscv/start/bspstart.c | 70 +++++ bsps/riscv/griscv/start/linkcmds.in | 46 +++ bsps/riscv/riscv/clock/clockdrv.c | 5 + bsps/riscv/riscv/start/linkcmds.base | 385 ----------------------- bsps/riscv/riscv/start/start.S | 147 --------- bsps/riscv/shared/start/linkcmds.base | 385 +++++++++++++++++++++++ bsps/riscv/shared/start/start.S | 147 +++++++++ c/src/lib/libbsp/riscv/acinclude.m4 | 2 + c/src/lib/libbsp/riscv/griscv/Makefile.am | 70 +++++ c/src/lib/libbsp/riscv/griscv/configure.ac | 40 +++ c/src/lib/libbsp/riscv/riscv/Makefile.am | 4 +- cpukit/score/cpu/riscv/include/rtems/score/cpu.h | 5 +- 26 files changed, 1962 insertions(+), 538 deletions(-) create mode 100644 bsps/riscv/griscv/clock/clockdrv.c create mode 100644 bsps/riscv/griscv/config/griscv.cfg create mode 100644 bsps/riscv/griscv/console/console.c create mode 100644 bsps/riscv/griscv/console/printk_support.c create mode 100644 bsps/riscv/griscv/headers.am create mode 100644 bsps/riscv/griscv/include/amba.h create mode 100644 bsps/riscv/griscv/include/bsp.h create mode 100644 bsps/riscv/griscv/include/bsp/irq.h create mode 100644 bsps/riscv/griscv/include/tm27.h create mode 100644 bsps/riscv/griscv/irq/irq.c create mode 100644 bsps/riscv/griscv/start/amba.c create mode 100644 bsps/riscv/griscv/start/bsp_fatal_halt.c create mode 100644 bsps/riscv/griscv/start/bsp_specs create mode 100644 bsps/riscv/griscv/start/bspsmp.c create mode 100644 bsps/riscv/griscv/start/bspstart.c create mode 100644 bsps/riscv/griscv/start/linkcmds.in delete mode 100644 bsps/riscv/riscv/start/linkcmds.base delete mode 100644 bsps/riscv/riscv/start/start.S create mode 100644 bsps/riscv/shared/start/linkcmds.base create mode 100644 bsps/riscv/shared/start/start.S create mode 100644 c/src/lib/libbsp/riscv/griscv/Makefile.am create mode 100644 c/src/lib/libbsp/riscv/griscv/configure.ac diff --git a/bsps/riscv/griscv/clock/clockdrv.c b/bsps/riscv/griscv/clock/clockdrv.c new file mode 100644 index 0000000000..47ed6b305d --- /dev/null +++ b/bsps/riscv/griscv/clock/clockdrv.c @@ -0,0 +1,202 @@ +/* + * Clock Tick Device Driver + * + * This routine initializes GRLIB gptimer 1 which used for the clock tick. + * + * The tick frequency is directly programmed to the configured number of + * microseconds per tick. + * + * COPYRIGHT (c) 1989-2006. + * On-Line Applications Research Corporation (OAR). + * + * Modified for GRLIB BSP. + * COPYRIGHT (c) 2004. + * Gaisler Research. + * + * Copyright (c) 2014, 2018 embedded brains GmbH + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +volatile uint32_t _RISCV_Counter_register; + +/* The GRLIB BSP Timer driver can rely on the Driver Manager if the + * DrvMgr is initialized during startup. Otherwise the classic driver + * must be used. + * + * The DrvMgr Clock driver is located in the shared/timer directory + */ +#ifndef RTEMS_DRVMGR_STARTUP + +/* GRLIB Timer system interrupt number */ +static int clkirq; + +static void (*grlib_tc_tick)(void); + +static struct timecounter grlib_tc; + +#ifdef RTEMS_PROFILING +#define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26)) + +static void grlib_tc_tick_irqmp_timestamp(void) +{ + volatile struct irqmp_timestamp_regs *irqmp_ts = + &GRLIB_IrqCtrl_Regs->timestamp[0]; + unsigned int first = irqmp_ts->assertion; + unsigned int second = irqmp_ts->counter; + + irqmp_ts->control |= IRQMP_TIMESTAMP_S1_S2; + + _Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first); + + rtems_timecounter_tick(); +} +#endif + +static void grlib_tc_tick_irqmp_timestamp_init(void) +{ +#ifdef RTEMS_PROFILING + /* + * Ignore the first clock interrupt, since it contains the sequential system + * initialization time. Do the timestamp initialization on the fly. + */ + +#ifdef RTEMS_SMP + static Atomic_Uint counter = ATOMIC_INITIALIZER_UINT(0); + + bool done = + _Atomic_Fetch_add_uint(&counter, 1, ATOMIC_ORDER_RELAXED) + == rtems_get_processor_count() - 1; +#else + bool done = true; +#endif + + volatile struct irqmp_timestamp_regs *irqmp_ts = + &GRLIB_IrqCtrl_Regs->timestamp[0]; + unsigned int ks = 1U << 5; + + irqmp_ts->control = ks | IRQMP_TIMESTAMP_S1_S2 | (unsigned int) clkirq; + + if (done) { + grlib_tc_tick = grlib_tc_tick_irqmp_timestamp; + } +#endif + + rtems_timecounter_tick(); +} + +static void grlib_tc_do_tick(void) +{ + (*grlib_tc_tick)(); +} + +#define Adjust_clkirq_for_node() do { clkirq += GRLIB_CLOCK_INDEX; } while(0) + +#define Clock_driver_support_find_timer() \ + do { \ + /* Assume timer found during BSP initialization */ \ + if (GRLIB_Timer_Regs) { \ + clkirq = (GRLIB_Timer_Regs->cfg & 0xf8) >> 3; \ + \ + Adjust_clkirq_for_node(); \ + } \ + } while (0) + +#define Clock_driver_support_install_isr( _new ) \ + bsp_clock_handler_install(_new) + +static void bsp_clock_handler_install(rtems_isr *new) +{ + rtems_status_code sc; + + sc = rtems_interrupt_handler_install( + clkirq, + "Clock", + RTEMS_INTERRUPT_UNIQUE, + new, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal(RTEMS_FATAL_SOURCE_BSP, LEON3_FATAL_CLOCK_INITIALIZATION); + } +} + +#define Clock_driver_support_set_interrupt_affinity(online_processors) \ + bsp_interrupt_set_affinity(clkirq, online_processors) + +uint32_t _CPU_Counter_frequency( void ) +{ + return grlib_up_counter_frequency(); +} + + +static uint32_t _RISCV_Get_timecount_csr(struct timecounter *tc) +{ + return read_csr(time); +} + +static void grlib_clock_initialize(void) +{ + volatile struct gptimer_regs *gpt; + struct timecounter *tc; + + gpt = GRLIB_Timer_Regs; + tc = &grlib_tc; + + gpt->timer[GRLIB_CLOCK_INDEX].reload = + rtems_configuration_get_microseconds_per_tick() - 1; + gpt->timer[GRLIB_CLOCK_INDEX].ctrl = + GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS | + GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE; + + /* Use the RISCV time register as up-counter */ + tc->tc_get_timecount = _RISCV_Get_timecount_csr; + tc->tc_frequency = grlib_up_counter_frequency(); + +#ifdef RTEMS_PROFILING + volatile struct irqmp_timestamp_regs *irqmp_ts = + &GRLIB_IrqCtrl_Regs->timestamp[0]; + + if (!grlib_irqmp_has_timestamp(irqmp_ts)) { + bsp_fatal(GRLIB_FATAL_CLOCK_NO_IRQMP_TIMESTAMP_SUPPORT); + } +#endif + + grlib_tc_tick = grlib_tc_tick_irqmp_timestamp_init; + + tc->tc_counter_mask = 0xffffffff; + tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; + rtems_timecounter_install(tc); +} + +CPU_Counter_ticks _CPU_Counter_read( void ) +{ + unsigned long timec; + + __asm__ volatile ( "csrr %0, time" : "=&r" ( timec ) ); + + return timec; +} + +#define Clock_driver_support_initialize_hardware() \ + grlib_clock_initialize() + +#define Clock_driver_timecounter_tick() grlib_tc_do_tick() + +#include "../../../shared/dev/clock/clockimpl.h" + +#endif diff --git a/bsps/riscv/griscv/config/griscv.cfg b/bsps/riscv/griscv/config/griscv.cfg new file mode 100644 index 0000000000..bd4a0cacbe --- /dev/null +++ b/bsps/riscv/griscv/config/griscv.cfg @@ -0,0 +1,9 @@ +include $(RTEMS_ROOT)/make/custom/default.cfg + +RTEMS_CPU = riscv + +CPU_CFLAGS = -march=rv32imafc -mabi=ilp32f + +LDFLAGS = -Wl,--gc-sections + +CFLAGS_OPTIMIZE_V ?= -O2 -g -ffunction-sections -fdata-sections diff --git a/bsps/riscv/griscv/console/console.c b/bsps/riscv/griscv/console/console.c new file mode 100644 index 0000000000..582b4c81b8 --- /dev/null +++ b/bsps/riscv/griscv/console/console.c @@ -0,0 +1,162 @@ +/* + * This file contains the TTY driver for the GRLIB APBUART + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * + * Modified for GRLIB BSP. + * COPYRIGHT (c) 2004. + * Gaisler Research. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +/* Define CONSOLE_USE_INTERRUPTS to enable APBUART interrupt handling instead + * of polling mode. + * + * Note that it is not possible to use the interrupt mode of the driver + * together with the "old" APBUART and -u to GRMON. However the new + * APBUART core (from GRLIB 1.0.17-b2710) has the GRMON debug bit and can + * handle interrupts. + * + * NOTE: This can be defined in the griscv.cfg file. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* The GRLIB BSP UART driver can rely on the Driver Manager if the + * DrvMgr is initialized during startup. Otherwise the classic driver + * must be used. + * + * The DrvMgr APBUART driver is located in the shared/uart directory + */ +#ifndef RTEMS_DRVMGR_STARTUP + +int syscon_uart_index __attribute__((weak)) = 0; + +/* body is in debugputs.c */ +static struct apbuart_context apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS]; +static int uarts = 0; + +static rtems_termios_device_context *grlib_console_get_context(int index) +{ + struct apbuart_context *uart = &apbuarts[index]; + + rtems_termios_device_context_initialize(&uart->base, "APBUART"); + + return &uart->base; +} + +/* AMBA PP find routine. Extract AMBA PnP information into data structure. */ +static int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg) +{ + struct ambapp_apb_info *apb = (struct ambapp_apb_info *)dev->devinfo; + + /* Extract needed information of one APBUART */ + apbuarts[uarts].regs = (struct apbuart_regs *)apb->start; + apbuarts[uarts].irq = apb->irq; + /* Get APBUART core frequency, it is assumed that it is the same + * as Bus frequency where the UART is situated + */ + apbuarts[uarts].freq_hz = ambapp_freq_get(&ambapp_plb, dev); + uarts++; + + if (uarts >= BSP_NUMBER_OF_TERMIOS_PORTS) + return 1; /* Satisfied number of UARTs, stop search */ + else + return 0; /* Continue searching for more UARTs */ +} + +/* Find all UARTs */ +static void grlib_console_scan_uarts(void) +{ + memset(apbuarts, 0, sizeof(apbuarts)); + + /* Find APBUART cores */ + ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), VENDOR_GAISLER, + GAISLER_APBUART, find_matching_apbuart, NULL); +} + +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + const rtems_termios_device_handler *handler = +#if CONSOLE_USE_INTERRUPTS + &apbuart_handler_interrupt; +#else + &apbuart_handler_polled; +#endif + rtems_status_code status; + int i; + char console_name[16]; + + rtems_termios_initialize(); + + /* Find UARTs */ + grlib_console_scan_uarts(); + + /* Update syscon_uart_index to index used as /dev/console + * Let user select System console by setting syscon_uart_index. If the + * BSP is to provide the default UART (syscon_uart_index==0): + * non-MP: APBUART[0] is system console + * MP: LEON CPU index select UART + */ + if (syscon_uart_index == 0) { +#if defined(RTEMS_MULTIPROCESSING) + syscon_uart_index = GRLIB_Cpu_Index; +#else + syscon_uart_index = 0; +#endif + } else { + syscon_uart_index = syscon_uart_index - 1; /* User selected sys-console */ + } + + /* Register Device Names + * + * 0 /dev/console - APBUART[USER-SELECTED, DEFAULT=APBUART[0]] + * 1 /dev/console_a - APBUART[0] (by default not present because is console) + * 2 /dev/console_b - APBUART[1] + * ... + * + * On a MP system one should not open UARTs that other OS instances use. + */ + if (syscon_uart_index < uarts) { + status = rtems_termios_device_install( + CONSOLE_DEVICE_NAME, + handler, + NULL, + grlib_console_get_context(syscon_uart_index) + ); + if (status != RTEMS_SUCCESSFUL) + bsp_fatal(LEON3_FATAL_CONSOLE_REGISTER_DEV); + } + strcpy(console_name,"/dev/console_a"); + for (i = 0; i < uarts; i++) { + if (i == syscon_uart_index) + continue; /* skip UART that is registered as /dev/console */ + console_name[13] = 'a' + i; + rtems_termios_device_install( + console_name, + handler, + NULL, + grlib_console_get_context(i) + ); + } + + return RTEMS_SUCCESSFUL; +} + +#endif diff --git a/bsps/riscv/griscv/console/printk_support.c b/bsps/riscv/griscv/console/printk_support.c new file mode 100644 index 0000000000..f8c14692c1 --- /dev/null +++ b/bsps/riscv/griscv/console/printk_support.c @@ -0,0 +1,126 @@ +/* + * This file contains the TTY driver for the GRLIb APBUART + * + * This driver uses the termios pseudo driver. + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * Modified for GRLIB BSP. + * COPYRIGHT (c) 2011. + * Aeroflex Gaisler. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int grlib_debug_uart_index __attribute__((weak)) = 0; +struct apbuart_regs *grlib_debug_uart = NULL; + +/* Before UART driver has registered (or when no UART is available), calls to + * printk that gets to bsp_out_char() will be filling data into the + * pre_printk_dbgbuf[] buffer, hopefully the buffer can help debugging the + * early BSP boot.. At least the last printk() will be caught. + * +static char pre_printk_dbgbuf[32] = {0}; +static int pre_printk_pos = 0; + */ + +/* Initialize the BSP system debug console layer. It will scan AMBA Plu&Play + * for a debug APBUART and enable RX/TX for that UART. + */ +static void bsp_debug_uart_init(void) +{ + int i; + struct ambapp_dev *adev; + struct ambapp_apb_info *apb; + + /* Update grlib_debug_uart_index to index used as debug console. Let user + * select Debug console by setting grlib_debug_uart_index. If the BSP is to + * provide the default UART (grlib_debug_uart_index==0): + * non-MP: APBUART[0] is debug console + * MP: LEON CPU index select UART + */ + if (grlib_debug_uart_index == 0) { +#if defined(RTEMS_MULTIPROCESSING) + grlib_debug_uart_index = GRLIB_Cpu_Index; +#else + grlib_debug_uart_index = 0; +#endif + } else { + grlib_debug_uart_index--; /* User selected dbg-console */ + } + + /* Find APBUART core for System Debug Console */ + i = grlib_debug_uart_index; + adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), + VENDOR_GAISLER, GAISLER_APBUART, + ambapp_find_by_idx, (void *)&i); + if (adev) { + /* Found a matching debug console, initialize debug uart if present + * for printk + */ + apb = (struct ambapp_apb_info *)adev->devinfo; + grlib_debug_uart = (struct apbuart_regs *)apb->start; + grlib_debug_uart->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; + grlib_debug_uart->status = 0; + } +} + +RTEMS_SYSINIT_ITEM( + bsp_debug_uart_init, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_FOURTH +); + +/* putchar/getchar for printk */ +static void bsp_out_char(char c) +{ + if (grlib_debug_uart == NULL) { + /* Try to assign standard UART address to debug driver to pass some tests */ + grlib_debug_uart = (struct apbuart_regs *) 0x80000100; + grlib_debug_uart->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; + grlib_debug_uart->status = 0; + /* Local debug buffer when UART driver has not registered */ + /* + pre_printk_dbgbuf[pre_printk_pos++] = c; + pre_printk_pos = pre_printk_pos & (sizeof(pre_printk_dbgbuf)-1); + return; + */ + } + + apbuart_outbyte_polled(grlib_debug_uart, c, 1, 1); +} + +/* + * To support printk + */ + +#include + +BSP_output_char_function_type BSP_output_char = bsp_out_char; + +static int bsp_in_char(void) +{ + int tmp; + + if (grlib_debug_uart == NULL) + return EOF; + + while ((tmp = apbuart_inbyte_nonblocking(grlib_debug_uart)) < 0) + ; + return tmp; +} + +BSP_polling_getchar_function_type BSP_poll_char = bsp_in_char; diff --git a/bsps/riscv/griscv/headers.am b/bsps/riscv/griscv/headers.am new file mode 100644 index 0000000000..f351d7c12b --- /dev/null +++ b/bsps/riscv/griscv/headers.am @@ -0,0 +1,11 @@ +## This file was generated by "./boostrap -H". + +include_HEADERS = +include_HEADERS += ../../../../../../bsps/riscv/griscv/include/amba.h +include_HEADERS += ../../../../../../bsps/riscv/griscv/include/bsp.h +include_HEADERS += include/bspopts.h +include_HEADERS += ../../../../../../bsps/riscv/griscv/include/tm27.h + +include_bspdir = $(includedir)/bsp +include_bsp_HEADERS = +include_bsp_HEADERS += ../../../../../../bsps/riscv/griscv/include/bsp/irq.h diff --git a/bsps/riscv/griscv/include/amba.h b/bsps/riscv/griscv/include/amba.h new file mode 100644 index 0000000000..e1c5c00464 --- /dev/null +++ b/bsps/riscv/griscv/include/amba.h @@ -0,0 +1,143 @@ +/** + * @file + * @defgroup amba AMBA Driver Handler + * @ingroup sparc_leon3 + * @brief AMBA Plag & Play Bus Driver Macros + */ + +/* + * AMBA Plag & Play Bus Driver Macros + * + * Macros used for AMBA Plug & Play bus scanning + * + * COPYRIGHT (c) 2004. + * Gaisler Research + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef __AMBA_H__ +#define __AMBA_H__ + +#ifndef GRLIB_IO_AREA +#define GRLIB_IO_AREA 0xfff00000 +#endif + +#define GRLIB_CONF_AREA 0xff000 +#define GRLIB_AHB_SLAVE_CONF_AREA (1 << 11) + +#define GRLIB_AHB_CONF_WORDS 8 +#define GRLIB_APB_CONF_WORDS 2 +#define GRLIB_AHB_MASTERS 64 +#define GRLIB_AHB_SLAVES 64 +#define GRLIB_APB_SLAVES 16 + +#if defined(RTEMS_MULTIPROCESSING) + #define GRLIB_CLOCK_INDEX \ + (rtems_configuration_get_user_multiprocessing_table() ? GRLIB_Cpu_Index : 0) +#else + #define GRLIB_CLOCK_INDEX 0 +#endif + +#if defined(RTEMS_SMP) +#define GRLIB_COUNTER_GPTIMER_INDEX (GRLIB_CLOCK_INDEX + 1) +#else +#define GRLIB_COUNTER_GPTIMER_INDEX GRLIB_CLOCK_INDEX +#endif + +#define GRLIB_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER 1000000 + +#define GRLIB_IRQMPSTATUS_CPUNR 28 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* The AMBA Plug&Play info of the bus that the cpu sits on */ +extern struct ambapp_bus ambapp_plb; + +extern uint32_t GRLIB_Cpu_Index; +extern const unsigned char GRLIB_mp_irq; + +extern volatile struct irqmp_regs *GRLIB_IrqCtrl_Regs; +extern struct ambapp_dev *GRLIB_IrqCtrl_Adev; +extern int GRLIB_IrqCtrl_EIrq; +extern volatile struct gptimer_regs *GRLIB_Timer_Regs; +extern struct ambapp_dev *GRLIB_Timer_Adev; +void gptimer_initialize(void); +void irqmp_initialize(void); + +static inline uint32_t grlib_up_counter_frequency(void) +{ + /* + * For simplicity, assume that the interrupt controller uses the processor + * clock. This is at least true on the GR740. + */ + return ambapp_freq_get(&ambapp_plb, GRLIB_IrqCtrl_Adev); +} + +extern rtems_interrupt_lock GRLIB_IrqCtrl_Lock; + + +static inline uint32_t grlib_get_cpu_count( + volatile struct irqmp_regs *irqmp +) +{ + uint32_t mpstat = irqmp->mpstat; + + return ((mpstat >> GRLIB_IRQMPSTATUS_CPUNR) & 0xf) + 1; +} + +#define GRLIB_IRQCTRL_ACQUIRE( _lock_context ) \ + rtems_interrupt_lock_acquire( &GRLIB_IrqCtrl_Lock, _lock_context ) + +#define GRLIB_IRQCTRL_RELEASE( _lock_context ) \ + rtems_interrupt_lock_release( &GRLIB_IrqCtrl_Lock, _lock_context ) + +#define GRLIB_Cpu_Unmask_interrupt( _source, _cpu ) \ + do { \ + rtems_interrupt_lock_context _lock_context; \ + GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \ + GRLIB_IrqCtrl_Regs->mask[_cpu] |= (1U << (_source)); \ + GRLIB_IRQCTRL_RELEASE( &_lock_context ); \ + } while (0) + +#define GRLIB_Cpu_Mask_interrupt( _source, _cpu ) \ + do { \ + rtems_interrupt_lock_context _lock_context; \ + GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \ + GRLIB_IrqCtrl_Regs->mask[_cpu] &= ~(1U << (_source)); \ + GRLIB_IRQCTRL_RELEASE( &_lock_context ); \ + } while (0) + +#define GRLIB_Enable_interrupt_broadcast( _source ) \ + do { \ + rtems_interrupt_lock_context _lock_context; \ + uint32_t _mask = 1U << ( _source ); \ + GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \ + GRLIB_IrqCtrl_Regs->bcast |= _mask; \ + GRLIB_IRQCTRL_RELEASE( &_lock_context ); \ + } while (0) + +#define GRLIB_Disable_interrupt_broadcast( _source ) \ + do { \ + rtems_interrupt_lock_context _lock_context; \ + uint32_t _mask = 1U << ( _source ); \ + GRLIB_IRQCTRL_ACQUIRE( &_lock_context ); \ + GRLIB_IrqCtrl_Regs->bcast &= ~_mask; \ + GRLIB_IRQCTRL_RELEASE( &_lock_context ); \ + } while (0) + +#define BSP_Cpu_Is_interrupt_masked( _source, _cpu ) \ + (!(GRLIB_IrqCtrl_Regs->mask[_cpu] & (1U << (_source)))) + +#ifdef __cplusplus +} +#endif + +#endif /* __AMBA_H__ */ diff --git a/bsps/riscv/griscv/include/bsp.h b/bsps/riscv/griscv/include/bsp.h new file mode 100644 index 0000000000..185bd5bb23 --- /dev/null +++ b/bsps/riscv/griscv/include/bsp.h @@ -0,0 +1,66 @@ +/* + * + * Copyright (c) 2015 University of York. + * Hesham Almatary + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LIBBSP_RISCV_GRISCV_H +#define LIBBSP_RISCV_GRISCV_H + +#include +#include +#include +#include + +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define BSP_FEATURE_IRQ_EXTENSION + +/* Maximum supported APBUARTs by BSP */ +#define BSP_NUMBER_OF_TERMIOS_PORTS 8 + +/* Make sure maximum number of consoles fit in filesystem */ +#define BSP_MAXIMUM_DEVICES 8 + +/* GRLIB driver functions */ + +extern void BSP_shared_interrupt_mask(int irq); +extern void BSP_shared_interrupt_clear(int irq); +extern void BSP_shared_interrupt_unmask(int irq); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBBSP_RISCV_GRISCV_H */ diff --git a/bsps/riscv/griscv/include/bsp/irq.h b/bsps/riscv/griscv/include/bsp/irq.h new file mode 100644 index 0000000000..cd6f1599ad --- /dev/null +++ b/bsps/riscv/griscv/include/bsp/irq.h @@ -0,0 +1,73 @@ +/** + * @file + * + * @ingroup RISCV_IRQ + * + * @brief Interrupt definitions. + */ + +/* + * Copyright (c) 2018 embedded brains GmbH + * + * Copyright (c) 2015 University of York. + * Hesham Almatary + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LIBBSP_RISCV_GRISCV_IRQ_H +#define LIBBSP_RISCV_GRISCV_IRQ_H + +#ifndef ASM + +#include +#include +#include +#include + +#define RISCV_INTERRUPT_VECTOR_SOFTWARE 0 + +#define RISCV_INTERRUPT_VECTOR_TIMER 1 + +#define RISCV_INTERRUPT_VECTOR_EXTERNAL(x) ((x) + 2) + +#define RISCV_INTERRUPT_VECTOR_IS_EXTERNAL(x) ((x) >= 2) + +#define RISCV_INTERRUPT_VECTOR_EXTERNAL_TO_INDEX(x) ((x) - 2) + +#define BSP_INTERRUPT_VECTOR_MIN 0 + +#define BSP_INTERRUPT_VECTOR_MAX RISCV_INTERRUPT_VECTOR_EXTERNAL(RISCV_MAXIMUM_EXTERNAL_INTERRUPTS - 1) + +void bsp_interrupt_set_affinity( + rtems_vector_number vector, + const Processor_mask *affinity +); + +void bsp_interrupt_get_affinity( + rtems_vector_number vector, + Processor_mask *affinity +); + +#endif /* ASM */ + +#endif /* LIBBSP_RISCV_GRISCV_IRQ_H */ diff --git a/bsps/riscv/griscv/include/tm27.h b/bsps/riscv/griscv/include/tm27.h new file mode 100644 index 0000000000..0dfa7bf628 --- /dev/null +++ b/bsps/riscv/griscv/include/tm27.h @@ -0,0 +1 @@ +#include diff --git a/bsps/riscv/griscv/irq/irq.c b/bsps/riscv/griscv/irq/irq.c new file mode 100644 index 0000000000..721cd98ffe --- /dev/null +++ b/bsps/riscv/griscv/irq/irq.c @@ -0,0 +1,144 @@ +/** + * @file + * + * @ingroup riscv_interrupt + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2018 embedded brains GmbH + * + * Copyright (c) 2015 University of York. + * Hesham Almatary + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include +#include +#include + +rtems_interrupt_lock GRLIB_IrqCtrl_Lock; + +#if defined(RTEMS_SMP) +/* Interrupt to CPU map. Default to CPU0 since in BSS. */ +const unsigned char GRLIB_irq_to_cpu[32] __attribute__((weak)); + +/* On SMP use map table above relative to SMP Boot CPU (normally CPU0) */ +static inline int bsp_irq_cpu(int irq) +{ + /* protect from bad user configuration, default to boot cpu */ + if (rtems_configuration_get_maximum_processors() <= GRLIB_irq_to_cpu[irq]) + return GRLIB_Cpu_Index; + else + return GRLIB_Cpu_Index + GRLIB_irq_to_cpu[irq]; +} +#else +/* when not SMP the local CPU is returned */ +static inline int bsp_irq_cpu(int irq) +{ + return read_csr(mhartid); +} +#endif + +void _RISCV_Interrupt_dispatch(uintptr_t mcause, Per_CPU_Control *cpu_self) +{ + if (mcause & 0x80000000) { + + bsp_interrupt_handler_dispatch(mcause & 0xf); + + } else { + bsp_fatal(RISCV_FATAL_UNEXPECTED_INTERRUPT_EXCEPTION); + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + + /* + * External M-mode interrupts on secondary processors are enabled in + * bsp_start_on_secondary_processor(). + */ + set_csr(mie, MIP_MEIP); + + return RTEMS_SUCCESSFUL; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + int irq = (int)vector; + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + GRLIB_Cpu_Unmask_interrupt(irq, bsp_irq_cpu(irq)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + int irq = (int)vector; + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + GRLIB_Cpu_Mask_interrupt(irq, bsp_irq_cpu(irq)); +} + +void bsp_interrupt_get_affinity( + rtems_vector_number vector, + Processor_mask *affinity +) +{ + uint32_t cpu_count = rtems_get_processor_count(); + uint32_t cpu_index; + + _Processor_mask_Zero(affinity); + + for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { + if (!BSP_Cpu_Is_interrupt_masked(vector, cpu_index)) { + _Processor_mask_Set(affinity, cpu_index); + } + } +} + +void bsp_interrupt_set_affinity( + rtems_vector_number vector, + const Processor_mask *affinity +) +{ + uint32_t unmasked = 0; + uint32_t cpu_count = rtems_get_processor_count(); + uint32_t cpu_index; + + for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { + if (_Processor_mask_Is_set(affinity, cpu_index)) { + GRLIB_Cpu_Unmask_interrupt(vector, cpu_index); + ++unmasked; + } + } + + if (unmasked > 1) { + GRLIB_Enable_interrupt_broadcast(vector); + } else { + GRLIB_Disable_interrupt_broadcast(vector); + } +} diff --git a/bsps/riscv/griscv/start/amba.c b/bsps/riscv/griscv/start/amba.c new file mode 100644 index 0000000000..182f659d69 --- /dev/null +++ b/bsps/riscv/griscv/start/amba.c @@ -0,0 +1,115 @@ + +/* + * Find and initialize irqmp and gptimer. + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include + +rtems_interrupt_lock GRLIB_IrqCtrl_Lock = + RTEMS_INTERRUPT_LOCK_INITIALIZER("GRLIB IrqCtrl"); + +/* Pointers to Interrupt Controller configuration registers */ +volatile struct irqmp_regs *GRLIB_IrqCtrl_Regs; +struct ambapp_dev *GRLIB_IrqCtrl_Adev; + +/* GRLIB extended IRQ controller IRQ number */ +int GRLIB_IrqCtrl_EIrq = -1; + +/* Initialize Extended Interrupt controller */ +static void grlib_ext_irq_init(void) +{ + if ( (GRLIB_IrqCtrl_Regs->mpstat >> 16) & 0xf ) { + /* Extended IRQ controller available */ + GRLIB_IrqCtrl_EIrq = (GRLIB_IrqCtrl_Regs->mpstat >> 16) & 0xf; + } +} + +/* + * irqmp_initialize + * + * Probes for IRQMP and initialises necessary registers. + * + */ + +void irqmp_initialize(void) +{ + int icsel; + struct ambapp_dev *adev; + + /* Find GRLIB Interrupt controller */ + adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), + VENDOR_GAISLER, GAISLER_IRQMP, + ambapp_find_by_idx, NULL); + if (adev != NULL) { + + GRLIB_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start; + GRLIB_IrqCtrl_Adev = adev; + if ((GRLIB_IrqCtrl_Regs->ampctrl >> 28) > 0) { + /* IRQ Controller has support for multiple IRQ Controllers, each + * CPU can be routed to different Controllers, we find out which + * controller by looking at the IRQCTRL Select Register for this CPU. + * Each Controller is located at a 4KByte offset. + */ + icsel = GRLIB_IrqCtrl_Regs->icsel[GRLIB_Cpu_Index/8]; + icsel = (icsel >> ((7 - (GRLIB_Cpu_Index & 0x7)) * 4)) & 0xf; + GRLIB_IrqCtrl_Regs += icsel; + } + GRLIB_IrqCtrl_Regs->mask[GRLIB_Cpu_Index] = 0; + GRLIB_IrqCtrl_Regs->force[GRLIB_Cpu_Index] = 0; + GRLIB_IrqCtrl_Regs->iclear = 0xffffffff; + + /* Init Extended IRQ controller if available */ + grlib_ext_irq_init(); + + } + +} + + +/* GPTIMER */ + +unsigned int grlib_timer_prescaler __attribute__((weak)) = 0; +int grlib_timer_core_index __attribute__((weak)) = 0; + +volatile struct gptimer_regs *GRLIB_Timer_Regs; +struct ambapp_dev *GRLIB_Timer_Adev; + +/* + * gptimer_initialize + * + */ + +void gptimer_initialize(void) +{ + struct ambapp_dev *adev; + + /* find GP Timer */ + adev = (void *)ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), + VENDOR_GAISLER, GAISLER_GPTIMER, + ambapp_find_by_idx, &grlib_timer_core_index); + if (adev) { + GRLIB_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start; + GRLIB_Timer_Adev = adev; + + /* Register AMBA Bus Frequency */ + ambapp_freq_init( + &ambapp_plb, + GRLIB_Timer_Adev, + (GRLIB_Timer_Regs->scaler_reload + 1) + * GRLIB_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER + ); + /* Set user prescaler configuration. Use this to increase accuracy of timer + * and accociated services like cpucounter. + * Note that minimum value is the number of timer instances present in + * GRTIMER/GPTIMER hardware. See HW manual. + */ + if (grlib_timer_prescaler) + GRLIB_Timer_Regs->scaler_reload = grlib_timer_prescaler; + } + +} diff --git a/bsps/riscv/griscv/start/bsp_fatal_halt.c b/bsps/riscv/griscv/start/bsp_fatal_halt.c new file mode 100644 index 0000000000..ced328ea0f --- /dev/null +++ b/bsps/riscv/griscv/start/bsp_fatal_halt.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 embedded brains GmbH + * + * Copyright (c) 2015 University of York. + * Hesham Almatary + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +void _CPU_Fatal_halt(uint32_t source, uint32_t error) +{ + /* ecall is currently used to halt the griscv cpu */ + asm ("ecall"); + for(;;); +} diff --git a/bsps/riscv/griscv/start/bsp_specs b/bsps/riscv/griscv/start/bsp_specs new file mode 100644 index 0000000000..87638cc027 --- /dev/null +++ b/bsps/riscv/griscv/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/bsps/riscv/griscv/start/bspsmp.c b/bsps/riscv/griscv/start/bspsmp.c new file mode 100644 index 0000000000..df826f8217 --- /dev/null +++ b/bsps/riscv/griscv/start/bspsmp.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +static rtems_isr bsp_inter_processor_interrupt( void *v ) +{ + _SMP_Inter_processor_interrupt_handler(_Per_CPU_Get()); +} + +void bsp_start_on_secondary_processor(Per_CPU_Control *cpu_self) +{ + uint32_t cpu_index_self; + + cpu_index_self = _Per_CPU_Get_index(cpu_self); + GRLIB_IrqCtrl_Regs->mask[cpu_index_self] |= 1U << GRLIB_mp_irq; + + if ( + cpu_index_self < rtems_configuration_get_maximum_processors() + && _SMP_Should_start_processor(cpu_index_self) + ) { + set_csr(mie, MIP_MEIP); + _SMP_Start_multitasking_on_secondary_processor(cpu_self); + } else { + _CPU_Thread_Idle_body(0); + } +} + +uint32_t _CPU_SMP_Initialize(void) +{ + if ( rtems_configuration_get_maximum_processors() > 1 ) { + GRLIB_Cpu_Unmask_interrupt(GRLIB_mp_irq, _CPU_SMP_Get_current_processor()); + + rtems_interrupt_handler_install( + GRLIB_mp_irq, + "IPI", + RTEMS_INTERRUPT_SHARED, + bsp_inter_processor_interrupt, + NULL + ); + + } + + return grlib_get_cpu_count(GRLIB_IrqCtrl_Regs); +} + +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ + GRLIB_IrqCtrl_Regs->mpstat = 1U << cpu_index; + + return true; +} + +void _CPU_SMP_Finalize_initialization(uint32_t cpu_count) +{ + (void) cpu_count; +// set_csr(mie, MIP_MSIP); +} + +void _CPU_SMP_Prepare_start_multitasking(void) +{ + /* Do nothing */ +} + +void _CPU_SMP_Send_interrupt(uint32_t target_processor_index) +{ + + GRLIB_IrqCtrl_Regs->force[target_processor_index] = 1 << GRLIB_mp_irq; + +} diff --git a/bsps/riscv/griscv/start/bspstart.c b/bsps/riscv/griscv/start/bspstart.c new file mode 100644 index 0000000000..dd83c80818 --- /dev/null +++ b/bsps/riscv/griscv/start/bspstart.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018 embedded brains GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include + +#if defined(RTEMS_SMP) || defined(RTEMS_MULTIPROCESSING) +/* Irq used by shared memory driver and for inter-processor interrupts. + * Can be overridden by being defined in the application. + */ +const unsigned char GRLIB_mp_irq __attribute__((weak)) = 14; +#endif + +uint32_t GRLIB_Cpu_Index = 0; + +#ifdef RTEMS_SMP +uint32_t riscv_hart_count = 1; +/* Index of the boot CPU. Set by the first CPU at boot to its CPU ID. */ +int GRLIB_Boot_Cpu = -1; +#endif + +void bsp_start(void) +{ + bsp_interrupt_initialize(); +#ifdef RTEMS_SMP + GRLIB_Cpu_Index = _CPU_SMP_Get_current_processor(); +#endif +} + +void amba_initialize(void); +struct ambapp_bus ambapp_plb; + +void amba_initialize(void) +{ + ambapp_scan(&ambapp_plb, GRLIB_IO_AREA, NULL, NULL); + gptimer_initialize(); + irqmp_initialize(); +} + +RTEMS_SYSINIT_ITEM( + amba_initialize, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_FIRST +); diff --git a/bsps/riscv/griscv/start/linkcmds.in b/bsps/riscv/griscv/start/linkcmds.in new file mode 100644 index 0000000000..80e2f5ef90 --- /dev/null +++ b/bsps/riscv/griscv/start/linkcmds.in @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015 University of York. + * Hesham ALMatary + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +MEMORY +{ + RAM : ORIGIN = @RISCV_RAM_REGION_BEGIN@, LENGTH = @RISCV_RAM_REGION_SIZE@ +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_RTEMSSTACK", RAM); +REGION_ALIAS ("REGION_WORK", RAM); + +INCLUDE linkcmds.base diff --git a/bsps/riscv/riscv/clock/clockdrv.c b/bsps/riscv/riscv/clock/clockdrv.c index 30a894f384..7e6034d4d1 100644 --- a/bsps/riscv/riscv/clock/clockdrv.c +++ b/bsps/riscv/riscv/clock/clockdrv.c @@ -189,6 +189,11 @@ uint32_t _CPU_Counter_frequency( void ) return riscv_clock_get_timebase_frequency(bsp_fdt_get()); } +CPU_Counter_ticks _CPU_Counter_read( void ) +{ + return *_RISCV_Counter; +} + RTEMS_SYSINIT_ITEM( riscv_counter_initialize, RTEMS_SYSINIT_CPU_COUNTER, diff --git a/bsps/riscv/riscv/start/linkcmds.base b/bsps/riscv/riscv/start/linkcmds.base deleted file mode 100644 index 7d889ab38c..0000000000 --- a/bsps/riscv/riscv/start/linkcmds.base +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright (C) 2014-2018 Free Software Foundation, Inc. - Copying and distribution of this script, with or without modification, - are permitted in any medium without royalty provided the copyright - notice and this notice are preserved. */ - -/* - * Copyright (c) 2018 embedded brains GmbH. - * - * Copyright (c) 2015 University of York. - * Hesham ALMatary - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -OUTPUT_ARCH(riscv) -ENTRY(_start) -STARTUP(start.o) - -bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1; -bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1; - -MEMORY { - UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 -} - -SECTIONS { - .start : ALIGN_WITH_INPUT { - bsp_section_start_begin = .; - KEEP (*(.bsp_start_text)) - KEEP (*(.bsp_start_data)) - bsp_section_start_end = .; - } > REGION_START AT > REGION_START - bsp_section_start_size = bsp_section_start_end - bsp_section_start_begin; - - .text : ALIGN_WITH_INPUT { - bsp_section_text_begin = .; - *(.text.unlikely .text.*_unlikely .text.unlikely.*) - *(.text.exit .text.exit.*) - *(.text.startup .text.startup.*) - *(.text.hot .text.hot.*) - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } > REGION_TEXT AT > REGION_TEXT_LOAD - .init : ALIGN_WITH_INPUT { - KEEP (*(SORT_NONE(.init))) - } > REGION_TEXT AT > REGION_TEXT_LOAD - .fini : ALIGN_WITH_INPUT { - KEEP (*(SORT_NONE(.fini))) - bsp_section_text_end = .; - } > REGION_TEXT AT > REGION_TEXT_LOAD - bsp_section_text_size = bsp_section_text_end - bsp_section_text_begin; - bsp_section_text_load_begin = LOADADDR (.text); - bsp_section_text_load_end = bsp_section_text_load_begin + bsp_section_text_size; - - .robarrier : ALIGN_WITH_INPUT { - . = ALIGN (bsp_section_robarrier_align); - } > REGION_RODATA AT > REGION_RODATA - - .rodata : ALIGN_WITH_INPUT { - bsp_section_rodata_begin = .; - *(.rodata .rodata.* .gnu.linkonce.r.*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .rodata1 : ALIGN_WITH_INPUT { - *(.rodata1) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .sdata2 : ALIGN_WITH_INPUT { - *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .sbss2 : ALIGN_WITH_INPUT { - *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .eh_frame_hdr : ALIGN_WITH_INPUT { - *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .eh_frame : ALIGN_WITH_INPUT { - KEEP (*(.eh_frame)) *(.eh_frame.*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .gcc_except_table : ALIGN_WITH_INPUT { - *(.gcc_except_table .gcc_except_table.*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .gnu_extab : ALIGN_WITH_INPUT { - *(.gnu_extab*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .tdata : ALIGN_WITH_INPUT { - _TLS_Data_begin = .; - *(.tdata .tdata.* .gnu.linkonce.td.*) - _TLS_Data_end = .; - } > REGION_RODATA AT > REGION_RODATA_LOAD - .tbss : ALIGN_WITH_INPUT { - _TLS_BSS_begin = .; - *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) - _TLS_BSS_end = .; - } > REGION_RODATA AT > REGION_RODATA_LOAD - _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; - _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; - _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; - _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; - _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; - _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); - .preinit_array : ALIGN_WITH_INPUT { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } > REGION_RODATA AT > REGION_RODATA_LOAD - .init_array : ALIGN_WITH_INPUT { - 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 = .); - } > REGION_RODATA AT > REGION_RODATA_LOAD - .fini_array : ALIGN_WITH_INPUT { - 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 = .); - } > REGION_RODATA AT > REGION_RODATA_LOAD - .ctors : ALIGN_WITH_INPUT { - /* 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)) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .dtors : ALIGN_WITH_INPUT { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .data.rel.ro : ALIGN_WITH_INPUT { - *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) - *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .jcr : ALIGN_WITH_INPUT { - KEEP (*(.jcr)) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .interp : ALIGN_WITH_INPUT { - *(.interp) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .note.gnu.build-id : { *(.note.gnu.build-id) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .hash : ALIGN_WITH_INPUT { - *(.hash) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .gnu.hash : ALIGN_WITH_INPUT { - *(.gnu.hash) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .dynsym : ALIGN_WITH_INPUT { - *(.dynsym) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .dynstr : ALIGN_WITH_INPUT { - *(.dynstr) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .gnu.version : ALIGN_WITH_INPUT { - *(.gnu.version) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .gnu.version_d : ALIGN_WITH_INPUT { - *(.gnu.version_d) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .gnu.version_r : ALIGN_WITH_INPUT { - *(.gnu.version_r) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .rela.dyn : ALIGN_WITH_INPUT { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) - *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) - *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) - *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - PROVIDE_HIDDEN (__rela_iplt_start = .); - *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); - } > REGION_RODATA AT > REGION_RODATA_LOAD - .rela.plt : ALIGN_WITH_INPUT { - *(.rela.plt) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .plt : ALIGN_WITH_INPUT { - *(.plt) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .iplt : ALIGN_WITH_INPUT { - *(.iplt) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .dynamic : ALIGN_WITH_INPUT { - *(.dynamic) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .tm_clone_table : ALIGN_WITH_INPUT { - *(.tm_clone_table) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .got : ALIGN_WITH_INPUT { - *(.got.plt) *(.igot.plt) *(.got) *(.igot) - } > REGION_RODATA AT > REGION_RODATA_LOAD - .rtemsroset : ALIGN_WITH_INPUT { - /* Special FreeBSD linker set sections */ - __start_set_sysctl_set = .; - *(set_sysctl_*); - __stop_set_sysctl_set = .; - *(set_domain_*); - *(set_pseudo_*); - - KEEP (*(SORT(.rtemsroset.*))) - bsp_section_rodata_end = .; - } > REGION_RODATA AT > REGION_RODATA_LOAD - bsp_section_rodata_size = bsp_section_rodata_end - bsp_section_rodata_begin; - bsp_section_rodata_load_begin = LOADADDR (.rodata); - bsp_section_rodata_load_end = bsp_section_rodata_load_begin + bsp_section_rodata_size; - - .rwbarrier : ALIGN_WITH_INPUT { - . = ALIGN (bsp_section_rwbarrier_align); - } > REGION_DATA AT > REGION_DATA - - .fast_text : ALIGN_WITH_INPUT { - bsp_section_fast_text_begin = .; - *(.bsp_fast_text) - bsp_section_fast_text_end = .; - } > REGION_FAST_TEXT AT > REGION_FAST_TEXT_LOAD - bsp_section_fast_text_size = bsp_section_fast_text_end - bsp_section_fast_text_begin; - bsp_section_fast_text_load_begin = LOADADDR (.fast_text); - bsp_section_fast_text_load_end = bsp_section_fast_text_load_begin + bsp_section_fast_text_size; - - .fast_data : ALIGN_WITH_INPUT { - bsp_section_fast_data_begin = .; - *(.bsp_fast_data) - bsp_section_fast_data_end = .; - } > REGION_FAST_DATA AT > REGION_FAST_DATA_LOAD - bsp_section_fast_data_size = bsp_section_fast_data_end - bsp_section_fast_data_begin; - bsp_section_fast_data_load_begin = LOADADDR (.fast_data); - bsp_section_fast_data_load_end = bsp_section_fast_data_load_begin + bsp_section_fast_data_size; - - .data : ALIGN_WITH_INPUT { - bsp_section_data_begin = .; - *(.data .data.* .gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } > REGION_DATA AT > REGION_DATA_LOAD - .data1 : ALIGN_WITH_INPUT { - *(.data1) - } > REGION_DATA AT > REGION_DATA_LOAD - .rtemsrwset : ALIGN_WITH_INPUT { - KEEP (*(SORT(.rtemsrwset.*))) - } > REGION_DATA AT > REGION_DATA_LOAD - .htif ALIGN(4096) : ALIGN_WITH_INPUT { - *(.htif) - } > REGION_DATA AT > REGION_DATA_LOAD - .sdata : ALIGN_WITH_INPUT { - __global_pointer$ = . + 0x800; - *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) - *(.sdata .sdata.* .gnu.linkonce.s.*) - bsp_section_data_end = .; - } > REGION_DATA AT > REGION_DATA_LOAD - bsp_section_data_size = bsp_section_data_end - bsp_section_data_begin; - bsp_section_data_load_begin = LOADADDR (.data); - bsp_section_data_load_end = bsp_section_data_load_begin + bsp_section_data_size; - - .sbss : ALIGN_WITH_INPUT { - bsp_section_bss_begin = .; - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - } > REGION_DATA AT > REGION_DATA - .bss : ALIGN_WITH_INPUT { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - bsp_section_bss_end = .; - } > REGION_DATA AT > REGION_DATA - bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; - - .rtemsstack (NOLOAD) : ALIGN_WITH_INPUT { - bsp_section_rtemsstack_begin = .; - *(SORT(.rtemsstack.*)) - bsp_section_rtemsstack_end = .; - } > REGION_RTEMSSTACK AT > REGION_RTEMSSTACK - bsp_section_rtemsstack_size = bsp_section_rtemsstack_end - bsp_section_rtemsstack_begin; - - .work : ALIGN_WITH_INPUT { - /* - * The work section will occupy the remaining REGION_WORK region and - * contains the RTEMS work space and heap. - */ - bsp_section_work_begin = .; - . += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.); - bsp_section_work_end = .; - } > REGION_WORK AT > REGION_WORK - bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; - - /* FIXME */ - RamBase = ORIGIN (REGION_WORK); - RamSize = LENGTH (REGION_WORK); - WorkAreaBase = bsp_section_work_begin; - HeapSize = 0; - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* DWARF 3 */ - .debug_pubtypes 0 : { *(.debug_pubtypes) } - .debug_ranges 0 : { *(.debug_ranges) } - /* DWARF Extension. */ - .debug_macro 0 : { *(.debug_macro) } - .debug_addr 0 : { *(.debug_addr) } - .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } - /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } - - /* - * This is a RTEMS specific section to catch all unexpected input - * sections. In case you get an error like - * "section `.unexpected_sections' will not fit in region - * `UNEXPECTED_SECTIONS'" - * you have to figure out the offending input section and add it to the - * appropriate output section definition above. - */ - .unexpected_sections : { *(*) } > UNEXPECTED_SECTIONS -} diff --git a/bsps/riscv/riscv/start/start.S b/bsps/riscv/riscv/start/start.S deleted file mode 100644 index a8ff1b079f..0000000000 --- a/bsps/riscv/riscv/start/start.S +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2018 embedded brains GmbH - - * Copyright (c) 2015 University of York. - * Hesham Almatary - * - * Copyright (c) 2013, The Regents of the University of California (Regents). - * All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -PUBLIC(_start) - - .section .bsp_start_text, "wax", @progbits - .align 2 - -TYPE_FUNC(_start) -SYM(_start): - /* Load global pointer */ - .option push - .option norelax - LADDR gp, __global_pointer$ - .option pop - - /* Init FPU */ -#ifdef __riscv_flen - li t0, MSTATUS_FS - csrs mstatus, t0 - csrw fcsr, zero -#endif - - /* Set exception handler */ - LADDR t0, _RISCV_Exception_handler - csrw mtvec, t0 - - /* Load stack pointer and branch to secondary processor start if necessary */ -#ifdef RTEMS_SMP - LADDR sp, _ISR_Stack_area_begin - LADDR t2, _ISR_Stack_size - csrr s0, mhartid - LADDR t0, _Per_CPU_Information - slli t1, s0, PER_CPU_CONTROL_SIZE_LOG2 - add s1, t0, t1 - csrw mscratch, s1 - bnez s0, .Lstart_on_secondary_processor - add sp, sp, t2 -#else - LADDR sp, _ISR_Stack_area_end -#endif - -#ifdef BSP_START_COPY_FDT_FROM_U_BOOT - mv a0, a1 - call bsp_fdt_copy -#endif - - /* Clear .bss */ - LADDR a0, bsp_section_bss_begin - li a1, 0 - LADDR a2, bsp_section_bss_size - call memset - -#ifdef RTEMS_SMP - /* Give go to secondary processors */ - LADDR t0, .Lsecondary_processor_go - fence iorw,ow - amoswap.w zero, zero, 0(t0) -#endif - - li a0, 0 - j boot_card - -#ifdef RTEMS_SMP - -.Lstart_on_secondary_processor: - - /* Adjust stack pointer */ -#ifdef __riscv_mul - addi t0, s0, 1 - mul t2, t2, t0 -#else - mv t0, s0 - mv t3, t2 - -.Ladd_more: - - add t2, t2, t3 - addi t0, t0, -1 - bnez t0, .Ladd_more -#endif - add sp, sp, t2 - - /* Wait for go issued by the boot processor (mhartid == 0) */ - LADDR t0, .Lsecondary_processor_go - -.Lwait_for_go_again: - - lw t1, 0(t0) - fence iorw, iorw - bnez t1, .Lwait_for_go_again - - mv a0, s1 - call bsp_start_on_secondary_processor - -#if __riscv_xlen == 32 - .align 2 -#elif __riscv_xlen == 64 - .align 3 -#endif - -.Lsecondary_processor_go: - - /* - * These are ebreak instructions, just in case we end up here executing - * code. - */ - .word 0x00100073 -#if __riscv_xlen == 64 - .word 0x00100073 -#endif - -#endif /* RTEMS_SMP */ diff --git a/bsps/riscv/shared/start/linkcmds.base b/bsps/riscv/shared/start/linkcmds.base new file mode 100644 index 0000000000..7d889ab38c --- /dev/null +++ b/bsps/riscv/shared/start/linkcmds.base @@ -0,0 +1,385 @@ +/* Copyright (C) 2014-2018 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ + +/* + * Copyright (c) 2018 embedded brains GmbH. + * + * Copyright (c) 2015 University of York. + * Hesham ALMatary + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +OUTPUT_ARCH(riscv) +ENTRY(_start) +STARTUP(start.o) + +bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1; +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1; + +MEMORY { + UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 +} + +SECTIONS { + .start : ALIGN_WITH_INPUT { + bsp_section_start_begin = .; + KEEP (*(.bsp_start_text)) + KEEP (*(.bsp_start_data)) + bsp_section_start_end = .; + } > REGION_START AT > REGION_START + bsp_section_start_size = bsp_section_start_end - bsp_section_start_begin; + + .text : ALIGN_WITH_INPUT { + bsp_section_text_begin = .; + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .init : ALIGN_WITH_INPUT { + KEEP (*(SORT_NONE(.init))) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : ALIGN_WITH_INPUT { + KEEP (*(SORT_NONE(.fini))) + bsp_section_text_end = .; + } > REGION_TEXT AT > REGION_TEXT_LOAD + bsp_section_text_size = bsp_section_text_end - bsp_section_text_begin; + bsp_section_text_load_begin = LOADADDR (.text); + bsp_section_text_load_end = bsp_section_text_load_begin + bsp_section_text_size; + + .robarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_robarrier_align); + } > REGION_RODATA AT > REGION_RODATA + + .rodata : ALIGN_WITH_INPUT { + bsp_section_rodata_begin = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rodata1 : ALIGN_WITH_INPUT { + *(.rodata1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sdata2 : ALIGN_WITH_INPUT { + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sbss2 : ALIGN_WITH_INPUT { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame_hdr : ALIGN_WITH_INPUT { + *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame : ALIGN_WITH_INPUT { + KEEP (*(.eh_frame)) *(.eh_frame.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gcc_except_table : ALIGN_WITH_INPUT { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu_extab : ALIGN_WITH_INPUT { + *(.gnu_extab*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tdata : ALIGN_WITH_INPUT { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tbss : ALIGN_WITH_INPUT { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + .preinit_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .init_array : ALIGN_WITH_INPUT { + 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 = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .fini_array : ALIGN_WITH_INPUT { + 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 = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ctors : ALIGN_WITH_INPUT { + /* 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)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dtors : ALIGN_WITH_INPUT { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .data.rel.ro : ALIGN_WITH_INPUT { + *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) + *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .jcr : ALIGN_WITH_INPUT { + KEEP (*(.jcr)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .interp : ALIGN_WITH_INPUT { + *(.interp) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .note.gnu.build-id : { *(.note.gnu.build-id) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .hash : ALIGN_WITH_INPUT { + *(.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.hash : ALIGN_WITH_INPUT { + *(.gnu.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynsym : ALIGN_WITH_INPUT { + *(.dynsym) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynstr : ALIGN_WITH_INPUT { + *(.dynstr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version : ALIGN_WITH_INPUT { + *(.gnu.version) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_d : ALIGN_WITH_INPUT { + *(.gnu.version_d) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_r : ALIGN_WITH_INPUT { + *(.gnu.version_r) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.dyn : ALIGN_WITH_INPUT { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.plt : ALIGN_WITH_INPUT { + *(.rela.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .plt : ALIGN_WITH_INPUT { + *(.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .iplt : ALIGN_WITH_INPUT { + *(.iplt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynamic : ALIGN_WITH_INPUT { + *(.dynamic) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tm_clone_table : ALIGN_WITH_INPUT { + *(.tm_clone_table) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got : ALIGN_WITH_INPUT { + *(.got.plt) *(.igot.plt) *(.got) *(.igot) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rtemsroset : ALIGN_WITH_INPUT { + /* Special FreeBSD linker set sections */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(.rtemsroset.*))) + bsp_section_rodata_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + bsp_section_rodata_size = bsp_section_rodata_end - bsp_section_rodata_begin; + bsp_section_rodata_load_begin = LOADADDR (.rodata); + bsp_section_rodata_load_end = bsp_section_rodata_load_begin + bsp_section_rodata_size; + + .rwbarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_rwbarrier_align); + } > REGION_DATA AT > REGION_DATA + + .fast_text : ALIGN_WITH_INPUT { + bsp_section_fast_text_begin = .; + *(.bsp_fast_text) + bsp_section_fast_text_end = .; + } > REGION_FAST_TEXT AT > REGION_FAST_TEXT_LOAD + bsp_section_fast_text_size = bsp_section_fast_text_end - bsp_section_fast_text_begin; + bsp_section_fast_text_load_begin = LOADADDR (.fast_text); + bsp_section_fast_text_load_end = bsp_section_fast_text_load_begin + bsp_section_fast_text_size; + + .fast_data : ALIGN_WITH_INPUT { + bsp_section_fast_data_begin = .; + *(.bsp_fast_data) + bsp_section_fast_data_end = .; + } > REGION_FAST_DATA AT > REGION_FAST_DATA_LOAD + bsp_section_fast_data_size = bsp_section_fast_data_end - bsp_section_fast_data_begin; + bsp_section_fast_data_load_begin = LOADADDR (.fast_data); + bsp_section_fast_data_load_end = bsp_section_fast_data_load_begin + bsp_section_fast_data_size; + + .data : ALIGN_WITH_INPUT { + bsp_section_data_begin = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > REGION_DATA AT > REGION_DATA_LOAD + .data1 : ALIGN_WITH_INPUT { + *(.data1) + } > REGION_DATA AT > REGION_DATA_LOAD + .rtemsrwset : ALIGN_WITH_INPUT { + KEEP (*(SORT(.rtemsrwset.*))) + } > REGION_DATA AT > REGION_DATA_LOAD + .htif ALIGN(4096) : ALIGN_WITH_INPUT { + *(.htif) + } > REGION_DATA AT > REGION_DATA_LOAD + .sdata : ALIGN_WITH_INPUT { + __global_pointer$ = . + 0x800; + *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + bsp_section_data_end = .; + } > REGION_DATA AT > REGION_DATA_LOAD + bsp_section_data_size = bsp_section_data_end - bsp_section_data_begin; + bsp_section_data_load_begin = LOADADDR (.data); + bsp_section_data_load_end = bsp_section_data_load_begin + bsp_section_data_size; + + .sbss : ALIGN_WITH_INPUT { + bsp_section_bss_begin = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } > REGION_DATA AT > REGION_DATA + .bss : ALIGN_WITH_INPUT { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + bsp_section_bss_end = .; + } > REGION_DATA AT > REGION_DATA + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; + + .rtemsstack (NOLOAD) : ALIGN_WITH_INPUT { + bsp_section_rtemsstack_begin = .; + *(SORT(.rtemsstack.*)) + bsp_section_rtemsstack_end = .; + } > REGION_RTEMSSTACK AT > REGION_RTEMSSTACK + bsp_section_rtemsstack_size = bsp_section_rtemsstack_end - bsp_section_rtemsstack_begin; + + .work : ALIGN_WITH_INPUT { + /* + * The work section will occupy the remaining REGION_WORK region and + * contains the RTEMS work space and heap. + */ + bsp_section_work_begin = .; + . += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.); + bsp_section_work_end = .; + } > REGION_WORK AT > REGION_WORK + bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; + + /* FIXME */ + RamBase = ORIGIN (REGION_WORK); + RamSize = LENGTH (REGION_WORK); + WorkAreaBase = bsp_section_work_begin; + HeapSize = 0; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .debug_addr 0 : { *(.debug_addr) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } + + /* + * This is a RTEMS specific section to catch all unexpected input + * sections. In case you get an error like + * "section `.unexpected_sections' will not fit in region + * `UNEXPECTED_SECTIONS'" + * you have to figure out the offending input section and add it to the + * appropriate output section definition above. + */ + .unexpected_sections : { *(*) } > UNEXPECTED_SECTIONS +} diff --git a/bsps/riscv/shared/start/start.S b/bsps/riscv/shared/start/start.S new file mode 100644 index 0000000000..a8ff1b079f --- /dev/null +++ b/bsps/riscv/shared/start/start.S @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2018 embedded brains GmbH + + * Copyright (c) 2015 University of York. + * Hesham Almatary + * + * Copyright (c) 2013, The Regents of the University of California (Regents). + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +PUBLIC(_start) + + .section .bsp_start_text, "wax", @progbits + .align 2 + +TYPE_FUNC(_start) +SYM(_start): + /* Load global pointer */ + .option push + .option norelax + LADDR gp, __global_pointer$ + .option pop + + /* Init FPU */ +#ifdef __riscv_flen + li t0, MSTATUS_FS + csrs mstatus, t0 + csrw fcsr, zero +#endif + + /* Set exception handler */ + LADDR t0, _RISCV_Exception_handler + csrw mtvec, t0 + + /* Load stack pointer and branch to secondary processor start if necessary */ +#ifdef RTEMS_SMP + LADDR sp, _ISR_Stack_area_begin + LADDR t2, _ISR_Stack_size + csrr s0, mhartid + LADDR t0, _Per_CPU_Information + slli t1, s0, PER_CPU_CONTROL_SIZE_LOG2 + add s1, t0, t1 + csrw mscratch, s1 + bnez s0, .Lstart_on_secondary_processor + add sp, sp, t2 +#else + LADDR sp, _ISR_Stack_area_end +#endif + +#ifdef BSP_START_COPY_FDT_FROM_U_BOOT + mv a0, a1 + call bsp_fdt_copy +#endif + + /* Clear .bss */ + LADDR a0, bsp_section_bss_begin + li a1, 0 + LADDR a2, bsp_section_bss_size + call memset + +#ifdef RTEMS_SMP + /* Give go to secondary processors */ + LADDR t0, .Lsecondary_processor_go + fence iorw,ow + amoswap.w zero, zero, 0(t0) +#endif + + li a0, 0 + j boot_card + +#ifdef RTEMS_SMP + +.Lstart_on_secondary_processor: + + /* Adjust stack pointer */ +#ifdef __riscv_mul + addi t0, s0, 1 + mul t2, t2, t0 +#else + mv t0, s0 + mv t3, t2 + +.Ladd_more: + + add t2, t2, t3 + addi t0, t0, -1 + bnez t0, .Ladd_more +#endif + add sp, sp, t2 + + /* Wait for go issued by the boot processor (mhartid == 0) */ + LADDR t0, .Lsecondary_processor_go + +.Lwait_for_go_again: + + lw t1, 0(t0) + fence iorw, iorw + bnez t1, .Lwait_for_go_again + + mv a0, s1 + call bsp_start_on_secondary_processor + +#if __riscv_xlen == 32 + .align 2 +#elif __riscv_xlen == 64 + .align 3 +#endif + +.Lsecondary_processor_go: + + /* + * These are ebreak instructions, just in case we end up here executing + * code. + */ + .word 0x00100073 +#if __riscv_xlen == 64 + .word 0x00100073 +#endif + +#endif /* RTEMS_SMP */ diff --git a/c/src/lib/libbsp/riscv/acinclude.m4 b/c/src/lib/libbsp/riscv/acinclude.m4 index d8b3319b08..db1a210fd4 100644 --- a/c/src/lib/libbsp/riscv/acinclude.m4 +++ b/c/src/lib/libbsp/riscv/acinclude.m4 @@ -2,6 +2,8 @@ AC_DEFUN([RTEMS_CHECK_BSPDIR], [ case "$1" in + griscv ) + AC_CONFIG_SUBDIRS([griscv]);; riscv ) AC_CONFIG_SUBDIRS([riscv]);; *) diff --git a/c/src/lib/libbsp/riscv/griscv/Makefile.am b/c/src/lib/libbsp/riscv/griscv/Makefile.am new file mode 100644 index 0000000000..4077ddebd2 --- /dev/null +++ b/c/src/lib/libbsp/riscv/griscv/Makefile.am @@ -0,0 +1,70 @@ +## +# +# @brief Makefile of LibBSP for the RISCV/Spike simulator. +# +# +ACLOCAL_AMFLAGS = -I ../../../../aclocal + +include $(top_srcdir)/../../../../automake/compile.am +include $(top_srcdir)/../../bsp.am + +dist_project_lib_DATA = ../../../../../../bsps/riscv/griscv/start/bsp_specs + +############################################################################### +# Header # +############################################################################### + +############################################################################### +# Data # +############################################################################### + +start.$(OBJEXT): ../../../../../../bsps/riscv/shared/start/start.S + $(CPPASCOMPILE) -o $@ -c $< +project_lib_DATA = start.$(OBJEXT) + +project_lib_DATA += linkcmds +project_lib_DATA += ../../../../../../bsps/riscv/shared/start/linkcmds.base + +############################################################################### +# LibBSP # +############################################################################### + +project_lib_LIBRARIES = librtemsbsp.a + +# Startup +librtemsbsp_a_SOURCES = ../../../../../../bsps/shared/start/bspreset-empty.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/bspstart.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/bsp_fatal_halt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/amba.c + +# Shared +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy-cpucounter.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspgetworkarea-default.c + +# clock +librtemsbsp_a_SOURCES +=../../../../../../bsps/riscv/griscv/clock/clockdrv.c + +# Timer +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/btimer/btimer-stub.c + +# IRQ +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/irq/irq.c + +# Cache +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c + +# Console +librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/console/console.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/console/printk_support.c + +if HAS_SMP +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/griscv/start/bspsmp.c +endif + +include $(srcdir)/../../../../../../bsps/shared/irq-sources.am +include $(srcdir)/../../../../../../bsps/shared/grlib-sources.am +include $(srcdir)/../../../../../../bsps/shared/shared-sources.am +include $(srcdir)/../../../../../../bsps/riscv/griscv/headers.am diff --git a/c/src/lib/libbsp/riscv/griscv/configure.ac b/c/src/lib/libbsp/riscv/griscv/configure.ac new file mode 100644 index 0000000000..ed5694c763 --- /dev/null +++ b/c/src/lib/libbsp/riscv/griscv/configure.ac @@ -0,0 +1,40 @@ +## +# +# @file +# +# @brief Configure script of LibBSP for riscv BSP. +# + +AC_PREREQ([2.69]) +AC_INIT([rtems-c-src-lib-libbsp-riscv],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +RTEMS_TOP(../../../../../..) +RTEMS_SOURCE_TOP +RTEMS_BUILD_TOP + +RTEMS_CANONICAL_TARGET_CPU +AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.12.2]) +RTEMS_BSP_CONFIGURE + +RTEMS_BSPOPTS_SET([BSP_CONSOLE_BAUD],[*],[115200]) +RTEMS_BSPOPTS_HELP([BSP_CONSOLE_BAUD],[default baud for console driver devices (default 115200)]) + +RTEMS_BSPOPTS_SET([RISCV_MAXIMUM_EXTERNAL_INTERRUPTS],[*],[64]) +RTEMS_BSPOPTS_HELP([RISCV_MAXIMUM_EXTERNAL_INTERRUPTS],[maximum number of external interrupts supported by the BSP (default 64)]) + +RTEMS_BSP_CLEANUP_OPTIONS + +RISCV_RAM_REGION_BEGIN_DEFAULT=0x40000000 + +AC_DEFUN([RISCV_LINKCMD],[ +AC_ARG_VAR([$1],[$2])dnl +[$1]=[$]{[$1]:-[$3]} +]) + +RISCV_LINKCMD([RISCV_RAM_REGION_BEGIN],[begin of the RAM region for linker command file (default is 0x40000000)],[${RISCV_RAM_REGION_BEGIN_DEFAULT}]) +RISCV_LINKCMD([RISCV_RAM_REGION_SIZE],[size of the RAM region for linker command file (default 16MiB)],[0x01000000]) + +AC_CONFIG_FILES([ +Makefile +linkcmds:../../../../../../bsps/riscv/griscv/start/linkcmds.in +]) +AC_OUTPUT diff --git a/c/src/lib/libbsp/riscv/riscv/Makefile.am b/c/src/lib/libbsp/riscv/riscv/Makefile.am index b8a034ccde..34bedf844f 100644 --- a/c/src/lib/libbsp/riscv/riscv/Makefile.am +++ b/c/src/lib/libbsp/riscv/riscv/Makefile.am @@ -18,12 +18,12 @@ dist_project_lib_DATA = ../../../../../../bsps/riscv/riscv/start/bsp_specs # Data # ############################################################################### -start.$(OBJEXT): ../../../../../../bsps/riscv/riscv/start/start.S +start.$(OBJEXT): ../../../../../../bsps/riscv/shared/start/start.S $(CPPASCOMPILE) -o $@ -c $< project_lib_DATA = start.$(OBJEXT) project_lib_DATA += linkcmds -project_lib_DATA += ../../../../../../bsps/riscv/riscv/start/linkcmds.base +project_lib_DATA += ../../../../../../bsps/riscv/shared/start/linkcmds.base ############################################################################### # LibBSP # diff --git a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h index fb358e167c..db46032df2 100644 --- a/cpukit/score/cpu/riscv/include/rtems/score/cpu.h +++ b/cpukit/score/cpu/riscv/include/rtems/score/cpu.h @@ -439,10 +439,7 @@ uint32_t _CPU_Counter_frequency( void ); extern volatile uint32_t * const _RISCV_Counter; -static inline CPU_Counter_ticks _CPU_Counter_read( void ) -{ - return *_RISCV_Counter; -} +CPU_Counter_ticks _CPU_Counter_read( void ); static inline CPU_Counter_ticks _CPU_Counter_difference( CPU_Counter_ticks second, -- cgit v1.2.3