Skip to content
Snippets Groups Projects
Commit 7d1d5e77 authored by kenrabold's avatar kenrabold
Browse files

cpu/fe310: add RISC-V cpu FE310

New CPU FE310 from SiFive based on RISC-V architecture

build: add makefile for RISC-V builds

Makefile for builds using RISC-V tools
parent a6ba0d85
No related branches found
No related tags found
No related merge requests found
Showing
with 2630 additions and 0 deletions
# define the module that is built
MODULE = cpu
# add a list of subdirectories, that should also be built
DIRS = periph nano vendor
include $(RIOTBASE)/Makefile.base
ifneq (,$(filter periph_rtc,$(USEMODULE)))
USEMODULE += periph_rtt
endif
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_pm
USEMODULE += newlib_nano
USEMODULE += newlib_syscalls_fe310
USEMODULE += sifive_drivers_fe310
USEMODULE += periph
USEMODULE += periph_pm
include $(RIOTMAKE)/arch/riscv.inc.mk
/*
* Copyright (C) 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @ingroup cpu
* @{
*
* @file
* @brief compile-time check of context_switch_frame offsets
*
* @author JP Bonn
* @}
*/
#include "context_frame.h"
#include "thread.h"
#define CHECK_OFFSET(member) \
_Static_assert(offsetof(struct context_switch_frame, member) == member ## _OFFSET, \
"context_switch_frame offset mismatch for offset member");
static void check_context_switch_frame_alignment(void) __attribute__ ((unused));
/**
* @brief Check size and offsets of context_switch_frame
*
* This does nothing at runtime. It is optimized out since it's only
* doing compile-time checks.
*/
static void check_context_switch_frame_alignment(void)
{
_Static_assert(sizeof(struct context_switch_frame) % 16 == 0,
"Stack pointer should be 16 byte aligned");
_Static_assert(sizeof(struct context_switch_frame) == CONTEXT_FRAME_SIZE,
"context_switch_frame size mismatch");
CHECK_OFFSET(filler0);
CHECK_OFFSET(filler1);
CHECK_OFFSET(pc);
CHECK_OFFSET(s0);
CHECK_OFFSET(s1);
CHECK_OFFSET(s2);
CHECK_OFFSET(s3);
CHECK_OFFSET(s4);
CHECK_OFFSET(s5);
CHECK_OFFSET(s6);
CHECK_OFFSET(s7);
CHECK_OFFSET(s8);
CHECK_OFFSET(s9);
CHECK_OFFSET(s10);
CHECK_OFFSET(s11);
CHECK_OFFSET(ra);
CHECK_OFFSET(tp);
CHECK_OFFSET(t0);
CHECK_OFFSET(t1);
CHECK_OFFSET(t2);
CHECK_OFFSET(t3);
CHECK_OFFSET(t4);
CHECK_OFFSET(t5);
CHECK_OFFSET(t6);
CHECK_OFFSET(a0);
CHECK_OFFSET(a1);
CHECK_OFFSET(a2);
CHECK_OFFSET(a3);
CHECK_OFFSET(a4);
CHECK_OFFSET(a5);
CHECK_OFFSET(a6);
CHECK_OFFSET(a7);
/*
* also check the SP offset in the _frame structure
*/
_Static_assert( offsetof(struct _thread, sp) == SP_OFFSET_IN_THREAD,
"Offset of SP in _thread mismatch");
}
/*
* Copyright (C) 2017 Ken Rabold, JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file cpu.c
* @brief Implementation of the CPU initialization for SiFive FE310
*
* @author Ken Rabold
* @}
*/
#include <stdio.h>
#include <errno.h>
#include "thread.h"
#include "irq.h"
#include "sched.h"
#include "thread.h"
#include "irq.h"
#include "cpu.h"
#include "context_frame.h"
#include "periph_cpu.h"
#include "panic.h"
#include "vendor/encoding.h"
#include "vendor/platform.h"
#include "vendor/plic_driver.h"
/* Default state of mstatus register */
#define MSTATUS_DEFAULT (MSTATUS_MPP | MSTATUS_MPIE)
volatile int __in_isr = 0;
void trap_entry(void);
void thread_start(void);
/* PLIC external ISR function list */
static external_isr_ptr_t _ext_isrs[PLIC_NUM_INTERRUPTS];
/* NULL interrupt handler */
void null_isr(int num)
{
(void) num;
}
/**
* @brief Initialize the CPU, set IRQ priorities, clocks
*/
void cpu_init(void)
{
volatile uint64_t *mtimecmp =
(uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
/* Setup trap handler function */
write_csr(mtvec, &trap_entry);
/* 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 */
}
/* Clear all interrupt enables */
write_csr(mie, 0);
/* Initial PLIC external interrupt controller */
PLIC_init(PLIC_CTRL_ADDR, PLIC_NUM_INTERRUPTS, PLIC_NUM_PRIORITIES);
/* Initialize ISR function list */
for (int i = 0; i < PLIC_NUM_INTERRUPTS; i++) {
_ext_isrs[i] = null_isr;
}
/* Set mtimecmp to largest value to avoid spurious timer interrupts */
*mtimecmp = 0xFFFFFFFFFFFFFFFF;
/* Enable SW, timer and external interrupts */
set_csr(mie, MIP_MSIP);
set_csr(mie, MIP_MTIP);
set_csr(mie, MIP_MEIP);
/* Set default state of mstatus */
set_csr(mstatus, MSTATUS_DEFAULT);
}
/**
* @brief Enable all maskable interrupts
*/
unsigned int irq_enable(void)
{
/* Enable all interrupts */
set_csr(mstatus, MSTATUS_MIE);
return read_csr(mstatus);
}
/**
* @brief Disable all maskable interrupts
*/
unsigned int irq_disable(void)
{
unsigned int state = read_csr(mstatus);
/* Disable all interrupts */
clear_csr(mstatus, MSTATUS_MIE);
return state;
}
/**
* @brief Restore the state of the IRQ flags
*/
void irq_restore(unsigned int state)
{
/* Restore all interrupts to given state */
write_csr(mstatus, state);
}
/**
* @brief See if the current context is inside an ISR
*/
int irq_is_in(void)
{
return __in_isr;
}
/**
* @brief Set External ISR callback
*/
void set_external_isr_cb(int intNum, external_isr_ptr_t cbFunc)
{
if ((intNum > 0) && (intNum < PLIC_NUM_INTERRUPTS)) {
_ext_isrs[intNum] = cbFunc;
}
}
/**
* @brief External interrupt handler
*/
void external_isr(void)
{
plic_source intNum = PLIC_claim_interrupt();
if ((intNum > 0) && (intNum < PLIC_NUM_INTERRUPTS)) {
_ext_isrs[intNum]((uint32_t) intNum);
}
PLIC_complete_interrupt(intNum);
}
/**
* @brief Global trap and interrupt handler
*/
void handle_trap(unsigned int mcause)
{
/* Tell RIOT to set sched_context_switch_request instead of
* calling thread_yield(). */
__in_isr = 1;
/* Check for INT or TRAP */
if ((mcause & MCAUSE_INT) == MCAUSE_INT) {
/* Cause is an interrupt - determine type */
switch (mcause & MCAUSE_CAUSE) {
#ifdef MODULE_PERIPH_TIMER
case IRQ_M_TIMER:
/* Handle timer interrupt */
timer_isr();
break;
#endif
case IRQ_M_EXT:
/* Handle external interrupt */
external_isr();
break;
default:
/* Unknown interrupt */
core_panic(PANIC_GENERAL_ERROR, "Unhandled interrupt");
break;
}
}
/* ISR done - no more changes to thread states */
__in_isr = 0;
}
/**
* @brief Noticeable marker marking the beginning of a stack segment
*
* This marker is used e.g. by *thread_start_threading* to identify the
* stacks beginning.
*/
#define STACK_MARKER (0x77777777)
/**
* @brief Initialize a thread's stack
*
* RIOT saves the tasks registers on the stack, not in the task control
* block. thread_stack_init() is responsible for allocating space for
* the registers on the stack and adjusting the stack pointer to account for
* the saved registers.
*
* The stack_start parameter is the bottom of the stack (low address). The
* return value is the top of stack: stack_start + stack_size - space reserved
* for thread context save - space reserved to align stack.
*
* thread_stack_init is called for each thread.
*
* RISCV ABI is here: https://github.com/riscv/riscv-elf-psabi-doc
* From ABI:
* The stack grows downwards and the stack pointer shall be aligned to a
* 128-bit boundary upon procedure entry, except for the RV32E ABI, where it
* need only be aligned to 32 bits. In the standard ABI, the stack pointer
* must remain aligned throughout procedure execution. Non-standard ABI code
* must realign the stack pointer prior to invoking standard ABI procedures.
* The operating system must realign the stack pointer prior to invoking a
* signal handler; hence, POSIX signal handlers need not realign the stack
* pointer. In systems that service interrupts using the interruptee's stack,
* the interrupt service routine must realign the stack pointer if linked
* with any code that uses a non-standard stack-alignment discipline, but
* need not realign the stack pointer if all code adheres to the standard ABI.
*
* @param[in] task_func pointer to the thread's code
* @param[in] arg argument to task_func
* @param[in] stack_start pointer to the start address of the thread
* @param[in] stack_size the maximum size of the stack
*
* @return pointer to the new top of the stack (128bit aligned)
*
*/
char *thread_stack_init(thread_task_func_t task_func,
void *arg,
void *stack_start,
int stack_size)
{
struct context_switch_frame *sf;
uint32_t *reg;
uint32_t *stk_top;
/* calculate the top of the stack */
stk_top = (uint32_t *)((uintptr_t)stack_start + stack_size);
/* Put a marker at the top of the stack. This is used by
* thread_stack_print to determine where to stop dumping the
* stack.
*/
stk_top--;
*stk_top = STACK_MARKER;
/* per ABI align stack pointer to 16 byte boundary. */
stk_top = (uint32_t *)(((uint32_t)stk_top) & ~((uint32_t)0xf));
/* reserve space for the stack frame. */
stk_top = (uint32_t *)((uint8_t *) stk_top - sizeof(*sf));
/* populate the stack frame with default values for starting the thread. */
sf = (struct context_switch_frame *) stk_top;
/* a7 is register with highest memory address in frame */
reg = &sf->a7;
while (reg != &sf->pc) {
*reg-- = 0;
}
sf->pc = (uint32_t) task_func;
sf->a0 = (uint32_t) arg;
/* if the thread exits go to sched_task_exit() */
sf->ra = (uint32_t) sched_task_exit;
return (char *) stk_top;
}
void thread_print_stack(void)
{
int count = 0;
uint32_t *sp = (uint32_t *) sched_active_thread->sp;
printf("printing the current stack of thread %" PRIkernel_pid "\n",
thread_getpid());
#ifdef DEVELHELP
printf("thread name: %s\n", sched_active_thread->name);
printf("stack start: 0x%08x\n", (unsigned int)(sched_active_thread->stack_start));
printf("stack end : 0x%08x\n", (unsigned int)(sched_active_thread->stack_start + sched_active_thread->stack_size));
#endif
printf(" address: data:\n");
do {
printf(" 0x%08x: 0x%08x\n", (unsigned int) sp, (unsigned int) *sp);
sp++;
count++;
} while (*sp != STACK_MARKER);
printf("current stack size: %i words\n", count);
}
int thread_isr_stack_usage(void)
{
return 0;
}
void *thread_isr_stack_pointer(void)
{
return NULL;
}
void *thread_isr_stack_start(void)
{
return NULL;
}
/**
* @brief Start or resume threading by loading a threads initial information
* from the stack.
*
* This is called is two situations: 1) after the initial main and idle threads
* have been created and 2) when a thread exits.
*
* sched_active_thread is not valid when cpu_switch_context_exit() is
* called. sched_run() must be called to determine the next valid thread.
* This is exploited in the context switch code.
*/
void cpu_switch_context_exit(void)
{
/* enable interrupts */
irq_enable();
/* start the thread */
thread_yield();
UNREACHABLE();
}
void thread_yield_higher(void)
{
/* Use SW intr to schedule context switch */
CLINT_REG(CLINT_MSIP) = 1;
}
/*
* Copyright (C) 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup cpu_fe310
* @ingroup cpu
* @brief Freedom E cpu
* @{
*
* @file
* @brief Thread context frame stored on stack.
*
* @author JP Bonn
*/
#ifndef CONTEXT_FRAME_H
#define CONTEXT_FRAME_H
#if !defined(__ASSEMBLER__)
#include <stdint.h>
#include <assert.h>
#endif /* __ASSEMBLER__ */
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief context_switch_frame stores the registers and PC for a context switch.
*
* This also defines context_switch_frame offsets for assembly language. The
* structure is sized to maintain 16 byte stack alignment per the ABI.
* https://github.com/riscv/riscv-elf-psabi-doc
*
*/
#if !defined(__ASSEMBLER__)
/* N.B.: update the definitions below if this changes */
struct context_switch_frame {
uint32_t filler0; /* filler to maintain 16 byte alignment */
uint32_t filler1; /* filler to maintain 16 byte alignment */
uint32_t pc;
/* Callee saved registers */
uint32_t s0;
uint32_t s1;
uint32_t s2;
uint32_t s3;
uint32_t s4;
uint32_t s5;
uint32_t s6;
uint32_t s7;
uint32_t s8;
uint32_t s9;
uint32_t s10;
uint32_t s11;
/* Caller saved register */
uint32_t ra;
uint32_t tp;
uint32_t t0;
uint32_t t1;
uint32_t t2;
uint32_t t3;
uint32_t t4;
uint32_t t5;
uint32_t t6;
uint32_t a0;
uint32_t a1;
uint32_t a2;
uint32_t a3;
uint32_t a4;
uint32_t a5;
uint32_t a6;
uint32_t a7;
};
#endif /* __ASSEMBLER__ */
/* These values are checked for correctness in context_frame.c */
#define filler0_OFFSET 0
#define filler1_OFFSET 4
#define pc_OFFSET 8
#define s0_OFFSET 12
#define s1_OFFSET 16
#define s2_OFFSET 20
#define s3_OFFSET 24
#define s4_OFFSET 28
#define s5_OFFSET 32
#define s6_OFFSET 36
#define s7_OFFSET 40
#define s8_OFFSET 44
#define s9_OFFSET 48
#define s10_OFFSET 52
#define s11_OFFSET 56
#define ra_OFFSET 60
#define tp_OFFSET 64
#define t0_OFFSET 68
#define t1_OFFSET 72
#define t2_OFFSET 76
#define t3_OFFSET 80
#define t4_OFFSET 84
#define t5_OFFSET 88
#define t6_OFFSET 92
#define a0_OFFSET 96
#define a1_OFFSET 100
#define a2_OFFSET 104
#define a3_OFFSET 108
#define a4_OFFSET 112
#define a5_OFFSET 116
#define a6_OFFSET 120
#define a7_OFFSET 124
#define CONTEXT_FRAME_SIZE (a7_OFFSET + 4)
#define SP_OFFSET_IN_THREAD 0
#ifdef __cplusplus
}
#endif
#endif /* CONTEXT_FRAME_H */
/** @} */
/*
* 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
* @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
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initialization of the CPU
*/
void cpu_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 */
/** @} */
/*
* 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
* @ingroup cpu
* @brief CPU specific implementations for the SiFive FE310 cpu
* @{
*
* @file
* @brief CPU specific configuration options
*
* @author Ken Rabold
*/
#ifndef CPU_CONF_H
#define CPU_CONF_H
#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
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* CPU_CONF_H */
/** @} */
/*
* Copyright (C) 2017 JP Bonn
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file
* @brief Functions to read CPU cycle counter
*
* @author JP Bonn
*/
#ifndef CPUCYCLE_H
#define CPUCYCLE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Returns a count of the number of clock cycles executed by the
* processor core on which the hart is running from an arbitrary
* start time in the past.
*/
uint64_t get_cycle_count(void);
#ifdef __cplusplus
}
#endif
#endif /* CPUCYCLE_H */
/** @} */
/*
* 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.
*/
/**
* @ingroup cpu_fe310
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author Ken Rabold
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Length of the CPU_ID in octets
*/
#define CPUID_LEN (12U)
/**
* @brief Timer ISR
*/
void timer_isr(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);
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */
This software, except as otherwise noted in subrepositories,
is licensed under the Apache 2 license, quoted below.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 SiFive, Inc.
Licensed 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.
// See LICENSE for license details.
#ifndef _SIFIVE_AON_H
#define _SIFIVE_AON_H
/* Register offsets */
#define AON_WDOGCFG 0x000
#define AON_WDOGCOUNT 0x008
#define AON_WDOGS 0x010
#define AON_WDOGFEED 0x018
#define AON_WDOGKEY 0x01C
#define AON_WDOGCMP 0x020
#define AON_RTCCFG 0x040
#define AON_RTCLO 0x048
#define AON_RTCHI 0x04C
#define AON_RTCS 0x050
#define AON_RTCCMP 0x060
#define AON_BACKUP0 0x080
#define AON_BACKUP1 0x084
#define AON_BACKUP2 0x088
#define AON_BACKUP3 0x08C
#define AON_BACKUP4 0x090
#define AON_BACKUP5 0x094
#define AON_BACKUP6 0x098
#define AON_BACKUP7 0x09C
#define AON_BACKUP8 0x0A0
#define AON_BACKUP9 0x0A4
#define AON_BACKUP10 0x0A8
#define AON_BACKUP11 0x0AC
#define AON_BACKUP12 0x0B0
#define AON_BACKUP13 0x0B4
#define AON_BACKUP14 0x0B8
#define AON_BACKUP15 0x0BC
#define AON_PMUWAKEUPI0 0x100
#define AON_PMUWAKEUPI1 0x104
#define AON_PMUWAKEUPI2 0x108
#define AON_PMUWAKEUPI3 0x10C
#define AON_PMUWAKEUPI4 0x110
#define AON_PMUWAKEUPI5 0x114
#define AON_PMUWAKEUPI6 0x118
#define AON_PMUWAKEUPI7 0x11C
#define AON_PMUSLEEPI0 0x120
#define AON_PMUSLEEPI1 0x124
#define AON_PMUSLEEPI2 0x128
#define AON_PMUSLEEPI3 0x12C
#define AON_PMUSLEEPI4 0x130
#define AON_PMUSLEEPI5 0x134
#define AON_PMUSLEEPI6 0x138
#define AON_PMUSLEEPI7 0x13C
#define AON_PMUIE 0x140
#define AON_PMUCAUSE 0x144
#define AON_PMUSLEEP 0x148
#define AON_PMUKEY 0x14C
#define AON_LFROSC 0x070
/* Constants */
#define AON_WDOGKEY_VALUE 0x51F15E
#define AON_WDOGFEED_VALUE 0xD09F00D
#define AON_WDOGCFG_SCALE 0x0000000F
#define AON_WDOGCFG_RSTEN 0x00000100
#define AON_WDOGCFG_ZEROCMP 0x00000200
#define AON_WDOGCFG_ENALWAYS 0x00001000
#define AON_WDOGCFG_ENCOREAWAKE 0x00002000
#define AON_WDOGCFG_CMPIP 0x10000000
#define AON_RTCCFG_SCALE 0x0000000F
#define AON_RTCCFG_ENALWAYS 0x00001000
#define AON_RTCCFG_CMPIP 0x10000000
#define AON_WAKEUPCAUSE_RESET 0x00
#define AON_WAKEUPCAUSE_RTC 0x01
#define AON_WAKEUPCAUSE_DWAKEUP 0x02
#define AON_WAKEUPCAUSE_AWAKEUP 0x03
#define AON_RESETCAUSE_POWERON 0x0000
#define AON_RESETCAUSE_EXTERNAL 0x0100
#define AON_RESETCAUSE_WATCHDOG 0x0200
#define AON_PMUCAUSE_WAKEUPCAUSE 0x00FF
#define AON_PMUCAUSE_RESETCAUSE 0xFF00
#endif /* _SIFIVE_AON_H */
// See LICENSE for license details
#ifndef _SIFIVE_CLINT_H
#define _SIFIVE_CLINT_H
#define CLINT_MSIP 0x0000
#define CLINT_MSIP_size 0x4
#define CLINT_MTIMECMP 0x4000
#define CLINT_MTIMECMP_size 0x8
#define CLINT_MTIME 0xBFF8
#define CLINT_MTIME_size 0x8
#endif /* _SIFIVE_CLINT_H */
This diff is collapsed.
// See LICENSE for license details.
#ifndef _SIFIVE_GPIO_H
#define _SIFIVE_GPIO_H
#define GPIO_INPUT_VAL (0x00)
#define GPIO_INPUT_EN (0x04)
#define GPIO_OUTPUT_EN (0x08)
#define GPIO_OUTPUT_VAL (0x0C)
#define GPIO_PULLUP_EN (0x10)
#define GPIO_DRIVE (0x14)
#define GPIO_RISE_IE (0x18)
#define GPIO_RISE_IP (0x1C)
#define GPIO_FALL_IE (0x20)
#define GPIO_FALL_IP (0x24)
#define GPIO_HIGH_IE (0x28)
#define GPIO_HIGH_IP (0x2C)
#define GPIO_LOW_IE (0x30)
#define GPIO_LOW_IP (0x34)
#define GPIO_IOF_EN (0x38)
#define GPIO_IOF_SEL (0x3C)
#define GPIO_OUTPUT_XOR (0x40)
#endif /* _SIFIVE_GPIO_H */
// See LICENSE for license details.
#ifndef _SIFIVE_OTP_H
#define _SIFIVE_OTP_H
/* Register offsets */
#define OTP_LOCK 0x00
#define OTP_CK 0x04
#define OTP_OE 0x08
#define OTP_SEL 0x0C
#define OTP_WE 0x10
#define OTP_MR 0x14
#define OTP_MRR 0x18
#define OTP_MPP 0x1C
#define OTP_VRREN 0x20
#define OTP_VPPEN 0x24
#define OTP_A 0x28
#define OTP_D 0x2C
#define OTP_Q 0x30
#define OTP_READ_TIMINGS 0x34
#endif
// See LICENSE for license details.
#ifndef _SIFIVE_PLATFORM_H
#define _SIFIVE_PLATFORM_H
// Some things missing from the official encoding.h
#define MCAUSE_INT 0x80000000
#define MCAUSE_CAUSE 0x7FFFFFFF
#include "vendor/aon.h"
#include "vendor/clint.h"
#include "vendor/gpio.h"
#include "vendor/otp.h"
#include "vendor/plic.h"
#include "vendor/prci.h"
#include "vendor/pwm.h"
#include "vendor/spi.h"
#include "vendor/uart.h"
/****************************************************************************
* Platform definitions
*****************************************************************************/
// Memory map
#define MASKROM_MEM_ADDR (0x00001000)
#define TRAPVEC_TABLE_CTRL_ADDR (0x00001010)
#define OTP_MEM_ADDR (0x00020000)
#define CLINT_CTRL_ADDR (0x02000000)
#define PLIC_CTRL_ADDR (0x0C000000)
#define AON_CTRL_ADDR (0x10000000)
#define PRCI_CTRL_ADDR (0x10008000)
#define OTP_CTRL_ADDR (0x10010000)
#define GPIO_CTRL_ADDR (0x10012000)
#define UART0_CTRL_ADDR (0x10013000)
#define SPI0_CTRL_ADDR (0x10014000)
#define PWM0_CTRL_ADDR (0x10015000)
#define UART1_CTRL_ADDR (0x10023000)
#define SPI1_CTRL_ADDR (0x10024000)
#define PWM1_CTRL_ADDR (0x10025000)
#define SPI2_CTRL_ADDR (0x10034000)
#define PWM2_CTRL_ADDR (0x10035000)
#define SPI0_MEM_ADDR (0x20000000)
#define MEM_CTRL_ADDR (0x80000000)
// IOF masks
#define IOF0_SPI1_MASK (0x000007FC)
#define SPI11_NUM_SS (4)
#define IOF_SPI1_SS0 (2u)
#define IOF_SPI1_SS1 (8u)
#define IOF_SPI1_SS2 (9u)
#define IOF_SPI1_SS3 (10u)
#define IOF_SPI1_MOSI (3u)
#define IOF_SPI1_MISO (4u)
#define IOF_SPI1_SCK (5u)
#define IOF_SPI1_DQ0 (3u)
#define IOF_SPI1_DQ1 (4u)
#define IOF_SPI1_DQ2 (6u)
#define IOF_SPI1_DQ3 (7u)
#define IOF0_SPI2_MASK (0xFC000000)
#define SPI2_NUM_SS (1)
#define IOF_SPI2_SS0 (26u)
#define IOF_SPI2_MOSI (27u)
#define IOF_SPI2_MISO (28u)
#define IOF_SPI2_SCK (29u)
#define IOF_SPI2_DQ0 (27u)
#define IOF_SPI2_DQ1 (28u)
#define IOF_SPI2_DQ2 (30u)
#define IOF_SPI2_DQ3 (31u)
//#define IOF0_I2C_MASK (0x00003000)
#define IOF0_UART0_MASK (0x00030000)
#define IOF_UART0_RX (16u)
#define IOF_UART0_TX (17u)
#define IOF0_UART1_MASK (0x03000000)
#define IOF_UART1_RX (24u)
#define IOF_UART1_TX (25u)
#define IOF1_PWM0_MASK (0x0000000F)
#define IOF1_PWM1_MASK (0x00780000)
#define IOF1_PWM2_MASK (0x00003C00)
// Interrupt numbers
#define INT_RESERVED 0
#define INT_WDOGCMP 1
#define INT_RTCCMP 2
#define INT_UART0_BASE 3
#define INT_UART1_BASE 4
#define INT_SPI0_BASE 5
#define INT_SPI1_BASE 6
#define INT_SPI2_BASE 7
#define INT_GPIO_BASE 8
#define INT_PWM0_BASE 40
#define INT_PWM1_BASE 44
#define INT_PWM2_BASE 48
// Helper functions
#define _REG32(p, i) (*(volatile uint32_t *) ((p) + (i)))
#define _REG32P(p, i) ((volatile uint32_t *) ((p) + (i)))
#define AON_REG(offset) _REG32(AON_CTRL_ADDR, offset)
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
#define OTP_REG(offset) _REG32(OTP_CTRL_ADDR, offset)
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
#define PRCI_REG(offset) _REG32(PRCI_CTRL_ADDR, offset)
#define PWM0_REG(offset) _REG32(PWM0_CTRL_ADDR, offset)
#define PWM1_REG(offset) _REG32(PWM1_CTRL_ADDR, offset)
#define PWM2_REG(offset) _REG32(PWM2_CTRL_ADDR, offset)
#define SPI0_REG(offset) _REG32(SPI0_CTRL_ADDR, offset)
#define SPI1_REG(offset) _REG32(SPI1_CTRL_ADDR, offset)
#define SPI2_REG(offset) _REG32(SPI2_CTRL_ADDR, offset)
#define UART0_REG(offset) _REG32(UART0_CTRL_ADDR, offset)
#define UART1_REG(offset) _REG32(UART1_CTRL_ADDR, offset)
// Misc
#define NUM_GPIO 32
#define PLIC_NUM_INTERRUPTS 52
#define PLIC_NUM_PRIORITIES 7
#define RTC_FREQ 32768
#endif /* _SIFIVE_PLATFORM_H */
// See LICENSE for license details.
#ifndef PLIC_H
#define PLIC_H
// 32 bits per source
#define PLIC_PRIORITY_OFFSET (0x0000)
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
// 1 bit per source (1 address)
#define PLIC_PENDING_OFFSET (0x1000)
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
//0x80 per target
#define PLIC_ENABLE_OFFSET (0x2000)
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
#define PLIC_THRESHOLD_OFFSET (0x200000)
#define PLIC_CLAIM_OFFSET (0x200004)
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
#define PLIC_MAX_SOURCE 1023
#define PLIC_SOURCE_MASK 0x3FF
#define PLIC_MAX_TARGET 15871
#define PLIC_TARGET_MASK 0x3FFF
#endif /* PLIC_H */
// See LICENSE file for licence details
#ifndef PLIC_DRIVER_H
#define PLIC_DRIVER_H
typedef uint32_t plic_source;
typedef uint32_t plic_priority;
typedef uint32_t plic_threshold;
void PLIC_init (
uintptr_t base_addr,
uint32_t num_sources,
uint32_t num_priorities
);
void PLIC_set_threshold (plic_threshold threshold);
void PLIC_enable_interrupt (plic_source source);
void PLIC_disable_interrupt (plic_source source);
void PLIC_set_priority (
plic_source source,
plic_priority priority);
plic_source PLIC_claim_interrupt(void);
void PLIC_complete_interrupt(plic_source source);
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment