litex: Support for kernel build with vexriscv-smp.

This commit is contained in:
Stuart Ianna 2023-03-28 10:08:51 +11:00 committed by Xiang Xiao
parent c4f3f8801f
commit 4cae98674d
31 changed files with 1578 additions and 123 deletions

View File

@ -0,0 +1,35 @@
=============
Vexriscv Core
=============
The vexriscv core only supports standard "Flat builds", consisting of a single binary.
Building
--------
Build the minimal NSH application::
# Configure for NSH
$ ./tools/configure.sh arty_a7:nsh
# Build Nuttx
$ make
Booting
--------
Create a file, 'boot.json' in the Nuttx root directory, with the following content::
{
"nuttx.bin": "0x40000000"
}
Load the application over serial with::
$ litex_term --images=boot.json --speed=1e6 /dev/ttyUSB0
Update the baud rate and serial port to suit your configuration.

View File

@ -0,0 +1,55 @@
==================
VexRISCV_SMP Core
==================
The vexrisc_smp core supports a two-pass build, producing the kernel (nuttx.bin), and a number of applications,
compiled into the apps/bin directory. In the standard configuration, the applications are loaded to the FPGA in a RAMdisk.
Although, for custom boards this could be extended to loading from SDCards, flash, or other mediums.
Building
--------
Nuttx uses openSBI to configure and prepare the vexriscv_smp core. With this configuration,
the Nuttx kernel is a binary payload for OpenSBI. The configuration used is
identical to that used for Linux on Litex project (https://github.com/litex-hub/linux-on-litex-vexriscv).
To build OpenSBI::
$ git clone https://github.com/litex-hub/opensbi --branch 0.8-linux-on-litex-vexriscv
$ cd opensbi
$ make CROSS_COMPILE=riscv64-unknown-elf- PLATFORM=litex/vexriscv
$ cp build/platform/litex/vexriscv/firmware/fw_jump.bin ../opensbi.bin"
Build the Nuttx kernel::
$ ./tools/configure.sh arty_a7:knsh
$ make
Build the loadable applications::
$ make export -j16
$ cd ../apps
$ make ./tools/mkimport.sh -z -x ../nuttx/nuttx-export-*.tar.gz
$ make import
Generate a romfs to be loaded to the FPGA as a ramdisk::
$ cd nuttx
$ genromfs -f romfs.img -d ../apps/bin -V "NuttXBootVol"
Booting
--------
Create a file, 'boot.json' in the Nuttx root directory, with the following content::
{
"romfs.img": "0x40C00000",
"nuttx.bin": "0x40000000",
"opensbi.bin": "0x40f00000"
}
Load the application over serial with::
litex_term --images=boot.json --speed=1e6 /dev/ttyUSB0
Update the baud rate and serial port to suit your configuration.

View File

@ -0,0 +1,70 @@
======================================
Enjoy Digital LiteX FPGA's
======================================
The LiteX framework provides a convenient and efficient infrastructure to create FPGA Cores/SoCs, to explore various digital design architectures and create full FPGA based systems.
Information specific to Litex and supported boards can be found on the project's homepage: https://github.com/enjoy-digital/litex
Nuttx has basic support for two softcores
- vexriscv: FPGA friendly RISC-V ISA CPU implementation
- vexriscv_smp: A more fully featured, Linux compatible core.
Currently, the only configured development board in the Arty A7 https://digilent.com/reference/programmable-logic/arty-a7/start. However, many Litex supported boards
should work with either core, requiring minimal adjustment to the configuration.
Toolchain
==============
Litex projects can be built with a generic RISC-V GCC toolchain. There are currently two options.
Prebuilt toolchain
------------------
A prebuilt RISC-V toolchain from SiFive can be used to build Litex projects::
# Download the prebuilt toolchain
$ curl https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14.tar.gz \
> riscv64-unknown-elf-gcc.tar.gz
# Unpack the archive
$ tar -xf riscv64-unknown-elf-gcc.tar.gz
# Add to path
$ export PATH="$HOME/path/to/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin:$PATH
Custom built toolchain
----------------------
The toolchain needs to be compiled locally in order to use a more modern version. At the time of writing,
the source can be obtained from https://github.com/riscv-collab/riscv-gnu-toolchain and built with the following configuration::
$ CFLAGS="-g0 -Os"
$ CXXFLAGS="-g0 -Os"
$ LDFLAGS="-s"
$ ./configure \
CFLAGS_FOR_TARGET='-O2 -mcmodel=medany' \
CXXFLAGS_FOR_TARGET='-O2 -mcmodel=medany' \
--prefix=path/to/install/to \
--with-system-zlib \
--with-arch=rv32ima \
--with-abi=ilp32
$ make
.. important:: The vexriscv_smp core requires `with-arch=rv32imac`.
Check the linked github repository for other options, including building with multilib enabled.
Core specific information
=========================
.. toctree::
:glob:
:maxdepth: 1
cores/*/*

View File

@ -354,6 +354,29 @@ config RISCV_SEMIHOSTING_HOSTFS_CACHE_COHERENCE
endif
if ARCH_CHIP_LITEX
choice
prompt "LITEX Core Selection"
default LITEX_CORE_VEXRISCV
config LITEX_CORE_VEXRISCV
bool "vexriscv core"
config LITEX_CORE_VEXRISCV_SMP
bool "vexriscv_smp core"
select ARCH_HAVE_MPU
select ARCH_HAVE_MMU
select ARCH_RV_ISA_C
select ARCH_MMU_TYPE_SV32
select ARCH_HAVE_ADDRENV
select ARCH_NEED_ADDRENV_MAPPING
select ARCH_HAVE_S_MODE
endchoice
endif
source "arch/risc-v/src/opensbi/Kconfig"
if ARCH_CHIP_FE310

View File

@ -29,17 +29,19 @@
#include CONFIG_LITEX_CUSTOM_IRQ_DEFINITIONS_PATH
#else
#include <arch/mode.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Map RISC-V exception code to NuttX IRQ */
#define LITEX_IRQ_UART0 (RISCV_IRQ_MEXT + 1)
#define LITEX_IRQ_TIMER0 (RISCV_IRQ_MEXT + 2)
#define LITEX_IRQ_ETHMAC (RISCV_IRQ_MEXT + 3)
#define LITEX_IRQ_SDCARD (RISCV_IRQ_MEXT + 4)
#define LITEX_IRQ_GPIO (RISCV_IRQ_MEXT + 5)
#define LITEX_IRQ_UART0 (RISCV_IRQ_EXT + 1)
#define LITEX_IRQ_TIMER0 (RISCV_IRQ_EXT + 2)
#define LITEX_IRQ_ETHMAC (RISCV_IRQ_EXT + 3)
#define LITEX_IRQ_SDCARD (RISCV_IRQ_EXT + 4)
#define LITEX_IRQ_GPIO (RISCV_IRQ_EXT + 5)
/* The last hardware IRQ number */

View File

@ -148,3 +148,32 @@ config LITEX_EMAC_PHYADDR
The 5-bit address of the PHY on the board. Default: 1
endmenu # PHY interface
menu "LITEX MMU options"
depends on ARCH_USE_MMU
config LITEX_MMU_IO_BASE
hex "IO base address."
default 0x80000000
---help---
The base address for the IO MMU mapping.
config LITEX_MMU_IO_SIZE
hex "IO base address."
default 0x7F000000
---help---
The size for the IO MMU mapping.
config LITEX_MMU_L1_SIZE
int "L1 page table size."
default 1024
---help---
The size of the L1 page table. Each entry in the page table represents a 4MB L1 page.
config LITEX_MMU_L2_SIZE
int "L2 page table size."
default 4096
---help---
The size of the L2 page table. Each entry in the page table represents a 4kB L1 page.
endmenu # LITEX MMU options

View File

@ -22,7 +22,11 @@ include common/Make.defs
# Specify our HEAD assembly file. This will be linked as
# the first object file, so it will appear at address 0
ifeq ($(CONFIG_LITEX_CORE_VEXRISCV_SMP),y)
HEAD_ASRC = litex_shead.S
else
HEAD_ASRC = litex_head.S
endif
# Specify our C code within this directory to be included
CHIP_CSRCS = litex_allocateheap.c litex_clockconfig.c
@ -31,6 +35,9 @@ CHIP_CSRCS += litex_lowputc.c litex_serial.c
CHIP_CSRCS += litex_start.c litex_timerisr.c
CHIP_ASRCS += litex_cache.S
ifeq ($(CONFIG_BUILD_KERNEL),y)
CHIP_CSRCS += litex_mm_init.c litex_pgalloc.c
endif
ifeq ($(CONFIG_LITEX_GPIO),y)
CHIP_CSRCS += litex_gpio.c

View File

@ -29,4 +29,28 @@
#include "litex_memorymap.h"
#include "riscv_internal.h"
#include "riscv_percpu.h"
#ifdef __ASSEMBLY__
/****************************************************************************
* Name: setintstack
*
* Description:
* Set the current stack pointer to the "top" the correct interrupt stack.
*
****************************************************************************/
#if CONFIG_ARCH_INTERRUPTSTACK > 15
#if !defined(CONFIG_SMP) && defined(CONFIG_ARCH_USE_S_MODE)
.macro setintstack tmp0, tmp1
csrr \tmp0, CSR_SCRATCH
REGLOAD sp, RISCV_PERCPU_IRQSTACK(\tmp0)
.endm
#endif /* !defined(CONFIG_SMP) && defined(CONFIG_ARCH_USE_S_MODE) */
#endif /* CONFIG_ARCH_INTERRUPTSTACK > 15 */
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_RISCV_SRC_LITEX_CHIP_H */

View File

@ -24,9 +24,18 @@
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
#define LITEX_CLINT_MSIP (LITEX_CLINT_BASE + 0x0000)
#define LITEX_CLINT_MTIMECMP (LITEX_CLINT_BASE + 0x4000)
#define LITEX_CLINT_MTIME (LITEX_CLINT_BASE + 0xbff8)
#else
#define LITEX_CLINT_LATCH (LITEX_CPUTIMER_BASE)
#define LITEX_CLINT_MTIME (LITEX_CPUTIMER_BASE + 0x04)
#define LITEX_CLINT_MTIMECMP (LITEX_CPUTIMER_BASE + 0x0C)
#endif /* CONFIG_LITEX_CORE_VEXRISCV_SMP */
#endif /* __ARCH_RISCV_SRC_LITEX_HARDWARE_LITEX_CLINT_H */

View File

@ -35,20 +35,30 @@
/* Register Base Address ****************************************************/
/* litex vexRiscv does not follow RISC-V privileged specification and
* uses two additional CSRs: mask and pending.
*/
#define LITEX_CPUTIMER_BASE 0xf0000800
#define LITEX_ETHMAC_BASE 0xf0001000
#define LITEX_ETHPHY_BASE 0xf0001800
#define LITEX_SDBLOCK2MEM_BASE 0xf0003000
#define LITEX_SDCORE_BASE 0xf0003800
#define LITEX_SDIRQ_BASE 0xf0004000
#define LITEX_SDMEM2BLOCK_BASE 0xf0004800
#define LITEX_SDPHY_BASE 0xf0005000
#define LITEX_TIMER0_BASE 0xf0006000
#define LITEX_UART0_BASE 0xf0006800
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
#define LITEX_CLINT_BASE 0xf0010000
#define LITEX_PLIC_BASE 0xf0c00000
#define LITEX_ETHMAC_BASE 0xf0002000
#define LITEX_ETHPHY_BASE 0xf0002800
#define LITEX_TIMER0_BASE 0xf0001800
#define LITEX_UART0_BASE 0xf0001000
#define LITEX_SDBLOCK2MEM_BASE 0xf0004000
#define LITEX_SDCORE_BASE 0xf0004800
#define LITEX_SDIRQ_BASE 0xf0005000
#define LITEX_SDMEM2BLOCK_BASE 0xf0005800
#define LITEX_SDPHY_BASE 0xf0006000
#else
#define LITEX_CPUTIMER_BASE 0xf0000800
#define LITEX_ETHMAC_BASE 0xf0001000
#define LITEX_ETHPHY_BASE 0xf0001800
#define LITEX_TIMER0_BASE 0xf0006000
#define LITEX_UART0_BASE 0xf0006800
#define LITEX_SDBLOCK2MEM_BASE 0xf0003000
#define LITEX_SDCORE_BASE 0xf0003800
#define LITEX_SDIRQ_BASE 0xf0004000
#define LITEX_SDMEM2BLOCK_BASE 0xf0004800
#define LITEX_SDPHY_BASE 0xf0005000
#endif
/* GPIO peripheral definitions.
* - LITEX_GPIO_BASE is the first 32-bit address which contains a block

View File

@ -21,14 +21,32 @@
#ifndef __ARCH_RISCV_SRC_LITEX_HARDWARE_LITEX_PLIC_H
#define __ARCH_RISCV_SRC_LITEX_HARDWARE_LITEX_PLIC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "litex_memorymap.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
# define LITEX_PLIC_PRIORITY (LITEX_PLIC_BASE + 0x000000)
# define LITEX_PLIC_PENDING1 (LITEX_PLIC_BASE + 0x001000)
# define LITEX_PLIC_ENABLE1 (LITEX_PLIC_BASE + 0x002080)
# define LITEX_PLIC_ENABLE2 (LITEX_PLIC_BASE + 0x002084)
# define LITEX_PLIC_THRESHOLD (LITEX_PLIC_BASE + 0x201000)
# define LITEX_PLIC_CLAIM (LITEX_PLIC_BASE + 0x201004)
#else
/* litex vexRiscv does not follow RISC-V privileged specification and
* uses two additional CSRs: mask and pending.
*/
#define LITEX_MMASK_CSR 0xBC0
#define LITEX_MPENDING_CSR 0xFC0
#endif
#endif /* __ARCH_RISCV_SRC_LITEX_HARDWARE_LITEX_PLIC_H */

View File

@ -0,0 +1,58 @@
/****************************************************************************
* arch/risc-v/src/litex/hardware/litex_timer.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_RISCV_SRC_LITEX_HARDWARE_LITEX_TIMER_H
#define __ARCH_RISCV_SRC_LITEX_HARDWARE_LITEX_TIMER_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "hardware/litex_memorymap.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* LITEX_TIMER register offsets *********************************************/
#define LITEX_TIMER_LOAD_OFFSET 0x0000
#define LITEX_TIMER_RELOAD_OFFSET 0x0004
#define LITEX_TIMER_EN_OFFSET 0x0008
#define LITEX_TIMER_UPDATE_VALUE_OFFSET 0x000C
#define LITEX_TIMER_VALUE_OFFSET 0x0010
#define LITEX_TIMER_EV_STATUS_OFFSET 0x0014
#define LITEX_TIMER_EV_PENDING_OFFSET 0x0018
#define LITEX_TIMER_EV_ENABLE_OFFSET 0x001C
/* LITEX_TIMER register addresses *******************************************/
#define LITEX_TIMER0_LOAD (LITEX_TIMER0_BASE+LITEX_TIMER_LOAD_OFFSET)
#define LITEX_TIMER0_RELOAD (LITEX_TIMER0_BASE+LITEX_TIMER_RELOAD_OFFSET)
#define LITEX_TIMER0_EN (LITEX_TIMER0_BASE+LITEX_TIMER_EN_OFFSET)
#define LITEX_TIMER0_UPDATE_VALUE (LITEX_TIMER0_BASE+LITEX_TIMER_UPDATE_VALUE_OFFSET)
#define LITEX_TIMER0_VALUE (LITEX_TIMER0_BASE+LITEX_TIMER_VALUE_OFFSET)
#define LITEX_TIMER0_EV_STATUS (LITEX_TIMER0_BASE+LITEX_TIMER_EV_STATUS_OFFSET)
#define LITEX_TIMER0_EV_PENDING (LITEX_TIMER0_BASE+LITEX_TIMER_EV_PENDING_OFFSET)
#define LITEX_TIMER0_EV_ENABLE (LITEX_TIMER0_BASE+LITEX_TIMER_EV_ENABLE_OFFSET)
/* LITEX_TIMER register bit definitions *************************************/
#endif /* __ARCH_RISCV_SRC_LITEX_HARDWARE_LITEX_TIMER_H */

View File

@ -29,10 +29,45 @@
#include "litex.h"
#ifdef CONFIG_MM_KERNEL_HEAP
#include <arch/board/board_memorymap.h>
#endif
#include "riscv_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_MM_KERNEL_HEAP
#define KRAM_END KSRAM_END
#else
#define KRAM_END CONFIG_RAM_END
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_allocate_heap
*
* Description:
* This function will be called to dynamically set aside the heap region
* based on kernel or flat builds.
*
****************************************************************************/
#ifdef CONFIG_BUILD_KERNEL
void up_allocate_kheap(void **heap_start, size_t *heap_size)
#else
void up_allocate_heap(void **heap_start, size_t *heap_size)
#endif /* CONFIG_BUILD_KERNEL */
{
*heap_start = (void *)g_idle_topstack;
*heap_size = KRAM_END - g_idle_topstack;
}
/****************************************************************************
* Name: riscv_addregion
*

View File

@ -51,7 +51,11 @@ void up_irqinitialize(void)
/* Disable all global interrupts */
#ifdef CONFIG_ARCH_USE_S_MODE
putreg32(0x0, LITEX_PLIC_ENABLE1);
#else
asm volatile ("csrw %0, %1" :: "i"(LITEX_MMASK_CSR), "r"(0));
#endif
/* Colorize the interrupt stack for debug purposes */
@ -62,6 +66,23 @@ void up_irqinitialize(void)
/* litex vexriscv dont have priority and threshold control */
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
/* litex vexriscv_smp does. */
/* Set priority for all global interrupts to 1 (lowest) */
int id;
for (id = 1; id <= 31; id++)
{
putreg32(1, (uintptr_t)(LITEX_PLIC_PRIORITY + 4 * id));
}
/* Set irq threshold to 0 (permits all global interrupts) */
putreg32(0, LITEX_PLIC_THRESHOLD);
#endif
/* Attach the common interrupt handler */
riscv_exception_attach();
@ -82,6 +103,41 @@ void up_irqinitialize(void)
*
****************************************************************************/
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
void up_disable_irq(int irq)
{
int extirq;
if (irq == RISCV_IRQ_SOFT)
{
/* Read m/sstatus & clear machine software interrupt enable in m/sie */
CLEAR_CSR(CSR_IE, IE_SIE);
}
else if (irq == RISCV_IRQ_TIMER)
{
/* Read m/sstatus & clear timer interrupt enable in m/sie */
CLEAR_CSR(CSR_IE, IE_TIE);
}
else if (irq > RISCV_IRQ_EXT)
{
extirq = irq - RISCV_IRQ_EXT;
/* Clear enable bit for the irq */
if (1 <= extirq && extirq <= 31)
{
modifyreg32(LITEX_PLIC_ENABLE1 + (4 * (extirq / 32)),
1 << (extirq % 32), 0);
}
else
{
PANIC();
}
}
}
#else
void up_disable_irq(int irq)
{
int extirq;
@ -118,6 +174,7 @@ void up_disable_irq(int irq)
}
}
}
#endif
/****************************************************************************
* Name: up_enable_irq
@ -127,6 +184,41 @@ void up_disable_irq(int irq)
*
****************************************************************************/
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
void up_enable_irq(int irq)
{
int extirq;
if (irq == RISCV_IRQ_SOFT)
{
/* Read sstatus and set supervisor software interrupt enable in sie */
SET_CSR(CSR_IE, IE_SIE);
}
else if (irq == RISCV_IRQ_TIMER)
{
/* Read sstatus & set timer interrupt enable in sie */
SET_CSR(CSR_IE, IE_TIE);
}
else if (irq >= RISCV_IRQ_EXT)
{
extirq = irq - RISCV_IRQ_EXT;
/* Set enable bit for the irq in plic */
if (0 <= extirq && extirq <= 31)
{
modifyreg32(LITEX_PLIC_ENABLE1 + (4 * (extirq / 32)),
0, 1 << (extirq % 32));
}
else
{
PANIC();
}
}
}
#else
void up_enable_irq(int irq)
{
int extirq;
@ -163,6 +255,7 @@ void up_enable_irq(int irq)
}
}
}
#endif
/****************************************************************************
* Name: riscv_ack_irq
@ -189,15 +282,15 @@ irqstate_t up_irq_enable(void)
irqstate_t oldstat;
#if 1
/* Enable MEIE (machine external interrupt enable) */
/* Enable EIE (machine/supervisor external interrupt enable) */
/* TODO: should move to up_enable_irq() */
SET_CSR(mie, MIE_MEIE);
SET_CSR(CSR_IE, IE_EIE);
#endif
/* Read mstatus & set machine interrupt enable (MIE) in mstatus */
/* Read s/mstatus & set interrupt enable (S/MIE) in s/mstatus */
oldstat = READ_AND_SET_CSR(mstatus, MSTATUS_MIE);
oldstat = READ_AND_SET_CSR(CSR_STATUS, STATUS_IE);
return oldstat;
}

