1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

riscv_common: Refactor common fe310 code to riscv_common

This commit is contained in:
Koen Zandberg 2020-09-09 21:37:15 +02:00
parent 746b91e1d1
commit 2692957c0e
No known key found for this signature in database
GPG Key ID: 0895A893E6D2985B
52 changed files with 481 additions and 285 deletions

View File

@ -21,6 +21,8 @@
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
#include "kernel_defines.h"
#include "macros/units.h"
#include "periph_cpu.h"
#include "clk_conf.h"

View File

@ -5,31 +5,15 @@
# directory for more details.
#
config CPU_ARCH_RISCV
bool
select HAS_ARCH_RISCV
select HAS_NEWLIB
select HAS_PICOLIBC if '$(RIOT_CI_BUILD)' != '1'
select MODULE_MALLOC_THREAD_SAFE if TEST_KCONFIG
config CPU_CORE_RV32M
bool
select CPU_ARCH_RISCV
select HAS_ARCH_32BIT
config CPU_FAM_FE310
bool
select CPU_CORE_RV32M
select CPU_CORE_RV32I
select HAS_CPU_FE310
select HAS_PERIPH_CPUID
select HAS_PERIPH_GPIO
select HAS_PERIPH_GPIO_IRQ
select HAS_PERIPH_PLIC
select HAS_PERIPH_PM
select HAS_PERIPH_WDT
select HAS_CPP
select HAS_LIBSTDCPP
select HAS_SSP
config CPU_MODEL_FE310_G000
bool
@ -39,24 +23,12 @@ config CPU_MODEL_FE310_G002
bool
select CPU_FAM_FE310
## Definition of specific features
config HAS_ARCH_RISCV
bool
help
Indicates that the current CPU has a RISC-V.
## Definition of specific features
config HAS_CPU_FE310
bool
help
Indicates that a 'fe310' cpu is being used.
config CPU_ARCH
default "risc-v" if CPU_ARCH_RISCV
config CPU_CORE
default "rv32m" if CPU_CORE_RV32M
config CPU_FAM
default "fe310" if CPU_FAM_FE310
@ -68,3 +40,5 @@ config CPU
default "fe310" if CPU_FAM_FE310
rsource "Kconfig.clk"
source "$(RIOTCPU)/riscv_common/Kconfig"

View File

@ -2,6 +2,6 @@
MODULE = cpu
# add a list of subdirectories, that should also be built
DIRS = periph vendor
DIRS = $(RIOTCPU)/riscv_common periph vendor
include $(RIOTBASE)/Makefile.base

View File

@ -5,10 +5,8 @@ ifneq (,$(filter newlib,$(USEMODULE)))
USEMODULE += newlib_syscalls_default
endif
USEMODULE += sifive_drivers_fe310
USEMODULE += periph
USEMODULE += periph_pm
USEMODULE += sifive_drivers_fe310
FEATURES_REQUIRED += periph_plic
@ -16,5 +14,8 @@ ifneq (,$(filter periph_rtc,$(USEMODULE)))
FEATURES_REQUIRED += periph_rtt
endif
# Make calls to malloc and friends thread-safe
USEMODULE += malloc_thread_safe
ifneq (,$(filter periph_timer,$(USEMODULE)))
FEATURES_REQUIRED += periph_coretimer
endif
include $(RIOTCPU)/riscv_common/Makefile.dep

View File

@ -1,16 +1,6 @@
FEATURES_PROVIDED += arch_32bit
FEATURES_PROVIDED += arch_riscv
FEATURES_PROVIDED += cpp
FEATURES_PROVIDED += libstdcpp
FEATURES_PROVIDED += newlib
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
FEATURES_PROVIDED += periph_plic
FEATURES_PROVIDED += periph_pm
FEATURES_PROVIDED += periph_wdt
FEATURES_PROVIDED += ssp
# RISC-V toolchain on CI does not work properly with picolibc yet
ifeq (,$(RIOT_CI_BUILD))
FEATURES_PROVIDED += picolibc
endif
include $(RIOTCPU)/riscv_common/Makefile.features

View File

