Add starting point for IGLOO2 RISV-V demo project.

This commit is contained in:
Richard Barry 2018-06-20 21:18:14 +00:00
parent 483f4a8c4b
commit 9119e1e0e3
42 changed files with 13068 additions and 0 deletions

View file

@ -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*/

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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