View File

@ -49,8 +49,48 @@
void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs)
{
int irq = (vector >> RV_IRQ_MASK) | (vector & 0xf);
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
int irq = (vector & 0x3f);
if ((vector & RISCV_IRQ_BIT) != 0)
{
irq += RISCV_IRQ_ASYNC;
}
/* Firstly, check if the irq is machine external interrupt */
if (irq == RISCV_IRQ_EXT)
{
uint32_t ext = getreg32(LITEX_PLIC_CLAIM);
/* Add the value to nuttx irq which is offset to the ext */
irq = RISCV_IRQ_EXT + ext;
}
/* Acknowledge the interrupt */
riscv_ack_irq(irq);
/* EXT means no interrupt */
if (irq != RISCV_IRQ_EXT)
{
/* Deliver the IRQ */
regs = riscv_doirq(irq, regs);
}
if (irq > RISCV_IRQ_EXT)
{
/* Then write PLIC_CLAIM to clear pending in PLIC */
putreg32(irq - RISCV_IRQ_EXT, LITEX_PLIC_CLAIM);
}
#else
int i;
int irq = (vector >> RV_IRQ_MASK) | (vector & 0xf);
/* Firstly, check if the irq is machine external interrupt */
@ -87,5 +127,6 @@ void *riscv_dispatch_irq(uintptr_t vector, uintptr_t *regs)
regs = riscv_doirq(irq, regs);
#endif /* CONFIG_LITEX_CORE_VEXRISCV_SMP */
return regs;
}

