mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 09:38:32 -04:00
Add starting point for IGLOO2 RISV-V demo project.
This commit is contained in:
parent
483f4a8c4b
commit
9119e1e0e3
42 changed files with 13068 additions and 0 deletions
|
@ -0,0 +1,596 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file encodings.h
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Mi-V soft processor register bit mask and shift constants encodings.
|
||||
*
|
||||
* SVN $Revision: 9825 $
|
||||
* SVN $Date: 2018-03-19 10:31:41 +0530 (Mon, 19 Mar 2018) $
|
||||
*/
|
||||
#ifndef RISCV_CSR_ENCODING_H
|
||||
#define RISCV_CSR_ENCODING_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MSTATUS_UIE 0x00000001
|
||||
#define MSTATUS_SIE 0x00000002
|
||||
#define MSTATUS_HIE 0x00000004
|
||||
#define MSTATUS_MIE 0x00000008
|
||||
#define MSTATUS_UPIE 0x00000010
|
||||
#define MSTATUS_SPIE 0x00000020
|
||||
#define MSTATUS_HPIE 0x00000040
|
||||
#define MSTATUS_MPIE 0x00000080
|
||||
#define MSTATUS_SPP 0x00000100
|
||||
#define MSTATUS_HPP 0x00000600
|
||||
#define MSTATUS_MPP 0x00001800
|
||||
#define MSTATUS_FS 0x00006000
|
||||
#define MSTATUS_XS 0x00018000
|
||||
#define MSTATUS_MPRV 0x00020000
|
||||
#define MSTATUS_SUM 0x00040000 /*changed in v1.10*/
|
||||
#define MSTATUS_MXR 0x00080000 /*changed in v1.10*/
|
||||
#define MSTATUS_TVM 0x00100000 /*changed in v1.10*/
|
||||
#define MSTATUS_TW 0x00200000 /*changed in v1.10*/
|
||||
#define MSTATUS_TSR 0x00400000 /*changed in v1.10*/
|
||||
#define MSTATUS_RES 0x7F800000 /*changed in v1.10*/
|
||||
#define MSTATUS32_SD 0x80000000
|
||||
#define MSTATUS64_SD 0x8000000000000000
|
||||
|
||||
#define MCAUSE32_CAUSE 0x7FFFFFFF
|
||||
#define MCAUSE64_CAUSE 0x7FFFFFFFFFFFFFFF
|
||||
#define MCAUSE32_INT 0x80000000
|
||||
#define MCAUSE64_INT 0x8000000000000000
|
||||
|
||||
#define SSTATUS_UIE 0x00000001
|
||||
#define SSTATUS_SIE 0x00000002
|
||||
#define SSTATUS_UPIE 0x00000010
|
||||
#define SSTATUS_SPIE 0x00000020
|
||||
#define SSTATUS_SPP 0x00000100
|
||||
#define SSTATUS_FS 0x00006000
|
||||
#define SSTATUS_XS 0x00018000
|
||||
#define SSTATUS_PUM 0x00040000
|
||||
#define SSTATUS32_SD 0x80000000
|
||||
#define SSTATUS64_SD 0x8000000000000000
|
||||
|
||||
#define MIP_SSIP (1u << IRQ_S_SOFT)
|
||||
#define MIP_HSIP (1u << IRQ_H_SOFT)
|
||||
#define MIP_MSIP (1u << IRQ_M_SOFT)
|
||||
#define MIP_STIP (1u << IRQ_S_TIMER)
|
||||
#define MIP_HTIP (1u << IRQ_H_TIMER)
|
||||
#define MIP_MTIP (1u << IRQ_M_TIMER)
|
||||
#define MIP_SEIP (1u << IRQ_S_EXT)
|
||||
#define MIP_HEIP (1u << IRQ_H_EXT)
|
||||
#define MIP_MEIP (1u << IRQ_M_EXT)
|
||||
|
||||
#define SIP_SSIP MIP_SSIP
|
||||
#define SIP_STIP MIP_STIP
|
||||
|
||||
#define PRV_U 0
|
||||
#define PRV_S 1
|
||||
#define PRV_H 2
|
||||
#define PRV_M 3
|
||||
|
||||
#define VM_MBARE 0
|
||||
#define VM_MBB 1
|
||||
#define VM_MBBID 2
|
||||
#define VM_SV32 8
|
||||
#define VM_SV39 9
|
||||
#define VM_SV48 10
|
||||
|
||||
#define IRQ_S_SOFT 1
|
||||
#define IRQ_H_SOFT 2
|
||||
#define IRQ_M_SOFT 3
|
||||
#define IRQ_S_TIMER 5
|
||||
#define IRQ_H_TIMER 6
|
||||
#define IRQ_M_TIMER 7
|
||||
#define IRQ_S_EXT 9
|
||||
#define IRQ_H_EXT 10
|
||||
#define IRQ_M_EXT 11
|
||||
|
||||
#define DEFAULT_RSTVEC 0x00001000
|
||||
#define DEFAULT_NMIVEC 0x00001004
|
||||
#define DEFAULT_MTVEC 0x00001010
|
||||
#define CONFIG_STRING_ADDR 0x0000100C
|
||||
#define EXT_IO_BASE 0x40000000
|
||||
#define DRAM_BASE 0x80000000
|
||||
|
||||
/* page table entry (PTE) fields */
|
||||
#define PTE_V 0x001 /* Valid */
|
||||
#define PTE_TYPE 0x01E /* Type */
|
||||
#define PTE_R 0x020 /* Referenced */
|
||||
#define PTE_D 0x040 /* Dirty */
|
||||
#define PTE_SOFT 0x380 /* Reserved for Software */
|
||||
|
||||
#define PTE_TYPE_TABLE 0x00
|
||||
#define PTE_TYPE_TABLE_GLOBAL 0x02
|
||||
#define PTE_TYPE_URX_SR 0x04
|
||||
#define PTE_TYPE_URWX_SRW 0x06
|
||||
#define PTE_TYPE_UR_SR 0x08
|
||||
#define PTE_TYPE_URW_SRW 0x0A
|
||||
#define PTE_TYPE_URX_SRX 0x0C
|
||||
#define PTE_TYPE_URWX_SRWX 0x0E
|
||||
#define PTE_TYPE_SR 0x10
|
||||
#define PTE_TYPE_SRW 0x12
|
||||
#define PTE_TYPE_SRX 0x14
|
||||
#define PTE_TYPE_SRWX 0x16
|
||||
#define PTE_TYPE_SR_GLOBAL 0x18
|
||||
#define PTE_TYPE_SRW_GLOBAL 0x1A
|
||||
#define PTE_TYPE_SRX_GLOBAL 0x1C
|
||||
#define PTE_TYPE_SRWX_GLOBAL 0x1E
|
||||
|
||||
#define PTE_PPN_SHIFT 10
|
||||
|
||||
#define PTE_TABLE(PTE) ((0x0000000AU >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_UR(PTE) ((0x0000AAA0U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_UW(PTE) ((0x00008880U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_UX(PTE) ((0x0000A0A0U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_SR(PTE) ((0xAAAAAAA0U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_SW(PTE) ((0x88888880U >> ((PTE) & 0x1F)) & 1)
|
||||
#define PTE_SX(PTE) ((0xA0A0A000U >> ((PTE) & 0x1F)) & 1)
|
||||
|
||||
#define PTE_CHECK_PERM(PTE, SUPERVISOR, STORE, FETCH) \
|
||||
((STORE) ? ((SUPERVISOR) ? PTE_SW(PTE) : PTE_UW(PTE)) : \
|
||||
(FETCH) ? ((SUPERVISOR) ? PTE_SX(PTE) : PTE_UX(PTE)) : \
|
||||
((SUPERVISOR) ? PTE_SR(PTE) : PTE_UR(PTE)))
|
||||
|
||||
#ifdef __riscv
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
# define MSTATUS_SD MSTATUS64_SD
|
||||
# define SSTATUS_SD SSTATUS64_SD
|
||||
# define MCAUSE_INT MCAUSE64_INT
|
||||
# define MCAUSE_CAUSE MCAUSE64_CAUSE
|
||||
# define RISCV_PGLEVEL_BITS 9
|
||||
#else
|
||||
# define MSTATUS_SD MSTATUS32_SD
|
||||
# define SSTATUS_SD SSTATUS32_SD
|
||||
# define RISCV_PGLEVEL_BITS 10
|
||||
# define MCAUSE_INT MCAUSE32_INT
|
||||
# define MCAUSE_CAUSE MCAUSE32_CAUSE
|
||||
#endif
|
||||
|
||||
#define RISCV_PGSHIFT 12
|
||||
#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define read_csr(reg) ({ unsigned long __tmp; \
|
||||
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
__tmp; })
|
||||
|
||||
#define write_csr(reg, val) ({ \
|
||||
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
|
||||
|
||||
#define swap_csr(reg, val) ({ unsigned long __tmp; \
|
||||
if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
|
||||
asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \
|
||||
else \
|
||||
asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
|
||||
__tmp; })
|
||||
|
||||
#define set_csr(reg, bit) ({ unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; })
|
||||
|
||||
#define clear_csr(reg, bit) ({ unsigned long __tmp; \
|
||||
if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
|
||||
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
|
||||
else \
|
||||
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
|
||||
__tmp; })
|
||||
|
||||
#define rdtime() read_csr(time)
|
||||
#define rdcycle() read_csr(cycle)
|
||||
#define rdinstret() read_csr(instret)
|
||||
|
||||
#ifdef __riscv_atomic
|
||||
|
||||
#define MASK(nr) (1UL << nr)
|
||||
#define MASK_NOT(nr) (~(1UL << nr))
|
||||
|
||||
/**
|
||||
* atomic_read - read atomic variable
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically reads the value of @v.
|
||||
*/
|
||||
static inline int atomic_read(const int *v)
|
||||
{
|
||||
return *((volatile int *)(v));
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_set - set atomic variable
|
||||
* @v: pointer of type int
|
||||
* @i: required value
|
||||
*
|
||||
* Atomically sets the value of @v to @i.
|
||||
*/
|
||||
static inline void atomic_set(int *v, int i)
|
||||
{
|
||||
*v = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_add - add integer to atomic variable
|
||||
* @i: integer value to add
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically adds @i to @v.
|
||||
*/
|
||||
static inline void atomic_add(int i, int *v)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"amoadd.w zero, %1, %0"
|
||||
: "+A" (*v)
|
||||
: "r" (i));
|
||||
}
|
||||
|
||||
static inline int atomic_fetch_add(unsigned int mask, int *v)
|
||||
{
|
||||
int out;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"amoadd.w %2, %1, %0"
|
||||
: "+A" (*v), "=r" (out)
|
||||
: "r" (mask));
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_sub - subtract integer from atomic variable
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically subtracts @i from @v.
|
||||
*/
|
||||
static inline void atomic_sub(int i, int *v)
|
||||
{
|
||||
atomic_add(-i, v);
|
||||
}
|
||||
|
||||
static inline int atomic_fetch_sub(unsigned int mask, int *v)
|
||||
{
|
||||
int out;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"amosub.w %2, %1, %0"
|
||||
: "+A" (*v), "=r" (out)
|
||||
: "r" (mask));
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_add_return - add integer to atomic variable
|
||||
* @i: integer value to add
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically adds @i to @v and returns the result
|
||||
*/
|
||||
static inline int atomic_add_return(int i, int *v)
|
||||
{
|
||||
register int c;
|
||||
__asm__ __volatile__ (
|
||||
"amoadd.w %0, %2, %1"
|
||||
: "=r" (c), "+A" (*v)
|
||||
: "r" (i));
|
||||
return (c + i);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_sub_return - subtract integer from atomic variable
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically subtracts @i from @v and returns the result
|
||||
*/
|
||||
static inline int atomic_sub_return(int i, int *v)
|
||||
{
|
||||
return atomic_add_return(-i, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_inc - increment atomic variable
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically increments @v by 1.
|
||||
*/
|
||||
static inline void atomic_inc(int *v)
|
||||
{
|
||||
atomic_add(1, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_dec - decrement atomic variable
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically decrements @v by 1.
|
||||
*/
|
||||
static inline void atomic_dec(int *v)
|
||||
{
|
||||
atomic_add(-1, v);
|
||||
}
|
||||
|
||||
static inline int atomic_inc_return(int *v)
|
||||
{
|
||||
return atomic_add_return(1, v);
|
||||
}
|
||||
|
||||
static inline int atomic_dec_return(int *v)
|
||||
{
|
||||
return atomic_sub_return(1, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_sub_and_test - subtract value from variable and test result
|
||||
* @i: integer value to subtract
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically subtracts @i from @v and returns
|
||||
* true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
static inline int atomic_sub_and_test(int i, int *v)
|
||||
{
|
||||
return (atomic_sub_return(i, v) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_inc_and_test - increment and test
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically increments @v by 1
|
||||
* and returns true if the result is zero, or false for all
|
||||
* other cases.
|
||||
*/
|
||||
static inline int atomic_inc_and_test(int *v)
|
||||
{
|
||||
return (atomic_inc_return(v) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_dec_and_test - decrement and test
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically decrements @v by 1 and
|
||||
* returns true if the result is 0, or false for all other
|
||||
* cases.
|
||||
*/
|
||||
static inline int atomic_dec_and_test(int *v)
|
||||
{
|
||||
return (atomic_dec_return(v) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_add_negative - add and test if negative
|
||||
* @i: integer value to add
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically adds @i to @v and returns true
|
||||
* if the result is negative, or false when
|
||||
* result is greater than or equal to zero.
|
||||
*/
|
||||
static inline int atomic_add_negative(int i, int *v)
|
||||
{
|
||||
return (atomic_add_return(i, v) < 0);
|
||||
}
|
||||
|
||||
static inline int atomic_xchg(int *v, int n)
|
||||
{
|
||||
register int c;
|
||||
__asm__ __volatile__ (
|
||||
"amoswap.w %0, %2, %1"
|
||||
: "=r" (c), "+A" (*v)
|
||||
: "r" (n));
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_and - Atomically clear bits in atomic variable
|
||||
* @mask: Mask of the bits to be retained
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically retains the bits set in @mask from @v
|
||||
*/
|
||||
static inline void atomic_and(unsigned int mask, int *v)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"amoand.w zero, %1, %0"
|
||||
: "+A" (*v)
|
||||
: "r" (mask));
|
||||
}
|
||||
|
||||
static inline int atomic_fetch_and(unsigned int mask, int *v)
|
||||
{
|
||||
int out;
|
||||
__asm__ __volatile__ (
|
||||
"amoand.w %2, %1, %0"
|
||||
: "+A" (*v), "=r" (out)
|
||||
: "r" (mask));
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_or - Atomically set bits in atomic variable
|
||||
* @mask: Mask of the bits to be set
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically sets the bits set in @mask in @v
|
||||
*/
|
||||
static inline void atomic_or(unsigned int mask, int *v)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"amoor.w zero, %1, %0"
|
||||
: "+A" (*v)
|
||||
: "r" (mask));
|
||||
}
|
||||
|
||||
static inline int atomic_fetch_or(unsigned int mask, int *v)
|
||||
{
|
||||
int out;
|
||||
__asm__ __volatile__ (
|
||||
"amoor.w %2, %1, %0"
|
||||
: "+A" (*v), "=r" (out)
|
||||
: "r" (mask));
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* atomic_xor - Atomically flips bits in atomic variable
|
||||
* @mask: Mask of the bits to be flipped
|
||||
* @v: pointer of type int
|
||||
*
|
||||
* Atomically flips the bits set in @mask in @v
|
||||
*/
|
||||
static inline void atomic_xor(unsigned int mask, int *v)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"amoxor.w zero, %1, %0"
|
||||
: "+A" (*v)
|
||||
: "r" (mask));
|
||||
}
|
||||
|
||||
static inline int atomic_fetch_xor(unsigned int mask, int *v)
|
||||
{
|
||||
int out;
|
||||
__asm__ __volatile__ (
|
||||
"amoxor.w %2, %1, %0"
|
||||
: "+A" (*v), "=r" (out)
|
||||
: "r" (mask));
|
||||
return out;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long __res, __mask;
|
||||
__mask = MASK(nr);
|
||||
__asm__ __volatile__ ( \
|
||||
"amoor.w %0, %2, %1" \
|
||||
: "=r" (__res), "+A" (*addr) \
|
||||
: "r" (__mask)); \
|
||||
|
||||
return ((__res & __mask) != 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long __res, __mask;
|
||||
__mask = MASK_NOT(nr);
|
||||
__asm__ __volatile__ ( \
|
||||
"amoand.w %0, %2, %1" \
|
||||
: "=r" (__res), "+A" (*addr) \
|
||||
: "r" (__mask)); \
|
||||
|
||||
return ((__res & __mask) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its old value
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to count from
|
||||
*
|
||||
* This operation is atomic and cannot be reordered.
|
||||
* It also implies a memory barrier.
|
||||
*/
|
||||
static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
|
||||
unsigned long __res, __mask;
|
||||
__mask = MASK(nr);
|
||||
__asm__ __volatile__ ( \
|
||||
"amoxor.w %0, %2, %1" \
|
||||
: "=r" (__res), "+A" (*addr) \
|
||||
: "r" (__mask)); \
|
||||
|
||||
return ((__res & __mask) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bit - Atomically set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* This function is atomic and may not be reordered.
|
||||
*/
|
||||
|
||||
static inline void set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
__asm__ __volatile__ ( \
|
||||
"AMOOR.w zero, %1, %0" \
|
||||
: "+A" (*addr) \
|
||||
: "r" (MASK(nr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* clear_bit() is atomic and may not be reordered.
|
||||
*/
|
||||
static inline void clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
__asm__ __volatile__ ( \
|
||||
"AMOAND.w zero, %1, %0" \
|
||||
: "+A" (*addr) \
|
||||
: "r" (MASK_NOT(nr)));
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to start counting from
|
||||
*
|
||||
* change_bit() is atomic and may not be reordered.
|
||||
*/
|
||||
static inline void change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
__asm__ __volatile__ ( \
|
||||
"AMOXOR.w zero, %1, %0" \
|
||||
: "+A" (*addr) \
|
||||
: "r" (MASK(nr)));
|
||||
}
|
||||
|
||||
#endif /* __riscv_atomic */
|
||||
|
||||
#endif /*__GNUC__*/
|
||||
|
||||
#endif /*__ASSEMBLER__*/
|
||||
|
||||
#endif /*__riscv*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*RISCV_CSR_ENCODING_H*/
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file entry.S
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Mi-V soft processor vectors, trap handling and startup code.
|
||||
*
|
||||
* SVN $Revision: 9947 $
|
||||
* SVN $Date: 2018-04-30 20:28:49 +0530 (Mon, 30 Apr 2018) $
|
||||
*/
|
||||
#ifndef ENTRY_S
|
||||
#define ENTRY_S
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
# define LREG ld
|
||||
# define SREG sd
|
||||
# define REGBYTES 8
|
||||
#else
|
||||
# define LREG lw
|
||||
# define SREG sw
|
||||
# define REGBYTES 4
|
||||
#endif
|
||||
|
||||
.section .text.entry
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
j handle_reset
|
||||
|
||||
nmi_vector:
|
||||
j nmi_vector
|
||||
|
||||
trap_vector:
|
||||
j trap_entry
|
||||
|
||||
handle_reset:
|
||||
la t0, trap_entry
|
||||
csrw mtvec, t0
|
||||
csrwi mstatus, 0
|
||||
csrwi mie, 0
|
||||
|
||||
/*Floating point support configuration*/
|
||||
|
||||
#ifdef __riscv_flen
|
||||
csrr t0, mstatus
|
||||
lui t1, 0xffffa
|
||||
addi t1, t1, -1
|
||||
and t0, t0, t1
|
||||
lui t1, 0x4
|
||||
or t1, t0, t1
|
||||
csrw mstatus, t1
|
||||
|
||||
lui t0, 0x0
|
||||
fscsr t0
|
||||
#endif
|
||||
.option push
|
||||
|
||||
# Ensure the instruction is not optimized, since gp is not yet set
|
||||
|
||||
.option norelax
|
||||
# initialize global pointer
|
||||
la gp, __global_pointer$
|
||||
|
||||
.option pop
|
||||
|
||||
# initialize stack pointer
|
||||
la sp, __stack_top
|
||||
|
||||
# perform the rest of initialization in C
|
||||
j _init
|
||||
|
||||
|
||||
trap_entry:
|
||||
addi sp, sp, -32*REGBYTES
|
||||
|
||||
SREG x1, 0 * REGBYTES(sp)
|
||||
SREG x2, 1 * REGBYTES(sp)
|
||||
SREG x3, 2 * REGBYTES(sp)
|
||||
SREG x4, 3 * REGBYTES(sp)
|
||||
SREG x5, 4 * REGBYTES(sp)
|
||||
SREG x6, 5 * REGBYTES(sp)
|
||||
SREG x7, 6 * REGBYTES(sp)
|
||||
SREG x8, 7 * REGBYTES(sp)
|
||||
SREG x9, 8 * REGBYTES(sp)
|
||||
SREG x10, 9 * REGBYTES(sp)
|
||||
SREG x11, 10 * REGBYTES(sp)
|
||||
SREG x12, 11 * REGBYTES(sp)
|
||||
SREG x13, 12 * REGBYTES(sp)
|
||||
SREG x14, 13 * REGBYTES(sp)
|
||||
SREG x15, 14 * REGBYTES(sp)
|
||||
SREG x16, 15 * REGBYTES(sp)
|
||||
SREG x17, 16 * REGBYTES(sp)
|
||||
SREG x18, 17 * REGBYTES(sp)
|
||||
SREG x19, 18 * REGBYTES(sp)
|
||||
SREG x20, 19 * REGBYTES(sp)
|
||||
SREG x21, 20 * REGBYTES(sp)
|
||||
SREG x22, 21 * REGBYTES(sp)
|
||||
SREG x23, 22 * REGBYTES(sp)
|
||||
SREG x24, 23 * REGBYTES(sp)
|
||||
SREG x25, 24 * REGBYTES(sp)
|
||||
SREG x26, 25 * REGBYTES(sp)
|
||||
SREG x27, 26 * REGBYTES(sp)
|
||||
SREG x28, 27 * REGBYTES(sp)
|
||||
SREG x29, 28 * REGBYTES(sp)
|
||||
SREG x30, 29 * REGBYTES(sp)
|
||||
SREG x31, 30 * REGBYTES(sp)
|
||||
|
||||
|
||||
csrr t0, mepc
|
||||
SREG t0, 31 * REGBYTES(sp)
|
||||
|
||||
csrr a0, mcause
|
||||
csrr a1, mepc
|
||||
mv a2, sp
|
||||
jal handle_trap
|
||||
csrw mepc, a0
|
||||
|
||||
# Remain in M-mode after mret
|
||||
li t0, MSTATUS_MPP
|
||||
csrs mstatus, t0
|
||||
|
||||
LREG x1, 0 * REGBYTES(sp)
|
||||
LREG x2, 1 * REGBYTES(sp)
|
||||
LREG x3, 2 * REGBYTES(sp)
|
||||
LREG x4, 3 * REGBYTES(sp)
|
||||
LREG x5, 4 * REGBYTES(sp)
|
||||
LREG x6, 5 * REGBYTES(sp)
|
||||
LREG x7, 6 * REGBYTES(sp)
|
||||
LREG x8, 7 * REGBYTES(sp)
|
||||
LREG x9, 8 * REGBYTES(sp)
|
||||
LREG x10, 9 * REGBYTES(sp)
|
||||
LREG x11, 10 * REGBYTES(sp)
|
||||
LREG x12, 11 * REGBYTES(sp)
|
||||
LREG x13, 12 * REGBYTES(sp)
|
||||
LREG x14, 13 * REGBYTES(sp)
|
||||
LREG x15, 14 * REGBYTES(sp)
|
||||
LREG x16, 15 * REGBYTES(sp)
|
||||
LREG x17, 16 * REGBYTES(sp)
|
||||
LREG x18, 17 * REGBYTES(sp)
|
||||
LREG x19, 18 * REGBYTES(sp)
|
||||
LREG x20, 19 * REGBYTES(sp)
|
||||
LREG x21, 20 * REGBYTES(sp)
|
||||
LREG x22, 21 * REGBYTES(sp)
|
||||
LREG x23, 22 * REGBYTES(sp)
|
||||
LREG x24, 23 * REGBYTES(sp)
|
||||
LREG x25, 24 * REGBYTES(sp)
|
||||
LREG x26, 25 * REGBYTES(sp)
|
||||
LREG x27, 26 * REGBYTES(sp)
|
||||
LREG x28, 27 * REGBYTES(sp)
|
||||
LREG x29, 28 * REGBYTES(sp)
|
||||
LREG x30, 29 * REGBYTES(sp)
|
||||
LREG x31, 30 * REGBYTES(sp)
|
||||
|
||||
addi sp, sp, 32*REGBYTES
|
||||
mret
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file init.c
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Mi-V soft processor memory section initializations and start-up code.
|
||||
*
|
||||
* SVN $Revision: 9661 $
|
||||
* SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern uint32_t __sdata_load;
|
||||
extern uint32_t __sdata_start;
|
||||
extern uint32_t __sdata_end;
|
||||
|
||||
extern uint32_t __data_load;
|
||||
extern uint32_t __data_start;
|
||||
extern uint32_t __data_end;
|
||||
|
||||
extern uint32_t __sbss_start;
|
||||
extern uint32_t __sbss_end;
|
||||
extern uint32_t __bss_start;
|
||||
extern uint32_t __bss_end;
|
||||
|
||||
|
||||
static void copy_section(uint32_t * p_load, uint32_t * p_vma, uint32_t * p_vma_end)
|
||||
{
|
||||
while(p_vma <= p_vma_end)
|
||||
{
|
||||
*p_vma = *p_load;
|
||||
++p_load;
|
||||
++p_vma;
|
||||
}
|
||||
}
|
||||
|
||||
static void zero_section(uint32_t * start, uint32_t * end)
|
||||
{
|
||||
uint32_t * p_zero = start;
|
||||
|
||||
while(p_zero <= end)
|
||||
{
|
||||
*p_zero = 0;
|
||||
++p_zero;
|
||||
}
|
||||
}
|
||||
|
||||
void _init(void)
|
||||
{
|
||||
extern int main(int, char**);
|
||||
const char *argv0 = "hello";
|
||||
char *argv[] = {(char *)argv0, NULL, NULL};
|
||||
|
||||
copy_section(&__sdata_load, &__sdata_start, &__sdata_end);
|
||||
copy_section(&__data_load, &__data_start, &__data_end);
|
||||
zero_section(&__sbss_start, &__sbss_end);
|
||||
zero_section(&__bss_start, &__bss_end);
|
||||
|
||||
main(1, argv);
|
||||
}
|
||||
|
||||
/* Function called after main() finishes */
|
||||
void
|
||||
_fini()
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* file name : microsemi-riscv-igloo2.ld
|
||||
* Mi-V soft processor linker script for creating a SoftConsole downloadable
|
||||
* image executing in eNVM.
|
||||
*
|
||||
* This linker script assumes that the eNVM is connected at on the Mi-V soft
|
||||
* processor memory space.
|
||||
*
|
||||
* SVN $Revision: 9661 $
|
||||
* SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
|
||||
MEMORY
|
||||
{
|
||||
envm (rx) : ORIGIN = 0x60000000, LENGTH = 240k
|
||||
ram (rwx) : ORIGIN = 0x80000000, LENGTH = 64k
|
||||
}
|
||||
|
||||
RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
|
||||
RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
|
||||
STACK_SIZE = 2k; /* needs to be calculated for your application */
|
||||
HEAP_SIZE = 2k; /* needs to be calculated for your application */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : ALIGN(0x10)
|
||||
{
|
||||
KEEP (*(SORT_NONE(.text.entry)))
|
||||
. = ALIGN(0x10);
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.plt)
|
||||
. = ALIGN(0x10);
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*crtend.o(.ctors))
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*crtend.o(.dtors))
|
||||
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.gcc_except_table)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
. = ALIGN(0x10);
|
||||
|
||||
} >envm
|
||||
|
||||
/* short/global data section */
|
||||
.sdata : ALIGN(0x10)
|
||||
{
|
||||
__sdata_load = LOADADDR(.sdata);
|
||||
__sdata_start = .;
|
||||
PROVIDE( __global_pointer$ = . + 0x800);
|
||||
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
|
||||
*(.srodata*)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
. = ALIGN(0x10);
|
||||
__sdata_end = .;
|
||||
} >ram AT>envm
|
||||
|
||||
/* data section */
|
||||
.data : ALIGN(0x10)
|
||||
{
|
||||
__data_load = LOADADDR(.data);
|
||||
__data_start = .;
|
||||
*(.got.plt) *(.got)
|
||||
*(.shdata)
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
. = ALIGN(0x10);
|
||||
__data_end = .;
|
||||
} >ram AT>envm
|
||||
|
||||
/* sbss section */
|
||||
.sbss : ALIGN(0x10)
|
||||
{
|
||||
__sbss_start = .;
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
. = ALIGN(0x10);
|
||||
__sbss_end = .;
|
||||
} > ram
|
||||
|
||||
/* sbss section */
|
||||
.bss : ALIGN(0x10)
|
||||
{
|
||||
__bss_start = .;
|
||||
*(.shbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(0x10);
|
||||
__bss_end = .;
|
||||
} > ram
|
||||
|
||||
/* End of uninitialized data segment */
|
||||
_end = .;
|
||||
|
||||
.heap : ALIGN(0x10)
|
||||
{
|
||||
__heap_start = .;
|
||||
. += HEAP_SIZE;
|
||||
__heap_end = .;
|
||||
. = ALIGN(0x10);
|
||||
_heap_end = __heap_end;
|
||||
} > ram
|
||||
|
||||
.stack : ALIGN(0x10)
|
||||
{
|
||||
__stack_bottom = .;
|
||||
. += STACK_SIZE;
|
||||
__stack_top = .;
|
||||
} > ram
|
||||
}
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* file name : microsemi-riscv-ram.ld
|
||||
* Mi-V soft processor linker script for creating a SoftConsole downloadable
|
||||
* debug image executing in SRAM.
|
||||
*
|
||||
* This linker script assumes that the SRAM is connected at on the Mi-V soft
|
||||
* processor memory space. The start address and size of the memory space must
|
||||
* be correct as per the Libero design.
|
||||
*
|
||||
* SVN $Revision: 9661 $
|
||||
* SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
|
||||
*/
|
||||
|
||||
OUTPUT_ARCH( "riscv" )
|
||||
ENTRY(_start)
|
||||
|
||||
|
||||
MEMORY
|
||||
{
|
||||
ram (rwx) : ORIGIN = 0x80000000, LENGTH = 512k
|
||||
}
|
||||
|
||||
RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
|
||||
RAM_SIZE = 512k; /* Must be the same value MEMORY region ram LENGTH above. */
|
||||
STACK_SIZE = 64k; /* needs to be calculated for your application */
|
||||
HEAP_SIZE = 64k; /* needs to be calculated for your application */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : ALIGN(0x10)
|
||||
{
|
||||
KEEP (*(SORT_NONE(.text.entry)))
|
||||
. = ALIGN(0x10);
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.plt)
|
||||
. = ALIGN(0x10);
|
||||
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*crtend.o(.ctors))
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*crtend.o(.dtors))
|
||||
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.gcc_except_table)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
|
||||
KEEP (*(.init))
|
||||
KEEP (*(.fini))
|
||||
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
. = ALIGN(0x10);
|
||||
|
||||
} > ram
|
||||
|
||||
/* short/global data section */
|
||||
.sdata : ALIGN(0x10)
|
||||
{
|
||||
__sdata_load = LOADADDR(.sdata);
|
||||
__sdata_start = .;
|
||||
PROVIDE( __global_pointer$ = . + 0x800);
|
||||
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
|
||||
*(.srodata*)
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
. = ALIGN(0x10);
|
||||
__sdata_end = .;
|
||||
} > ram
|
||||
|
||||
/* data section */
|
||||
.data : ALIGN(0x10)
|
||||
{
|
||||
__data_load = LOADADDR(.data);
|
||||
__data_start = .;
|
||||
*(.got.plt) *(.got)
|
||||
*(.shdata)
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
. = ALIGN(0x10);
|
||||
__data_end = .;
|
||||
} > ram
|
||||
|
||||
/* sbss section */
|
||||
.sbss : ALIGN(0x10)
|
||||
{
|
||||
__sbss_start = .;
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
. = ALIGN(0x10);
|
||||
__sbss_end = .;
|
||||
} > ram
|
||||
|
||||
/* sbss section */
|
||||
.bss : ALIGN(0x10)
|
||||
{
|
||||
__bss_start = .;
|
||||
*(.shbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(0x10);
|
||||
__bss_end = .;
|
||||
} > ram
|
||||
|
||||
/* End of uninitialized data segment */
|
||||
_end = .;
|
||||
|
||||
.heap : ALIGN(0x10)
|
||||
{
|
||||
__heap_start = .;
|
||||
. += HEAP_SIZE;
|
||||
__heap_end = .;
|
||||
. = ALIGN(0x10);
|
||||
_heap_end = __heap_end;
|
||||
} > ram
|
||||
|
||||
.stack : ALIGN(0x10)
|
||||
{
|
||||
__stack_bottom = .;
|
||||
. += STACK_SIZE;
|
||||
__stack_top = .;
|
||||
} > ram
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file riscv_hal.c
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Implementation of Hardware Abstraction Layer for Mi-V soft processors
|
||||
*
|
||||
* SVN $Revision: 9835 $
|
||||
* SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "riscv_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RTC_PRESCALER 100UL
|
||||
|
||||
#define SUCCESS 0U
|
||||
#define ERROR 1U
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
uint8_t Invalid_IRQHandler(void);
|
||||
uint8_t External_1_IRQHandler(void);
|
||||
uint8_t External_2_IRQHandler(void);
|
||||
uint8_t External_3_IRQHandler(void);
|
||||
uint8_t External_4_IRQHandler(void);
|
||||
uint8_t External_5_IRQHandler(void);
|
||||
uint8_t External_6_IRQHandler(void);
|
||||
uint8_t External_7_IRQHandler(void);
|
||||
uint8_t External_8_IRQHandler(void);
|
||||
uint8_t External_9_IRQHandler(void);
|
||||
uint8_t External_10_IRQHandler(void);
|
||||
uint8_t External_11_IRQHandler(void);
|
||||
uint8_t External_12_IRQHandler(void);
|
||||
uint8_t External_13_IRQHandler(void);
|
||||
uint8_t External_14_IRQHandler(void);
|
||||
uint8_t External_15_IRQHandler(void);
|
||||
uint8_t External_16_IRQHandler(void);
|
||||
uint8_t External_17_IRQHandler(void);
|
||||
uint8_t External_18_IRQHandler(void);
|
||||
uint8_t External_19_IRQHandler(void);
|
||||
uint8_t External_20_IRQHandler(void);
|
||||
uint8_t External_21_IRQHandler(void);
|
||||
uint8_t External_22_IRQHandler(void);
|
||||
uint8_t External_23_IRQHandler(void);
|
||||
uint8_t External_24_IRQHandler(void);
|
||||
uint8_t External_25_IRQHandler(void);
|
||||
uint8_t External_26_IRQHandler(void);
|
||||
uint8_t External_27_IRQHandler(void);
|
||||
uint8_t External_28_IRQHandler(void);
|
||||
uint8_t External_29_IRQHandler(void);
|
||||
uint8_t External_30_IRQHandler(void);
|
||||
uint8_t External_31_IRQHandler(void);
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
extern void Software_IRQHandler(void);
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Increment value for the mtimecmp register in order to achieve a system tick
|
||||
* interrupt as specified through the SysTick_Config() function.
|
||||
*/
|
||||
static uint64_t g_systick_increment = 0U;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Disable all interrupts.
|
||||
*/
|
||||
void __disable_irq(void)
|
||||
{
|
||||
clear_csr(mstatus, MSTATUS_MPIE);
|
||||
clear_csr(mstatus, MSTATUS_MIE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Enabler all interrupts.
|
||||
*/
|
||||
void __enable_irq(void)
|
||||
{
|
||||
set_csr(mstatus, MSTATUS_MIE);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configure the machine timer to generate an interrupt.
|
||||
*/
|
||||
uint32_t SysTick_Config(uint32_t ticks)
|
||||
{
|
||||
uint32_t ret_val = ERROR;
|
||||
|
||||
g_systick_increment = (uint64_t)(ticks) / RTC_PRESCALER;
|
||||
|
||||
if (g_systick_increment > 0U)
|
||||
{
|
||||
uint32_t mhart_id = read_csr(mhartid);
|
||||
|
||||
PRCI->MTIMECMP[mhart_id] = PRCI->MTIME + g_systick_increment;
|
||||
|
||||
set_csr(mie, MIP_MTIP);
|
||||
|
||||
__enable_irq();
|
||||
|
||||
ret_val = SUCCESS;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* RISC-V interrupt handler for machine timer interrupts.
|
||||
*/
|
||||
static void handle_m_timer_interrupt(void)
|
||||
{
|
||||
clear_csr(mie, MIP_MTIP);
|
||||
|
||||
SysTick_Handler();
|
||||
|
||||
PRCI->MTIMECMP[read_csr(mhartid)] = PRCI->MTIME + g_systick_increment;
|
||||
|
||||
set_csr(mie, MIP_MTIP);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* RISC-V interrupt handler for external interrupts.
|
||||
*/
|
||||
uint8_t (*ext_irq_handler_table[32])(void) =
|
||||
{
|
||||
Invalid_IRQHandler,
|
||||
External_1_IRQHandler,
|
||||
External_2_IRQHandler,
|
||||
External_3_IRQHandler,
|
||||
External_4_IRQHandler,
|
||||
External_5_IRQHandler,
|
||||
External_6_IRQHandler,
|
||||
External_7_IRQHandler,
|
||||
External_8_IRQHandler,
|
||||
External_9_IRQHandler,
|
||||
External_10_IRQHandler,
|
||||
External_11_IRQHandler,
|
||||
External_12_IRQHandler,
|
||||
External_13_IRQHandler,
|
||||
External_14_IRQHandler,
|
||||
External_15_IRQHandler,
|
||||
External_16_IRQHandler,
|
||||
External_17_IRQHandler,
|
||||
External_18_IRQHandler,
|
||||
External_19_IRQHandler,
|
||||
External_20_IRQHandler,
|
||||
External_21_IRQHandler,
|
||||
External_22_IRQHandler,
|
||||
External_23_IRQHandler,
|
||||
External_24_IRQHandler,
|
||||
External_25_IRQHandler,
|
||||
External_26_IRQHandler,
|
||||
External_27_IRQHandler,
|
||||
External_28_IRQHandler,
|
||||
External_29_IRQHandler,
|
||||
External_30_IRQHandler,
|
||||
External_31_IRQHandler
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
static void handle_m_ext_interrupt(void)
|
||||
{
|
||||
uint32_t int_num = PLIC_ClaimIRQ();
|
||||
uint8_t disable = EXT_IRQ_KEEP_ENABLED;
|
||||
|
||||
disable = ext_irq_handler_table[int_num]();
|
||||
|
||||
PLIC_CompleteIRQ(int_num);
|
||||
|
||||
if(EXT_IRQ_DISABLE == disable)
|
||||
{
|
||||
PLIC_DisableIRQ((IRQn_Type)int_num);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_m_soft_interrupt(void)
|
||||
{
|
||||
Software_IRQHandler();
|
||||
|
||||
/*Clear software interrupt*/
|
||||
PRCI->MSIP[0] = 0x00U;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Trap/Interrupt handler
|
||||
*/
|
||||
uintptr_t handle_trap(uintptr_t mcause, uintptr_t mepc)
|
||||
{
|
||||
if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT))
|
||||
{
|
||||
handle_m_ext_interrupt();
|
||||
}
|
||||
else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER))
|
||||
{
|
||||
handle_m_timer_interrupt();
|
||||
}
|
||||
else if ( (mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT))
|
||||
{
|
||||
handle_m_soft_interrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
/*
|
||||
Arguments supplied to this function are mcause, mepc (exception PC) and stack pointer
|
||||
based onprivileged-isa specification
|
||||
mcause values and meanings are:
|
||||
0 Instruction address misaligned (mtval/mbadaddr is the address)
|
||||
1 Instruction access fault (mtval/mbadaddr is the address)
|
||||
2 Illegal instruction (mtval/mbadaddr contains the offending instruction opcode)
|
||||
3 Breakpoint
|
||||
4 Load address misaligned (mtval/mbadaddr is the address)
|
||||
5 Load address fault (mtval/mbadaddr is the address)
|
||||
6 Store/AMO address fault (mtval/mbadaddr is the address)
|
||||
7 Store/AMO access fault (mtval/mbadaddr is the address)
|
||||
8 Environment call from U-mode
|
||||
9 Environment call from S-mode
|
||||
A Environment call from M-mode
|
||||
B Instruction page fault
|
||||
C Load page fault (mtval/mbadaddr is the address)
|
||||
E Store page fault (mtval/mbadaddr is the address)
|
||||
*/
|
||||
|
||||
uintptr_t mip = read_csr(mip); /* interrupt pending */
|
||||
uintptr_t mbadaddr = read_csr(mbadaddr); /* additional info and meaning depends on mcause */
|
||||
uintptr_t mtvec = read_csr(mtvec); /* trap vector */
|
||||
uintptr_t mscratch = read_csr(mscratch); /* temporary, sometimes might hold temporary value of a0 */
|
||||
uintptr_t mstatus = read_csr(mstatus); /* status contains many smaller fields: */
|
||||
|
||||
/* breakpoint*/
|
||||
__asm("ebreak");
|
||||
#else
|
||||
_exit(1 + mcause);
|
||||
#endif
|
||||
}
|
||||
return mepc;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file riscv_hal.h
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Hardware Abstraction Layer functions for Mi-V soft processors
|
||||
*
|
||||
* SVN $Revision: 9835 $
|
||||
* SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $
|
||||
*/
|
||||
|
||||
#ifndef RISCV_HAL_H
|
||||
#define RISCV_HAL_H
|
||||
|
||||
#include "riscv_plic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
*Return value from External IRQ handler. This will be used to disable the External
|
||||
*interrupt.
|
||||
*/
|
||||
#define EXT_IRQ_KEEP_ENABLED 0U
|
||||
#define EXT_IRQ_DISABLE 1U
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Interrupt enable/disable.
|
||||
*/
|
||||
void __disable_irq(void);
|
||||
void __enable_irq(void);
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* System tick handler. This is generated from the RISC-V machine timer.
|
||||
*/
|
||||
void SysTick_Handler(void);
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* System tick configuration.
|
||||
* Configures the machine timer to generate a system tick interrupt at regular
|
||||
* intervals.
|
||||
* Takes the number of system clock ticks between interrupts.
|
||||
*
|
||||
* Returns 0 if successful.
|
||||
* Returns 1 if the interrupt interval cannot be achieved.
|
||||
*/
|
||||
uint32_t SysTick_Config(uint32_t ticks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RISCV_HAL_H */
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file riscv_hal_stubs.c
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Mi-V soft processor Interrupt Function stubs.
|
||||
* The functions below will only be linked with the application code if the user
|
||||
* does not provide an implementation for these functions. These functions are
|
||||
* defined with weak linking so that they can be overridden by a function with
|
||||
* same prototype in the user's application code.
|
||||
*
|
||||
* SVN $Revision: 9835 $
|
||||
* SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $
|
||||
*/
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) void Software_IRQHandler(void)
|
||||
{
|
||||
_exit(10);
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) void SysTick_Handler(void)
|
||||
{
|
||||
/*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_1_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_2_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_3_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_4_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_5_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_6_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_7_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_8_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_9_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_10_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_11_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_12_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_13_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_14_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_15_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_16_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_17_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_18_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_19_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_20_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_21_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_22_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_23_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_24_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_25_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_26_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_27_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_28_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_29_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provided*/
|
||||
__attribute__((weak)) uint8_t External_30_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
/*Weakly linked handler. Will be replaced with user's definition if provide*/
|
||||
__attribute__((weak)) uint8_t External_31_IRQHandler(void)
|
||||
{
|
||||
return(0U); /*Default handler*/
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,249 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file riscv_plic.h
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Mi-V soft processor PLIC and PRCI access data structures and functions.
|
||||
*
|
||||
* SVN $Revision: 9838 $
|
||||
* SVN $Date: 2018-03-19 19:22:54 +0530 (Mon, 19 Mar 2018) $
|
||||
*/
|
||||
#ifndef RISCV_PLIC_H
|
||||
#define RISCV_PLIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PLIC_NUM_SOURCES 31
|
||||
#define PLIC_NUM_PRIORITIES 0
|
||||
|
||||
/*==============================================================================
|
||||
* Interrupt numbers:
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NoInterrupt_IRQn = 0,
|
||||
External_1_IRQn = 1,
|
||||
External_2_IRQn = 2,
|
||||
External_3_IRQn = 3,
|
||||
External_4_IRQn = 4,
|
||||
External_5_IRQn = 5,
|
||||
External_6_IRQn = 6,
|
||||
External_7_IRQn = 7,
|
||||
External_8_IRQn = 8,
|
||||
External_9_IRQn = 9,
|
||||
External_10_IRQn = 10,
|
||||
External_11_IRQn = 11,
|
||||
External_12_IRQn = 12,
|
||||
External_13_IRQn = 13,
|
||||
External_14_IRQn = 14,
|
||||
External_15_IRQn = 15,
|
||||
External_16_IRQn = 16,
|
||||
External_17_IRQn = 17,
|
||||
External_18_IRQn = 18,
|
||||
External_19_IRQn = 19,
|
||||
External_20_IRQn = 20,
|
||||
External_21_IRQn = 21,
|
||||
External_22_IRQn = 22,
|
||||
External_23_IRQn = 23,
|
||||
External_24_IRQn = 24,
|
||||
External_25_IRQn = 25,
|
||||
External_26_IRQn = 26,
|
||||
External_27_IRQn = 27,
|
||||
External_28_IRQn = 28,
|
||||
External_29_IRQn = 29,
|
||||
External_30_IRQn = 30,
|
||||
External_31_IRQn = 31
|
||||
} IRQn_Type;
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
* PLIC: Platform Level Interrupt Controller
|
||||
*/
|
||||
#define PLIC_BASE_ADDR 0x40000000UL
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t PRIORITY_THRESHOLD;
|
||||
volatile uint32_t CLAIM_COMPLETE;
|
||||
volatile uint32_t reserved[1022];
|
||||
} IRQ_Target_Type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t ENABLES[32];
|
||||
} Target_Enables_Type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*-------------------- Source Priority --------------------*/
|
||||
volatile uint32_t SOURCE_PRIORITY[1024];
|
||||
|
||||
/*-------------------- Pending array --------------------*/
|
||||
volatile const uint32_t PENDING_ARRAY[32];
|
||||
volatile uint32_t RESERVED1[992];
|
||||
|
||||
/*-------------------- Target enables --------------------*/
|
||||
volatile Target_Enables_Type TARGET_ENABLES[15808];
|
||||
|
||||
volatile uint32_t RESERVED2[16384];
|
||||
|
||||
/*--- Target Priority threshold and claim/complete---------*/
|
||||
IRQ_Target_Type TARGET[15872];
|
||||
|
||||
} PLIC_Type;
|
||||
|
||||
|
||||
#define PLIC ((PLIC_Type *)PLIC_BASE_ADDR)
|
||||
|
||||
/*==============================================================================
|
||||
* PRCI: Power, Reset, Clock, Interrupt
|
||||
*/
|
||||
#define PRCI_BASE 0x44000000UL
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint32_t MSIP[4095];
|
||||
volatile uint32_t reserved;
|
||||
volatile uint64_t MTIMECMP[4095];
|
||||
volatile const uint64_t MTIME;
|
||||
} PRCI_Type;
|
||||
|
||||
#define PRCI ((PRCI_Type *)PRCI_BASE)
|
||||
|
||||
/*==============================================================================
|
||||
* The function PLIC_init() initializes the PLIC controller and enables the
|
||||
* global external interrupt bit.
|
||||
*/
|
||||
static inline void PLIC_init(void)
|
||||
{
|
||||
uint32_t inc;
|
||||
unsigned long hart_id = read_csr(mhartid);
|
||||
|
||||
/* Disable all interrupts for the current hart. */
|
||||
for(inc = 0; inc < ((PLIC_NUM_SOURCES + 32u) / 32u); ++inc)
|
||||
{
|
||||
PLIC->TARGET_ENABLES[hart_id].ENABLES[inc] = 0;
|
||||
}
|
||||
|
||||
/* Set priorities to zero. */
|
||||
/* Should this really be done??? Calling PLIC_init() on one hart will cause
|
||||
* the priorities previously set by other harts to be messed up. */
|
||||
for(inc = 0; inc < PLIC_NUM_SOURCES; ++inc)
|
||||
{
|
||||
PLIC->SOURCE_PRIORITY[inc] = 0;
|
||||
}
|
||||
|
||||
/* Set the threshold to zero. */
|
||||
PLIC->TARGET[hart_id].PRIORITY_THRESHOLD = 0;
|
||||
|
||||
/* Enable machine external interrupts. */
|
||||
set_csr(mie, MIP_MEIP);
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function PLIC_EnableIRQ() enables the external interrupt for the interrupt
|
||||
* number indicated by the parameter IRQn.
|
||||
*/
|
||||
static inline void PLIC_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
unsigned long hart_id = read_csr(mhartid);
|
||||
uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];
|
||||
current |= (uint32_t)1 << (IRQn % 32);
|
||||
PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function PLIC_DisableIRQ() disables the external interrupt for the interrupt
|
||||
* number indicated by the parameter IRQn.
|
||||
|
||||
* NOTE:
|
||||
* This function can be used to disable the external interrupt from outside
|
||||
* external interrupt handler function.
|
||||
* This function MUST NOT be used from within the External Interrupt handler.
|
||||
* If you wish to disable the external interrupt while the interrupt handler
|
||||
* for that external interrupt is executing then you must use the return value
|
||||
* EXT_IRQ_DISABLE to return from the extern interrupt handler.
|
||||
*/
|
||||
static inline void PLIC_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
unsigned long hart_id = read_csr(mhartid);
|
||||
uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];
|
||||
|
||||
current &= ~((uint32_t)1 << (IRQn % 32));
|
||||
|
||||
PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function PLIC_SetPriority() sets the priority for the external interrupt
|
||||
* for the interrupt number indicated by the parameter IRQn.
|
||||
*/
|
||||
static inline void PLIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
|
||||
{
|
||||
PLIC->SOURCE_PRIORITY[IRQn] = priority;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function PLIC_GetPriority() returns the priority for the external interrupt
|
||||
* for the interrupt number indicated by the parameter IRQn.
|
||||
*/
|
||||
static inline uint32_t PLIC_GetPriority(IRQn_Type IRQn)
|
||||
{
|
||||
return PLIC->SOURCE_PRIORITY[IRQn];
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function PLIC_ClaimIRQ() claims the interrupt from the PLIC controller.
|
||||
*/
|
||||
static inline uint32_t PLIC_ClaimIRQ(void)
|
||||
{
|
||||
unsigned long hart_id = read_csr(mhartid);
|
||||
|
||||
return PLIC->TARGET[hart_id].CLAIM_COMPLETE;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function PLIC_CompleteIRQ() indicates to the PLIC controller the interrupt
|
||||
* is processed and claim is complete.
|
||||
*/
|
||||
static inline void PLIC_CompleteIRQ(uint32_t source)
|
||||
{
|
||||
unsigned long hart_id = read_csr(mhartid);
|
||||
|
||||
PLIC->TARGET[hart_id].CLAIM_COMPLETE = source;
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function raise_soft_interrupt() raises a synchronous software interrupt by
|
||||
* writing into the MSIP register.
|
||||
*/
|
||||
static inline void raise_soft_interrupt()
|
||||
{
|
||||
unsigned long hart_id = read_csr(mhartid);
|
||||
|
||||
/*You need to make sure that the global interrupt is enabled*/
|
||||
set_csr(mie, MIP_MSIP); /*Enable software interrupt bit */
|
||||
PRCI->MSIP[hart_id] = 0x01; /*raise soft interrupt for hart0*/
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
* The function clear_soft_interrupt() clears a synchronous software interrupt by
|
||||
* clearing the MSIP register.
|
||||
*/
|
||||
static inline void clear_soft_interrupt()
|
||||
{
|
||||
unsigned long hart_id = read_csr(mhartid);
|
||||
PRCI->MSIP[hart_id] = 0x00; /*clear soft interrupt for hart0*/
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* RISCV_PLIC_H */
|
|
@ -0,0 +1,120 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi Corporation. All rights reserved.
|
||||
*
|
||||
* Platform definitions
|
||||
* Version based on requirements of RISCV-HAL
|
||||
*
|
||||
* SVN $Revision: 9946 $
|
||||
* SVN $Date: 2018-04-30 20:26:55 +0530 (Mon, 30 Apr 2018) $
|
||||
*/
|
||||
/*=========================================================================*//**
|
||||
@mainpage Sample file detailing how hw_platform.h should be constructed for
|
||||
the Mi-V processors.
|
||||
|
||||
@section intro_sec Introduction
|
||||
The hw_platform.h is to be located in the project root directory.
|
||||
Currently this file must be hand crafted when using the Mi-V Soft Processor.
|
||||
|
||||
You can use this file as sample.
|
||||
Rename this file from sample_hw_platform.h to hw_platform.h and store it in
|
||||
the root folder of your project. Then customize it per your HW design.
|
||||
|
||||
@section driver_configuration Project configuration Instructions
|
||||
1. Change SYS_CLK_FREQ define to frequency of Mi-V Soft processor clock
|
||||
2 Add all other core BASE addresses
|
||||
3. Add peripheral Core Interrupt to Mi-V Soft processor interrupt mappings
|
||||
4. Define MSCC_STDIO_UART_BASE_ADDR if you want a CoreUARTapb mapped to STDIO
|
||||
*//*=========================================================================*/
|
||||
|
||||
#ifndef HW_PLATFORM_H
|
||||
#define HW_PLATFORM_H
|
||||
|
||||
/***************************************************************************//**
|
||||
* Soft-processor clock definition
|
||||
* This is the only clock brought over from the Mi-V Soft processor Libero design.
|
||||
*/
|
||||
#ifndef SYS_CLK_FREQ
|
||||
#define SYS_CLK_FREQ 83000000UL
|
||||
#endif
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* Non-memory Peripheral base addresses
|
||||
* Format of define is:
|
||||
* <corename>_<instance>_BASE_ADDR
|
||||
*/
|
||||
#define COREUARTAPB0_BASE_ADDR 0x70001000UL
|
||||
#define COREGPIO_IN_BASE_ADDR 0x70002000UL
|
||||
#define CORETIMER0_BASE_ADDR 0x70003000UL
|
||||
#define CORETIMER1_BASE_ADDR 0x70004000UL
|
||||
#define COREGPIO_OUT_BASE_ADDR 0x70005000UL
|
||||
#define FLASH_CORE_SPI_BASE 0x70006000UL
|
||||
#define CORE16550_BASE_ADDR 0x70007000UL
|
||||
|
||||
/***************************************************************************//**
|
||||
* Peripheral Interrupts are mapped to the corresponding Mi-V Soft processor
|
||||
* interrupt from the Libero design.
|
||||
* There can be up to 31 external interrupts (IRQ[30:0] pins) on the Mi-V Soft
|
||||
* processor.The Mi-V Soft processor external interrupts are defined in the
|
||||
* riscv_plic.h
|
||||
* These are of the form
|
||||
* typedef enum
|
||||
{
|
||||
NoInterrupt_IRQn = 0,
|
||||
External_1_IRQn = 1,
|
||||
External_2_IRQn = 2,
|
||||
.
|
||||
.
|
||||
.
|
||||
External_31_IRQn = 31
|
||||
} IRQn_Type;
|
||||
|
||||
The interrupt 0 on RISC-V processor is not used. The pin IRQ[0] should map to
|
||||
External_1_IRQn likewise IRQ[30] should map to External_31_IRQn
|
||||
* Format of define is:
|
||||
* <corename>_<instance>_<core interrupt name>
|
||||
*/
|
||||
|
||||
#define TIMER0_IRQn External_30_IRQn
|
||||
#define TIMER1_IRQn External_31_IRQn
|
||||
|
||||
/****************************************************************************
|
||||
* Baud value to achieve a 115200 baud rate with a 83MHz system clock.
|
||||
* This value is calculated using the following equation:
|
||||
* BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
|
||||
*****************************************************************************/
|
||||
#define BAUD_VALUE_115200 (SYS_CLK_FREQ / (16 * 115200)) - 1
|
||||
|
||||
/***************************************************************************//**
|
||||
* User edit section- Edit sections below if required
|
||||
*/
|
||||
#ifdef MSCC_STDIO_THRU_CORE_UART_APB
|
||||
/*
|
||||
* A base address mapping for the STDIO printf/scanf mapping to CortUARTapb
|
||||
* must be provided if it is being used
|
||||
*
|
||||
* e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
|
||||
*/
|
||||
#define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB0_BASE_ADDR
|
||||
|
||||
#ifndef MSCC_STDIO_UART_BASE_ADDR
|
||||
#error MSCC_STDIO_UART_BASE_ADDR not defined- e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
|
||||
#endif
|
||||
|
||||
#ifndef MSCC_STDIO_BAUD_VALUE
|
||||
/*
|
||||
* The MSCC_STDIO_BAUD_VALUE define should be set in your project's settings to
|
||||
* specify the baud value used by the standard output CoreUARTapb instance for
|
||||
* generating the UART's baud rate if you want a different baud rate from the
|
||||
* default of 115200 baud
|
||||
*/
|
||||
#define MSCC_STDIO_BAUD_VALUE 115200
|
||||
#endif /*MSCC_STDIO_BAUD_VALUE*/
|
||||
|
||||
#endif /* end of MSCC_STDIO_THRU_CORE_UART_APB */
|
||||
/*******************************************************************************
|
||||
* End of user edit section
|
||||
*/
|
||||
#endif /* HW_PLATFORM_H */
|
||||
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/*******************************************************************************
|
||||
* (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
|
||||
*
|
||||
* @file syscall.c
|
||||
* @author Microsemi SoC Products Group
|
||||
* @brief Stubs for system calls.
|
||||
*
|
||||
* SVN $Revision: 9661 $
|
||||
* SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/times.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "encoding.h"
|
||||
|
||||
#ifdef MSCC_STDIO_THRU_CORE_UART_APB
|
||||
|
||||
#include "core_uart_apb.h"
|
||||
#include "hw_platform.h"
|
||||
|
||||
#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef MSCC_STDIO_THRU_CORE_UART_APB
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* CoreUARTapb instance data for the CoreUARTapb instance used for standard
|
||||
* output.
|
||||
*/
|
||||
static UART_instance_t g_stdio_uart;
|
||||
|
||||
/*==============================================================================
|
||||
* Flag used to indicate if the UART driver needs to be initialized.
|
||||
*/
|
||||
static int g_stdio_uart_init_done = 0;
|
||||
#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/
|
||||
|
||||
#undef errno
|
||||
int errno;
|
||||
|
||||
char *__env[1] = { 0 };
|
||||
char **environ = __env;
|
||||
|
||||
void write_hex(int fd, uint32_t hex)
|
||||
{
|
||||
uint8_t ii;
|
||||
uint8_t jj;
|
||||
char towrite;
|
||||
uint8_t digit;
|
||||
|
||||
write( fd , "0x", 2 );
|
||||
|
||||
for (ii = 8 ; ii > 0; ii--)
|
||||
{
|
||||
jj = ii-1;
|
||||
digit = ((hex & (0xF << (jj*4))) >> (jj*4));
|
||||
towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA));
|
||||
write( fd, &towrite, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _exit(int code)
|
||||
{
|
||||
#ifdef MSCC_STDIO_THRU_CORE_UART_APB
|
||||
const char * message = "\nProgam has exited with code:";
|
||||
|
||||
write(STDERR_FILENO, message, strlen(message));
|
||||
write_hex(STDERR_FILENO, code);
|
||||
#endif
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
void *_sbrk(ptrdiff_t incr)
|
||||
{
|
||||
extern char _end[];
|
||||
extern char _heap_end[];
|
||||
static char *curbrk = _end;
|
||||
|
||||
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))
|
||||
{
|
||||
return ((char *) - 1);
|
||||
}
|
||||
|
||||
curbrk += incr;
|
||||
return curbrk - incr;
|
||||
}
|
||||
|
||||
int _isatty(int fd)
|
||||
{
|
||||
if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
errno = EBADF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stub(int err)
|
||||
{
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _open(const char* name, int flags, int mode)
|
||||
{
|
||||
return stub(ENOENT);
|
||||
}
|
||||
|
||||
int _openat(int dirfd, const char* name, int flags, int mode)
|
||||
{
|
||||
return stub(ENOENT);
|
||||
}
|
||||
|
||||
int _close(int fd)
|
||||
{
|
||||
return stub(EBADF);
|
||||
}
|
||||
|
||||
int _execve(const char* name, char* const argv[], char* const env[])
|
||||
{
|
||||
return stub(ENOMEM);
|
||||
}
|
||||
|
||||
int _fork()
|
||||
{
|
||||
return stub(EAGAIN);
|
||||
}
|
||||
|
||||
int _fstat(int fd, struct stat *st)
|
||||
{
|
||||
if (isatty(fd))
|
||||
{
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stub(EBADF);
|
||||
}
|
||||
|
||||
int _getpid()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig)
|
||||
{
|
||||
return stub(EINVAL);
|
||||
}
|
||||
|
||||
int _link(const char *old_name, const char *new_name)
|
||||
{
|
||||
return stub(EMLINK);
|
||||
}
|
||||
|
||||
off_t _lseek(int fd, off_t ptr, int dir)
|
||||
{
|
||||
if (_isatty(fd))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stub(EBADF);
|
||||
}
|
||||
|
||||
ssize_t _read(int fd, void* ptr, size_t len)
|
||||
{
|
||||
#ifdef MSCC_STDIO_THRU_CORE_UART_APB
|
||||
if (_isatty(fd))
|
||||
{
|
||||
/*--------------------------------------------------------------------------
|
||||
* Initialize the UART driver if it is the first time this function is
|
||||
* called.
|
||||
*/
|
||||
if ( !g_stdio_uart_init_done )
|
||||
{
|
||||
/******************************************************************************
|
||||
* Baud value:
|
||||
* This value is calculated using the following equation:
|
||||
* BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
|
||||
*****************************************************************************/
|
||||
UART_init( &g_stdio_uart, MSCC_STDIO_UART_BASE_ADDR, ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1), (DATA_8_BITS | NO_PARITY));
|
||||
g_stdio_uart_init_done = 1;
|
||||
}
|
||||
|
||||
return UART_get_rx(&g_stdio_uart, (uint8_t*) ptr, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
return stub(EBADF);
|
||||
}
|
||||
|
||||
int _stat(const char* file, struct stat* st)
|
||||
{
|
||||
return stub(EACCES);
|
||||
}
|
||||
|
||||
clock_t _times(struct tms* buf)
|
||||
{
|
||||
return stub(EACCES);
|
||||
}
|
||||
|
||||
int _unlink(const char* name)
|
||||
{
|
||||
return stub(ENOENT);
|
||||
}
|
||||
|
||||
int _wait(int* status)
|
||||
{
|
||||
return stub(ECHILD);
|
||||
}
|
||||
|
||||
ssize_t _write(int fd, const void* ptr, size_t len)
|
||||
{
|
||||
|
||||
#ifdef MSCC_STDIO_THRU_CORE_UART_APB
|
||||
const uint8_t * current = (const uint8_t *) ptr;
|
||||
size_t jj;
|
||||
|
||||
if (_isatty(fd))
|
||||
{
|
||||
/*--------------------------------------------------------------------------
|
||||
* Initialize the UART driver if it is the first time this function is
|
||||
* called.
|
||||
*/
|
||||
if ( !g_stdio_uart_init_done )
|
||||
{
|
||||
/******************************************************************************
|
||||
* Baud value:
|
||||
* This value is calculated using the following equation:
|
||||
* BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
|
||||
*****************************************************************************/
|
||||
UART_init( &g_stdio_uart, MSCC_STDIO_UART_BASE_ADDR, ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1), (DATA_8_BITS | NO_PARITY));
|
||||
g_stdio_uart_init_done = 1;
|
||||
}
|
||||
|
||||
for (jj = 0; jj < len; jj++)
|
||||
{
|
||||
UART_send(&g_stdio_uart, current + jj, 1);
|
||||
if (current[jj] == '\n')
|
||||
{
|
||||
UART_send(&g_stdio_uart, (const uint8_t *)"\r", 1);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
return stub(EBADF);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue