Merge pull request #14887 from bergzand/pr/fe310/plic_periph
fe310: Add custom PLIC driver as peripheral
This commit is contained in:
commit
53ac29aca4
@ -44,7 +44,7 @@
|
|||||||
/cpu/cortexm_common/ @haukepetersen @thomaseichinger @DipSwitch
|
/cpu/cortexm_common/ @haukepetersen @thomaseichinger @DipSwitch
|
||||||
/cpu/efm32/ @basilfx
|
/cpu/efm32/ @basilfx
|
||||||
/cpu/esp*/ @gschorcht
|
/cpu/esp*/ @gschorcht
|
||||||
/cpu/fe310/ @aabadie @kaspar030
|
/cpu/fe310/ @aabadie @kaspar030 @bergzand
|
||||||
/cpu/kinetis/ @fjmolinas
|
/cpu/kinetis/ @fjmolinas
|
||||||
/cpu/lpc2387/ @benpicco @maribu
|
/cpu/lpc2387/ @benpicco @maribu
|
||||||
/cpu/mips*/ @kaspar030 @francois-berder
|
/cpu/mips*/ @kaspar030 @francois-berder
|
||||||
|
|||||||
@ -21,6 +21,7 @@ config CPU_FAM_FE310
|
|||||||
select HAS_PERIPH_CPUID
|
select HAS_PERIPH_CPUID
|
||||||
select HAS_PERIPH_GPIO
|
select HAS_PERIPH_GPIO
|
||||||
select HAS_PERIPH_GPIO_IRQ
|
select HAS_PERIPH_GPIO_IRQ
|
||||||
|
select HAS_PERIPH_PLIC
|
||||||
select HAS_PERIPH_PM
|
select HAS_PERIPH_PM
|
||||||
select HAS_PERIPH_WDT
|
select HAS_PERIPH_WDT
|
||||||
select HAS_CPP
|
select HAS_CPP
|
||||||
|
|||||||
@ -10,6 +10,8 @@ USEMODULE += sifive_drivers_fe310
|
|||||||
USEMODULE += periph
|
USEMODULE += periph
|
||||||
USEMODULE += periph_pm
|
USEMODULE += periph_pm
|
||||||
|
|
||||||
|
FEATURES_REQUIRED += periph_plic
|
||||||
|
|
||||||
ifneq (,$(filter periph_rtc,$(USEMODULE)))
|
ifneq (,$(filter periph_rtc,$(USEMODULE)))
|
||||||
FEATURES_REQUIRED += periph_rtt
|
FEATURES_REQUIRED += periph_rtt
|
||||||
endif
|
endif
|
||||||
|
|||||||
@ -4,6 +4,7 @@ FEATURES_PROVIDED += cpp
|
|||||||
FEATURES_PROVIDED += libstdcpp
|
FEATURES_PROVIDED += libstdcpp
|
||||||
FEATURES_PROVIDED += periph_cpuid
|
FEATURES_PROVIDED += periph_cpuid
|
||||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||||
|
FEATURES_PROVIDED += periph_plic
|
||||||
FEATURES_PROVIDED += periph_pm
|
FEATURES_PROVIDED += periph_pm
|
||||||
FEATURES_PROVIDED += periph_wdt
|
FEATURES_PROVIDED += periph_wdt
|
||||||
FEATURES_PROVIDED += ssp
|
FEATURES_PROVIDED += ssp
|
||||||
|
|||||||
@ -56,16 +56,6 @@ uint32_t cpu_freq(void);
|
|||||||
*/
|
*/
|
||||||
void irq_init(void);
|
void irq_init(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief External ISR callback
|
|
||||||
*/
|
|
||||||
typedef void (*external_isr_ptr_t)(int intNum);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set External ISR callback
|
|
||||||
*/
|
|
||||||
void set_external_isr_cb(int intNum, external_isr_ptr_t cbFunc);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Print the last instruction's address
|
* @brief Print the last instruction's address
|
||||||
*
|
*
|
||||||
|
|||||||
86
cpu/fe310/include/plic.h
Normal file
86
cpu/fe310/include/plic.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* 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_fe310
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Platform-Level interrupt controller driver
|
||||||
|
*
|
||||||
|
* @author Koen Zandberg <koen@bergzand.net>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLIC_H
|
||||||
|
#define PLIC_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PLIC callback declaration
|
||||||
|
*
|
||||||
|
* @param irq Interrupt number
|
||||||
|
*/
|
||||||
|
typedef void (*plic_isr_cb_t)(int irq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize the Platform-level interrupt controller
|
||||||
|
*/
|
||||||
|
void plic_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disable an interrupt on the PLIC
|
||||||
|
*
|
||||||
|
* @param irq Interrupt number
|
||||||
|
*/
|
||||||
|
void plic_disable_interrupt(unsigned irq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable an interrupt on the PLIC
|
||||||
|
*
|
||||||
|
* @param irq Interrupt number
|
||||||
|
*/
|
||||||
|
void plic_enable_interrupt(unsigned irq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set an interrupt priority
|
||||||
|
*
|
||||||
|
* @param irq Interrupt number
|
||||||
|
* @param priority Priority
|
||||||
|
*/
|
||||||
|
void plic_set_priority(unsigned irq, unsigned priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the interrupt callback
|
||||||
|
*
|
||||||
|
* @param irq Interrupt number
|
||||||
|
* @param cb Callback to call on interrupt
|
||||||
|
*/
|
||||||
|
void plic_set_isr_cb(unsigned irq, plic_isr_cb_t cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief External ISR callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt handler for the PLIC
|
||||||
|
*
|
||||||
|
* Must be called from the trap handler when an interrupt from the PLIC is
|
||||||
|
* pending
|
||||||
|
*/
|
||||||
|
void plic_isr_handler(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* PLIC_H */
|
||||||
|
/** @} */
|
||||||
6
cpu/fe310/include/vendor/plic.h
vendored
6
cpu/fe310/include/vendor/plic.h
vendored
@ -1,7 +1,7 @@
|
|||||||
// See LICENSE for license details.
|
// See LICENSE for license details.
|
||||||
|
|
||||||
#ifndef PLIC_H
|
#ifndef VENDOR_PLIC_H
|
||||||
#define PLIC_H
|
#define VENDOR_PLIC_H
|
||||||
|
|
||||||
|
|
||||||
// 32 bits per source
|
// 32 bits per source
|
||||||
@ -27,4 +27,4 @@
|
|||||||
#define PLIC_MAX_TARGET 15871
|
#define PLIC_MAX_TARGET 15871
|
||||||
#define PLIC_TARGET_MASK 0x3FFF
|
#define PLIC_TARGET_MASK 0x3FFF
|
||||||
|
|
||||||
#endif /* PLIC_H */
|
#endif /* VENDOR_PLIC_H */
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "irq_arch.h"
|
#include "irq_arch.h"
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "sched.h"
|
#include "sched.h"
|
||||||
|
#include "plic.h"
|
||||||
|
|
||||||
#include "vendor/encoding.h"
|
#include "vendor/encoding.h"
|
||||||
#include "vendor/platform.h"
|
#include "vendor/platform.h"
|
||||||
@ -38,9 +39,6 @@
|
|||||||
|
|
||||||
volatile int fe310_in_isr = 0;
|
volatile int fe310_in_isr = 0;
|
||||||
|
|
||||||
/* PLIC external ISR function list */
|
|
||||||
static external_isr_ptr_t _ext_isrs[PLIC_NUM_INTERRUPTS];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ISR trap vector
|
* @brief ISR trap vector
|
||||||
*/
|
*/
|
||||||
@ -60,7 +58,9 @@ void irq_init(void)
|
|||||||
write_csr(mie, 0);
|
write_csr(mie, 0);
|
||||||
|
|
||||||
/* Initial PLIC external interrupt controller */
|
/* Initial PLIC external interrupt controller */
|
||||||
PLIC_init(PLIC_CTRL_ADDR, PLIC_NUM_INTERRUPTS, PLIC_NUM_PRIORITIES);
|
if (IS_ACTIVE(MODULE_PERIPH_PLIC)) {
|
||||||
|
plic_init();
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable SW and external interrupts */
|
/* Enable SW and external interrupts */
|
||||||
set_csr(mie, MIP_MSIP);
|
set_csr(mie, MIP_MSIP);
|
||||||
@ -70,30 +70,6 @@ void irq_init(void)
|
|||||||
set_csr(mstatus, MSTATUS_DEFAULT);
|
set_csr(mstatus, MSTATUS_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set External ISR callback
|
|
||||||
*/
|
|
||||||
void set_external_isr_cb(int intNum, external_isr_ptr_t cbFunc)
|
|
||||||
{
|
|
||||||
assert((intNum > 0) && (intNum < PLIC_NUM_INTERRUPTS));
|
|
||||||
|
|
||||||
_ext_isrs[intNum] = cbFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief External interrupt handler
|
|
||||||
*/
|
|
||||||
void external_isr(void)
|
|
||||||
{
|
|
||||||
uint32_t intNum = (uint32_t)PLIC_claim_interrupt();
|
|
||||||
|
|
||||||
if ((intNum > 0) && (intNum < PLIC_NUM_INTERRUPTS) && (_ext_isrs[intNum] != NULL)) {
|
|
||||||
_ext_isrs[intNum](intNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
PLIC_complete_interrupt(intNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Global trap and interrupt handler
|
* @brief Global trap and interrupt handler
|
||||||
*/
|
*/
|
||||||
@ -121,7 +97,9 @@ void handle_trap(uint32_t mcause)
|
|||||||
#endif
|
#endif
|
||||||
case IRQ_M_EXT:
|
case IRQ_M_EXT:
|
||||||
/* Handle external interrupt */
|
/* Handle external interrupt */
|
||||||
external_isr();
|
if (IS_ACTIVE(MODULE_PERIPH_PLIC)) {
|
||||||
|
plic_isr_handler();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
#include "periph_conf.h"
|
#include "periph_conf.h"
|
||||||
#include "periph/gpio.h"
|
#include "periph/gpio.h"
|
||||||
|
#include "plic.h"
|
||||||
#include "vendor/encoding.h"
|
#include "vendor/encoding.h"
|
||||||
#include "vendor/platform.h"
|
#include "vendor/platform.h"
|
||||||
#include "vendor/plic_driver.h"
|
#include "vendor/plic_driver.h"
|
||||||
@ -159,9 +160,9 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
|||||||
clear_csr(mie, MIP_MEIP);
|
clear_csr(mie, MIP_MEIP);
|
||||||
|
|
||||||
/* Configure GPIO ISR with PLIC */
|
/* Configure GPIO ISR with PLIC */
|
||||||
set_external_isr_cb(INT_GPIO_BASE + pin, gpio_isr);
|
plic_set_isr_cb(INT_GPIO_BASE + pin, gpio_isr);
|
||||||
PLIC_enable_interrupt(INT_GPIO_BASE + pin);
|
plic_enable_interrupt(INT_GPIO_BASE + pin);
|
||||||
PLIC_set_priority(INT_GPIO_BASE + pin, GPIO_INTR_PRIORITY);
|
plic_set_priority(INT_GPIO_BASE + pin, GPIO_INTR_PRIORITY);
|
||||||
|
|
||||||
/* Configure the active flank(s) */
|
/* Configure the active flank(s) */
|
||||||
gpio_irq_enable(pin);
|
gpio_irq_enable(pin);
|
||||||
|
|||||||
121
cpu/fe310/periph/plic.c
Normal file
121
cpu/fe310/periph/plic.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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_fe310
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Platform-Level interrupt controller driver
|
||||||
|
*
|
||||||
|
* @author Koen Zandberg <koen@bergzand.net>
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "vendor/encoding.h"
|
||||||
|
#include "vendor/platform.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "plic.h"
|
||||||
|
|
||||||
|
/* PLIC external ISR function list */
|
||||||
|
static plic_isr_cb_t _ext_isrs[PLIC_NUM_INTERRUPTS];
|
||||||
|
|
||||||
|
static inline volatile uint32_t *_get_claim_complete_addr(void)
|
||||||
|
{
|
||||||
|
uint32_t hart_id = read_csr(mhartid);
|
||||||
|
|
||||||
|
/* Construct the claim address */
|
||||||
|
return &PLIC_REG(PLIC_CLAIM_OFFSET +
|
||||||
|
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline volatile uint32_t *_get_threshold_addr(void)
|
||||||
|
{
|
||||||
|
uint32_t hart_id = read_csr(mhartid);
|
||||||
|
|
||||||
|
/* Construct the claim address */
|
||||||
|
return &PLIC_REG(PLIC_THRESHOLD_OFFSET +
|
||||||
|
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline volatile uint32_t *_get_irq_reg(unsigned irq)
|
||||||
|
{
|
||||||
|
uint32_t hart_id = read_csr(mhartid);
|
||||||
|
|
||||||
|
return &PLIC_REG(PLIC_ENABLE_OFFSET +
|
||||||
|
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)) +
|
||||||
|
(irq >> 5); /* Intentionally outside the PLIC_REG macro */
|
||||||
|
}
|
||||||
|
|
||||||
|
void plic_enable_interrupt(unsigned irq)
|
||||||
|
{
|
||||||
|
volatile uint32_t *irq_reg = _get_irq_reg(irq);
|
||||||
|
|
||||||
|
__atomic_fetch_or(irq_reg, 1 << (irq & 0x1f), __ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plic_disable_interrupt(unsigned irq)
|
||||||
|
{
|
||||||
|
volatile uint32_t *irq_reg = _get_irq_reg(irq);
|
||||||
|
|
||||||
|
__atomic_fetch_and(irq_reg, ~(1 << (irq & 0x1f)), __ATOMIC_RELAXED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plic_set_threshold(unsigned threshold)
|
||||||
|
{
|
||||||
|
volatile uint32_t *plic_threshold = _get_threshold_addr();
|
||||||
|
|
||||||
|
*plic_threshold = threshold;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void plic_set_priority(unsigned irq, unsigned priority)
|
||||||
|
{
|
||||||
|
assert(irq <= PLIC_NUM_INTERRUPTS);
|
||||||
|
assert(irq != 0);
|
||||||
|
*(&PLIC_REG(PLIC_PRIORITY_OFFSET) + irq) = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void plic_complete_interrupt(unsigned irq)
|
||||||
|
{
|
||||||
|
volatile uint32_t *complete_addr = _get_claim_complete_addr();
|
||||||
|
|
||||||
|
*complete_addr = irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned plic_claim_interrupt(void)
|
||||||
|
{
|
||||||
|
return *_get_claim_complete_addr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void plic_set_isr_cb(unsigned irq, plic_isr_cb_t cb)
|
||||||
|
{
|
||||||
|
assert(irq <= PLIC_NUM_INTERRUPTS);
|
||||||
|
assert(irq != 0);
|
||||||
|
_ext_isrs[irq] = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plic_init(void)
|
||||||
|
{
|
||||||
|
for (unsigned i = 1; i <= PLIC_NUM_INTERRUPTS; i++) {
|
||||||
|
plic_disable_interrupt(i);
|
||||||
|
plic_set_priority(i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
plic_set_threshold(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void plic_isr_handler(void)
|
||||||
|
{
|
||||||
|
unsigned irq = plic_claim_interrupt();
|
||||||
|
|
||||||
|
/* Don't check here, just crash hard if no handler is available */
|
||||||
|
_ext_isrs[irq](irq);
|
||||||
|
|
||||||
|
plic_complete_interrupt(irq);
|
||||||
|
}
|
||||||
@ -29,6 +29,7 @@
|
|||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
#include "periph_conf.h"
|
#include "periph_conf.h"
|
||||||
#include "periph/rtt.h"
|
#include "periph/rtt.h"
|
||||||
|
#include "plic.h"
|
||||||
#include "vendor/encoding.h"
|
#include "vendor/encoding.h"
|
||||||
#include "vendor/platform.h"
|
#include "vendor/platform.h"
|
||||||
#include "vendor/plic_driver.h"
|
#include "vendor/plic_driver.h"
|
||||||
@ -76,9 +77,9 @@ void rtt_init(void)
|
|||||||
clear_csr(mie, MIP_MEIP);
|
clear_csr(mie, MIP_MEIP);
|
||||||
|
|
||||||
/* Configure RTC ISR with PLIC */
|
/* Configure RTC ISR with PLIC */
|
||||||
set_external_isr_cb(INT_RTCCMP, rtt_isr);
|
plic_set_isr_cb(INT_RTCCMP, rtt_isr);
|
||||||
PLIC_enable_interrupt(INT_RTCCMP);
|
plic_enable_interrupt(INT_RTCCMP);
|
||||||
PLIC_set_priority(INT_RTCCMP, RTT_INTR_PRIORITY);
|
plic_set_priority(INT_RTCCMP, RTT_INTR_PRIORITY);
|
||||||
|
|
||||||
/* Configure RTC scaler, etc... */
|
/* Configure RTC scaler, etc... */
|
||||||
AON_REG(AON_RTCCFG) = RTT_SCALE;
|
AON_REG(AON_RTCCFG) = RTT_SCALE;
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "periph/uart.h"
|
#include "periph/uart.h"
|
||||||
|
#include "plic.h"
|
||||||
#include "vendor/encoding.h"
|
#include "vendor/encoding.h"
|
||||||
#include "vendor/platform.h"
|
#include "vendor/platform.h"
|
||||||
#include "vendor/plic_driver.h"
|
#include "vendor/plic_driver.h"
|
||||||
@ -111,9 +112,9 @@ int uart_init(uart_t dev, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
|||||||
clear_csr(mie, MIP_MEIP);
|
clear_csr(mie, MIP_MEIP);
|
||||||
|
|
||||||
/* Configure UART ISR with PLIC */
|
/* Configure UART ISR with PLIC */
|
||||||
set_external_isr_cb(uart_config[dev].isr_num, uart_isr);
|
plic_set_isr_cb(uart_config[dev].isr_num, uart_isr);
|
||||||
PLIC_enable_interrupt(uart_config[dev].isr_num);
|
plic_enable_interrupt(uart_config[dev].isr_num);
|
||||||
PLIC_set_priority(uart_config[dev].isr_num, UART_ISR_PRIO);
|
plic_set_priority(uart_config[dev].isr_num, UART_ISR_PRIO);
|
||||||
|
|
||||||
/* avoid trap by emptying RX FIFO */
|
/* avoid trap by emptying RX FIFO */
|
||||||
_drain(dev);
|
_drain(dev);
|
||||||
|
|||||||
153
cpu/fe310/vendor/plic_driver.c
vendored
153
cpu/fe310/vendor/plic_driver.c
vendored
@ -1,153 +0,0 @@
|
|||||||
// See LICENSE for license details.
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "vendor/encoding.h"
|
|
||||||
#include "vendor/platform.h"
|
|
||||||
#include "vendor/plic_driver.h"
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct __plic_instance_t
|
|
||||||
{
|
|
||||||
uintptr_t base_addr;
|
|
||||||
uint32_t num_sources;
|
|
||||||
uint32_t num_priorities;
|
|
||||||
|
|
||||||
} plic_instance_t;
|
|
||||||
|
|
||||||
|
|
||||||
// PLIC instance
|
|
||||||
static plic_instance_t _plic;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Note that there are no assertions or bounds checking on these
|
|
||||||
// parameter values.
|
|
||||||
|
|
||||||
void volatile_memzero(uint8_t * base, unsigned int size)
|
|
||||||
{
|
|
||||||
volatile uint8_t * ptr;
|
|
||||||
for (ptr = base; ptr < (base + size); ptr++){
|
|
||||||
*ptr = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PLIC_init (
|
|
||||||
uintptr_t base_addr,
|
|
||||||
uint32_t num_sources,
|
|
||||||
uint32_t num_priorities
|
|
||||||
)
|
|
||||||
{
|
|
||||||
plic_instance_t* this_plic = &_plic;
|
|
||||||
|
|
||||||
this_plic->base_addr = base_addr;
|
|
||||||
this_plic->num_sources = num_sources;
|
|
||||||
this_plic->num_priorities = num_priorities;
|
|
||||||
|
|
||||||
// Disable all interrupts (don't assume that these registers are reset).
|
|
||||||
unsigned long hart_id = read_csr(mhartid);
|
|
||||||
volatile_memzero((uint8_t*) (this_plic->base_addr +
|
|
||||||
PLIC_ENABLE_OFFSET +
|
|
||||||
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
|
|
||||||
(num_sources + 8) / 8);
|
|
||||||
|
|
||||||
// Set all priorities to 0 (equal priority -- don't assume that these are reset).
|
|
||||||
volatile_memzero ((uint8_t *)(this_plic->base_addr +
|
|
||||||
PLIC_PRIORITY_OFFSET),
|
|
||||||
(num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE);
|
|
||||||
|
|
||||||
// Set the threshold to 0.
|
|
||||||
volatile plic_threshold* threshold = (plic_threshold*)
|
|
||||||
(this_plic->base_addr +
|
|
||||||
PLIC_THRESHOLD_OFFSET +
|
|
||||||
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
|
|
||||||
|
|
||||||
*threshold = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PLIC_set_threshold (plic_threshold threshold)
|
|
||||||
{
|
|
||||||
plic_instance_t* this_plic = &_plic;
|
|
||||||
|
|
||||||
unsigned long hart_id = read_csr(mhartid);
|
|
||||||
volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
|
|
||||||
PLIC_THRESHOLD_OFFSET +
|
|
||||||
(hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
|
|
||||||
|
|
||||||
*threshold_ptr = threshold;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PLIC_enable_interrupt (plic_source source)
|
|
||||||
{
|
|
||||||
plic_instance_t* this_plic = &_plic;
|
|
||||||
|
|
||||||
unsigned long hart_id = read_csr(mhartid);
|
|
||||||
volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr +
|
|
||||||
PLIC_ENABLE_OFFSET +
|
|
||||||
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
|
||||||
(source >> 3));
|
|
||||||
uint8_t current = *current_ptr;
|
|
||||||
current = current | ( 1 << (source & 0x7));
|
|
||||||
*current_ptr = current;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PLIC_disable_interrupt (plic_source source)
|
|
||||||
{
|
|
||||||
plic_instance_t* this_plic = &_plic;
|
|
||||||
|
|
||||||
unsigned long hart_id = read_csr(mhartid);
|
|
||||||
volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr +
|
|
||||||
PLIC_ENABLE_OFFSET +
|
|
||||||
(hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
|
|
||||||
(source >> 3));
|
|
||||||
uint8_t current = *current_ptr;
|
|
||||||
current = current & ~(( 1 << (source & 0x7)));
|
|
||||||
*current_ptr = current;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PLIC_set_priority (plic_source source, plic_priority priority)
|
|
||||||
{
|
|
||||||
plic_instance_t* this_plic = &_plic;
|
|
||||||
|
|
||||||
if (this_plic->num_priorities > 0) {
|
|
||||||
volatile plic_priority * priority_ptr = (volatile plic_priority *)
|
|
||||||
(this_plic->base_addr +
|
|
||||||
PLIC_PRIORITY_OFFSET +
|
|
||||||
(source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
|
|
||||||
*priority_ptr = priority;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plic_source PLIC_claim_interrupt(void)
|
|
||||||
{
|
|
||||||
plic_instance_t* this_plic = &_plic;
|
|
||||||
|
|
||||||
unsigned long hart_id = read_csr(mhartid);
|
|
||||||
|
|
||||||
volatile plic_source * claim_addr = (volatile plic_source * )
|
|
||||||
(this_plic->base_addr +
|
|
||||||
PLIC_CLAIM_OFFSET +
|
|
||||||
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
|
||||||
|
|
||||||
return *claim_addr;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void PLIC_complete_interrupt(plic_source source)
|
|
||||||
{
|
|
||||||
plic_instance_t* this_plic = &_plic;
|
|
||||||
|
|
||||||
unsigned long hart_id = read_csr(mhartid);
|
|
||||||
volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
|
|
||||||
PLIC_CLAIM_OFFSET +
|
|
||||||
(hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
|
|
||||||
*claim_addr = source;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -180,6 +180,11 @@ config HAS_PERIPH_MCG
|
|||||||
help
|
help
|
||||||
Indicates that an MCG peripheral is present.
|
Indicates that an MCG peripheral is present.
|
||||||
|
|
||||||
|
config HAS_PERIPH_PLIC
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Indicates that a RISC-V Platform-local Interrupt Controller (PLIC) peripheral is present.
|
||||||
|
|
||||||
config HAS_PERIPH_PM
|
config HAS_PERIPH_PM
|
||||||
bool
|
bool
|
||||||
help
|
help
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user