View File

@ -0,0 +1,263 @@
/****************************************************************************
* arch/risc-v/src/litex/litex_mm_init.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <stdint.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board_memorymap.h>
#include "litex_memorymap.h"
#include "riscv_internal.h"
#include "riscv_mmu.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Map the whole I/O memory with vaddr = paddr mappings */
#define MMU_IO_BASE CONFIG_LITEX_MMU_IO_BASE
#define MMU_IO_SIZE CONFIG_LITEX_MMU_IO_SIZE
#ifdef CONFIG_ARCH_MMU_TYPE_SV32
/* Physical and virtual addresses to page tables (vaddr = paddr mapping) */
#define PGT_L1_PBASE (uintptr_t)&m_l1_pgtable
#define PGT_L2_PBASE (uintptr_t)&m_l2_pgtable
#define PGT_L1_VBASE PGT_L1_PBASE
#define PGT_L2_VBASE PGT_L2_PBASE
#define PGT_L1_SIZE (CONFIG_LITEX_MMU_L1_SIZE)
#define PGT_L2_SIZE (CONFIG_LITEX_MMU_L2_SIZE)
#define SLAB_COUNT (sizeof(m_l2_pgtable) / RV_MMU_PAGE_SIZE)
#define KMM_PAGE_SIZE RV_MMU_L2_PAGE_SIZE
#define KMM_PBASE PGT_L2_PBASE
#define KMM_PBASE_IDX 2
#define KMM_SPBASE PGT_L1_PBASE
#define KMM_SPBASE_IDX 1
#else
#error No valid MMU defined.
#endif
/****************************************************************************
* Private Types
****************************************************************************/
struct pgalloc_slab_s
{
sq_entry_t *next;
void *memory;
};
typedef struct pgalloc_slab_s pgalloc_slab_t;
/****************************************************************************
* Private Data
****************************************************************************/
/* Kernel mappings simply here, mapping is vaddr=paddr */
static size_t m_l1_pgtable[PGT_L1_SIZE] locate_data(".pgtables");
static size_t m_l2_pgtable[PGT_L2_SIZE] locate_data(".pgtables");
/* Kernel mappings (L1 base) */
uintptr_t g_kernel_mappings = PGT_L1_VBASE;
uintptr_t g_kernel_pgt_pbase = PGT_L1_PBASE;
/* L2 page table allocator */
static sq_queue_t g_free_slabs;
static pgalloc_slab_t g_slabs[SLAB_COUNT];
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: slab_init
*
* Description:
* Initialize slab allocator for L2 page table entries
*
* Input Parameters:
* start - Beginning of the L2 page table pool
*
****************************************************************************/
static void slab_init(uintptr_t start)
{
int i;
sq_init(&g_free_slabs);
for (i = 0; i < SLAB_COUNT; i++)
{
g_slabs[i].memory = (void *)start;
sq_addlast((sq_entry_t *)&g_slabs[i], (sq_queue_t *)&g_free_slabs);
start += RV_MMU_PAGE_SIZE;
}
}
/****************************************************************************
* Name: slab_alloc
*
* Description:
* Allocate single slab for L2 page table entry
*
****************************************************************************/
static uintptr_t slab_alloc(void)
{
pgalloc_slab_t *slab = (pgalloc_slab_t *)sq_remfirst(&g_free_slabs);
return slab ? (uintptr_t)slab->memory : 0;
}
/****************************************************************************
* Name: map_region
*
* Description:
* Map a region of physical memory to the L2 page table
*
* Input Parameters:
* paddr - Beginning of the physical address mapping
* vaddr - Beginning of the virtual address mapping
* size - Size of the region in bytes
* mmuflags - The MMU flags to use in the mapping
*
****************************************************************************/
static void map_region(uintptr_t paddr, uintptr_t vaddr, size_t size,
uint32_t mmuflags)
{
uintptr_t endaddr;
uintptr_t pbase;
int npages;
int i;
int j;
/* How many pages */
npages = (size + RV_MMU_PAGE_MASK) >> RV_MMU_PAGE_SHIFT;
endaddr = vaddr + size;
for (i = 0; i < npages; i += RV_MMU_PAGE_ENTRIES)
{
/* See if a L2 mapping exists ? */
pbase = mmu_pte_to_paddr(mmu_ln_getentry(
KMM_SPBASE_IDX, KMM_SPBASE, vaddr));
if (!pbase)
{
/* No, allocate 1 page, this must not fail */
pbase = slab_alloc();
DEBUGASSERT(pbase);
/* Map it to the L2 table */
mmu_ln_setentry(
KMM_SPBASE_IDX, KMM_SPBASE, pbase, vaddr, MMU_UPGT_FLAGS);
}
/* Then add the L2 mappings */
for (j = 0; j < RV_MMU_PAGE_ENTRIES && vaddr < endaddr; j++)
{
mmu_ln_setentry(KMM_PBASE_IDX, pbase, paddr, vaddr, mmuflags);
paddr += KMM_PAGE_SIZE;
vaddr += KMM_PAGE_SIZE;
}
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: litex_kernel_mappings
*
* Description:
* Setup kernel mappings when usinc CONFIG_BUILD_KERNEL. Sets up the kernel
* MMU mappings.
*
****************************************************************************/
void litex_kernel_mappings(void)
{
/* Initialize slab allocator for L2 page tables */
slab_init(KMM_PBASE);
/* Begin mapping memory to MMU; note that at this point the MMU is not yet
* active, so the page table virtual addresses are actually physical
* addresses and so forth. M-mode does not perform translations anyhow, so
* this mapping is quite simple to do
*/
binfo("map I/O regions\n");
mmu_ln_map_region(1, PGT_L1_VBASE, MMU_IO_BASE, MMU_IO_BASE,
MMU_IO_SIZE, MMU_IO_FLAGS);
/* Map the kernel text and data for L2 */
binfo("map kernel text\n");
map_region(KFLASH_START, KFLASH_START, KFLASH_SIZE, MMU_KTEXT_FLAGS);
binfo("map kernel data\n");
map_region(KSRAM_START, KSRAM_START, KSRAM_SIZE, MMU_KDATA_FLAGS);
binfo("map the page pool\n");
map_region(PGPOOL_START, PGPOOL_START, PGPOOL_SIZE, MMU_KDATA_FLAGS);
}
/****************************************************************************
* Name: litex_mm_init
*
* Description:
* Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU
* mappings. Function also sets the first address environment (satp value).
*
****************************************************************************/
void litex_mm_init(void)
{
/* Setup the kernel mappings */
litex_kernel_mappings();
/* Enable MMU (note: system is still in M-mode) */
binfo("mmu_enable: satp=%" PRIuPTR "\n", g_kernel_pgt_pbase);
mmu_enable(g_kernel_pgt_pbase, 0);
}

View File

@ -0,0 +1,58 @@
/****************************************************************************
* arch/risc-v/src/litex/litex_mm_init.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __ARCH_RISC_V_SRC_LITEX_LITEX_MM_INIT_H
#define __ARCH_RISC_V_SRC_LITEX_LITEX_MM_INIT_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include "riscv_mmu.h"
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
/****************************************************************************
* Name: litex_kernel_mappings
*
* Description:
* Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up the kernel
* MMU mappings.
*
****************************************************************************/
void litex_kernel_mappings(void);
/****************************************************************************
* Name: litex_mm_init
*
* Description:
* Setup kernel mappings when using CONFIG_BUILD_KERNEL. Sets up kernel MMU
* mappings. Function also sets the first address environment (satp value).
*
****************************************************************************/
void litex_mm_init(void);
#endif /* __ARCH_RISC_V_SRC_LITEX_LITEX_MM_INIT_H */

View File

@ -0,0 +1,67 @@
/****************************************************************************
* arch/risc-v/src/litex/litex_pgalloc.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/arch.h>
#include <nuttx/config.h>
#include <nuttx/pgalloc.h>
#include <assert.h>
#include <debug.h>
#include <arch/board/board_memorymap.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: up_allocate_pgheap
*
* Description:
* If there is a page allocator in the configuration, then this function
* must be provided by the platform-specific code. The OS initialization
* logic will call this function early in the initialization sequence to
* get the page heap information needed to configure the page allocator.
*
****************************************************************************/
void up_allocate_pgheap(void **heap_start, size_t *heap_size)
{
DEBUGASSERT(heap_start && heap_size);
*heap_start = (void *)PGPOOL_START;
*heap_size = (size_t)PGPOOL_SIZE;
}

View File

@ -0,0 +1,94 @@
/****************************************************************************
* arch/risc-v/src/litex/litex_shead.S
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/irq.h>
#include "chip.h"
#include "litex_memorymap.h"
#include "riscv_internal.h"
/****************************************************************************
* Public Symbols
****************************************************************************/
/* Imported symbols */
.extern __trap_vec
.section .text
.global __start
/****************************************************************************
* Name: __start
*
* Description:
* Supervisor mode start function.
*
* Input Parameters:
* a0 - hartid
*
****************************************************************************/
__start:
/* Disable all interrupts in sie */
csrw sie, zero
csrw sip, zero
/* Set the S-mode trap vector */
la t0, __trap_vec
csrw stvec, t0
/* Clear sscratch */
csrw sscratch, zero
csrw scause, zero
csrw sepc, zero
/* initialize global pointer, global data */
.option push
.option norelax
la gp, __global_pointer$
.option pop
lui sp, %hi(LITEX_IDLESTACK_TOP)
addi sp, sp, %lo(LITEX_IDLESTACK_TOP)
/* Make sure the writes to CSR stick before continuing */
fence
/* Set stack pointer and jump to start */
/*la sp, LITEX_IDLESTACK_TOP*/
j __litex_start

View File

@ -33,6 +33,10 @@
#include "litex.h"
#include "chip.h"
#ifdef CONFIG_BUILD_KERNEL
# include "litex_mm_init.h"
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -43,6 +47,10 @@
# define showprogress(c)
#endif
#if defined (CONFIG_BUILD_KERNEL) && !defined (CONFIG_ARCH_USE_S_MODE)
# error "Target requires kernel in S-mode, enable CONFIG_ARCH_USE_S_MODE"
#endif
/****************************************************************************
* Public Data
****************************************************************************/
@ -96,6 +104,10 @@ void __litex_start(void)
*dest++ = *src++;
}
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
riscv_percpu_add_hart(0);
#endif
/* Setup PLL */
litex_clockconfig();
@ -114,7 +126,11 @@ void __litex_start(void)
/* Do board initialization */
litex_boardinitialize();
#ifdef CONFIG_BUILD_KERNEL
/* Setup page tables for kernel and enable MMU */
litex_mm_init();
#endif
showprogress('C');

View File

@ -23,19 +23,17 @@
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <time.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/clock.h>
#include <nuttx/spinlock.h>
#include <arch/board/board.h>
#include <nuttx/timers/arch_alarm.h>
#include <nuttx/init.h>
#include <debug.h>
#include "riscv_internal.h"
#include "litex.h"
#include "litex_clockconfig.h"
#include "hardware/litex_timer.h"
#include "riscv_mtimer.h"
/****************************************************************************
* Pre-processor Definitions
@ -47,95 +45,33 @@
* Private Data
****************************************************************************/
static bool _b_tick_started = false;
/****************************************************************************
* Private Functions
****************************************************************************/
/* litex mmio registers are a bit odd, by default they are byte-wide
* registers that are on 32-bit word boundaries. So a "32-bit" registers
* is actually broken into four bytes spanning a total address space of
* 16 bytes.
*/
static inline uint64_t litex_clint_time_read(void)
{
uint64_t r = getreg32(LITEX_CLINT_MTIME);
r <<= 32;
r |= getreg32(LITEX_CLINT_MTIME + 0x04);
return r;
}
static inline uint64_t litex_clint_time_cmp_read(void)
{
uint64_t r = getreg32(LITEX_CLINT_MTIMECMP);
r <<= 32;
r |= getreg32(LITEX_CLINT_MTIMECMP + 0x04);
return r;
}
static inline void litex_clint_time_cmp_write(uint64_t v)
{
putreg32(v >> 32, LITEX_CLINT_MTIMECMP);
putreg32(v, LITEX_CLINT_MTIMECMP + 0x04);
}
/* helper function to set/clear csr */
#define csr_clear(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
__asm__ __volatile__ ("csrc " #csr ", %0" \
: : "rK" (__v)); \
})
#define csr_set(csr, val) \
({ \
unsigned long __v = (unsigned long)(val); \
__asm__ __volatile__ ("csrs " #csr ", %0" \
: : "rK" (__v)); \
})
/****************************************************************************
* Name: litex_reload_mtimecmp
****************************************************************************/
static void litex_reload_mtimecmp(void)
{
irqstate_t flags = spin_lock_irqsave(NULL);
uint64_t current;
uint64_t next;
if (!_b_tick_started)
{
_b_tick_started = true;
putreg32(1, LITEX_CLINT_LATCH);
current = litex_clint_time_read();
}
else
{
current = litex_clint_time_cmp_read();
}
next = current + TICK_COUNT;
litex_clint_time_cmp_write(next);
putreg32(1, LITEX_CLINT_LATCH);
csr_set(mie, MIE_MTIE);
csr_clear(mip, MIP_MTIP);
spin_unlock_irqrestore(NULL, flags);
}
/****************************************************************************
* Name: litex_timerisr
****************************************************************************/
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
static void litex_mtimer_initialise(void)
{
struct oneshot_lowerhalf_s *lower = riscv_mtimer_initialize(
LITEX_CLINT_MTIME, LITEX_CLINT_MTIMECMP,
RISCV_IRQ_TIMER, litex_get_hfclk());
DEBUGASSERT(lower);
up_alarm_set_lowerhalf(lower);
}
#else
static int litex_timerisr(int irq, void *context, void *arg)
{
litex_reload_mtimecmp();
/* Clear timer interrupt */
putreg32(0xffffffff, LITEX_TIMER0_EV_PENDING);
/* Process timer interrupt */
@ -143,6 +79,33 @@ static int litex_timerisr(int irq, void *context, void *arg)
return 0;
}
static void litex_timer0_initialize(void)
{
/* Disable the timer and clear any pending interrupt */
putreg32(0, LITEX_TIMER0_EN);
putreg32(getreg32(LITEX_TIMER0_EV_PENDING), LITEX_TIMER0_EV_PENDING);
/* Set the timer period */
putreg32(TICK_COUNT, LITEX_TIMER0_RELOAD);
putreg32(getreg32(LITEX_TIMER0_RELOAD), LITEX_TIMER0_LOAD);
/* Attach timer interrupt handler */
irq_attach(LITEX_IRQ_TIMER0, litex_timerisr, NULL);
/* Enable the timer */
putreg32(1, LITEX_TIMER0_EN);
/* And enable the timer interrupt */
putreg32(1, LITEX_TIMER0_EV_ENABLE);
up_enable_irq(LITEX_IRQ_TIMER0);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -158,15 +121,9 @@ static int litex_timerisr(int irq, void *context, void *arg)
void up_timer_initialize(void)
{
/* Attach timer interrupt handler */
irq_attach(RISCV_IRQ_MTIMER, litex_timerisr, NULL);
/* Reload CLINT mtimecmp */
litex_reload_mtimecmp();
/* And enable the timer interrupt */
up_enable_irq(RISCV_IRQ_MTIMER);
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
litex_mtimer_initialise();
#else
litex_timer0_initialize();
#endif
}

View File

@ -25,4 +25,12 @@ config LITEX_SDIO_MOUNT_FSTYPE
default "vfat"
depends on LITEX_SDIO
config LITEX_APPLICATION_RAMDISK
bool "Use application ramdisk"
depends on BUILD_KERNEL
---help---
The application ramdisk is currently only intended only to hold
application elfs in the romfs format. These applications must loaded
externally into ram through litex_term, or similar method.
endif

View File

@ -0,0 +1,84 @@
#
# This file is autogenerated: PLEASE DO NOT EDIT IT.
#
# You can use "make menuconfig" to make any modifications to the installed .config file.
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
# modifications.
#
# CONFIG_DEBUG_OPT_UNUSED_SECTIONS is not set
# CONFIG_NSH_DISABLE_LOSMART is not set
# CONFIG_STANDARD_SERIAL is not set
CONFIG_ALARM_ARCH=y
CONFIG_ARCH="risc-v"
CONFIG_ARCH_ADDRENV=y
CONFIG_ARCH_BOARD="arty_a7"
CONFIG_ARCH_BOARD_ARTY_A7=y
CONFIG_ARCH_CHIP="litex"
CONFIG_ARCH_CHIP_LITEX=y
CONFIG_ARCH_DATA_NPAGES=128
CONFIG_ARCH_DATA_VBASE=0x10400000
CONFIG_ARCH_HEAP_NPAGES=128
CONFIG_ARCH_HEAP_VBASE=0x10800000
CONFIG_ARCH_INTERRUPTSTACK=8192
CONFIG_ARCH_KERNEL_STACKSIZE=3072
CONFIG_ARCH_PGPOOL_MAPPING=y
CONFIG_ARCH_PGPOOL_PBASE=0x40800000
CONFIG_ARCH_PGPOOL_SIZE=4194304
CONFIG_ARCH_PGPOOL_VBASE=0x40800000
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_TEXT_NPAGES=128
CONFIG_ARCH_TEXT_VBASE=0x10000000
CONFIG_ARCH_USE_MMU=y
CONFIG_ARCH_USE_MPU=y
CONFIG_ARCH_USE_S_MODE=y
CONFIG_BOARDCTL_ROMDISK=y
CONFIG_BOARD_LATE_INITIALIZE=y
CONFIG_BOARD_LOOPSPERMSEC=10000
CONFIG_BUILD_KERNEL=y
CONFIG_DEV_ZERO=y
CONFIG_ELF=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_FS_PROCFS=y
CONFIG_FS_PROCFS_EXCLUDE_ENVIRON=y
CONFIG_FS_ROMFS=y
CONFIG_IDLETHREAD_STACKSIZE=2048
CONFIG_INIT_FILEPATH="/system/bin/init"
CONFIG_INIT_MOUNT=y
CONFIG_INIT_MOUNT_FLAGS=0x1
CONFIG_INIT_MOUNT_TARGET="/system/bin"
CONFIG_INIT_STACKSIZE=3072
CONFIG_INTELHEX_BINARY=y
CONFIG_LIBC_ENVPATH=y
CONFIG_LIBC_EXECFUNCS=y
CONFIG_LIBC_PERROR_STDOUT=y
CONFIG_LIBC_STRERROR=y
CONFIG_LITEX_APPLICATION_RAMDISK=y
CONFIG_LITEX_CORE_VEXRISCV_SMP=y
CONFIG_LITEX_SYS_CORE_FREQ_HZ=300000000
CONFIG_MM_PGALLOC=y
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_FILE_APPS=y
CONFIG_NSH_READLINE=y
CONFIG_ONESHOT=y
CONFIG_PATH_INITIAL="/system/bin"
CONFIG_RAM_SIZE=4194304
CONFIG_RAM_START=0x40400000
CONFIG_RAW_BINARY=y
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_LPWORK=y
CONFIG_SCHED_WAITPID=y
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2021
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSLOG_PROCESS_NAME=y
CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_CLE=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_PROGNAME="init"
CONFIG_TESTING_GETPRIME=y
CONFIG_UART0_RXBUFSIZE=128
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_UART0_TXBUFSIZE=128

View File

@ -0,0 +1,93 @@
/****************************************************************************
* boards/risc-v/litex/arty_a7/include/board_memorymap.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __BOARDS_RISCV_LITEX_ARTY_A7_INCLUDE_BOARD_MEMORYMAP_H
#define __BOARDS_RISCV_LITEX_ARTY_A7_INCLUDE_BOARD_MEMORYMAP_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Kernel code memory (RX) */
#define KFLASH_START (uintptr_t)__kflash_start
#define KFLASH_SIZE (uintptr_t)__kflash_size
#define KSRAM_START (uintptr_t)__ksram_start
#define KSRAM_SIZE (uintptr_t)__ksram_size
#define KSRAM_END (uintptr_t)__ksram_end
/* Kernel RAM (RW) */
#define PGPOOL_START (uintptr_t)__pgheap_start
#define PGPOOL_SIZE (uintptr_t)__pgheap_size
/* Page pool (RWX) */
#define PGPOOL_START (uintptr_t)__pgheap_start
#define PGPOOL_SIZE (uintptr_t)__pgheap_size
#define PGPOOL_END (PGPOOL_START + PGPOOL_SIZE)
/* User flash */
#define UFLASH_START (uintptr_t)__uflash_start
#define UFLASH_SIZE (uintptr_t)__uflash_size
/* RAMDisk */
#define RAMDISK_START (uintptr_t)__ramdisk_start
#define RAMDISK_SIZE (uintptr_t)__ramdisk_size
/****************************************************************************
* Public Data
****************************************************************************/
/* Kernel code memory (RX) */
extern uint8_t __kflash_start[];
extern uint8_t __kflash_size[];
/* Kernel RAM (RW) */
extern uint8_t __ksram_start[];
extern uint8_t __ksram_size[];
extern uint8_t __ksram_end[];
/* Page pool (RWX) */
extern uint8_t __pgheap_start[];
extern uint8_t __pgheap_size[];
/* User code memory (RX) */
extern uint8_t __uflash_start[];
extern uint8_t __uflash_size[];
/* ramdisk (RW) */
extern uint8_t __ramdisk_start[];
extern uint8_t __ramdisk_size[];
#endif /* __BOARDS_RISC_V_LITEX_ARTY_A7_INCLUDE_BOARD_MEMORYMAP_H */

View File

@ -22,7 +22,12 @@ include $(TOPDIR)/.config
include $(TOPDIR)/tools/Config.mk
include $(TOPDIR)/arch/risc-v/src/common/Toolchain.defs
ifeq ($(CONFIG_BUILD_KERNEL),y)
LDSCRIPT = ld-kernel.script
else
LDSCRIPT = ld.script
endif
ARCHSCRIPT += $(BOARD_DIR)$(DELIM)scripts$(DELIM)$(LDSCRIPT)
ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10
@ -33,3 +38,11 @@ CXXFLAGS := $(ARCHCXXFLAGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES
CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
CPPFLAGS := $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRAFLAGS)
AFLAGS += $(CFLAGS) -D__ASSEMBLY__
CELFFLAGS = $(CFLAGS)
CXXELFFLAGS = $(CXXFLAGS)
LDELFFLAGS = --oformat elf32-littleriscv
LDELFFLAGS += -r -e main
LDELFFLAGS += -T $(call CONVERT_PATH,$(TOPDIR)/binfmt/libelf/gnu-elf.ld)

View File

@ -0,0 +1,135 @@
/****************************************************************************
* boards/risc-v/litex/arty_a7/scripts/ld-kernel.script
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
MEMORY
{
kflash (rx) : ORIGIN = 0x40000000, LENGTH = 4096K /* w/ cache */
ksram (rwx) : ORIGIN = 0x40400000, LENGTH = 4096K /* w/ cache */
pgram (rwx) : ORIGIN = 0x40800000, LENGTH = 4096K /* w/ cache */
ramdisk (rwx) : ORIGIN = 0x40C00000, LENGTH = 4096K /* w/ cache */
}
OUTPUT_ARCH("riscv")
/* Provide the kernel boundaries */
__kflash_start = ORIGIN(kflash);
__kflash_size = LENGTH(kflash);
__ksram_start = ORIGIN(ksram);
__ksram_size = LENGTH(ksram);
__ksram_end = ORIGIN(ksram) + LENGTH(ksram);
/* Page heap */
__pgheap_start = ORIGIN(pgram);
__pgheap_size = LENGTH(pgram) + LENGTH(ramdisk);
/* Application ramdisk */
__ramdisk_start = ORIGIN(ramdisk);
__ramdisk_size = LENGTH(ramdisk);
__ramdisk_end = ORIGIN(ramdisk) + LENGTH(ramdisk);
ENTRY(_stext)
EXTERN(__start)
SECTIONS
{
. = 0x40000000;
.text : {
_stext = ABSOLUTE(.);
*(.start .start.*)
*(.text .text.*)
*(.fixup)
*(.gnu.warning)
*(.rodata .rodata.* .srodata .srodata.*)
*(.gnu.linkonce.t.*)
*(.glue_7)
*(.glue_7t)
*(.got)
*(.gcc_except_table)
*(.gnu.linkonce.r.*)
_etext = ABSOLUTE(.);
} > kflash
.init_section : ALIGN(4) {
_sinit = ABSOLUTE(.);
KEEP(*(.init_array .init_array.*))
_einit = ABSOLUTE(.);
} > kflash
_eronly = ABSOLUTE(.);
/* No init section */
.noinit (NOLOAD) : ALIGN(4) {
*(.noinit)
*(.noinit.*)
} > ksram
.data : ALIGN(4) {
_sdata = ABSOLUTE(.);
*(.data .data.*)
*(.sdata .sdata.* .sdata2.*)
*(.gnu.linkonce.d.*)
*(.gnu.linkonce.s.*)
CONSTRUCTORS
. = ALIGN(4);
_edata = ABSOLUTE(.);
} > ksram AT > kflash
PROVIDE(__global_pointer$ = _sdata + ((_edata - _sdata) / 2));
.bss : ALIGN(4) {
_sbss = ABSOLUTE(.);
*(.bss .bss.*)
*(.sbss .sbss.*)
*(.gnu.linkonce.b.*)
*(.gnu.linkonce.sb.*)
*(COMMON)
} > ksram
/* Page tables here, align to 4K boundary */
.pgtables (NOLOAD) : ALIGN(0x1000) {
*(.pgtables)
. = ALIGN(4);
} > ksram
/* Stack top */
.stack_top : {
. = ALIGN(32);
_ebss = ABSOLUTE(.);
} > ksram
/* 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) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_info 0 : { *(.debug_info) }
.debug_line 0 : { *(.debug_line) }
.debug_pubnames 0 : { *(.debug_pubnames) }
.debug_aranges 0 : { *(.debug_aranges) }
}

View File

@ -38,4 +38,8 @@ ifeq ($(CONFIG_LITEX_PWM),y)
CSRCS += litex_pwm.c
endif
ifeq ($(CONFIG_LITEX_APPLICATION_RAMDISK),y)
CSRCS += litex_ramdisk.c
endif
include $(TOPDIR)/boards/Board.mk

View File

@ -161,4 +161,22 @@ bool litex_cardinserted(int slotno);
int litex_pwm_setup(void);
#endif
/****************************************************************************
* Name: litex_mount_ramdisk
*
* Description:
* Mount a ramdisk defined in the ld-kernel.script to /dev/ramX.
* The ramdisk is intended to contain a romfs with applications which can
* be spawned at runtime.
*
* Returned Value:
* OK is returned on success.
* -ERRORNO is returned on failure.
*
****************************************************************************/
#ifdef CONFIG_LITEX_APPLICATION_RAMDISK
int litex_mount_ramdisk(void);
#endif
#endif /* __BOARDS_RISCV_LITEX_ARTY_A7_SRC_ARTY_A7_H */

View File

@ -73,3 +73,31 @@ int board_app_initialize(uintptr_t arg)
return litex_bringup();
#endif
}
/****************************************************************************
* Name: board_late_initialize
*
* Description:
* If CONFIG_BOARD_LATE_INITIALIZE is selected, then an additional
* initialization call will be performed in the boot-up sequence to a
* function called board_late_initialize(). board_late_initialize() will
* be called after up_initialize() and board_early_initialize() and just
* before the initial application is started. This additional
* initialization phase may be used, for example, to initialize board-
* specific device drivers for which board_early_initialize() is not
* suitable.
*
* Waiting for events, use of I2C, SPI, etc are permissible in the context
* of board_late_initialize(). That is because board_late_initialize()
* will run on a temporary, internal kernel thread.
*
****************************************************************************/
void board_late_initialize(void)
{
#ifdef CONFIG_LITEX_APPLICATION_RAMDISK
litex_mount_ramdisk();
#endif
litex_bringup();
}