@ -11,24 +11,4 @@ else ifeq ($(CPU_MODEL), fe310_g002)
ROM_LEN ?= 0x0006a120
endif
# All variables must be defined in the CPU configuration when using the common
# `ldscripts/fe310.ld`
ifneq (,$(ROM_START_ADDR)$(RAM_START_ADDR)$(ROM_LEN)$(RAM_LEN))
$(if $(ROM_START_ADDR),,$(error ROM_START_ADDR is not defined))
$(if $(RAM_START_ADDR),,$(error RAM_START_ADDR is not defined))
$(if $(ROM_LEN),,$(error ROM_LEN is not defined))
$(if $(RAM_LEN),,$(error RAM_LEN is not defined))
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_rom_start_addr=$(ROM_START_ADDR)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_ram_start_addr=$(RAM_START_ADDR)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_rom_length=$(ROM_LEN)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_ram_length=$(RAM_LEN)
endif
ifneq (,$(ITIM_START_ADDR))
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_itim_start_addr=$(ITIM_START_ADDR)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_itim_length=$(ITIM_LEN)
endif
LINKER_SCRIPT ?= fe310.ld
include $(RIOTMAKE)/arch/riscv.inc.mk
include $(RIOTCPU)/riscv_common/Makefile.include

View File

@ -26,7 +26,7 @@
static uint32_t _cpu_frequency = 0;
#endif
void clock_init(void)
void fe310_clock_init(void)
{
/* Ensure that we aren't running off the PLL before we mess with it. */
if (PRCI_REG(PRCI_PLLCFG) & PLL_SEL(1)) {

View File

@ -21,8 +21,7 @@
#include "periph/init.h"
#include "periph_conf.h"
#include "vendor/encoding.h"
#include "vendor/plic_driver.h"
#include "vendor/riscv_csr.h"
#include "stdio_uart.h"
@ -95,7 +94,7 @@ void flash_init(void)
void cpu_init(void)
{
/* Initialize clock */
clock_init();
fe310_clock_init();
#if USE_CLOCK_HFROSC_PLL
/* Initialize flash memory, only when using the PLL: in this
@ -104,14 +103,8 @@ void cpu_init(void)
flash_init();
#endif
/* Enable FPU if present */
if (read_csr(misa) & (1 << ('F' - 'A'))) {
write_csr(mstatus, MSTATUS_FS); /* allow FPU instructions without trapping */
write_csr(fcsr, 0); /* initialize rounding mode, undefined at reset */
}
/* Initialize IRQs */
irq_init();
/* Common RISC-V initialization */
riscv_init();
/* Initialize stdio */
stdio_init();

9
cpu/fe310/doc.txt Normal file
View File

@ -0,0 +1,9 @@
/**
* @defgroup cpu_fe310 SiFive fe310
* @ingroup cpu
* @brief SiFive fe310 RISC-V MCU specific implementation.
*
* This module contains SiFive fe310 specific code and definition.
*
* @see cpu_riscv_common
*/

View File

@ -20,6 +20,7 @@
#define CLK_CONF_H
#include "macros/units.h"
#include "kernel_defines.h"
#ifdef __cplusplus
extern "C" {

View File

@ -1,80 +0,0 @@
/*
* Copyright (C) 2017 Ken Rabold
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup cpu_fe310 SiFive FE310
* @ingroup cpu
* @brief Common implementations and headers for RISC-V
* @{
*
* @file
* @brief Basic definitions for the RISC-V common module
*
* When ever you want to do something hardware related, that is accessing MCUs
* registers, just include this file. It will then make sure that the MCU
* specific headers are included.
*
* @author Ken Rabold
*/
#ifndef CPU_H
#define CPU_H
#include "thread.h"
#include "macros/units.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialization of the CPU
*/
void cpu_init(void);
/**
* @brief Initialization of the clock
*/
void clock_init(void);
/**
* @brief Get and eventually compute the current CPU core clock frequency
*
* @return the cpu core clock frequency in Hz
*/
uint32_t cpu_freq(void);
/**
* @brief Initialization of interrupts
*/
void irq_init(void);
/**
* @brief Print the last instruction's address
*
* @todo: Not supported
*/
static inline void cpu_print_last_instruction(void)
{
/* This function must exist else RIOT won't compile */
}
/**
* @brief Initialization of the Newlib-nano stub
*/
void nanostubs_init(void);
#ifdef __cplusplus
}
#endif
#endif /* CPU_H */
/** @} */

View File

@ -19,35 +19,23 @@
#ifndef CPU_CONF_H
#define CPU_CONF_H
/**
* @name Configuration of default stack sizes
* @{
*/
#ifndef THREAD_EXTRA_STACKSIZE_PRINTF
#define THREAD_EXTRA_STACKSIZE_PRINTF (256)
#endif
#ifndef THREAD_STACKSIZE_DEFAULT
#define THREAD_STACKSIZE_DEFAULT (1024)
#endif
#ifndef THREAD_STACKSIZE_IDLE
#define THREAD_STACKSIZE_IDLE (256)
#endif
/** @} */
/**
* @brief Declare the heap_stats function as available
*/
#define HAVE_HEAP_STATS
/**
* @brief This arch uses the inlined irq API.
*/
#define IRQ_API_INLINED (1)
#include "cpu_conf_common.h"
#include "vendor/platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Base address of the CLINT
*/
#define CLINT_BASE_ADDR (CLINT_CTRL_ADDR)
/**
* @brief Base address of the PLIC peripheral
*/
#define PLIC_BASE_ADDR (PLIC_CTRL_ADDR)
#ifdef __cplusplus
}
#endif

View File

@ -21,24 +21,13 @@
#include <inttypes.h>
#include "periph_cpu_common.h"
#include "cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Power management configuration
* @{
*/
#define PROVIDES_PM_SET_LOWEST
/** @} */
/**
* @brief Length of the CPU_ID in octets
*/
#define CPUID_LEN (12U)
#ifndef DOXYGEN
/**
* @brief Overwrite the default gpio_t type definition
@ -47,6 +36,11 @@ extern "C" {
typedef uint8_t gpio_t;
#endif
/**
* @brief Length of the CPU_ID in octets
*/
#define CPUID_LEN (12U)
/**
* @brief Definition of a fitting UNDEF value
*/
@ -66,10 +60,10 @@ typedef uint8_t gpio_t;
* @brief Structure for UART configuration data
*/
typedef struct {
uint32_t addr; /**< UART control register address */
gpio_t rx; /**< RX pin */
gpio_t tx; /**< TX pin */
plic_source isr_num; /**< ISR source number */
uint32_t addr; /**< UART control register address */
gpio_t rx; /**< RX pin */
gpio_t tx; /**< TX pin */
irqn_t isr_num; /**< ISR source number */
} uart_conf_t;
/**
@ -180,6 +174,17 @@ typedef struct {
#endif
#endif
/**
* @brief Initialization of the clock
*/
void fe310_clock_init(void);
/**
* @brief Get and eventually compute the current CPU core clock frequency
*
* @return the cpu core clock frequency in Hz
*/
uint32_t cpu_freq(void);
/** @} */

View File

@ -17,7 +17,6 @@
* @}
*/
#include "cpucycle.h"
#include "vendor/encoding.h"
uint64_t get_cycle_count(void)

View File

@ -22,7 +22,7 @@
#include "periph/cpuid.h"
#include "cpu.h"
#include "vendor/encoding.h"
#include "vendor/riscv_csr.h"
#include "vendor/platform.h"
void cpuid_get(void *id)

View File

@ -26,9 +26,8 @@
#include "periph_conf.h"
#include "periph/gpio.h"
#include "plic.h"
#include "vendor/encoding.h"
#include "vendor/riscv_csr.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
/* Num of GPIOs supported */
#define GPIO_NUMOF (32)

View File

@ -30,9 +30,8 @@
#include "periph_conf.h"
#include "periph/rtt.h"
#include "plic.h"
#include "vendor/encoding.h"
#include "vendor/riscv_csr.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
#define ENABLE_DEBUG 0
#include "debug.h"

View File

@ -26,9 +26,8 @@
#include "cpu.h"
#include "periph/uart.h"
#include "plic.h"
#include "vendor/encoding.h"
#include "vendor/riscv_csr.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
#include "vendor/prci_driver.h"
/**

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#include <unistd.h>
#include "vendor/encoding.h"
#include "vendor/riscv_csr.h"
#include "vendor/platform.h"
#include "vendor/prci_driver.h"
@ -36,31 +36,31 @@ uint32_t PRCI_measure_mcycle_freq(uint32_t mtime_ticks, uint32_t mtime_freq)
do {
start_mtime = CLINT_REG(CLINT_MTIME);
} while (start_mtime == tmp);
uint64_t start_mcycle;
rdmcycle(&start_mcycle);
while (CLINT_REG(CLINT_MTIME) < end_mtime) ;
uint64_t end_mcycle;
rdmcycle(&end_mcycle);
uint32_t difference = (uint32_t) (end_mcycle - start_mcycle);
uint64_t freq = ((uint64_t) difference * mtime_freq) / mtime_ticks;
return (uint32_t) freq & 0xFFFFFFFF;
}
void PRCI_use_hfrosc(int div, int trim)
{
// Make sure the HFROSC is running at its default setting
// It is OK to change this even if we are running off of it.
PRCI_REG(PRCI_HFROSCCFG) = (ROSC_DIV(div) | ROSC_TRIM(trim) | ROSC_EN(1));
while ((PRCI_REG(PRCI_HFROSCCFG) & ROSC_RDY(1)) == 0);
PRCI_REG(PRCI_PLLCFG) &= ~PLL_SEL(1);
}
@ -73,12 +73,12 @@ void PRCI_use_pll(int refsel, int bypass,
// Make sure the HFROSC is running at its default setting
PRCI_use_hfrosc(4, 16);
}
// Set PLL Source to be HFXOSC if desired.
uint32_t config_value = 0;
config_value |= PLL_REFSEL(refsel);
if (bypass) {
// Bypass
config_value |= PLL_BYPASS(1);
@ -89,14 +89,14 @@ void PRCI_use_pll(int refsel, int bypass,
// Set our Final output divide to divide-by-1:
PRCI_REG(PRCI_PLLDIV) = (PLL_FINAL_DIV_BY_1(1) | PLL_FINAL_DIV(0));
} else {
// To overclock, use the hfrosc
if (hfrosctrim >= 0 && hfroscdiv >= 0) {
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
}
// Set DIV Settings for PLL
// (Legal values of f_REF are 6-48MHz)
// Set DIVR to divide-by-2 to get 8MHz frequency
@ -134,7 +134,7 @@ void PRCI_use_pll(int refsel, int bypass,
// So wait 4 ticks of RTC.
uint32_t now = CLINT_REG(CLINT_MTIME);
while (CLINT_REG(CLINT_MTIME) - now < 4) ;
// Now it is safe to check for PLL Lock
while ((PRCI_REG(PRCI_PLLCFG) & PLL_LOCK(1)) == 0);
@ -148,7 +148,7 @@ void PRCI_use_pll(int refsel, int bypass,
if (refsel) {
PRCI_REG(PRCI_HFROSCCFG) &= ~ROSC_EN(1);
}
}
void PRCI_use_default_clocks(void)
@ -162,7 +162,7 @@ void PRCI_use_default_clocks(void)
void PRCI_use_hfxosc(uint32_t finaldiv)
{
PRCI_use_pll(1, // Use HFXTAL
1, // Bypass = 1
0, // PLL settings don't matter
@ -216,20 +216,20 @@ uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target )
uint32_t desired_hfrosc_freq = (f_cpu/ 16);
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
// Ignore the first run (for icache reasons)
uint32_t cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
uint32_t prev_freq = cpu_freq;
while ((cpu_freq < desired_hfrosc_freq) && (hfrosctrim < 0x1F)){
prev_trim = hfrosctrim;
prev_freq = cpu_freq;
hfrosctrim ++;
PRCI_use_hfrosc(hfroscdiv, hfrosctrim);
cpu_freq = PRCI_measure_mcycle_freq(3000, RTC_FREQ);
}
}
// We couldn't go low enough
if (prev_freq > desired_hfrosc_freq){
@ -237,7 +237,7 @@ uint32_t PRCI_set_hfrosctrim_for_f_cpu(uint32_t f_cpu, PRCI_freq_target target )
cpu_freq = PRCI_measure_mcycle_freq(1000, RTC_FREQ);
return cpu_freq;
}
// We couldn't go high enough
if (cpu_freq < desired_hfrosc_freq){
PRCI_use_pll(0, 0, 1, 31, 1, 1, hfroscdiv, prev_trim);

34
cpu/riscv_common/Kconfig Normal file
View File

@ -0,0 +1,34 @@
# Copyright (c) 2020 Inria
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
config CPU_ARCH_RISCV
bool
select HAS_ARCH_RISCV
select HAS_CPP
select HAS_LIBSTDCPP
select HAS_NEWLIB
select HAS_PERIPH_CORETIMER
select HAS_PERIPH_PLIC
select HAS_PICOLIBC if '$(RIOT_CI_BUILD)' != '1'
select MODULE_MALLOC_THREAD_SAFE if TEST_KCONFIG
select HAS_SSP
config CPU_CORE_RV32I
bool
select CPU_ARCH_RISCV
select HAS_ARCH_32BIT
## Definition of specific features
config HAS_ARCH_RISCV
bool
help
Indicates that the current CPU has a RISC-V.
config CPU_ARCH
default "risc-v" if CPU_ARCH_RISCV
config CPU_CORE
default "rv32i" if CPU_CORE_RV32I

View File

@ -0,0 +1,3 @@
DIRS = periph
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,8 @@
# Tell the build system that the CPU depends on the risc-v common files:
USEMODULE += riscv_common
# include common periph code
USEMODULE += riscv_common_periph
# Make calls to malloc and friends thread-safe
USEMODULE += malloc_thread_safe

View File

@ -0,0 +1,13 @@
FEATURES_PROVIDED += arch_32bit
FEATURES_PROVIDED += arch_riscv
FEATURES_PROVIDED += cpp
FEATURES_PROVIDED += libstdcpp
FEATURES_PROVIDED += newlib
FEATURES_PROVIDED += periph_coretimer
FEATURES_PROVIDED += periph_plic
FEATURES_PROVIDED += ssp
# RISC-V toolchain on CI does not work properly with picolibc yet
ifeq (,$(RIOT_CI_BUILD))
FEATURES_PROVIDED += picolibc
endif

View File

@ -0,0 +1,24 @@
CFLAGS += -Wno-pedantic
INCLUDES += -I$(RIOTCPU)/riscv_common/include
# All variables must be defined in the CPU configuration when using the common
# `ldscripts/riscv.ld`
ifneq (,$(ROM_START_ADDR)$(RAM_START_ADDR)$(ROM_LEN)$(RAM_LEN))
$(if $(ROM_START_ADDR),,$(error ROM_START_ADDR is not defined))
$(if $(RAM_START_ADDR),,$(error RAM_START_ADDR is not defined))
$(if $(ROM_LEN),,$(error ROM_LEN is not defined))
$(if $(RAM_LEN),,$(error RAM_LEN is not defined))
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_rom_start_addr=$(ROM_START_ADDR)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_ram_start_addr=$(RAM_START_ADDR)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_rom_length=$(ROM_LEN)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_ram_length=$(RAM_LEN)
endif
ifneq (,$(ITIM_START_ADDR))
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_itim_start_addr=$(ITIM_START_ADDR)
LINKFLAGS += $(LINKFLAGPREFIX)--defsym=_itim_length=$(ITIM_LEN)
endif
LINKER_SCRIPT ?= riscv.ld
include $(RIOTMAKE)/arch/riscv.inc.mk

View File

@ -7,7 +7,7 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @ingroup cpu
* @{
*

View File

@ -7,7 +7,7 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2020, Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup cpu_riscv_common RISC-V common
* @ingroup cpu
* @brief Common implementations and headers for the RISC-V CPU
* @{
*
* @file
* @brief Basic definitions for the RISC-V CPU module
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#include <stdint.h>
#include "irq_arch.h"
#ifndef CPU_H
#define CPU_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialization of the CPU
*/
void cpu_init(void);
/**
* @brief Initialize rv32i specific core parts of the CPU
*
* Initialized the interrupt controller and the enables the FPU if present
*/
void riscv_init(void);
/**
* @brief Enable the rv32i FPU when present
*/
void riscv_fpu_init(void);
/**
* @brief Initialization of the interrupt controller
*/
void riscv_irq_init(void);
/**
* @brief Print the last instruction's address
*
* @todo: Not supported
*/
static inline void cpu_print_last_instruction(void)
{
/* This function must exist else RIOT won't compile */
}
#ifdef __cplusplus
}
#endif
#endif /* CPU_H */
/** @} */

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2020 Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_riscv_common
* @{
*
* @file
* @brief RISC-V CPU configuration options
*
* @author Koen Zandberg
*/
#ifndef CPU_CONF_COMMON_H
#define CPU_CONF_COMMON_H
#include "vendor/riscv_csr.h"
#include "cpu_conf_common.h"
/**
* @name Configuration of default stack sizes
* @{
*/
#ifndef THREAD_EXTRA_STACKSIZE_PRINTF
#define THREAD_EXTRA_STACKSIZE_PRINTF (256)
#endif
#ifndef THREAD_STACKSIZE_DEFAULT
#define THREAD_STACKSIZE_DEFAULT (1024)
#endif
#ifndef THREAD_STACKSIZE_IDLE
#define THREAD_STACKSIZE_IDLE (256)
#endif
/** @} */
/**
* @brief Declare the heap_stats function as available
*/
#define HAVE_HEAP_STATS
/**
* @brief This arch uses the inlined irq API.
*/
#define IRQ_API_INLINED (1)
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* CPU_CONF_COMMON_H */
/** @} */

View File

@ -7,7 +7,7 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file

View File

@ -9,7 +9,7 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file
@ -24,17 +24,15 @@
#define IRQ_ARCH_H
#include <stdint.h>
#include "irq.h"
#include "cpu_conf.h"
#include "cpu.h"
#include "vendor/encoding.h"
#include "irq.h"
#include "vendor/riscv_csr.h"
#ifdef __cplusplus
extern "C" {
#endif
extern volatile int fe310_in_isr;
extern volatile int riscv_in_isr;
/**
* @brief Enable all maskable interrupts
@ -91,7 +89,7 @@ static inline __attribute__((always_inline)) void irq_restore(
*/
static inline __attribute__((always_inline)) int irq_is_in(void)
{
return fe310_in_isr;
return riscv_in_isr;
}
#ifdef __cplusplus

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2020 Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_riscv_common
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef PERIPH_CPU_COMMON_H
#define PERIPH_CPU_COMMON_H
#include <inttypes.h>
#include "cpu.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Power management configuration
* @{
*/
#define PROVIDES_PM_SET_LOWEST
/** @} */
/**
* @brief Convenience typedef for interrupt lines
*/
typedef unsigned irqn_t;
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_COMMON_H */
/** @} */

View File

@ -7,7 +7,7 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file

View File

@ -1,8 +1,5 @@
// See LICENSE for license details
#ifndef _SIFIVE_CLINT_H
#define _SIFIVE_CLINT_H
#ifndef RISCV_CLINT_H
#define RISCV_CLINT_H
#define CLINT_MSIP 0x0000
#define CLINT_MSIP_size 0x4
@ -11,4 +8,4 @@
#define CLINT_MTIME 0xBFF8
#define CLINT_MTIME_size 0x8
#endif /* _SIFIVE_CLINT_H */
#endif /* RISCV_CLINT_H */

View File

@ -1,7 +1,26 @@
// See LICENSE for license details.
/*
* Copyright (C) 2020, Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#ifndef RISCV_CSR_ENCODING_H
#define RISCV_CSR_ENCODING_H
/**
* @defgroup cpu_riscv_common_vendor
* @ingroup cpu_riscv_common
* @brief RISC-V CSR definitions
* @{
*
* @file
* @brief Basic definitions for the RISC-V CSRs. Upstream usually calls
* this file `encoding.h`
*
* @author Koen Zandberg <koen@bergzand.net>
*/
#ifndef RISCV_CSR_H
#define RISCV_CSR_H
#define MSTATUS_UIE 0x00000001
#define MSTATUS_SIE 0x00000002
@ -1311,3 +1330,4 @@ DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL)
DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
#endif

View File

@ -7,11 +7,12 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file cpu.c
* @brief Implementation of the CPU IRQ management for SiFive FE310
* @brief Implementation of the CPU IRQ management for RISC-V clint/plic
* peripheral
*
* @author Ken Rabold
* @}
@ -29,14 +30,12 @@
#include "sched.h"
#include "plic.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
#include "vendor/riscv_csr.h"
/* Default state of mstatus register */
#define MSTATUS_DEFAULT (MSTATUS_MPP | MSTATUS_MPIE)
volatile int fe310_in_isr = 0;
volatile int riscv_in_isr = 0;
/**
* @brief ISR trap vector
@ -48,7 +47,7 @@ static void trap_entry(void);
*/
void timer_isr(void);
void irq_init(void)
void riscv_irq_init(void)
{
/* Setup trap handler function */
write_csr(mtvec, &trap_entry);
@ -75,7 +74,7 @@ void handle_trap(uint32_t mcause)
{
/* Tell RIOT to set sched_context_switch_request instead of
* calling thread_yield(). */
fe310_in_isr = 1;
riscv_in_isr = 1;
/* Check for INT or TRAP */
if ((mcause & MCAUSE_INT) == MCAUSE_INT) {
@ -125,7 +124,7 @@ void handle_trap(uint32_t mcause)
}
}
/* ISR done - no more changes to thread states */
fe310_in_isr = 0;
riscv_in_isr = 0;
}
/* Marking this as interrupt to ensure an mret at the end, provided by the

View File

@ -7,24 +7,24 @@
*/
/**
* @addtogroup cpu_fe310
* @addtogroup cpu_riscv_common
* @{
*
* @file
* @brief Memory definitions for the SiFive FE310
* @brief Memory definitions for the RISC-V CPU
*
* @author Ken Rabold
* @author Koen Zandberg <koen@bergzand.net>
*
* @}
*/
INCLUDE fe310_vars.ld
INCLUDE riscv_vars.ld
MEMORY
{
flash (rxai!w) : ORIGIN = _rom_start_addr , LENGTH = _rom_length
flash (rxai!w) : ORIGIN = _rom_start_addr, LENGTH = _rom_length
ram (wxa!ri) : ORIGIN = _ram_start_addr, LENGTH = _ram_length
itim (wxa!ri) : ORIGIN = _itim_start_addr, LENGTH = _itim_length
}
INCLUDE fe310_base.ld
INCLUDE riscv_base.ld

View File

@ -7,11 +7,11 @@
*/
/**
* @addtogroup cpu_fe310
* @addtogroup cpu_riscv_common
* @{
*
* @file
* @brief Common linker directives for the SiFive FE310
* @brief Common linker directives for the RISC-V CPU
*
* @author Ken Rabold
*

View File

@ -8,11 +8,11 @@
*/
/**
* @addtogroup cpu_fe310
* @addtogroup cpu_riscv_common
* @{
*
* @file
* @brief Linker variables for SiFive FE310
* @brief Linker variables for the RISC-V CPU
*
* @author Koen Zandberg <koen@bergzand.net>
*

View File

@ -7,11 +7,11 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file cpu.c
* @brief Implementation of the CPU panic for SiFive FE310
* @brief Implementation of the CPU panic for RISC-V
*
* @author Ken Rabold
* @}

View File

@ -0,0 +1,2 @@
MODULE = riscv_common_periph
include $(RIOTMAKE)/periph.mk

View File

@ -7,11 +7,21 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file timer.c
* @brief Low-level timer implementation
* @brief Low-level timer implementation based on the CLINT
*
* RISCV implementations using this peripheral must define the `CLINT_BASE_ADDR`
* in order to use the clint as timer.
*
* This implementation assumes the following registers at their offsets:
*
* - mtimecmp: 0x4000
* - mtime: 0xBFF8
*
* The MTIP flag in the mie csr is used to enable and disable the interrupt
*
* @author Ken Rabold
* @}
@ -21,11 +31,15 @@
#include <unistd.h>
#include "cpu.h"
#include "cpu_conf.h"
#include "periph_cpu.h"
#include "periph_conf.h"
#include "periph/timer.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/riscv_csr.h"
#ifndef CLINT_BASE_ADDR
#error CLINT_BASE_ADDR must be defined to use the CLINT as timer
#endif
/**
* @brief Save reference to the timer callback
@ -44,7 +58,6 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
return -1;
}
/* Built in timer for FE310 is 32KHz */
if (freq != RTC_FREQ) {
return -1;
}
@ -55,7 +68,7 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
/* reset timer counter */
volatile uint64_t *mtime = (uint64_t *)(CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t *mtime = (uint64_t *)(CLINT_BASE_ADDR + CLINT_MTIME);
*mtime = 0;
@ -64,9 +77,9 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
int timer_set(tim_t dev, int channel, unsigned int timeout)
{
volatile uint64_t *mtime = (uint64_t *)(CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t *mtime = (uint64_t *)(CLINT_BASE_ADDR + CLINT_MTIME);
volatile uint64_t *mtimecmp =
(uint64_t *)(CLINT_CTRL_ADDR + CLINT_MTIMECMP);
(uint64_t *)(CLINT_BASE_ADDR + CLINT_MTIMECMP);
/* Compute delta for timer */
uint64_t now = *mtime;
@ -90,9 +103,9 @@ int timer_set(tim_t dev, int channel, unsigned int timeout)
int timer_set_absolute(tim_t dev, int channel, unsigned int value)
{
volatile uint64_t *mtime = (uint64_t *)(CLINT_CTRL_ADDR + CLINT_MTIME);
volatile uint64_t *mtime = (uint64_t *)(CLINT_BASE_ADDR + CLINT_MTIME);
volatile uint64_t *mtimecmp =
(uint64_t *)(CLINT_CTRL_ADDR + CLINT_MTIMECMP);
(uint64_t *)(CLINT_BASE_ADDR + CLINT_MTIMECMP);
/* Compute absolute for timer */
uint64_t now = *mtime;
@ -124,7 +137,7 @@ int timer_clear(tim_t dev, int channel)
unsigned int timer_read(tim_t dev)
{
uint32_t lo = *(volatile uint32_t *)(CLINT_CTRL_ADDR + CLINT_MTIME);
uint32_t lo = *(volatile uint32_t *)(CLINT_BASE_ADDR + CLINT_MTIME);
if (dev != 0) {
return 0;
@ -158,7 +171,7 @@ void timer_stop(tim_t dev)
void timer_isr(void)
{
volatile uint64_t *mtimecmp =
(uint64_t *)(CLINT_CTRL_ADDR + CLINT_MTIMECMP);
(uint64_t *)(CLINT_BASE_ADDR + CLINT_MTIMECMP);
/* Clear intr */
clear_csr(mie, MIP_MTIP);

View File

@ -7,23 +7,32 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file
* @brief Platform-Level interrupt controller driver
*
* RISCV implementations using this peripheral must define the `PLIC_BASE_ADDR`,
* in order to use the PLIC as interrupt controller. Also required are:
* PLIC_NUM_INTERRUPTS and PLIC_NUM_PRIORITIES (future compatibility).
*
* @author Koen Zandberg <koen@bergzand.net>
* @}
*/
#include <assert.h>
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/riscv_csr.h"
#include "assert.h"
#include "cpu.h"
#include "plic.h"
/* Local macros to calculate register offsets */
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
/* PLIC external ISR function list */
static plic_isr_cb_t _ext_isrs[PLIC_NUM_INTERRUPTS];

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2020, Koen Zandberg <koen@bergzand.net>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_riscv_common
* @{
*
* @file cpu.c
* @brief Common CPU initialization for RISC-V rv32i architecture
*
* @author Koen Zandberg <koen@bergzand.net>
* @}
*/
#include "cpu.h"
#include "cpu_conf_common.h"
#include "periph_cpu_common.h"
void riscv_fpu_init(void)
{
/* Enable FPU if present */
if (read_csr(misa) & (1 << ('F' - 'A'))) {
write_csr(mstatus, MSTATUS_FS); /* allow FPU instructions without trapping */
write_csr(fcsr, 0); /* initialize rounding mode, undefined at reset */
}
}
void riscv_init(void)
{
riscv_fpu_init();
riscv_irq_init();
}

View File

@ -7,11 +7,11 @@
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu_riscv_common
* @{
*
* @file cpu.c
* @brief Implementation of the CPU thread management for SiFive FE310
* @brief Implementation of the CPU thread management for RISC-V
*
* @author Ken Rabold
* @}

View File

@ -94,6 +94,11 @@ config HAS_PERIPH_CAN
help
Indicates that a CAN peripheral is present.
config HAS_PERIPH_CORETIMER
bool
help
Indicates that the CLINT timer can be used as timer peripheral
config HAS_PERIPH_CPUID
bool
help

View File

@ -35,7 +35,7 @@ CFLAGS_LINK = -nostartfiles -ffunction-sections -fdata-sections
CFLAGS_DBG ?= -g3
CFLAGS_OPT ?= -Os
LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ldscripts
LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ldscripts -L$(RIOTCPU)/riscv_common/ldscripts
LINKER_SCRIPT ?= $(CPU_MODEL).ld
LINKFLAGS += -T$(LINKER_SCRIPT)