View File

@ -0,0 +1,98 @@
/****************************************************************************
* boards/risc-v/litex/arty_a7/src/litex_ramdisk.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <syslog.h>
#include <errno.h>
#include <nuttx/board.h>
#include <arch/board/board_memorymap.h>
#include <nuttx/drivers/ramdisk.h>
#include <sys/boardctl.h>
#include <sys/mount.h>
#include "litex.h"
#include "arty_a7.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef CONFIG_BUILD_KERNEL
#error "Ramdisk usage is intended to be used with kernel build only"
#endif
#define SECTORSIZE 512
#define NSECTORS(b) (((b) + SECTORSIZE - 1) / SECTORSIZE)
#define RAMDISK_DEVICE_MINOR 0
/****************************************************************************
* Private Types
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: litex_mount_ramdisk
*
* Description:
* Mount a ramdisk defined in the ld-kernel.script to /dev/ramX.
* The ramdisk is intended to contain a romfs with applications which can
* be spawned at runtime.
*
* Returned Value:
* OK is returned on success.
* -ERRORNO is returned on failure.
*
****************************************************************************/
int litex_mount_ramdisk(void)
{
int ret;
struct boardioc_romdisk_s desc;
desc.minor = RAMDISK_DEVICE_MINOR;
desc.nsectors = NSECTORS((ssize_t)__ramdisk_size);
desc.sectsize = SECTORSIZE;
desc.image = __ramdisk_start;
ret = boardctl(BOARDIOC_ROMDISK, (uintptr_t)&desc);
if (ret < 0)
{
syslog(LOG_ERR, "Ramdisk register failed: %s\n", strerror(errno));
syslog(LOG_ERR, "Ramdisk mountpoint /dev/ram%d\n",
RAMDISK_DEVICE_MINOR);
syslog(LOG_ERR, "Ramdisk length %u, origin %x\n",
(ssize_t)__ramdisk_size,
(uintptr_t)__ramdisk_start);
}
return ret;
}

View File

@ -564,6 +564,11 @@ int up_relocateadd(const Elf_Rela *rel, const Elf_Sym *sym,
*(uint64_t *)addr += (uint64_t)(sym->st_value + rel->r_addend);
}
break;
case R_RISCV_SUB16:
{
*(uint16_t *)addr -= (uint16_t)(sym->st_value + rel->r_addend);
}
break;
case R_RISCV_SUB32:
{
*(uint32_t *)addr -= (uint32_t)(sym->st_value + rel->r_addend);
@ -574,6 +579,11 @@ int up_relocateadd(const Elf_Rela *rel, const Elf_Sym *sym,
*(uint64_t *)addr -= (uint64_t)(sym->st_value + rel->r_addend);
}
break;
case R_RISCV_SET16:
{
*(uint16_t *)addr = (uint16_t)(sym->st_value + rel->r_addend);
}
break;
default:
berr("ERROR: Unsupported relocation: %ld\n",
ARCH_ELF_RELTYPE(rel->r_info));