Browse Source
Remove architecture and dependencies. Remove altera HAL supporting nios2 Signed-off-by: Anas Nashif <anas.nashif@intel.com>pull/86868/merge
83 changed files with 17 additions and 3673 deletions
@ -1,37 +0,0 @@ |
|||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
if(CONFIG_GP_NONE) |
|
||||||
set(gpopt none) |
|
||||||
elseif(CONFIG_GP_LOCAL) |
|
||||||
set(gpopt local) |
|
||||||
elseif(CONFIG_GP_GLOBAL) |
|
||||||
set(gpopt global) |
|
||||||
elseif(CONFIG_GP_ALL_DATA) |
|
||||||
set(gpopt data) |
|
||||||
endif() |
|
||||||
|
|
||||||
# Set Global Pointer option based on Kconfig. |
|
||||||
zephyr_cc_option(-mgpopt=${gpopt}) |
|
||||||
|
|
||||||
# TODO Find a way to pull this out of system.h somehow |
|
||||||
# instead of having Kconfig for it |
|
||||||
|
|
||||||
if(CONFIG_HAS_MUL_INSTRUCTION) |
|
||||||
zephyr_cc_option(-mhw-mul) |
|
||||||
else() |
|
||||||
zephyr_cc_option(-mno-hw-mul) |
|
||||||
endif() |
|
||||||
|
|
||||||
if(CONFIG_HAS_MULX_INSTRUCTION) |
|
||||||
zephyr_cc_option(-mhw-mulx) |
|
||||||
else() |
|
||||||
zephyr_cc_option(-mno-hw-mulx) |
|
||||||
endif() |
|
||||||
|
|
||||||
if(CONFIG_HAS_DIV_INSTRUCTION) |
|
||||||
zephyr_cc_option(-mhw-div) |
|
||||||
else() |
|
||||||
zephyr_cc_option(-mno-hw-div) |
|
||||||
endif() |
|
||||||
|
|
||||||
add_subdirectory(core) |
|
@ -1,96 +0,0 @@ |
|||||||
# Copyright (c) 2016 Intel Corporation |
|
||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
menu "Nios II Options" |
|
||||||
depends on NIOS2 |
|
||||||
|
|
||||||
config ARCH |
|
||||||
string |
|
||||||
default "nios2" |
|
||||||
|
|
||||||
menu "Nios II Gen 2 Processor Options" |
|
||||||
|
|
||||||
config CPU_NIOS2_GEN2 |
|
||||||
bool |
|
||||||
default y |
|
||||||
select BUILD_OUTPUT_HEX |
|
||||||
select ARCH_HAS_EXTRA_EXCEPTION_INFO |
|
||||||
help |
|
||||||
This option signifies the use of a Nios II Gen 2 CPU |
|
||||||
|
|
||||||
endmenu |
|
||||||
|
|
||||||
menu "Nios II Family Options" |
|
||||||
|
|
||||||
config GEN_ISR_TABLES |
|
||||||
default y |
|
||||||
|
|
||||||
config GEN_IRQ_VECTOR_TABLE |
|
||||||
default n |
|
||||||
|
|
||||||
config NUM_IRQS |
|
||||||
int |
|
||||||
default 32 |
|
||||||
|
|
||||||
config HAS_MUL_INSTRUCTION |
|
||||||
bool |
|
||||||
|
|
||||||
config HAS_DIV_INSTRUCTION |
|
||||||
bool |
|
||||||
|
|
||||||
config HAS_MULX_INSTRUCTION |
|
||||||
bool |
|
||||||
|
|
||||||
config INCLUDE_RESET_VECTOR |
|
||||||
bool "Include Reset vector" |
|
||||||
default y |
|
||||||
help |
|
||||||
Include the reset vector stub, which enables instruction/data caches |
|
||||||
and then jumps to __start. This code is typically located at the very |
|
||||||
beginning of flash memory. You may need to omit this if using the |
|
||||||
nios2-download tool since it refuses to load data anywhere other than |
|
||||||
RAM. |
|
||||||
|
|
||||||
config EXTRA_EXCEPTION_INFO |
|
||||||
bool "Extra exception debug information" |
|
||||||
help |
|
||||||
Have exceptions print additional useful debugging information in |
|
||||||
human-readable form, at the expense of code size. For example, |
|
||||||
the cause code for an exception will be supplemented by a string |
|
||||||
describing what that cause code means. |
|
||||||
|
|
||||||
choice |
|
||||||
prompt "Global Pointer options" |
|
||||||
default GP_GLOBAL |
|
||||||
|
|
||||||
config GP_NONE |
|
||||||
bool "No global pointer" |
|
||||||
help |
|
||||||
Do not use global pointer relative offsets at all |
|
||||||
|
|
||||||
config GP_LOCAL |
|
||||||
bool "Local data global pointer references" |
|
||||||
help |
|
||||||
Use global pointer relative offsets for small globals declared in the |
|
||||||
same C file as the code that uses it. |
|
||||||
|
|
||||||
config GP_GLOBAL |
|
||||||
bool "Global data global pointer references" |
|
||||||
help |
|
||||||
Use global pointer relative offsets for small globals declared |
|
||||||
anywhere in the executable. Note that if any small globals that are put |
|
||||||
in alternate sections they must be declared |
|
||||||
in headers with proper __attribute__((section)) or the linker will |
|
||||||
error out. |
|
||||||
|
|
||||||
config GP_ALL_DATA |
|
||||||
bool "All data global pointer references" |
|
||||||
help |
|
||||||
Use GP relative access for all data in the program, not just |
|
||||||
small data. Use this if your board has 64K or less of RAM. |
|
||||||
|
|
||||||
endchoice |
|
||||||
|
|
||||||
endmenu |
|
||||||
|
|
||||||
endmenu |
|
@ -1,19 +0,0 @@ |
|||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
zephyr_library() |
|
||||||
|
|
||||||
zephyr_library_sources( |
|
||||||
thread.c |
|
||||||
cpu_idle.c |
|
||||||
fatal.c |
|
||||||
irq_manage.c |
|
||||||
swap.S |
|
||||||
prep_c.c |
|
||||||
reset.S |
|
||||||
cache.c |
|
||||||
exception.S |
|
||||||
crt0.S |
|
||||||
) |
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) |
|
||||||
zephyr_library_sources_ifdef(CONFIG_TIMING_FUNCTIONS timing.c) |
|
@ -1,92 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/arch/cpu.h> |
|
||||||
#include <zephyr/sys/__assert.h> |
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush the entire instruction cache and pipeline. |
|
||||||
* |
|
||||||
* You will need to call this function if the application writes new program |
|
||||||
* text to memory, such as a boot copier or runtime synthesis of code. If the |
|
||||||
* new text was written with instructions that do not bypass cache memories, |
|
||||||
* this should immediately be followed by an invocation of |
|
||||||
* z_nios2_dcache_flush_all() so that cached instruction data is committed to |
|
||||||
* RAM. |
|
||||||
* |
|
||||||
* See Chapter 9 of the Nios II Gen 2 Software Developer's Handbook for more |
|
||||||
* information on cache considerations. |
|
||||||
*/ |
|
||||||
#if ALT_CPU_ICACHE_SIZE > 0 |
|
||||||
void z_nios2_icache_flush_all(void) |
|
||||||
{ |
|
||||||
uint32_t i; |
|
||||||
|
|
||||||
for (i = 0U; i < ALT_CPU_ICACHE_SIZE; i += ALT_CPU_ICACHE_LINE_SIZE) { |
|
||||||
z_nios2_icache_flush(i); |
|
||||||
} |
|
||||||
|
|
||||||
/* Get rid of any stale instructions in the pipeline */ |
|
||||||
z_nios2_pipeline_flush(); |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush the entire data cache. |
|
||||||
* |
|
||||||
* This will be typically needed after writing new program text to memory |
|
||||||
* after flushing the instruction cache. |
|
||||||
* |
|
||||||
* The Nios II does not support hardware cache coherency for multi-master |
|
||||||
* or multi-processor systems and software coherency must be implemented |
|
||||||
* when communicating with shared memory. If support for this is introduced |
|
||||||
* in Zephyr additional APIs for flushing ranges of the data cache will need |
|
||||||
* to be implemented. |
|
||||||
* |
|
||||||
* See Chapter 9 of the Nios II Gen 2 Software Developer's Handbook for more |
|
||||||
* information on cache considerations. |
|
||||||
*/ |
|
||||||
#if ALT_CPU_DCACHE_SIZE > 0 |
|
||||||
void z_nios2_dcache_flush_all(void) |
|
||||||
{ |
|
||||||
uint32_t i; |
|
||||||
|
|
||||||
for (i = 0U; i < ALT_CPU_DCACHE_SIZE; i += ALT_CPU_DCACHE_LINE_SIZE) { |
|
||||||
z_nios2_dcache_flush(i); |
|
||||||
} |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
/*
|
|
||||||
* z_nios2_dcache_flush_no_writeback() is called to flush the data cache for a |
|
||||||
* memory region of length "len" bytes, starting at address "start". |
|
||||||
* |
|
||||||
* Any dirty lines in the data cache are NOT written back to memory. |
|
||||||
* Make sure you really want this behavior. If you aren't 100% sure, |
|
||||||
* use the z_nios2_dcache_flush() routine instead. |
|
||||||
*/ |
|
||||||
#if ALT_CPU_DCACHE_SIZE > 0 |
|
||||||
void z_nios2_dcache_flush_no_writeback(void *start, uint32_t len) |
|
||||||
{ |
|
||||||
uint8_t *i; |
|
||||||
uint8_t *end = ((char *) start) + len; |
|
||||||
|
|
||||||
for (i = start; i < end; i += ALT_CPU_DCACHE_LINE_SIZE) { |
|
||||||
__asm__ volatile ("initda (%0)" :: "r" (i)); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* For an unaligned flush request, we've got one more line left. |
|
||||||
* Note that this is dependent on ALT_CPU_DCACHE_LINE_SIZE to be a |
|
||||||
* multiple of 2 (which it always is). |
|
||||||
*/ |
|
||||||
|
|
||||||
if (((uint32_t) start) & (ALT_CPU_DCACHE_LINE_SIZE - 1)) { |
|
||||||
__asm__ volatile ("initda (%0)" :: "r" (i)); |
|
||||||
} |
|
||||||
} |
|
||||||
#endif |
|
@ -1,28 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/kernel_structs.h> |
|
||||||
|
|
||||||
#ifndef CONFIG_ARCH_HAS_CUSTOM_CPU_IDLE |
|
||||||
void arch_cpu_idle(void) |
|
||||||
{ |
|
||||||
/* Do nothing but unconditionally unlock interrupts and return to the
|
|
||||||
* caller. This CPU does not have any kind of power saving instruction. |
|
||||||
*/ |
|
||||||
irq_unlock(NIOS2_STATUS_PIE_MSK); |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifndef CONFIG_ARCH_HAS_CUSTOM_CPU_ATOMIC_IDLE |
|
||||||
void arch_cpu_atomic_idle(unsigned int key) |
|
||||||
{ |
|
||||||
/* Do nothing but restore IRQ state. This CPU does not have any
|
|
||||||
* kind of power saving instruction. |
|
||||||
*/ |
|
||||||
irq_unlock(key); |
|
||||||
} |
|
||||||
#endif |
|
@ -1,146 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/toolchain.h> |
|
||||||
#include <zephyr/linker/sections.h> |
|
||||||
|
|
||||||
/* exports */ |
|
||||||
GTEXT(__start) |
|
||||||
GTEXT(__reset) |
|
||||||
|
|
||||||
/* imports */ |
|
||||||
GTEXT(z_prep_c) |
|
||||||
GTEXT(z_interrupt_stacks) |
|
||||||
|
|
||||||
/* Allow use of r1/at (the assembler temporary register) in this |
|
||||||
* code, normally reserved for internal assembler use |
|
||||||
*/ |
|
||||||
.set noat
|
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_INCLUDE_RESET_VECTOR |
|
||||||
/* |
|
||||||
* Reset vector entry point into the system. Placed into special 'reset' |
|
||||||
* section so that the linker puts this at ALT_CPU_RESET_ADDR defined in |
|
||||||
* system.h |
|
||||||
* |
|
||||||
* This code can be at most 0x20 bytes, since the exception vector for Nios II |
|
||||||
* is usually configured to be 0x20 past the reset vector. |
|
||||||
*/ |
|
||||||
SECTION_FUNC(reset, __reset) |
|
||||||
|
|
||||||
#if ALT_CPU_ICACHE_SIZE > 0 |
|
||||||
/* Aside from the instruction cache line associated with the reset |
|
||||||
* vector, the contents of the cache memories are indeterminate after |
|
||||||
* reset. To ensure cache coherency after reset, the reset handler |
|
||||||
* located at the reset vector must immediately initialize the |
|
||||||
* instruction cache. Next, either the reset handler or a subsequent |
|
||||||
* routine should proceed to initialize the data cache. |
|
||||||
* |
|
||||||
* The cache memory sizes are *always* a power of 2. |
|
||||||
*/ |
|
||||||
#if ALT_CPU_ICACHE_SIZE > 0x8000 |
|
||||||
movhi r2, %hi(ALT_CPU_ICACHE_SIZE) |
|
||||||
#else |
|
||||||
movui r2, ALT_CPU_ICACHE_SIZE |
|
||||||
#endif |
|
||||||
0: |
|
||||||
/* If ECC present, need to execute initd for each word address |
|
||||||
* to ensure ECC parity bits in data RAM get initialized |
|
||||||
*/ |
|
||||||
#ifdef ALT_CPU_ECC_PRESENT |
|
||||||
subi r2, r2, 4 |
|
||||||
#else |
|
||||||
subi r2, r2, ALT_CPU_ICACHE_LINE_SIZE |
|
||||||
#endif |
|
||||||
initi r2 |
|
||||||
bgt r2, zero, 0b |
|
||||||
#endif /* ALT_CPU_ICACHE_SIZE > 0 */ |
|
||||||
|
|
||||||
/* Done all we need to do here, jump to __text_start */ |
|
||||||
movhi r1, %hi(__start) |
|
||||||
ori r1, r1, %lo(__start) |
|
||||||
jmp r1 |
|
||||||
#endif /* CONFIG_INCLUDE_RESET_VECTOR */ |
|
||||||
|
|
||||||
/* Remainder of asm-land initialization code before we can jump into |
|
||||||
* the C domain |
|
||||||
*/ |
|
||||||
SECTION_FUNC(TEXT, __start) |
|
||||||
|
|
||||||
/* TODO if shadow register sets enabled, ensure we are in set 0 |
|
||||||
* GH-1821 |
|
||||||
*/ |
|
||||||
|
|
||||||
/* Initialize the data cache if booting from bare metal. If |
|
||||||
* we're not booting from our reset vector, either by a bootloader |
|
||||||
* or JTAG, assume caches already initialized. |
|
||||||
*/ |
|
||||||
#if ALT_CPU_DCACHE_SIZE > 0 && defined(CONFIG_INCLUDE_RESET_VECTOR) |
|
||||||
/* Per documentation data cache size is always a power of two. */ |
|
||||||
#if ALT_CPU_DCACHE_SIZE > 0x8000 |
|
||||||
movhi r2, %hi(ALT_CPU_DCACHE_SIZE) |
|
||||||
#else |
|
||||||
movui r2, ALT_CPU_DCACHE_SIZE |
|
||||||
#endif |
|
||||||
0: |
|
||||||
/* If ECC present, need to execute initd for each word address |
|
||||||
* to ensure ECC parity bits in data RAM get initialized |
|
||||||
*/ |
|
||||||
#ifdef ALT_CPU_ECC_PRESENT |
|
||||||
subi r2, r2, 4 |
|
||||||
#else |
|
||||||
subi r2, r2, ALT_CPU_DCACHE_LINE_SIZE |
|
||||||
#endif |
|
||||||
initd 0(r2) |
|
||||||
bgt r2, zero, 0b |
|
||||||
#endif /* ALT_CPU_DCACHE_SIZE && defined(CONFIG_INCLUDE_RESET_VECTOR) */ |
|
||||||
|
|
||||||
#ifdef CONFIG_INIT_STACKS |
|
||||||
/* Pre-populate all bytes in z_interrupt_stacks with 0xAA |
|
||||||
* init.c enforces that the z_interrupt_stacks pointer |
|
||||||
* and CONFIG_ISR_STACK_SIZE are a multiple of ARCH_STACK_PTR_ALIGN (4) |
|
||||||
*/ |
|
||||||
movhi r1, %hi(z_interrupt_stacks) |
|
||||||
ori r1, r1, %lo(z_interrupt_stacks) |
|
||||||
movhi r2, %hi(CONFIG_ISR_STACK_SIZE) |
|
||||||
ori r2, r2, %lo(CONFIG_ISR_STACK_SIZE) |
|
||||||
/* Put constant 0xaaaaaaaa in r3 */ |
|
||||||
movhi r3, 0xaaaa |
|
||||||
ori r3, r3, 0xaaaa |
|
||||||
1: |
|
||||||
/* Loop through the z_interrupt_stacks treating it as an array of |
|
||||||
* uint32_t, setting each element to r3 */ |
|
||||||
stw r3, (r1) |
|
||||||
subi r2, r2, 4 |
|
||||||
addi r1, r1, 4 |
|
||||||
blt r0, r2, 1b |
|
||||||
#endif |
|
||||||
|
|
||||||
/* Set up the initial stack pointer to the interrupt stack, safe |
|
||||||
* to use this as the CPU boots up with interrupts disabled and we |
|
||||||
* don't turn them on until much later, when the kernel is on |
|
||||||
* the main stack */ |
|
||||||
movhi sp, %hi(z_interrupt_stacks) |
|
||||||
ori sp, sp, %lo(z_interrupt_stacks) |
|
||||||
addi sp, sp, CONFIG_ISR_STACK_SIZE |
|
||||||
|
|
||||||
#if defined(CONFIG_GP_LOCAL) || defined(CONFIG_GP_GLOBAL) || \ |
|
||||||
defined(CONFIG_GP_ALL_DATA) |
|
||||||
/* Initialize global pointer with the linker variable we set */ |
|
||||||
movhi gp, %hi(_gp) |
|
||||||
ori gp, gp, %lo(_gp) |
|
||||||
#endif |
|
||||||
|
|
||||||
/* TODO if shadow register sets enabled, interate through them to set |
|
||||||
* up. Need to clear r0, write gp, set the exception stack pointer |
|
||||||
* GH-1821 |
|
||||||
*/ |
|
||||||
|
|
||||||
/* Jump into C domain. z_prep_c zeroes BSS, copies rw data into RAM, |
|
||||||
* and then enters z_cstart */ |
|
||||||
call z_prep_c |
|
||||||
|
|
@ -1,227 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/toolchain.h> |
|
||||||
#include <zephyr/linker/sections.h> |
|
||||||
#include <offsets_short.h> |
|
||||||
|
|
||||||
/* exports */ |
|
||||||
GTEXT(_exception) |
|
||||||
|
|
||||||
/* import */ |
|
||||||
GTEXT(z_nios2_fault) |
|
||||||
GTEXT(arch_swap) |
|
||||||
#ifdef CONFIG_IRQ_OFFLOAD |
|
||||||
GTEXT(z_irq_do_offload) |
|
||||||
GTEXT(_offload_routine) |
|
||||||
#endif |
|
||||||
|
|
||||||
/* Allows use of r1/at register, otherwise reserved for assembler use */ |
|
||||||
.set noat
|
|
||||||
|
|
||||||
/* Placed into special 'exception' section so that the linker can put this code |
|
||||||
* at ALT_CPU_EXCEPTION_ADDR defined in system.h |
|
||||||
* |
|
||||||
* This is the common entry point for processor exceptions and interrupts from |
|
||||||
* the Internal Interrupt Controller (IIC). |
|
||||||
* |
|
||||||
* If the External (EIC) controller is in use, then we will never get here on |
|
||||||
* behalf of an interrupt, instead the EIC driver will have set up a vector |
|
||||||
* table and the processor will jump directly into the appropriate table |
|
||||||
* entry. |
|
||||||
*/ |
|
||||||
SECTION_FUNC(exception.entry, _exception) |
|
||||||
/* Reserve thread stack space for saving context */ |
|
||||||
subi sp, sp, __struct_arch_esf_SIZEOF |
|
||||||
|
|
||||||
/* Preserve all caller-saved registers onto the thread's stack */ |
|
||||||
stw ra, __struct_arch_esf_ra_OFFSET(sp) |
|
||||||
stw r1, __struct_arch_esf_r1_OFFSET(sp) |
|
||||||
stw r2, __struct_arch_esf_r2_OFFSET(sp) |
|
||||||
stw r3, __struct_arch_esf_r3_OFFSET(sp) |
|
||||||
stw r4, __struct_arch_esf_r4_OFFSET(sp) |
|
||||||
stw r5, __struct_arch_esf_r5_OFFSET(sp) |
|
||||||
stw r6, __struct_arch_esf_r6_OFFSET(sp) |
|
||||||
stw r7, __struct_arch_esf_r7_OFFSET(sp) |
|
||||||
stw r8, __struct_arch_esf_r8_OFFSET(sp) |
|
||||||
stw r9, __struct_arch_esf_r9_OFFSET(sp) |
|
||||||
stw r10, __struct_arch_esf_r10_OFFSET(sp) |
|
||||||
stw r11, __struct_arch_esf_r11_OFFSET(sp) |
|
||||||
stw r12, __struct_arch_esf_r12_OFFSET(sp) |
|
||||||
stw r13, __struct_arch_esf_r13_OFFSET(sp) |
|
||||||
stw r14, __struct_arch_esf_r14_OFFSET(sp) |
|
||||||
stw r15, __struct_arch_esf_r15_OFFSET(sp) |
|
||||||
|
|
||||||
/* Store value of estatus control register */ |
|
||||||
rdctl et, estatus |
|
||||||
stw et, __struct_arch_esf_estatus_OFFSET(sp) |
|
||||||
|
|
||||||
/* ea-4 is the address of the instruction when the exception happened, |
|
||||||
* put this in the stack frame as well |
|
||||||
*/ |
|
||||||
addi r15, ea, -4 |
|
||||||
stw r15, __struct_arch_esf_instr_OFFSET(sp) |
|
||||||
|
|
||||||
/* Figure out whether we are here because of an interrupt or an |
|
||||||
* exception. If an interrupt, switch stacks and enter IRQ handling |
|
||||||
* code. If an exception, remain on current stack and enter exception |
|
||||||
* handing code. From the CPU manual, ipending must be nonzero and |
|
||||||
* estatis.PIE must be enabled for this to be considered an interrupt. |
|
||||||
* |
|
||||||
* Stick ipending in r4 since it will be an arg for _enter_irq |
|
||||||
*/ |
|
||||||
rdctl r4, ipending |
|
||||||
beq r4, zero, not_interrupt |
|
||||||
/* We stashed estatus in et earlier */ |
|
||||||
andi r15, et, 1 |
|
||||||
beq r15, zero, not_interrupt |
|
||||||
|
|
||||||
is_interrupt: |
|
||||||
/* If we get here, this is an interrupt */ |
|
||||||
|
|
||||||
/* Grab a reference to _kernel in r10 so we can determine the |
|
||||||
* current irq stack pointer |
|
||||||
*/ |
|
||||||
movhi r10, %hi(_kernel) |
|
||||||
ori r10, r10, %lo(_kernel) |
|
||||||
|
|
||||||
/* Stash a copy of thread's sp in r12 so that we can put it on the IRQ |
|
||||||
* stack |
|
||||||
*/ |
|
||||||
mov r12, sp |
|
||||||
|
|
||||||
/* Switch to interrupt stack */ |
|
||||||
ldw sp, _kernel_offset_to_irq_stack(r10) |
|
||||||
|
|
||||||
/* Store thread stack pointer onto IRQ stack */ |
|
||||||
addi sp, sp, -4 |
|
||||||
stw r12, 0(sp) |
|
||||||
|
|
||||||
on_irq_stack: |
|
||||||
|
|
||||||
/* Enter C interrupt handling code. Value of ipending will be the |
|
||||||
* function parameter since we put it in r4 |
|
||||||
*/ |
|
||||||
call _enter_irq |
|
||||||
|
|
||||||
/* Interrupt handler finished and the interrupt should be serviced |
|
||||||
* now, the appropriate bits in ipending should be cleared */ |
|
||||||
|
|
||||||
/* Get a reference to _kernel again in r10 */ |
|
||||||
movhi r10, %hi(_kernel) |
|
||||||
ori r10, r10, %lo(_kernel) |
|
||||||
|
|
||||||
#ifdef CONFIG_PREEMPT_ENABLED |
|
||||||
ldw r11, _kernel_offset_to_current(r10) |
|
||||||
/* Determine whether the exception of the ISR requires context |
|
||||||
* switch |
|
||||||
*/ |
|
||||||
|
|
||||||
/* Call into the kernel to see if a scheduling decision is necessary */ |
|
||||||
ldw r2, _kernel_offset_to_ready_q_cache(r10) |
|
||||||
beq r2, r11, no_reschedule |
|
||||||
|
|
||||||
/* |
|
||||||
* A context reschedule is required: keep the volatile registers of |
|
||||||
* the interrupted thread on the context's stack. Utilize |
|
||||||
* the existing arch_swap() primitive to save the remaining |
|
||||||
* thread's registers (including floating point) and perform |
|
||||||
* a switch to the new thread. |
|
||||||
*/ |
|
||||||
|
|
||||||
/* We put the thread stack pointer on top of the IRQ stack before |
|
||||||
* we switched stacks. Restore it to go back to thread stack |
|
||||||
*/ |
|
||||||
ldw sp, 0(sp) |
|
||||||
|
|
||||||
/* Argument to Swap() is estatus since that's the state of the |
|
||||||
* status register before the exception happened. When coming |
|
||||||
* out of the context switch we need this info to restore |
|
||||||
* IRQ lock state. We put this value in et earlier. |
|
||||||
*/ |
|
||||||
mov r4, et |
|
||||||
|
|
||||||
call arch_swap |
|
||||||
jmpi _exception_exit |
|
||||||
#else |
|
||||||
jmpi no_reschedule |
|
||||||
#endif /* CONFIG_PREEMPT_ENABLED */ |
|
||||||
|
|
||||||
not_interrupt: |
|
||||||
|
|
||||||
/* Since this wasn't an interrupt we're not going to restart the |
|
||||||
* faulting instruction. |
|
||||||
* |
|
||||||
* We earlier put ea - 4 in the stack frame, replace it with just ea |
|
||||||
*/ |
|
||||||
stw ea, __struct_arch_esf_instr_OFFSET(sp) |
|
||||||
|
|
||||||
#ifdef CONFIG_IRQ_OFFLOAD |
|
||||||
/* Check the contents of _offload_routine. If non-NULL, jump into |
|
||||||
* the interrupt code anyway. |
|
||||||
*/ |
|
||||||
movhi r10, %hi(_offload_routine) |
|
||||||
ori r10, r10, %lo(_offload_routine) |
|
||||||
ldw r11, (r10) |
|
||||||
bne r11, zero, is_interrupt |
|
||||||
#endif |
|
||||||
|
|
||||||
_exception_enter_fault: |
|
||||||
/* If we get here, the exception wasn't in interrupt or an |
|
||||||
* invocation of irq_offload(). Let z_nios2_fault() handle it in |
|
||||||
* C domain |
|
||||||
*/ |
|
||||||
|
|
||||||
mov r4, sp |
|
||||||
call z_nios2_fault |
|
||||||
jmpi _exception_exit |
|
||||||
|
|
||||||
no_reschedule: |
|
||||||
|
|
||||||
/* We put the thread stack pointer on top of the IRQ stack before |
|
||||||
* we switched stacks. Restore it to go back to thread stack |
|
||||||
*/ |
|
||||||
ldw sp, 0(sp) |
|
||||||
|
|
||||||
/* Fall through */ |
|
||||||
|
|
||||||
_exception_exit: |
|
||||||
/* We are on the thread stack. Restore all saved registers |
|
||||||
* and return to the interrupted context */ |
|
||||||
|
|
||||||
/* Return address from the exception */ |
|
||||||
ldw ea, __struct_arch_esf_instr_OFFSET(sp) |
|
||||||
|
|
||||||
/* Restore estatus |
|
||||||
* XXX is this right??? */ |
|
||||||
ldw r5, __struct_arch_esf_estatus_OFFSET(sp) |
|
||||||
wrctl estatus, r5 |
|
||||||
|
|
||||||
/* Restore caller-saved registers */ |
|
||||||
ldw ra, __struct_arch_esf_ra_OFFSET(sp) |
|
||||||
ldw r1, __struct_arch_esf_r1_OFFSET(sp) |
|
||||||
ldw r2, __struct_arch_esf_r2_OFFSET(sp) |
|
||||||
ldw r3, __struct_arch_esf_r3_OFFSET(sp) |
|
||||||
ldw r4, __struct_arch_esf_r4_OFFSET(sp) |
|
||||||
ldw r5, __struct_arch_esf_r5_OFFSET(sp) |
|
||||||
ldw r6, __struct_arch_esf_r6_OFFSET(sp) |
|
||||||
ldw r7, __struct_arch_esf_r7_OFFSET(sp) |
|
||||||
ldw r8, __struct_arch_esf_r8_OFFSET(sp) |
|
||||||
ldw r9, __struct_arch_esf_r9_OFFSET(sp) |
|
||||||
ldw r10, __struct_arch_esf_r10_OFFSET(sp) |
|
||||||
ldw r11, __struct_arch_esf_r11_OFFSET(sp) |
|
||||||
ldw r12, __struct_arch_esf_r12_OFFSET(sp) |
|
||||||
ldw r13, __struct_arch_esf_r13_OFFSET(sp) |
|
||||||
ldw r14, __struct_arch_esf_r14_OFFSET(sp) |
|
||||||
ldw r15, __struct_arch_esf_r15_OFFSET(sp) |
|
||||||
|
|
||||||
/* Put the stack pointer back where it was when we entered |
|
||||||
* exception state |
|
||||||
*/ |
|
||||||
addi sp, sp, __struct_arch_esf_SIZEOF |
|
||||||
|
|
||||||
/* All done, copy estatus into status and transfer to ea */ |
|
||||||
eret |
|
@ -1,144 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/arch/cpu.h> |
|
||||||
#include <zephyr/kernel_structs.h> |
|
||||||
#include <inttypes.h> |
|
||||||
#include <zephyr/logging/log.h> |
|
||||||
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); |
|
||||||
|
|
||||||
FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason, |
|
||||||
const struct arch_esf *esf) |
|
||||||
{ |
|
||||||
#if CONFIG_EXCEPTION_DEBUG |
|
||||||
if (esf != NULL) { |
|
||||||
/* Subtract 4 from EA since we added 4 earlier so that the
|
|
||||||
* faulting instruction isn't retried. |
|
||||||
* |
|
||||||
* TODO: Only caller-saved registers get saved upon exception |
|
||||||
* entry. We may want to introduce a config option to save and |
|
||||||
* dump all registers, at the expense of some stack space. |
|
||||||
*/ |
|
||||||
LOG_ERR("Faulting instruction: 0x%08x", esf->instr - 4); |
|
||||||
LOG_ERR(" r1: 0x%08x r2: 0x%08x r3: 0x%08x r4: 0x%08x", |
|
||||||
esf->r1, esf->r2, esf->r3, esf->r4); |
|
||||||
LOG_ERR(" r5: 0x%08x r6: 0x%08x r7: 0x%08x r8: 0x%08x", |
|
||||||
esf->r5, esf->r6, esf->r7, esf->r8); |
|
||||||
LOG_ERR(" r9: 0x%08x r10: 0x%08x r11: 0x%08x r12: 0x%08x", |
|
||||||
esf->r9, esf->r10, esf->r11, esf->r12); |
|
||||||
LOG_ERR(" r13: 0x%08x r14: 0x%08x r15: 0x%08x ra: 0x%08x", |
|
||||||
esf->r13, esf->r14, esf->r15, esf->ra); |
|
||||||
LOG_ERR("estatus: %08x", esf->estatus); |
|
||||||
} |
|
||||||
#endif /* CONFIG_EXCEPTION_DEBUG */ |
|
||||||
|
|
||||||
z_fatal_error(reason, esf); |
|
||||||
CODE_UNREACHABLE; |
|
||||||
} |
|
||||||
|
|
||||||
#if defined(CONFIG_EXTRA_EXCEPTION_INFO) && \ |
|
||||||
(defined(CONFIG_PRINTK) || defined(CONFIG_LOG)) \ |
|
||||||
&& defined(ALT_CPU_HAS_EXTRA_EXCEPTION_INFO) |
|
||||||
static char *cause_str(uint32_t cause_code) |
|
||||||
{ |
|
||||||
switch (cause_code) { |
|
||||||
case 0: |
|
||||||
return "reset"; |
|
||||||
case 1: |
|
||||||
return "processor-only reset request"; |
|
||||||
case 2: |
|
||||||
return "interrupt"; |
|
||||||
case 3: |
|
||||||
return "trap"; |
|
||||||
case 4: |
|
||||||
return "unimplemented instruction"; |
|
||||||
case 5: |
|
||||||
return "illegal instruction"; |
|
||||||
case 6: |
|
||||||
return "misaligned data address"; |
|
||||||
case 7: |
|
||||||
return "misaligned destination address"; |
|
||||||
case 8: |
|
||||||
return "division error"; |
|
||||||
case 9: |
|
||||||
return "supervisor-only instruction address"; |
|
||||||
case 10: |
|
||||||
return "supervisor-only instruction"; |
|
||||||
case 11: |
|
||||||
return "supervisor-only data address"; |
|
||||||
case 12: |
|
||||||
return "TLB miss"; |
|
||||||
case 13: |
|
||||||
return "TLB permission violation (execute)"; |
|
||||||
case 14: |
|
||||||
return "TLB permission violation (read)"; |
|
||||||
case 15: |
|
||||||
return "TLB permission violation (write)"; |
|
||||||
case 16: |
|
||||||
return "MPU region violation (instruction)"; |
|
||||||
case 17: |
|
||||||
return "MPU region violation (data)"; |
|
||||||
case 18: |
|
||||||
return "ECC TLB error"; |
|
||||||
case 19: |
|
||||||
return "ECC fetch error (instruction)"; |
|
||||||
case 20: |
|
||||||
return "ECC register file error"; |
|
||||||
case 21: |
|
||||||
return "ECC data error"; |
|
||||||
case 22: |
|
||||||
return "ECC data cache writeback error"; |
|
||||||
case 23: |
|
||||||
return "bus instruction fetch error"; |
|
||||||
case 24: |
|
||||||
return "bus data region violation"; |
|
||||||
default: |
|
||||||
return "unknown"; |
|
||||||
} |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
FUNC_NORETURN void z_nios2_fault(const struct arch_esf *esf) |
|
||||||
{ |
|
||||||
#if defined(CONFIG_PRINTK) || defined(CONFIG_LOG) |
|
||||||
/* Unfortunately, completely unavailable on Nios II/e cores */ |
|
||||||
#ifdef ALT_CPU_HAS_EXTRA_EXCEPTION_INFO |
|
||||||
uint32_t exc_reg, badaddr_reg, eccftl; |
|
||||||
enum nios2_exception_cause cause; |
|
||||||
|
|
||||||
exc_reg = z_nios2_creg_read(NIOS2_CR_EXCEPTION); |
|
||||||
|
|
||||||
/* Bit 31 indicates potentially fatal ECC error */ |
|
||||||
eccftl = (exc_reg & NIOS2_EXCEPTION_REG_ECCFTL_MASK) != 0U; |
|
||||||
|
|
||||||
/* Bits 2-6 contain the cause code */ |
|
||||||
cause = (exc_reg & NIOS2_EXCEPTION_REG_CAUSE_MASK) |
|
||||||
>> NIOS2_EXCEPTION_REG_CAUSE_OFST; |
|
||||||
|
|
||||||
LOG_ERR("Exception cause: %d ECCFTL: 0x%x", cause, eccftl); |
|
||||||
#if CONFIG_EXTRA_EXCEPTION_INFO |
|
||||||
LOG_ERR("reason: %s", cause_str(cause)); |
|
||||||
#endif |
|
||||||
if (BIT(cause) & NIOS2_BADADDR_CAUSE_MASK) { |
|
||||||
badaddr_reg = z_nios2_creg_read(NIOS2_CR_BADADDR); |
|
||||||
LOG_ERR("Badaddr: 0x%x", badaddr_reg); |
|
||||||
} |
|
||||||
#endif /* ALT_CPU_HAS_EXTRA_EXCEPTION_INFO */ |
|
||||||
#endif /* CONFIG_PRINTK || CONFIG_LOG */ |
|
||||||
|
|
||||||
z_nios2_fatal_error(K_ERR_CPU_EXCEPTION, esf); |
|
||||||
} |
|
||||||
|
|
||||||
#ifdef ALT_CPU_HAS_DEBUG_STUB |
|
||||||
FUNC_NORETURN void arch_system_halt(unsigned int reason) |
|
||||||
{ |
|
||||||
ARG_UNUSED(reason); |
|
||||||
|
|
||||||
z_nios2_break(); |
|
||||||
CODE_UNREACHABLE; |
|
||||||
} |
|
||||||
#endif |
|
@ -1,124 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
* @file |
|
||||||
* @brief Nios II C-domain interrupt management code for use with Internal |
|
||||||
* Interrupt Controller (IIC) |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/kernel_structs.h> |
|
||||||
#include <zephyr/arch/cpu.h> |
|
||||||
#include <zephyr/irq.h> |
|
||||||
#include <zephyr/sw_isr_table.h> |
|
||||||
#include <ksched.h> |
|
||||||
#include <kswap.h> |
|
||||||
#include <zephyr/tracing/tracing.h> |
|
||||||
#include <zephyr/logging/log.h> |
|
||||||
LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); |
|
||||||
|
|
||||||
FUNC_NORETURN void z_irq_spurious(const void *unused) |
|
||||||
{ |
|
||||||
ARG_UNUSED(unused); |
|
||||||
LOG_ERR("Spurious interrupt detected! ipending: %x", |
|
||||||
z_nios2_creg_read(NIOS2_CR_IPENDING)); |
|
||||||
z_nios2_fatal_error(K_ERR_SPURIOUS_IRQ, NULL); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void arch_irq_enable(unsigned int irq) |
|
||||||
{ |
|
||||||
uint32_t ienable; |
|
||||||
unsigned int key; |
|
||||||
|
|
||||||
key = irq_lock(); |
|
||||||
|
|
||||||
ienable = z_nios2_creg_read(NIOS2_CR_IENABLE); |
|
||||||
ienable |= BIT(irq); |
|
||||||
z_nios2_creg_write(NIOS2_CR_IENABLE, ienable); |
|
||||||
|
|
||||||
irq_unlock(key); |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void arch_irq_disable(unsigned int irq) |
|
||||||
{ |
|
||||||
uint32_t ienable; |
|
||||||
unsigned int key; |
|
||||||
|
|
||||||
key = irq_lock(); |
|
||||||
|
|
||||||
ienable = z_nios2_creg_read(NIOS2_CR_IENABLE); |
|
||||||
ienable &= ~BIT(irq); |
|
||||||
z_nios2_creg_write(NIOS2_CR_IENABLE, ienable); |
|
||||||
|
|
||||||
irq_unlock(key); |
|
||||||
}; |
|
||||||
|
|
||||||
int arch_irq_is_enabled(unsigned int irq) |
|
||||||
{ |
|
||||||
uint32_t ienable; |
|
||||||
|
|
||||||
ienable = z_nios2_creg_read(NIOS2_CR_IENABLE); |
|
||||||
return ienable & BIT(irq); |
|
||||||
} |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Interrupt demux function |
|
||||||
* |
|
||||||
* Given a bitfield of pending interrupts, execute the appropriate handler |
|
||||||
* |
|
||||||
* @param ipending Bitfield of interrupts |
|
||||||
*/ |
|
||||||
void _enter_irq(uint32_t ipending) |
|
||||||
{ |
|
||||||
int index; |
|
||||||
|
|
||||||
_kernel.cpus[0].nested++; |
|
||||||
|
|
||||||
#ifdef CONFIG_IRQ_OFFLOAD |
|
||||||
z_irq_do_offload(); |
|
||||||
#endif |
|
||||||
|
|
||||||
while (ipending) { |
|
||||||
struct _isr_table_entry *ite; |
|
||||||
|
|
||||||
#ifdef CONFIG_TRACING_ISR |
|
||||||
sys_trace_isr_enter(); |
|
||||||
#endif |
|
||||||
|
|
||||||
index = find_lsb_set(ipending) - 1; |
|
||||||
ipending &= ~BIT(index); |
|
||||||
|
|
||||||
ite = &_sw_isr_table[index]; |
|
||||||
|
|
||||||
ite->isr(ite->arg); |
|
||||||
#ifdef CONFIG_TRACING_ISR |
|
||||||
sys_trace_isr_exit(); |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
_kernel.cpus[0].nested--; |
|
||||||
#ifdef CONFIG_STACK_SENTINEL |
|
||||||
z_check_stack_sentinel(); |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
#ifdef CONFIG_DYNAMIC_INTERRUPTS |
|
||||||
int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, |
|
||||||
void (*routine)(const void *parameter), |
|
||||||
const void *parameter, uint32_t flags) |
|
||||||
{ |
|
||||||
ARG_UNUSED(flags); |
|
||||||
ARG_UNUSED(priority); |
|
||||||
|
|
||||||
z_isr_install(irq, routine, parameter); |
|
||||||
return irq; |
|
||||||
} |
|
||||||
#endif /* CONFIG_DYNAMIC_INTERRUPTS */ |
|
@ -1,47 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/kernel_structs.h> |
|
||||||
#include <zephyr/irq_offload.h> |
|
||||||
|
|
||||||
volatile irq_offload_routine_t _offload_routine; |
|
||||||
static volatile const void *offload_param; |
|
||||||
|
|
||||||
/* Called by _enter_irq if it was passed 0 for ipending.
|
|
||||||
* Just in case the offload routine itself generates an unhandled |
|
||||||
* exception, clear the offload_routine global before executing. |
|
||||||
*/ |
|
||||||
void z_irq_do_offload(void) |
|
||||||
{ |
|
||||||
irq_offload_routine_t tmp; |
|
||||||
|
|
||||||
if (!_offload_routine) { |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
tmp = _offload_routine; |
|
||||||
_offload_routine = NULL; |
|
||||||
|
|
||||||
tmp((const void *)offload_param); |
|
||||||
} |
|
||||||
|
|
||||||
void arch_irq_offload(irq_offload_routine_t routine, const void *parameter) |
|
||||||
{ |
|
||||||
unsigned int key; |
|
||||||
|
|
||||||
key = irq_lock(); |
|
||||||
_offload_routine = routine; |
|
||||||
offload_param = parameter; |
|
||||||
|
|
||||||
__asm__ volatile ("trap"); |
|
||||||
|
|
||||||
irq_unlock(key); |
|
||||||
} |
|
||||||
|
|
||||||
void arch_irq_offload_init(void) |
|
||||||
{ |
|
||||||
} |
|
@ -1,67 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
* @file |
|
||||||
* @brief Nios II kernel structure member offset definition file |
|
||||||
* |
|
||||||
* This module is responsible for the generation of the absolute symbols whose |
|
||||||
* value represents the member offsets for various Nios II kernel |
|
||||||
* structures. |
|
||||||
* |
|
||||||
* All of the absolute symbols defined by this module will be present in the |
|
||||||
* final kernel ELF image (due to the linker's reference to the _OffsetAbsSyms |
|
||||||
* symbol). |
|
||||||
* |
|
||||||
* INTERNAL |
|
||||||
* It is NOT necessary to define the offset for every member of a structure. |
|
||||||
* Typically, only those members that are accessed by assembly language routines |
|
||||||
* are defined; however, it doesn't hurt to define all fields for the sake of |
|
||||||
* completeness. |
|
||||||
*/ |
|
||||||
|
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <kernel_arch_data.h> |
|
||||||
#include <gen_offset.h> |
|
||||||
#include <kernel_offsets.h> |
|
||||||
|
|
||||||
/* struct coop member offsets */ |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r16); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r17); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r18); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r19); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r20); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r21); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r22); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r23); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, r28); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, ra); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, sp); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, key); |
|
||||||
GEN_OFFSET_SYM(_callee_saved_t, retval); |
|
||||||
|
|
||||||
GEN_OFFSET_STRUCT(arch_esf, ra); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r1); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r2); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r3); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r4); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r5); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r6); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r7); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r8); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r9); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r10); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r11); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r12); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r13); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r14); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, r15); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, estatus); |
|
||||||
GEN_OFFSET_STRUCT(arch_esf, instr); |
|
||||||
GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, sizeof(struct arch_esf)); |
|
||||||
|
|
||||||
GEN_ABS_SYM_END |
|
@ -1,59 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2014 Wind River Systems, Inc. |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
* @file |
|
||||||
* @brief Full C support initialization |
|
||||||
* |
|
||||||
* |
|
||||||
* Initialization of full C support: zero the .bss, copy the .data if XIP, |
|
||||||
* call z_cstart(). |
|
||||||
* |
|
||||||
* Stack is available in this module, but not the global data/bss until their |
|
||||||
* initialization is performed. |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/types.h> |
|
||||||
#include <zephyr/toolchain.h> |
|
||||||
#include <zephyr/linker/linker-defs.h> |
|
||||||
#include <zephyr/kernel_structs.h> |
|
||||||
#include <kernel_internal.h> |
|
||||||
#include <zephyr/platform/hooks.h> |
|
||||||
#include <zephyr/arch/cache.h> |
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prepare to and run C code |
|
||||||
* |
|
||||||
* This routine prepares for the execution of and runs C code. |
|
||||||
*/ |
|
||||||
|
|
||||||
void z_prep_c(void) |
|
||||||
{ |
|
||||||
#if defined(CONFIG_SOC_PREP_HOOK) |
|
||||||
soc_prep_hook(); |
|
||||||
#endif |
|
||||||
|
|
||||||
z_bss_zero(); |
|
||||||
z_data_copy(); |
|
||||||
/* In most XIP scenarios we copy the exception code into RAM, so need
|
|
||||||
* to flush instruction cache. |
|
||||||
*/ |
|
||||||
#ifdef CONFIG_XIP |
|
||||||
z_nios2_icache_flush_all(); |
|
||||||
#if ALT_CPU_ICACHE_SIZE > 0 |
|
||||||
/* Only need to flush the data cache here if there actually is an
|
|
||||||
* instruction cache, so that the cached instruction data written is |
|
||||||
* actually committed. |
|
||||||
*/ |
|
||||||
z_nios2_dcache_flush_all(); |
|
||||||
#endif |
|
||||||
#endif |
|
||||||
#if CONFIG_ARCH_CACHE |
|
||||||
arch_cache_init(); |
|
||||||
#endif |
|
||||||
z_cstart(); |
|
||||||
CODE_UNREACHABLE; |
|
||||||
} |
|
@ -1,10 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/toolchain.h> |
|
||||||
|
|
||||||
GTEXT(__start) |
|
||||||
|
|
@ -1,167 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/toolchain.h> |
|
||||||
#include <zephyr/linker/sections.h> |
|
||||||
#include <offsets_short.h> |
|
||||||
|
|
||||||
/* exports */ |
|
||||||
GTEXT(arch_swap) |
|
||||||
GTEXT(z_thread_entry_wrapper) |
|
||||||
|
|
||||||
/* imports */ |
|
||||||
GTEXT(_k_neg_eagain) |
|
||||||
|
|
||||||
/* unsigned int arch_swap(unsigned int key) |
|
||||||
* |
|
||||||
* Always called with interrupts locked |
|
||||||
*/ |
|
||||||
SECTION_FUNC(exception.other, arch_swap) |
|
||||||
|
|
||||||
#if defined(CONFIG_INSTRUMENT_THREAD_SWITCHING) |
|
||||||
/* Need to preserve r4 as it has the function argument. */ |
|
||||||
addi sp, sp, -12 |
|
||||||
stw ra, 8(sp) |
|
||||||
stw fp, 4(sp) |
|
||||||
stw r4, 0(sp) |
|
||||||
|
|
||||||
call z_thread_mark_switched_out |
|
||||||
|
|
||||||
ldw r4, 0(sp) |
|
||||||
ldw fp, 4(sp) |
|
||||||
ldw ra, 8(sp) |
|
||||||
addi sp, sp, 12 |
|
||||||
#endif |
|
||||||
|
|
||||||
/* Get a reference to _kernel in r10 */ |
|
||||||
movhi r10, %hi(_kernel) |
|
||||||
ori r10, r10, %lo(_kernel) |
|
||||||
|
|
||||||
/* Get the pointer to kernel->current */ |
|
||||||
ldw r11, _kernel_offset_to_current(r10) |
|
||||||
|
|
||||||
/* Store all the callee saved registers. We either got here via |
|
||||||
* an exception or from a cooperative invocation of arch_swap() from C |
|
||||||
* domain, so all the caller-saved registers have already been |
|
||||||
* saved by the exception asm or the calling C code already. |
|
||||||
*/ |
|
||||||
stw r16, _thread_offset_to_r16(r11) |
|
||||||
stw r17, _thread_offset_to_r17(r11) |
|
||||||
stw r18, _thread_offset_to_r18(r11) |
|
||||||
stw r19, _thread_offset_to_r19(r11) |
|
||||||
stw r20, _thread_offset_to_r20(r11) |
|
||||||
stw r21, _thread_offset_to_r21(r11) |
|
||||||
stw r22, _thread_offset_to_r22(r11) |
|
||||||
stw r23, _thread_offset_to_r23(r11) |
|
||||||
stw r28, _thread_offset_to_r28(r11) |
|
||||||
stw ra, _thread_offset_to_ra(r11) |
|
||||||
stw sp, _thread_offset_to_sp(r11) |
|
||||||
|
|
||||||
/* r4 has the 'key' argument which is the result of irq_lock() |
|
||||||
* before this was called |
|
||||||
*/ |
|
||||||
stw r4, _thread_offset_to_key(r11) |
|
||||||
|
|
||||||
/* Populate default return value */ |
|
||||||
movhi r5, %hi(_k_neg_eagain) |
|
||||||
ori r5, r5, %lo(_k_neg_eagain) |
|
||||||
ldw r4, (r5) |
|
||||||
stw r4, _thread_offset_to_retval(r11) |
|
||||||
|
|
||||||
/* get cached thread to run */ |
|
||||||
ldw r2, _kernel_offset_to_ready_q_cache(r10) |
|
||||||
|
|
||||||
/* At this point r2 points to the next thread to be swapped in */ |
|
||||||
|
|
||||||
/* the thread to be swapped in is now the current thread */ |
|
||||||
stw r2, _kernel_offset_to_current(r10) |
|
||||||
|
|
||||||
/* Restore callee-saved registers and switch to the incoming |
|
||||||
* thread's stack |
|
||||||
*/ |
|
||||||
ldw r16, _thread_offset_to_r16(r2) |
|
||||||
ldw r17, _thread_offset_to_r17(r2) |
|
||||||
ldw r18, _thread_offset_to_r18(r2) |
|
||||||
ldw r19, _thread_offset_to_r19(r2) |
|
||||||
ldw r20, _thread_offset_to_r20(r2) |
|
||||||
ldw r21, _thread_offset_to_r21(r2) |
|
||||||
ldw r22, _thread_offset_to_r22(r2) |
|
||||||
ldw r23, _thread_offset_to_r23(r2) |
|
||||||
ldw r28, _thread_offset_to_r28(r2) |
|
||||||
ldw ra, _thread_offset_to_ra(r2) |
|
||||||
ldw sp, _thread_offset_to_sp(r2) |
|
||||||
|
|
||||||
/* We need to irq_unlock(current->coopReg.key);
|
|
||||||
* key was supplied as argument to arch_swap(). Fetch it. |
|
||||||
*/ |
|
||||||
ldw r3, _thread_offset_to_key(r2) |
|
||||||
|
|
||||||
/* |
|
||||||
* Load return value into r2 (return value register). -EAGAIN unless |
|
||||||
* someone previously called arch_thread_return_value_set(). Do this |
|
||||||
* before we potentially unlock interrupts. |
|
||||||
*/ |
|
||||||
ldw r2, _thread_offset_to_retval(r2) |
|
||||||
|
|
||||||
/* Now do irq_unlock(current->coopReg.key) */ |
|
||||||
#if (ALT_CPU_NUM_OF_SHADOW_REG_SETS > 0) || \ |
|
||||||
(defined ALT_CPU_EIC_PRESENT) || \ |
|
||||||
(defined ALT_CPU_MMU_PRESENT) || \ |
|
||||||
(defined ALT_CPU_MPU_PRESENT) |
|
||||||
andi r3, r3, NIOS2_STATUS_PIE_MSK |
|
||||||
beq r3, zero, no_unlock |
|
||||||
rdctl r3, status |
|
||||||
ori r3, r3, NIOS2_STATUS_PIE_MSK |
|
||||||
wrctl status, r3 |
|
||||||
|
|
||||||
no_unlock: |
|
||||||
#else |
|
||||||
wrctl status, r3 |
|
||||||
#endif |
|
||||||
|
|
||||||
#if defined(CONFIG_INSTRUMENT_THREAD_SWITCHING) |
|
||||||
/* Also need to preserve r2, r3 as return values */ |
|
||||||
addi sp, sp, -20 |
|
||||||
stw ra, 16(sp) |
|
||||||
stw fp, 12(sp) |
|
||||||
stw r4, 8(sp) |
|
||||||
stw r3, 4(sp) |
|
||||||
stw r2, 0(sp) |
|
||||||
|
|
||||||
call z_thread_mark_switched_in |
|
||||||
|
|
||||||
ldw r2, 0(sp) |
|
||||||
ldw r3, 4(sp) |
|
||||||
ldw r4, 8(sp) |
|
||||||
ldw fp, 12(sp) |
|
||||||
ldw ra, 16(sp) |
|
||||||
addi sp, sp, 20 |
|
||||||
#endif |
|
||||||
ret |
|
||||||
|
|
||||||
|
|
||||||
/* void z_thread_entry_wrapper(void) |
|
||||||
*/ |
|
||||||
SECTION_FUNC(TEXT, z_thread_entry_wrapper) |
|
||||||
/* This all corresponds to struct init_stack_frame defined in |
|
||||||
* thread.c. We need to take this stuff off the stack and put |
|
||||||
* it in the appropriate registers |
|
||||||
*/ |
|
||||||
|
|
||||||
/* Can't return from here, just put NULL in ra */ |
|
||||||
movi ra, 0 |
|
||||||
|
|
||||||
/* Calling convention has first 4 arguments in registers r4-r7. */ |
|
||||||
ldw r4, 0(sp) |
|
||||||
ldw r5, 4(sp) |
|
||||||
ldw r6, 8(sp) |
|
||||||
ldw r7, 12(sp) |
|
||||||
|
|
||||||
/* pop all the stuff that we just loaded into registers */ |
|
||||||
addi sp, sp, 16 |
|
||||||
|
|
||||||
call z_thread_entry |
|
||||||
|
|
@ -1,50 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <ksched.h> |
|
||||||
|
|
||||||
/* forward declaration to asm function to adjust setup the arguments
|
|
||||||
* to z_thread_entry() since this arch puts the first four arguments |
|
||||||
* in r4-r7 and not on the stack |
|
||||||
*/ |
|
||||||
void z_thread_entry_wrapper(k_thread_entry_t, void *, void *, void *); |
|
||||||
|
|
||||||
struct init_stack_frame { |
|
||||||
/* top of the stack / most recently pushed */ |
|
||||||
|
|
||||||
/* Used by z_thread_entry_wrapper. pulls these off the stack and
|
|
||||||
* into argument registers before calling z_thread_entry() |
|
||||||
*/ |
|
||||||
k_thread_entry_t entry_point; |
|
||||||
void *arg1; |
|
||||||
void *arg2; |
|
||||||
void *arg3; |
|
||||||
|
|
||||||
/* least recently pushed */ |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, |
|
||||||
char *stack_ptr, k_thread_entry_t entry, |
|
||||||
void *arg1, void *arg2, void *arg3) |
|
||||||
{ |
|
||||||
struct init_stack_frame *iframe; |
|
||||||
|
|
||||||
/* Initial stack frame data, stored at the base of the stack */ |
|
||||||
iframe = Z_STACK_PTR_TO_FRAME(struct init_stack_frame, stack_ptr); |
|
||||||
|
|
||||||
/* Setup the initial stack frame */ |
|
||||||
iframe->entry_point = entry; |
|
||||||
iframe->arg1 = arg1; |
|
||||||
iframe->arg2 = arg2; |
|
||||||
iframe->arg3 = arg3; |
|
||||||
|
|
||||||
thread->callee_saved.sp = (uint32_t)iframe; |
|
||||||
thread->callee_saved.ra = (uint32_t)z_thread_entry_wrapper; |
|
||||||
thread->callee_saved.key = NIOS2_STATUS_PIE_MSK; |
|
||||||
/* Leave the rest of thread->callee_saved junk */ |
|
||||||
} |
|
@ -1,71 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2020 Intel Corporation. |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/sys_clock.h> |
|
||||||
#include <zephyr/timing/timing.h> |
|
||||||
#include "altera_avalon_timer_regs.h" |
|
||||||
|
|
||||||
#define NIOS2_SUBTRACT_CLOCK_CYCLES(val) \ |
|
||||||
((IORD_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE) << 16 | \ |
|
||||||
(IORD_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE))) - \ |
|
||||||
((uint32_t)val)) |
|
||||||
|
|
||||||
#define TIMING_INFO_OS_GET_TIME() \ |
|
||||||
(NIOS2_SUBTRACT_CLOCK_CYCLES( \ |
|
||||||
((uint32_t)IORD_ALTERA_AVALON_TIMER_SNAPH(TIMER_0_BASE) \ |
|
||||||
<< 16) | \ |
|
||||||
((uint32_t)IORD_ALTERA_AVALON_TIMER_SNAPL(TIMER_0_BASE)))) |
|
||||||
|
|
||||||
void arch_timing_init(void) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
void arch_timing_start(void) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
void arch_timing_stop(void) |
|
||||||
{ |
|
||||||
} |
|
||||||
|
|
||||||
timing_t arch_timing_counter_get(void) |
|
||||||
{ |
|
||||||
IOWR_ALTERA_AVALON_TIMER_SNAPL(TIMER_0_BASE, 10); |
|
||||||
return TIMING_INFO_OS_GET_TIME(); |
|
||||||
} |
|
||||||
|
|
||||||
uint64_t arch_timing_cycles_get(volatile timing_t *const start, |
|
||||||
volatile timing_t *const end) |
|
||||||
{ |
|
||||||
timing_t start_ = *start; |
|
||||||
timing_t end_ = *end; |
|
||||||
|
|
||||||
if (end_ >= start_) { |
|
||||||
return (end_ - start_); |
|
||||||
} |
|
||||||
return (end_ + NIOS2_SUBTRACT_CLOCK_CYCLES(start_)); |
|
||||||
} |
|
||||||
|
|
||||||
uint64_t arch_timing_freq_get(void) |
|
||||||
{ |
|
||||||
return sys_clock_hw_cycles_per_sec(); |
|
||||||
} |
|
||||||
|
|
||||||
uint64_t arch_timing_cycles_to_ns(uint64_t cycles) |
|
||||||
{ |
|
||||||
return k_cyc_to_ns_floor64(cycles); |
|
||||||
} |
|
||||||
|
|
||||||
uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count) |
|
||||||
{ |
|
||||||
return arch_timing_cycles_to_ns(cycles) / count; |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t arch_timing_freq_get_mhz(void) |
|
||||||
{ |
|
||||||
return (uint32_t)(arch_timing_freq_get() / 1000000U); |
|
||||||
} |
|
@ -1,45 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* Copyright (c) 2016 Wind River Systems, Inc. |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
* @file |
|
||||||
* @brief Private kernel definitions |
|
||||||
* |
|
||||||
* This file contains private kernel structures definitions and various |
|
||||||
* other definitions for the Nios II processor architecture. |
|
||||||
* |
|
||||||
* This file is also included by assembly language files which must #define |
|
||||||
* _ASMLANGUAGE before including this header file. Note that kernel |
|
||||||
* assembly source files obtains structure offset values via "absolute |
|
||||||
* symbols" in the offsets.o module. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_ARCH_NIOS2_INCLUDE_KERNEL_ARCH_DATA_H_ |
|
||||||
#define ZEPHYR_ARCH_NIOS2_INCLUDE_KERNEL_ARCH_DATA_H_ |
|
||||||
|
|
||||||
#include <zephyr/toolchain.h> |
|
||||||
#include <zephyr/linker/sections.h> |
|
||||||
#include <zephyr/arch/cpu.h> |
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/types.h> |
|
||||||
#include <zephyr/sys/util.h> |
|
||||||
#include <zephyr/sys/dlist.h> |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */ |
|
||||||
|
|
||||||
#endif /* ZEPHYR_ARCH_NIOS2_INCLUDE_KERNEL_ARCH_DATA_H_ */ |
|
@ -1,80 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
* @file |
|
||||||
* @brief Private kernel definitions |
|
||||||
* |
|
||||||
* This file contains private kernel function/macro definitions and various |
|
||||||
* other definitions for the Nios II processor architecture. |
|
||||||
* |
|
||||||
* This file is also included by assembly language files which must #define |
|
||||||
* _ASMLANGUAGE before including this header file. Note that kernel |
|
||||||
* assembly source files obtains structure offset values via "absolute |
|
||||||
* symbols" in the offsets.o module. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_ARCH_NIOS2_INCLUDE_KERNEL_ARCH_FUNC_H_ |
|
||||||
#define ZEPHYR_ARCH_NIOS2_INCLUDE_KERNEL_ARCH_FUNC_H_ |
|
||||||
|
|
||||||
#include <kernel_arch_data.h> |
|
||||||
|
|
||||||
#include <zephyr/platform/hooks.h> |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE |
|
||||||
|
|
||||||
static ALWAYS_INLINE void arch_kernel_init(void) |
|
||||||
{ |
|
||||||
#ifdef CONFIG_SOC_PER_CORE_INIT_HOOK |
|
||||||
soc_per_core_init_hook(); |
|
||||||
#endif /* CONFIG_SOC_PER_CORE_INIT_HOOK */ |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE void |
|
||||||
arch_thread_return_value_set(struct k_thread *thread, unsigned int value) |
|
||||||
{ |
|
||||||
thread->callee_saved.retval = value; |
|
||||||
} |
|
||||||
|
|
||||||
FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason, |
|
||||||
const struct arch_esf *esf); |
|
||||||
|
|
||||||
static inline bool arch_is_in_isr(void) |
|
||||||
{ |
|
||||||
return _kernel.cpus[0].nested != 0U; |
|
||||||
} |
|
||||||
|
|
||||||
int arch_swap(unsigned int key); |
|
||||||
|
|
||||||
#ifdef CONFIG_IRQ_OFFLOAD |
|
||||||
void z_irq_do_offload(void); |
|
||||||
#endif |
|
||||||
|
|
||||||
#if ALT_CPU_ICACHE_SIZE > 0 |
|
||||||
void z_nios2_icache_flush_all(void); |
|
||||||
#else |
|
||||||
#define z_nios2_icache_flush_all() do { } while (false) |
|
||||||
#endif |
|
||||||
|
|
||||||
#if ALT_CPU_DCACHE_SIZE > 0 |
|
||||||
void z_nios2_dcache_flush_all(void); |
|
||||||
void z_nios2_dcache_flush_no_writeback(void *start, uint32_t len); |
|
||||||
#else |
|
||||||
#define z_nios2_dcache_flush_all() do { } while (false) |
|
||||||
#define z_nios2_dcache_flush_no_writeback(x, y) do { } while (false) |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */ |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* ZEPHYR_ARCH_NIOS2_INCLUDE_KERNEL_ARCH_FUNC_H_ */ |
|
@ -1,61 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Wind River Systems, Inc. |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_ARCH_NIOS2_INCLUDE_OFFSETS_SHORT_ARCH_H_ |
|
||||||
#define ZEPHYR_ARCH_NIOS2_INCLUDE_OFFSETS_SHORT_ARCH_H_ |
|
||||||
|
|
||||||
#include <zephyr/offsets.h> |
|
||||||
|
|
||||||
/* kernel */ |
|
||||||
|
|
||||||
/* nothing for now */ |
|
||||||
|
|
||||||
/* end - kernel */ |
|
||||||
|
|
||||||
/* threads */ |
|
||||||
|
|
||||||
#define _thread_offset_to_r16 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r16_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r17 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r17_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r18 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r18_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r19 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r19_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r20 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r20_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r21 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r21_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r22 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r22_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r23 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r23_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_r28 \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_r28_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_ra \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_ra_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_sp \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_sp_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_key \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_key_OFFSET) |
|
||||||
|
|
||||||
#define _thread_offset_to_retval \ |
|
||||||
(___thread_t_callee_saved_OFFSET + ___callee_saved_t_retval_OFFSET) |
|
||||||
|
|
||||||
/* end - threads */ |
|
||||||
|
|
||||||
#endif /* ZEPHYR_ARCH_NIOS2_INCLUDE_OFFSETS_SHORT_ARCH_H_ */ |
|
@ -1,11 +0,0 @@ |
|||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
config SOC_FLASH_NIOS2_QSPI |
|
||||||
bool "Nios-II QSPI flash driver" |
|
||||||
default y |
|
||||||
depends on HAS_ALTERA_HAL |
|
||||||
depends on DT_HAS_ALTR_NIOS2_QSPI_NOR_ENABLED |
|
||||||
select FLASH_HAS_DRIVER_ENABLED |
|
||||||
select FLASH_HAS_EXPLICIT_ERASE |
|
||||||
help |
|
||||||
Enables the Nios-II QSPI flash driver. |
|
@ -1,531 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2017 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/*
|
|
||||||
* This driver is written based on the Altera's |
|
||||||
* Nios-II QSPI Controller HAL driver. |
|
||||||
*/ |
|
||||||
|
|
||||||
#define DT_DRV_COMPAT altr_nios2_qspi_nor |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/device.h> |
|
||||||
#include <string.h> |
|
||||||
#include <zephyr/drivers/flash.h> |
|
||||||
#include <errno.h> |
|
||||||
#include <zephyr/init.h> |
|
||||||
#include <soc.h> |
|
||||||
#include <zephyr/sys/util.h> |
|
||||||
#include "flash_priv.h" |
|
||||||
#include "altera_generic_quad_spi_controller2_regs.h" |
|
||||||
#include "altera_generic_quad_spi_controller2.h" |
|
||||||
|
|
||||||
#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL |
|
||||||
#include <zephyr/logging/log.h> |
|
||||||
LOG_MODULE_REGISTER(flash_nios2_qspi); |
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove the following macros once the Altera HAL |
|
||||||
* supports the QSPI Controller v2 IP. |
|
||||||
*/ |
|
||||||
#define ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG 0x0000001C |
|
||||||
#define FLAG_STATUS_PROTECTION_ERROR (1 << 1) |
|
||||||
#define FLAG_STATUS_PROGRAM_SUSPENDED (1 << 2) |
|
||||||
#define FLAG_STATUS_PROGRAM_ERROR (1 << 4) |
|
||||||
#define FLAG_STATUS_ERASE_ERROR (1 << 5) |
|
||||||
#define FLAG_STATUS_ERASE_SUSPENDED (1 << 6) |
|
||||||
#define FLAG_STATUS_CONTROLLER_READY (1 << 7) |
|
||||||
|
|
||||||
/* ALTERA_QSPI_CONTROLLER2_STATUS_REG bits */ |
|
||||||
#define STATUS_PROTECTION_POS 2 |
|
||||||
#define STATUS_PROTECTION_MASK 0x1F |
|
||||||
#define STATUS_PROTECTION_EN_VAL 0x17 |
|
||||||
#define STATUS_PROTECTION_DIS_VAL 0x0 |
|
||||||
|
|
||||||
/* ALTERA_QSPI_CONTROLLER2_MEM_OP_REG bits */ |
|
||||||
#define MEM_OP_ERASE_CMD 0x00000002 |
|
||||||
#define MEM_OP_WRITE_EN_CMD 0x00000004 |
|
||||||
#define MEM_OP_SECTOR_OFFSET_BIT_POS 8 |
|
||||||
#define MEM_OP_UNLOCK_ALL_SECTORS 0x00000003 |
|
||||||
#define MEM_OP_LOCK_ALL_SECTORS 0x00000F03 |
|
||||||
|
|
||||||
#define NIOS2_QSPI_BLANK_WORD 0xFFFFFFFF |
|
||||||
|
|
||||||
#define NIOS2_WRITE_BLOCK_SIZE 4 |
|
||||||
|
|
||||||
#define USEC_TO_MSEC(x) (x / 1000) |
|
||||||
|
|
||||||
struct flash_nios2_qspi_config { |
|
||||||
alt_qspi_controller2_dev qspi_dev; |
|
||||||
struct k_sem sem_lock; |
|
||||||
}; |
|
||||||
|
|
||||||
static const struct flash_parameters flash_nios2_qspi_parameters = { |
|
||||||
.write_block_size = NIOS2_WRITE_BLOCK_SIZE, |
|
||||||
.erase_value = 0xff, |
|
||||||
}; |
|
||||||
|
|
||||||
static int flash_nios2_qspi_write_protection(const struct device *dev, |
|
||||||
bool enable); |
|
||||||
|
|
||||||
static int flash_nios2_qspi_erase(const struct device *dev, off_t offset, |
|
||||||
size_t len) |
|
||||||
{ |
|
||||||
struct flash_nios2_qspi_config *flash_cfg = dev->data; |
|
||||||
alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev; |
|
||||||
uint32_t block_offset, offset_in_block, length_to_erase; |
|
||||||
uint32_t erase_offset = offset; /* address of next byte to erase */ |
|
||||||
uint32_t remaining_length = len; /* length of data left to be erased */ |
|
||||||
uint32_t flag_status; |
|
||||||
int32_t rc = 0, i, timeout, rc2; |
|
||||||
|
|
||||||
k_sem_take(&flash_cfg->sem_lock, K_FOREVER); |
|
||||||
|
|
||||||
rc = flash_nios2_qspi_write_protection(dev, false); |
|
||||||
if (rc) { |
|
||||||
goto qspi_erase_err; |
|
||||||
} |
|
||||||
/*
|
|
||||||
* check if offset is word aligned and |
|
||||||
* length is with in the range |
|
||||||
*/ |
|
||||||
if (((offset + len) > qspi_dev->data_end) || |
|
||||||
(0 != (erase_offset & |
|
||||||
(NIOS2_WRITE_BLOCK_SIZE - 1)))) { |
|
||||||
LOG_ERR("erase failed at offset 0x%lx", (long)offset); |
|
||||||
rc = -EINVAL; |
|
||||||
goto qspi_erase_err; |
|
||||||
} |
|
||||||
|
|
||||||
for (i = offset/qspi_dev->sector_size; |
|
||||||
i < qspi_dev->number_of_sectors; i++) { |
|
||||||
|
|
||||||
if ((remaining_length <= 0U) || |
|
||||||
erase_offset >= (offset + len)) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
block_offset = 0U; /* block offset in byte addressing */ |
|
||||||
offset_in_block = 0U; /* offset into current sector to erase */ |
|
||||||
length_to_erase = 0U; /* length to erase in current sector */ |
|
||||||
|
|
||||||
/* calculate current sector/block offset in byte addressing */ |
|
||||||
block_offset = erase_offset & ~(qspi_dev->sector_size - 1); |
|
||||||
|
|
||||||
/* calculate offset into sector/block if there is one */ |
|
||||||
if (block_offset != erase_offset) { |
|
||||||
offset_in_block = erase_offset - block_offset; |
|
||||||
} |
|
||||||
|
|
||||||
/* calculate the byte size of data to be written in a sector */ |
|
||||||
length_to_erase = MIN(qspi_dev->sector_size - offset_in_block, |
|
||||||
remaining_length); |
|
||||||
|
|
||||||
/* Erase sector */ |
|
||||||
IOWR_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_MEM_OP_REG, |
|
||||||
MEM_OP_WRITE_EN_CMD); |
|
||||||
IOWR_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_MEM_OP_REG, |
|
||||||
(i << MEM_OP_SECTOR_OFFSET_BIT_POS) |
|
||||||
| MEM_OP_ERASE_CMD); |
|
||||||
|
|
||||||
/*
|
|
||||||
* poll the status register to know the |
|
||||||
* completion of the erase operation. |
|
||||||
*/ |
|
||||||
timeout = ALTERA_QSPI_CONTROLLER2_1US_TIMEOUT_VALUE; |
|
||||||
while (timeout > 0) { |
|
||||||
/* wait for 1 usec */ |
|
||||||
k_busy_wait(1); |
|
||||||
|
|
||||||
flag_status = IORD_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG); |
|
||||||
|
|
||||||
if (flag_status & FLAG_STATUS_CONTROLLER_READY) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
timeout--; |
|
||||||
} |
|
||||||
|
|
||||||
if ((flag_status & FLAG_STATUS_ERASE_ERROR) || |
|
||||||
(flag_status & FLAG_STATUS_PROTECTION_ERROR)) { |
|
||||||
LOG_ERR("erase failed, Flag Status Reg:0x%x", |
|
||||||
flag_status); |
|
||||||
rc = -EIO; |
|
||||||
goto qspi_erase_err; |
|
||||||
} |
|
||||||
|
|
||||||
/* update remaining length and erase_offset */ |
|
||||||
remaining_length -= length_to_erase; |
|
||||||
erase_offset += length_to_erase; |
|
||||||
} |
|
||||||
|
|
||||||
qspi_erase_err: |
|
||||||
rc2 = flash_nios2_qspi_write_protection(dev, true); |
|
||||||
|
|
||||||
if (!rc) { |
|
||||||
rc = rc2; |
|
||||||
} |
|
||||||
|
|
||||||
k_sem_give(&flash_cfg->sem_lock); |
|
||||||
return rc; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
static int flash_nios2_qspi_write_block(const struct device *dev, |
|
||||||
int block_offset, |
|
||||||
int mem_offset, const void *data, |
|
||||||
size_t len) |
|
||||||
{ |
|
||||||
struct flash_nios2_qspi_config *flash_cfg = dev->data; |
|
||||||
alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev; |
|
||||||
uint32_t buffer_offset = 0U; /* offset into data buffer to get write data */ |
|
||||||
int32_t remaining_length = len; /* length left to write */ |
|
||||||
uint32_t write_offset = mem_offset; /* offset into flash to write too */ |
|
||||||
uint32_t word_to_write, padding, bytes_to_copy; |
|
||||||
uint32_t flag_status; |
|
||||||
int32_t rc = 0; |
|
||||||
|
|
||||||
while (remaining_length > 0) { |
|
||||||
/* initialize word to write to blank word */ |
|
||||||
word_to_write = NIOS2_QSPI_BLANK_WORD; |
|
||||||
|
|
||||||
/* bytes to pad the next word that is written */ |
|
||||||
padding = 0U; |
|
||||||
|
|
||||||
/* number of bytes from source to copy */ |
|
||||||
bytes_to_copy = NIOS2_WRITE_BLOCK_SIZE; |
|
||||||
|
|
||||||
/*
|
|
||||||
* we need to make sure the write is word aligned |
|
||||||
* this should only be true at most 1 time |
|
||||||
*/ |
|
||||||
if (0 != (write_offset & (NIOS2_WRITE_BLOCK_SIZE - 1))) { |
|
||||||
/*
|
|
||||||
* data is not word aligned calculate padding bytes |
|
||||||
* need to add before start of a data offset |
|
||||||
*/ |
|
||||||
padding = write_offset & (NIOS2_WRITE_BLOCK_SIZE - 1); |
|
||||||
|
|
||||||
/*
|
|
||||||
* update variables to account |
|
||||||
* for padding being added |
|
||||||
*/ |
|
||||||
bytes_to_copy -= padding; |
|
||||||
|
|
||||||
if (bytes_to_copy > remaining_length) { |
|
||||||
bytes_to_copy = remaining_length; |
|
||||||
} |
|
||||||
|
|
||||||
write_offset = write_offset - padding; |
|
||||||
|
|
||||||
if (0 != (write_offset & |
|
||||||
(NIOS2_WRITE_BLOCK_SIZE - 1))) { |
|
||||||
rc = -EINVAL; |
|
||||||
goto qspi_write_block_err; |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (bytes_to_copy > remaining_length) { |
|
||||||
bytes_to_copy = remaining_length; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* Check memcpy length is within NIOS2_WRITE_BLOCK_SIZE */ |
|
||||||
if (padding + bytes_to_copy > NIOS2_WRITE_BLOCK_SIZE) { |
|
||||||
rc = -EINVAL; |
|
||||||
goto qspi_write_block_err; |
|
||||||
} |
|
||||||
|
|
||||||
/* prepare the word to be written */ |
|
||||||
memcpy((uint8_t *)&word_to_write + padding, |
|
||||||
(const uint8_t *)data + buffer_offset, |
|
||||||
bytes_to_copy); |
|
||||||
|
|
||||||
/* enable write */ |
|
||||||
IOWR_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_MEM_OP_REG, |
|
||||||
MEM_OP_WRITE_EN_CMD); |
|
||||||
|
|
||||||
/* write to flash 32 bits at a time */ |
|
||||||
IOWR_32DIRECT(qspi_dev->data_base, write_offset, word_to_write); |
|
||||||
|
|
||||||
/* check whether write operation is successful */ |
|
||||||
flag_status = IORD_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG); |
|
||||||
|
|
||||||
if ((flag_status & FLAG_STATUS_PROGRAM_ERROR) || |
|
||||||
(flag_status & FLAG_STATUS_PROTECTION_ERROR)) { |
|
||||||
LOG_ERR("write failed, Flag Status Reg:0x%x", |
|
||||||
flag_status); |
|
||||||
rc = -EIO; /* sector might be protected */ |
|
||||||
goto qspi_write_block_err; |
|
||||||
} |
|
||||||
|
|
||||||
/* update offset and length variables */ |
|
||||||
buffer_offset += bytes_to_copy; |
|
||||||
remaining_length -= bytes_to_copy; |
|
||||||
write_offset = write_offset + NIOS2_WRITE_BLOCK_SIZE; |
|
||||||
} |
|
||||||
|
|
||||||
qspi_write_block_err: |
|
||||||
return rc; |
|
||||||
} |
|
||||||
|
|
||||||
static int flash_nios2_qspi_write(const struct device *dev, off_t offset, |
|
||||||
const void *data, size_t len) |
|
||||||
{ |
|
||||||
struct flash_nios2_qspi_config *flash_cfg = dev->data; |
|
||||||
alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev; |
|
||||||
uint32_t block_offset, offset_in_block, length_to_write; |
|
||||||
uint32_t write_offset = offset; /* address of next byte to write */ |
|
||||||
uint32_t buffer_offset = 0U; /* offset into source buffer */ |
|
||||||
uint32_t remaining_length = len; /* length of data left to be written */ |
|
||||||
int32_t rc = 0, i, rc2; |
|
||||||
|
|
||||||
k_sem_take(&flash_cfg->sem_lock, K_FOREVER); |
|
||||||
|
|
||||||
rc = flash_nios2_qspi_write_protection(dev, false); |
|
||||||
if (rc) { |
|
||||||
goto qspi_write_err; |
|
||||||
} |
|
||||||
/*
|
|
||||||
* check if offset is word aligned and |
|
||||||
* length is with in the range |
|
||||||
*/ |
|
||||||
if ((data == NULL) || ((offset + len) > qspi_dev->data_end) || |
|
||||||
(0 != (write_offset & |
|
||||||
(NIOS2_WRITE_BLOCK_SIZE - 1)))) { |
|
||||||
LOG_ERR("write failed at offset 0x%lx", (long)offset); |
|
||||||
rc = -EINVAL; |
|
||||||
goto qspi_write_err; |
|
||||||
} |
|
||||||
|
|
||||||
for (i = offset/qspi_dev->sector_size; |
|
||||||
i < qspi_dev->number_of_sectors; i++) { |
|
||||||
|
|
||||||
if (remaining_length <= 0U) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
block_offset = 0U; /* block offset in byte addressing */ |
|
||||||
offset_in_block = 0U; /* offset into current sector to write */ |
|
||||||
length_to_write = 0U; /* length to write to current sector */ |
|
||||||
|
|
||||||
/* calculate current sector/block offset in byte addressing */ |
|
||||||
block_offset = write_offset & ~(qspi_dev->sector_size - 1); |
|
||||||
|
|
||||||
/* calculate offset into sector/block if there is one */ |
|
||||||
if (block_offset != write_offset) { |
|
||||||
offset_in_block = write_offset - block_offset; |
|
||||||
} |
|
||||||
|
|
||||||
/* calculate the byte size of data to be written in a sector */ |
|
||||||
length_to_write = MIN(qspi_dev->sector_size - offset_in_block, |
|
||||||
remaining_length); |
|
||||||
|
|
||||||
rc = flash_nios2_qspi_write_block(dev, |
|
||||||
block_offset, write_offset, |
|
||||||
(const uint8_t *)data + buffer_offset, |
|
||||||
length_to_write); |
|
||||||
if (rc < 0) { |
|
||||||
goto qspi_write_err; |
|
||||||
} |
|
||||||
|
|
||||||
/* update remaining length and buffer_offset */ |
|
||||||
remaining_length -= length_to_write; |
|
||||||
buffer_offset += length_to_write; |
|
||||||
write_offset += length_to_write; |
|
||||||
} |
|
||||||
|
|
||||||
qspi_write_err: |
|
||||||
rc2 = flash_nios2_qspi_write_protection(dev, true); |
|
||||||
|
|
||||||
if (!rc) { |
|
||||||
rc = rc2; |
|
||||||
} |
|
||||||
|
|
||||||
k_sem_give(&flash_cfg->sem_lock); |
|
||||||
return rc; |
|
||||||
} |
|
||||||
|
|
||||||
static int flash_nios2_qspi_read(const struct device *dev, off_t offset, |
|
||||||
void *data, size_t len) |
|
||||||
{ |
|
||||||
struct flash_nios2_qspi_config *flash_cfg = dev->data; |
|
||||||
alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev; |
|
||||||
uint32_t buffer_offset = 0U; /* offset into data buffer to get read data */ |
|
||||||
uint32_t remaining_length = len; /* length left to read */ |
|
||||||
uint32_t read_offset = offset; /* offset into flash to read from */ |
|
||||||
uint32_t word_to_read, bytes_to_copy; |
|
||||||
int32_t rc = 0; |
|
||||||
|
|
||||||
/*
|
|
||||||
* check if offset and length are within the range |
|
||||||
*/ |
|
||||||
if ((data == NULL) || (offset < qspi_dev->data_base) || |
|
||||||
((offset + len) > qspi_dev->data_end)) { |
|
||||||
LOG_ERR("read failed at offset 0x%lx", (long)offset); |
|
||||||
return -EINVAL; |
|
||||||
} |
|
||||||
|
|
||||||
if (!len) { |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
k_sem_take(&flash_cfg->sem_lock, K_FOREVER); |
|
||||||
|
|
||||||
/* first unaligned start */ |
|
||||||
read_offset &= ~(NIOS2_WRITE_BLOCK_SIZE - 1U); |
|
||||||
if (offset > read_offset) { |
|
||||||
/* number of bytes from source to copy */ |
|
||||||
bytes_to_copy = NIOS2_WRITE_BLOCK_SIZE - (offset - read_offset); |
|
||||||
if (bytes_to_copy > remaining_length) { |
|
||||||
bytes_to_copy = remaining_length; |
|
||||||
} |
|
||||||
/* read from flash 32 bits at a time */ |
|
||||||
word_to_read = IORD_32DIRECT(qspi_dev->data_base, read_offset); |
|
||||||
memcpy((uint8_t *)data, (uint8_t *)&word_to_read + offset - |
|
||||||
read_offset, bytes_to_copy); |
|
||||||
/* update offset and length variables */ |
|
||||||
read_offset += NIOS2_WRITE_BLOCK_SIZE; |
|
||||||
buffer_offset += bytes_to_copy; |
|
||||||
remaining_length -= bytes_to_copy; |
|
||||||
} |
|
||||||
|
|
||||||
/* aligned part, including unaligned end */ |
|
||||||
while (remaining_length > 0) { |
|
||||||
/* number of bytes from source to copy */ |
|
||||||
bytes_to_copy = NIOS2_WRITE_BLOCK_SIZE; |
|
||||||
|
|
||||||
if (bytes_to_copy > remaining_length) { |
|
||||||
bytes_to_copy = remaining_length; |
|
||||||
} |
|
||||||
|
|
||||||
/* read from flash 32 bits at a time */ |
|
||||||
word_to_read = IORD_32DIRECT(qspi_dev->data_base, read_offset); |
|
||||||
memcpy((uint8_t *)data + buffer_offset, &word_to_read, |
|
||||||
bytes_to_copy); |
|
||||||
/* update offset and length variables */ |
|
||||||
read_offset += bytes_to_copy; |
|
||||||
buffer_offset += bytes_to_copy; |
|
||||||
remaining_length -= bytes_to_copy; |
|
||||||
} |
|
||||||
|
|
||||||
k_sem_give(&flash_cfg->sem_lock); |
|
||||||
return rc; |
|
||||||
} |
|
||||||
|
|
||||||
static int flash_nios2_qspi_write_protection(const struct device *dev, |
|
||||||
bool enable) |
|
||||||
{ |
|
||||||
struct flash_nios2_qspi_config *flash_cfg = dev->data; |
|
||||||
alt_qspi_controller2_dev *qspi_dev = &flash_cfg->qspi_dev; |
|
||||||
uint32_t status, lock_val; |
|
||||||
int32_t rc = 0, timeout; |
|
||||||
|
|
||||||
/* set write enable */ |
|
||||||
IOWR_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_MEM_OP_REG, |
|
||||||
MEM_OP_WRITE_EN_CMD); |
|
||||||
if (enable) { |
|
||||||
IOWR_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_MEM_OP_REG, |
|
||||||
MEM_OP_LOCK_ALL_SECTORS); |
|
||||||
lock_val = STATUS_PROTECTION_EN_VAL; |
|
||||||
} else { |
|
||||||
IOWR_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_MEM_OP_REG, |
|
||||||
MEM_OP_UNLOCK_ALL_SECTORS); |
|
||||||
lock_val = STATUS_PROTECTION_DIS_VAL; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* poll the status register to know the |
|
||||||
* completion of the erase operation. |
|
||||||
*/ |
|
||||||
timeout = ALTERA_QSPI_CONTROLLER2_1US_TIMEOUT_VALUE; |
|
||||||
while (timeout > 0) { |
|
||||||
/* wait for 1 usec */ |
|
||||||
k_busy_wait(1); |
|
||||||
|
|
||||||
/*
|
|
||||||
* read flash flag status register before |
|
||||||
* checking the QSPI status |
|
||||||
*/ |
|
||||||
IORD_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG); |
|
||||||
|
|
||||||
/* read QPSI status register */ |
|
||||||
status = IORD_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_STATUS_REG); |
|
||||||
if (((status >> STATUS_PROTECTION_POS) & |
|
||||||
STATUS_PROTECTION_MASK) == lock_val) { |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
timeout--; |
|
||||||
} |
|
||||||
|
|
||||||
if (timeout <= 0) { |
|
||||||
LOG_ERR("locking failed, status-reg 0x%x", status); |
|
||||||
rc = -EIO; |
|
||||||
} |
|
||||||
|
|
||||||
/* clear flag status register */ |
|
||||||
IOWR_32DIRECT(qspi_dev->csr_base, |
|
||||||
ALTERA_QSPI_CONTROLLER2_FLAG_STATUS_REG, 0x0); |
|
||||||
return rc; |
|
||||||
} |
|
||||||
|
|
||||||
static const struct flash_parameters * |
|
||||||
flash_nios2_qspi_get_parameters(const struct device *dev) |
|
||||||
{ |
|
||||||
ARG_UNUSED(dev); |
|
||||||
|
|
||||||
return &flash_nios2_qspi_parameters; |
|
||||||
} |
|
||||||
|
|
||||||
static DEVICE_API(flash, flash_nios2_qspi_api) = { |
|
||||||
.erase = flash_nios2_qspi_erase, |
|
||||||
.write = flash_nios2_qspi_write, |
|
||||||
.read = flash_nios2_qspi_read, |
|
||||||
.get_parameters = flash_nios2_qspi_get_parameters, |
|
||||||
#if defined(CONFIG_FLASH_PAGE_LAYOUT) |
|
||||||
.page_layout = (flash_api_pages_layout) |
|
||||||
flash_page_layout_not_implemented, |
|
||||||
#endif |
|
||||||
}; |
|
||||||
|
|
||||||
static int flash_nios2_qspi_init(const struct device *dev) |
|
||||||
{ |
|
||||||
struct flash_nios2_qspi_config *flash_cfg = dev->data; |
|
||||||
|
|
||||||
k_sem_init(&flash_cfg->sem_lock, 1, 1); |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
struct flash_nios2_qspi_config flash_cfg = { |
|
||||||
.qspi_dev = { |
|
||||||
.data_base = EXT_FLASH_AVL_MEM_BASE, |
|
||||||
.data_end = EXT_FLASH_AVL_MEM_BASE + EXT_FLASH_AVL_MEM_SPAN, |
|
||||||
.csr_base = EXT_FLASH_AVL_CSR_BASE, |
|
||||||
.size_in_bytes = EXT_FLASH_AVL_MEM_SPAN, |
|
||||||
.is_epcs = EXT_FLASH_AVL_MEM_IS_EPCS, |
|
||||||
.number_of_sectors = EXT_FLASH_AVL_MEM_NUMBER_OF_SECTORS, |
|
||||||
.sector_size = EXT_FLASH_AVL_MEM_SECTOR_SIZE, |
|
||||||
.page_size = EXT_FLASH_AVL_MEM_PAGE_SIZE, |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, |
|
||||||
"only one 'altr,nios2-qspi-nor' compatible node may be present"); |
|
||||||
|
|
||||||
DEVICE_DT_INST_DEFINE(0, |
|
||||||
flash_nios2_qspi_init, NULL, &flash_cfg, NULL, |
|
||||||
POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, |
|
||||||
&flash_nios2_qspi_api); |
|
@ -1,14 +0,0 @@ |
|||||||
# Copyright (c) 2014-2015 Wind River Systems, Inc. |
|
||||||
# Copyright (c) 2016 Cadence Design Systems, Inc. |
|
||||||
# Copyright (c) 2019 Intel Corp. |
|
||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
config ALTERA_AVALON_TIMER |
|
||||||
bool "Altera Avalon Interval Timer" |
|
||||||
default y |
|
||||||
depends on NIOS2 |
|
||||||
help |
|
||||||
This module implements a kernel device driver for the Altera Avalon |
|
||||||
Interval Timer as described in the Embedded IP documentation, for use |
|
||||||
with Nios II and possibly other Altera soft CPUs. It provides the |
|
||||||
standard "system clock driver" interfaces. |
|
@ -1,94 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2017 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/kernel.h> |
|
||||||
#include <zephyr/arch/cpu.h> |
|
||||||
#include <zephyr/init.h> |
|
||||||
#include <zephyr/drivers/timer/system_timer.h> |
|
||||||
#include <altera_common.h> |
|
||||||
#include <zephyr/irq.h> |
|
||||||
|
|
||||||
#include "altera_avalon_timer_regs.h" |
|
||||||
#include "altera_avalon_timer.h" |
|
||||||
|
|
||||||
/* The old driver "now" API would return a full uptime value. The new
|
|
||||||
* one only requires the driver to track ticks since the last announce |
|
||||||
* call. Implement the new call in terms of the old one on legacy |
|
||||||
* drivers by keeping (yet another) uptime value locally. |
|
||||||
*/ |
|
||||||
static uint32_t driver_uptime; |
|
||||||
|
|
||||||
static uint32_t accumulated_cycle_count; |
|
||||||
|
|
||||||
static int32_t _sys_idle_elapsed_ticks = 1; |
|
||||||
|
|
||||||
#if defined(CONFIG_TEST) |
|
||||||
const int32_t z_sys_timer_irq_for_test = TIMER_0_IRQ; |
|
||||||
#endif |
|
||||||
|
|
||||||
static void wrapped_announce(int32_t ticks) |
|
||||||
{ |
|
||||||
driver_uptime += ticks; |
|
||||||
sys_clock_announce(ticks); |
|
||||||
} |
|
||||||
|
|
||||||
static void timer_irq_handler(const void *unused) |
|
||||||
{ |
|
||||||
ARG_UNUSED(unused); |
|
||||||
|
|
||||||
accumulated_cycle_count += k_ticks_to_cyc_floor32(1); |
|
||||||
|
|
||||||
/* Clear the interrupt */ |
|
||||||
alt_handle_irq((void *)TIMER_0_BASE, TIMER_0_IRQ); |
|
||||||
|
|
||||||
wrapped_announce(_sys_idle_elapsed_ticks); |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t sys_clock_cycle_get_32(void) |
|
||||||
{ |
|
||||||
/* Per the Altera Embedded IP Peripherals guide, you cannot
|
|
||||||
* use a timer instance for both the system clock and timestamps |
|
||||||
* at the same time. |
|
||||||
* |
|
||||||
* Having this function return accumulated_cycle_count + get_snapshot() |
|
||||||
* does not work reliably. It's possible for the current countdown |
|
||||||
* to reset to the next interval before the timer interrupt is |
|
||||||
* delivered (and accumulated cycle count gets updated). The result |
|
||||||
* is an unlucky call to this function will appear to jump backward |
|
||||||
* in time. |
|
||||||
* |
|
||||||
* To properly obtain timestamps, the CPU must be configured with |
|
||||||
* a second timer peripheral instance that is configured to |
|
||||||
* count down from some large initial 64-bit value. This |
|
||||||
* is currently unimplemented. |
|
||||||
*/ |
|
||||||
return accumulated_cycle_count; |
|
||||||
} |
|
||||||
|
|
||||||
uint32_t sys_clock_elapsed(void) |
|
||||||
{ |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
static int sys_clock_driver_init(void) |
|
||||||
{ |
|
||||||
|
|
||||||
IOWR_ALTERA_AVALON_TIMER_PERIODL(TIMER_0_BASE, |
|
||||||
k_ticks_to_cyc_floor32(1) & 0xFFFF); |
|
||||||
IOWR_ALTERA_AVALON_TIMER_PERIODH(TIMER_0_BASE, |
|
||||||
(k_ticks_to_cyc_floor32(1) >> 16) & 0xFFFF); |
|
||||||
|
|
||||||
IRQ_CONNECT(TIMER_0_IRQ, 0, timer_irq_handler, NULL, 0); |
|
||||||
irq_enable(TIMER_0_IRQ); |
|
||||||
|
|
||||||
alt_avalon_timer_sc_init((void *)TIMER_0_BASE, 0, |
|
||||||
TIMER_0_IRQ, k_ticks_to_cyc_floor32(1)); |
|
||||||
|
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, |
|
||||||
CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); |
|
@ -1,15 +0,0 @@ |
|||||||
# Copyright (c) 2018 Nordic Semiconductor ASA |
|
||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
description: Altera NIOS-2F CPU |
|
||||||
|
|
||||||
compatible: "altr,nios2f" |
|
||||||
|
|
||||||
include: [interrupt-controller.yaml, base.yaml] |
|
||||||
|
|
||||||
properties: |
|
||||||
"#interrupt-cells": |
|
||||||
const: 1 |
|
||||||
|
|
||||||
interrupt-cells: |
|
||||||
- irq |
|
@ -1,15 +0,0 @@ |
|||||||
# Copyright (c) 2020 Nordic Semiconductor ASA |
|
||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
description: QEMU NIOS2 Zephyr CPU |
|
||||||
|
|
||||||
compatible: "qemu,nios2-zephyr" |
|
||||||
|
|
||||||
include: [interrupt-controller.yaml, base.yaml] |
|
||||||
|
|
||||||
properties: |
|
||||||
"#interrupt-cells": |
|
||||||
const: 1 |
|
||||||
|
|
||||||
interrupt-cells: |
|
||||||
- irq |
|
@ -1,52 +0,0 @@ |
|||||||
/* SPDX-License-Identifier: Apache-2.0 */ |
|
||||||
|
|
||||||
#include "skeleton.dtsi" |
|
||||||
|
|
||||||
/ { |
|
||||||
cpus { |
|
||||||
#address-cells = <1>; |
|
||||||
#size-cells = <0>; |
|
||||||
|
|
||||||
cpu: cpu@0 { |
|
||||||
device_type = "cpu"; |
|
||||||
compatible = "qemu,nios2-zephyr"; |
|
||||||
reg = <0>; |
|
||||||
interrupt-controller; |
|
||||||
#interrupt-cells = <1>; |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
flash0: flash@420000 { |
|
||||||
compatible = "soc-nv-flash"; |
|
||||||
reg = <0x420000 0x20000>; |
|
||||||
}; |
|
||||||
|
|
||||||
sram0: memory@400000 { |
|
||||||
compatible = "mmio-sram"; |
|
||||||
reg = <0x400000 0x20000>; |
|
||||||
}; |
|
||||||
|
|
||||||
soc { |
|
||||||
#address-cells = <1>; |
|
||||||
#size-cells = <1>; |
|
||||||
compatible = "simple-bus"; |
|
||||||
interrupt-parent = <&cpu>; |
|
||||||
ranges; |
|
||||||
|
|
||||||
jtag_uart: uart@201000 { |
|
||||||
compatible = "altr,jtag-uart"; |
|
||||||
reg = <0x201000 0x400>; |
|
||||||
interrupts = <0>; |
|
||||||
status = "disabled"; |
|
||||||
}; |
|
||||||
|
|
||||||
ns16550_uart: uart@440000 { |
|
||||||
compatible = "ns16550"; |
|
||||||
reg = <0x440000 0x400>; |
|
||||||
interrupts = <1>; |
|
||||||
clock-frequency = <50000000>; |
|
||||||
reg-shift = <2>; |
|
||||||
status = "disabled"; |
|
||||||
}; |
|
||||||
}; |
|
||||||
}; |
|
@ -1,79 +0,0 @@ |
|||||||
/* SPDX-License-Identifier: Apache-2.0 */ |
|
||||||
|
|
||||||
#include "skeleton.dtsi" |
|
||||||
#include <zephyr/dt-bindings/i2c/i2c.h> |
|
||||||
|
|
||||||
/ { |
|
||||||
cpus { |
|
||||||
#address-cells = <1>; |
|
||||||
#size-cells = <0>; |
|
||||||
|
|
||||||
cpu: cpu@0 { |
|
||||||
device_type = "cpu"; |
|
||||||
compatible = "altr,nios2f"; |
|
||||||
reg = <0>; |
|
||||||
interrupt-controller; |
|
||||||
#interrupt-cells = <1>; |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
flash0: flash@0 { |
|
||||||
compatible = "soc-nv-flash"; |
|
||||||
reg = <0x00 0xb8000>; |
|
||||||
}; |
|
||||||
|
|
||||||
sram0: memory@400000 { |
|
||||||
compatible = "mmio-sram"; |
|
||||||
reg = <0x400000 0x20000>; |
|
||||||
}; |
|
||||||
|
|
||||||
soc { |
|
||||||
#address-cells = <1>; |
|
||||||
#size-cells = <1>; |
|
||||||
compatible = "simple-bus"; |
|
||||||
interrupt-parent = <&cpu>; |
|
||||||
ranges; |
|
||||||
|
|
||||||
uart0: uart@100000 { |
|
||||||
compatible = "ns16550"; |
|
||||||
reg = <0x100000 0x400>; |
|
||||||
clock-frequency = <50000000>; |
|
||||||
interrupts = <1 0>; |
|
||||||
reg-shift = <2>; |
|
||||||
status = "disabled"; |
|
||||||
}; |
|
||||||
|
|
||||||
jtag_uart: uart@201000 { |
|
||||||
compatible = "altr,jtag-uart"; |
|
||||||
reg = <0x201000 0x8>; |
|
||||||
|
|
||||||
status = "disabled"; |
|
||||||
}; |
|
||||||
|
|
||||||
i2c0: i2c@100200 { |
|
||||||
compatible = "altr,nios2-i2c"; |
|
||||||
clock-frequency = <I2C_BITRATE_ULTRA>; |
|
||||||
#address-cells = <1>; |
|
||||||
#size-cells = <0>; |
|
||||||
reg = <0x100200 0x400>; |
|
||||||
interrupts = <4 10>; |
|
||||||
}; |
|
||||||
|
|
||||||
dma: dma@1002c0 { |
|
||||||
compatible = "altr,msgdma"; |
|
||||||
reg = <0x1002c0 0x30>; |
|
||||||
interrupts = <3 3>; |
|
||||||
#dma-cells = <0>; |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
qspi: qspi@100240 { |
|
||||||
compatible = "altr,nios2-qspi"; |
|
||||||
#address-cells = <1>; |
|
||||||
#size-cells = <0>; |
|
||||||
reg = <0x100240 0x40>, <0x8000000 0x4000000>; |
|
||||||
reg-names = "qspi", "qspi_mm"; |
|
||||||
status = "disabled"; |
|
||||||
}; |
|
||||||
}; |
|
||||||
}; |
|
@ -1,175 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
* @file |
|
||||||
* @brief Nios II specific kernel interface header |
|
||||||
* This header contains the Nios II specific kernel interface. It is |
|
||||||
* included by the generic kernel interface header (include/arch/cpu.h) |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_ARCH_H_ |
|
||||||
#define ZEPHYR_INCLUDE_ARCH_NIOS2_ARCH_H_ |
|
||||||
|
|
||||||
#include <system.h> |
|
||||||
|
|
||||||
#include <zephyr/arch/nios2/thread.h> |
|
||||||
#include <zephyr/arch/nios2/exception.h> |
|
||||||
#include <zephyr/arch/nios2/asm_inline.h> |
|
||||||
#include <zephyr/arch/common/addr_types.h> |
|
||||||
#include <zephyr/devicetree.h> |
|
||||||
#include <zephyr/arch/nios2/nios2.h> |
|
||||||
#include <zephyr/arch/common/sys_bitops.h> |
|
||||||
#include <zephyr/sys/sys_io.h> |
|
||||||
#include <zephyr/arch/common/ffs.h> |
|
||||||
|
|
||||||
#define ARCH_STACK_PTR_ALIGN 4 |
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE |
|
||||||
#include <zephyr/types.h> |
|
||||||
#include <zephyr/irq.h> |
|
||||||
#include <zephyr/sw_isr_table.h> |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
/* There is no notion of priority with the Nios II internal interrupt
|
|
||||||
* controller and no flags are currently supported. |
|
||||||
*/ |
|
||||||
#define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ |
|
||||||
{ \ |
|
||||||
Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \ |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE unsigned int arch_irq_lock(void) |
|
||||||
{ |
|
||||||
unsigned int key, tmp; |
|
||||||
|
|
||||||
__asm__ volatile ( |
|
||||||
"rdctl %[key], status\n\t" |
|
||||||
"movi %[tmp], -2\n\t" |
|
||||||
"and %[tmp], %[key], %[tmp]\n\t" |
|
||||||
"wrctl status, %[tmp]\n\t" |
|
||||||
: [key] "=r" (key), [tmp] "=r" (tmp) |
|
||||||
: : "memory"); |
|
||||||
|
|
||||||
return key; |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE void arch_irq_unlock(unsigned int key) |
|
||||||
{ |
|
||||||
/* If the CPU is built without certain features, then
|
|
||||||
* the only writable bit in the status register is PIE |
|
||||||
* in which case we can just write the value stored in key, |
|
||||||
* all the other writable bits will be the same. |
|
||||||
* |
|
||||||
* If not, other stuff could have changed and we need to |
|
||||||
* specifically flip just that bit. |
|
||||||
*/ |
|
||||||
|
|
||||||
#if (ALT_CPU_NUM_OF_SHADOW_REG_SETS > 0) || \ |
|
||||||
(defined ALT_CPU_EIC_PRESENT) || \ |
|
||||||
(defined ALT_CPU_MMU_PRESENT) || \ |
|
||||||
(defined ALT_CPU_MPU_PRESENT) |
|
||||||
__asm__ volatile ( |
|
||||||
"andi %[key], %[key], 1\n\t" |
|
||||||
"beq %[key], zero, 1f\n\t" |
|
||||||
"rdctl %[key], status\n\t" |
|
||||||
"ori %[key], %[key], 1\n\t" |
|
||||||
"wrctl status, %[key]\n\t" |
|
||||||
"1:\n\t" |
|
||||||
: [key] "+r" (key) |
|
||||||
: : "memory"); |
|
||||||
#else |
|
||||||
__asm__ volatile ( |
|
||||||
"wrctl status, %[key]" |
|
||||||
: : [key] "r" (key) |
|
||||||
: "memory"); |
|
||||||
#endif |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) |
|
||||||
{ |
|
||||||
return key & 1; |
|
||||||
} |
|
||||||
|
|
||||||
void arch_irq_enable(unsigned int irq); |
|
||||||
void arch_irq_disable(unsigned int irq); |
|
||||||
|
|
||||||
FUNC_NORETURN void z_SysFatalErrorHandler(unsigned int reason, |
|
||||||
const struct arch_esf *esf); |
|
||||||
|
|
||||||
FUNC_NORETURN void z_NanoFatalErrorHandler(unsigned int reason, |
|
||||||
const struct arch_esf *esf); |
|
||||||
|
|
||||||
enum nios2_exception_cause { |
|
||||||
NIOS2_EXCEPTION_UNKNOWN = -1, |
|
||||||
NIOS2_EXCEPTION_RESET = 0, |
|
||||||
NIOS2_EXCEPTION_CPU_ONLY_RESET_REQUEST = 1, |
|
||||||
NIOS2_EXCEPTION_INTERRUPT = 2, |
|
||||||
NIOS2_EXCEPTION_TRAP_INST = 3, |
|
||||||
NIOS2_EXCEPTION_UNIMPLEMENTED_INST = 4, |
|
||||||
NIOS2_EXCEPTION_ILLEGAL_INST = 5, |
|
||||||
NIOS2_EXCEPTION_MISALIGNED_DATA_ADDR = 6, |
|
||||||
NIOS2_EXCEPTION_MISALIGNED_TARGET_PC = 7, |
|
||||||
NIOS2_EXCEPTION_DIVISION_ERROR = 8, |
|
||||||
NIOS2_EXCEPTION_SUPERVISOR_ONLY_INST_ADDR = 9, |
|
||||||
NIOS2_EXCEPTION_SUPERVISOR_ONLY_INST = 10, |
|
||||||
NIOS2_EXCEPTION_SUPERVISOR_ONLY_DATA_ADDR = 11, |
|
||||||
NIOS2_EXCEPTION_TLB_MISS = 12, |
|
||||||
NIOS2_EXCEPTION_TLB_EXECUTE_PERM_VIOLATION = 13, |
|
||||||
NIOS2_EXCEPTION_TLB_READ_PERM_VIOLATION = 14, |
|
||||||
NIOS2_EXCEPTION_TLB_WRITE_PERM_VIOLATION = 15, |
|
||||||
NIOS2_EXCEPTION_MPU_INST_REGION_VIOLATION = 16, |
|
||||||
NIOS2_EXCEPTION_MPU_DATA_REGION_VIOLATION = 17, |
|
||||||
NIOS2_EXCEPTION_ECC_TLB_ERR = 18, |
|
||||||
NIOS2_EXCEPTION_ECC_FETCH_ERR = 19, |
|
||||||
NIOS2_EXCEPTION_ECC_REGISTER_FILE_ERR = 20, |
|
||||||
NIOS2_EXCEPTION_ECC_DATA_ERR = 21, |
|
||||||
NIOS2_EXCEPTION_ECC_DATA_CACHE_WRITEBACK_ERR = 22 |
|
||||||
}; |
|
||||||
|
|
||||||
/* Bitfield indicating which exception cause codes report a valid
|
|
||||||
* badaddr register. NIOS2_EXCEPTION_TLB_MISS and NIOS2_EXCEPTION_ECC_TLB_ERR |
|
||||||
* are deliberately not included here, you need to check if TLBMISC.D=1 |
|
||||||
*/ |
|
||||||
#define NIOS2_BADADDR_CAUSE_MASK \ |
|
||||||
(BIT(NIOS2_EXCEPTION_SUPERVISOR_ONLY_DATA_ADDR) | \ |
|
||||||
BIT(NIOS2_EXCEPTION_MISALIGNED_DATA_ADDR) | \ |
|
||||||
BIT(NIOS2_EXCEPTION_MISALIGNED_TARGET_PC) | \ |
|
||||||
BIT(NIOS2_EXCEPTION_TLB_READ_PERM_VIOLATION) | \ |
|
||||||
BIT(NIOS2_EXCEPTION_TLB_WRITE_PERM_VIOLATION) | \ |
|
||||||
BIT(NIOS2_EXCEPTION_MPU_DATA_REGION_VIOLATION) | \ |
|
||||||
BIT(NIOS2_EXCEPTION_ECC_DATA_ERR)) |
|
||||||
|
|
||||||
|
|
||||||
extern uint32_t sys_clock_cycle_get_32(void); |
|
||||||
|
|
||||||
static inline uint32_t arch_k_cycle_get_32(void) |
|
||||||
{ |
|
||||||
return sys_clock_cycle_get_32(); |
|
||||||
} |
|
||||||
|
|
||||||
extern uint64_t sys_clock_cycle_get_64(void); |
|
||||||
|
|
||||||
static inline uint64_t arch_k_cycle_get_64(void) |
|
||||||
{ |
|
||||||
return sys_clock_cycle_get_64(); |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE void arch_nop(void) |
|
||||||
{ |
|
||||||
__asm__ volatile("nop"); |
|
||||||
} |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */ |
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_ARCH_H_ */ |
|
@ -1,17 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2022 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_ARCH_INLINES_H |
|
||||||
#define ZEPHYR_INCLUDE_ARCH_NIOS2_ARCH_INLINES_H |
|
||||||
|
|
||||||
#include <zephyr/kernel_structs.h> |
|
||||||
|
|
||||||
static ALWAYS_INLINE unsigned int arch_num_cpus(void) |
|
||||||
{ |
|
||||||
return CONFIG_MP_MAX_NUM_CPUS; |
|
||||||
} |
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_ARCH_INLINES_H */ |
|
@ -1,21 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_ASM_INLINE_H_ |
|
||||||
#define ZEPHYR_INCLUDE_ARCH_NIOS2_ASM_INLINE_H_ |
|
||||||
|
|
||||||
/*
|
|
||||||
* The file must not be included directly |
|
||||||
* Include kernel.h instead |
|
||||||
*/ |
|
||||||
|
|
||||||
#if defined(__GNUC__) |
|
||||||
#include <zephyr/arch/nios2/asm_inline_gcc.h> |
|
||||||
#else |
|
||||||
#include <arch/nios2/asm_inline_other.h> |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_ASM_INLINE_H_ */ |
|
@ -1,56 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_ASM_INLINE_GCC_H_ |
|
||||||
#define ZEPHYR_INCLUDE_ARCH_NIOS2_ASM_INLINE_GCC_H_ |
|
||||||
|
|
||||||
/*
|
|
||||||
* The file must not be included directly |
|
||||||
* Include arch/cpu.h instead |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE |
|
||||||
#include <zephyr/types.h> |
|
||||||
#include <zephyr/sys/sys_io.h> |
|
||||||
#include <zephyr/toolchain.h> |
|
||||||
|
|
||||||
/* Using the *io variants of these instructions to prevent issues on
|
|
||||||
* devices that have an instruction/data cache |
|
||||||
*/ |
|
||||||
|
|
||||||
static ALWAYS_INLINE void sys_write32(uint32_t data, mm_reg_t addr) |
|
||||||
{ |
|
||||||
__builtin_stwio((void *)addr, data); |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE uint32_t sys_read32(mm_reg_t addr) |
|
||||||
{ |
|
||||||
return __builtin_ldwio((void *)addr); |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE void sys_write8(uint8_t data, mm_reg_t addr) |
|
||||||
{ |
|
||||||
sys_write32(data, addr); |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE uint8_t sys_read8(mm_reg_t addr) |
|
||||||
{ |
|
||||||
return __builtin_ldbuio((void *)addr); |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE void sys_write16(uint16_t data, mm_reg_t addr) |
|
||||||
{ |
|
||||||
sys_write32(data, addr); |
|
||||||
} |
|
||||||
|
|
||||||
static ALWAYS_INLINE uint16_t sys_read16(mm_reg_t addr) |
|
||||||
{ |
|
||||||
return __builtin_ldhuio((void *)addr); |
|
||||||
} |
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */ |
|
||||||
|
|
||||||
#endif /* _ASM_INLINE_GCC_PUBLIC_GCC_H */ |
|
@ -1,44 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_EXCEPTION_H_ |
|
||||||
#define ZEPHYR_INCLUDE_ARCH_NIOS2_EXCEPTION_H_ |
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE |
|
||||||
#include <zephyr/types.h> |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" { |
|
||||||
#endif |
|
||||||
|
|
||||||
struct arch_esf { |
|
||||||
uint32_t ra; /* return address r31 */ |
|
||||||
uint32_t r1; /* at */ |
|
||||||
uint32_t r2; /* return value */ |
|
||||||
uint32_t r3; /* return value */ |
|
||||||
uint32_t r4; /* register args */ |
|
||||||
uint32_t r5; /* register args */ |
|
||||||
uint32_t r6; /* register args */ |
|
||||||
uint32_t r7; /* register args */ |
|
||||||
uint32_t r8; /* Caller-saved general purpose */ |
|
||||||
uint32_t r9; /* Caller-saved general purpose */ |
|
||||||
uint32_t r10; /* Caller-saved general purpose */ |
|
||||||
uint32_t r11; /* Caller-saved general purpose */ |
|
||||||
uint32_t r12; /* Caller-saved general purpose */ |
|
||||||
uint32_t r13; /* Caller-saved general purpose */ |
|
||||||
uint32_t r14; /* Caller-saved general purpose */ |
|
||||||
uint32_t r15; /* Caller-saved general purpose */ |
|
||||||
uint32_t estatus; |
|
||||||
uint32_t instr; /* Instruction being executed when exc occurred */ |
|
||||||
}; |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */ |
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_EXCEPTION_H_ */ |
|
@ -1,286 +0,0 @@ |
|||||||
/* |
|
||||||
* Copyright (c) 2016 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/** |
|
||||||
* @file |
|
||||||
* @brief Linker command/script file |
|
||||||
* |
|
||||||
* Linker script for the Nios II platform |
|
||||||
*/ |
|
||||||
|
|
||||||
#include <zephyr/linker/sections.h> |
|
||||||
|
|
||||||
#include <zephyr/linker/linker-defs.h> |
|
||||||
#include <zephyr/linker/linker-tool.h> |
|
||||||
|
|
||||||
/* These sections are specific to this CPU */ |
|
||||||
#define _EXCEPTION_SECTION_NAME exceptions |
|
||||||
#define _RESET_SECTION_NAME reset |
|
||||||
|
|
||||||
/* This linker script requires the following macros to be defined in the |
|
||||||
* SOC-specific linker script. All of these values can be found defined |
|
||||||
* in system.h for CPU configurations that can generate a HAL. |
|
||||||
* |
|
||||||
* _RESET_VECTOR CPU entry point at boot |
|
||||||
* _EXC_VECTOR General exception vector |
|
||||||
* _ROM_ADDR Beginning of flash memory |
|
||||||
* _ROM_SIZE Size in bytes of flash memory |
|
||||||
* _RAM_ADDR Beginning of RAM |
|
||||||
* _RAM_SIZE Size of RAM in bytes |
|
||||||
* |
|
||||||
* For now we support two scenarios: |
|
||||||
* |
|
||||||
* 1. Non-XIP systems where the reset vector is at the beginning of RAM |
|
||||||
* with the exception vector 0x20 bytes after it. |
|
||||||
* 2. XIP systems where the reset vector is at the beginning of ROM and |
|
||||||
* the exception vector is in RAM |
|
||||||
*/ |
|
||||||
|
|
||||||
#if defined(CONFIG_ROM_END_OFFSET) |
|
||||||
#define ROM_END_OFFSET CONFIG_ROM_END_OFFSET |
|
||||||
#else |
|
||||||
#define ROM_END_OFFSET 0 |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifdef CONFIG_XIP |
|
||||||
#define ROMABLE_REGION FLASH |
|
||||||
#else |
|
||||||
#define ROMABLE_REGION RAM |
|
||||||
#endif |
|
||||||
#define RAMABLE_REGION RAM |
|
||||||
|
|
||||||
#ifdef CONFIG_XIP |
|
||||||
|
|
||||||
ASSERT(_RESET_VECTOR == _ROM_ADDR, "Reset vector not at beginning of ROM!") |
|
||||||
|
|
||||||
MEMORY |
|
||||||
{ |
|
||||||
RESET (rx) : ORIGIN = _RESET_VECTOR, LENGTH = 0x20 |
|
||||||
FLASH (rx) : ORIGIN = _RESET_VECTOR + 0x20 , LENGTH = (_ROM_SIZE - 0x20 - ROM_END_OFFSET) |
|
||||||
RAM (wx) : ORIGIN = _EXC_VECTOR, LENGTH = _RAM_SIZE - (_EXC_VECTOR - _RAM_ADDR) |
|
||||||
/* Used by and documented in include/linker/intlist.ld */ |
|
||||||
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
#else |
|
||||||
|
|
||||||
MEMORY |
|
||||||
{ |
|
||||||
RESET (wx) : ORIGIN = _RESET_VECTOR, LENGTH = 0x20 |
|
||||||
RAM (wx) : ORIGIN = _EXC_VECTOR, LENGTH = _RAM_SIZE - (_EXC_VECTOR - _RAM_ADDR) |
|
||||||
|
|
||||||
/* Used by and documented in include/linker/intlist.ld */ |
|
||||||
IDT_LIST (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
ENTRY(CONFIG_KERNEL_ENTRY) |
|
||||||
|
|
||||||
SECTIONS |
|
||||||
{ |
|
||||||
|
|
||||||
#include <zephyr/linker/rel-sections.ld> |
|
||||||
|
|
||||||
#ifdef CONFIG_LLEXT |
|
||||||
#include <zephyr/linker/llext-sections.ld> |
|
||||||
#endif |
|
||||||
|
|
||||||
/* |
|
||||||
* .plt and .iplt are here according to |
|
||||||
* 'nios2-zephyr-elf-ld --verbose', before text section. |
|
||||||
*/ |
|
||||||
SECTION_PROLOGUE(.plt,,) |
|
||||||
{ |
|
||||||
*(.plt) |
|
||||||
} |
|
||||||
|
|
||||||
SECTION_PROLOGUE(.iplt,,) |
|
||||||
{ |
|
||||||
*(.iplt) |
|
||||||
} |
|
||||||
|
|
||||||
GROUP_START(ROMABLE_REGION) |
|
||||||
__rom_region_start = _ROM_ADDR; |
|
||||||
|
|
||||||
SECTION_PROLOGUE(_RESET_SECTION_NAME,,) |
|
||||||
{ |
|
||||||
KEEP(*(.reset.*)) |
|
||||||
} GROUP_LINK_IN(RESET) |
|
||||||
|
|
||||||
#ifndef CONFIG_XIP |
|
||||||
SECTION_PROLOGUE(_EXCEPTION_SECTION_NAME,,) |
|
||||||
{ |
|
||||||
KEEP(*(".exception.entry.*")) |
|
||||||
*(".exception.other.*") |
|
||||||
|
|
||||||
} GROUP_LINK_IN(ROMABLE_REGION) |
|
||||||
#endif |
|
||||||
|
|
||||||
SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) |
|
||||||
{ |
|
||||||
/* XXX If ALT_CPU_RESET_ADDR is not the same as _ROM_ADDR |
|
||||||
* we are going to waste flash space? */ |
|
||||||
. = ALT_CPU_RESET_ADDR; |
|
||||||
|
|
||||||
__text_region_start = .; |
|
||||||
|
|
||||||
*(.text) |
|
||||||
*(".text.*") |
|
||||||
*(.gnu.linkonce.t.*) |
|
||||||
} GROUP_LINK_IN(ROMABLE_REGION) |
|
||||||
|
|
||||||
__text_region_end = .; |
|
||||||
|
|
||||||
#if defined(CONFIG_GP_ALL_DATA) |
|
||||||
_gp = ABSOLUTE(. + 0x8000); |
|
||||||
PROVIDE(gp = _gp); |
|
||||||
#endif |
|
||||||
|
|
||||||
__rodata_region_start = .; |
|
||||||
|
|
||||||
#include <zephyr/linker/common-rom.ld> |
|
||||||
/* Located in generated directory. This file is populated by calling |
|
||||||
* zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs. |
|
||||||
*/ |
|
||||||
#include <snippets-rom-sections.ld> |
|
||||||
|
|
||||||
SECTION_PROLOGUE(_RODATA_SECTION_NAME,,) |
|
||||||
{ |
|
||||||
. = ALIGN(4); |
|
||||||
|
|
||||||
*(.rodata) |
|
||||||
*(".rodata.*") |
|
||||||
*(.gnu.linkonce.r.*) |
|
||||||
|
|
||||||
/* Located in generated directory. This file is populated by the |
|
||||||
* zephyr_linker_sources() Cmake function. |
|
||||||
*/ |
|
||||||
#include <snippets-rodata.ld> |
|
||||||
|
|
||||||
. = ALIGN(4); |
|
||||||
} GROUP_LINK_IN(ROMABLE_REGION) |
|
||||||
|
|
||||||
#include <zephyr/linker/cplusplus-rom.ld> |
|
||||||
|
|
||||||
__rodata_region_end = .; |
|
||||||
__rodata_region_size = __rodata_region_end - __rodata_region_start; |
|
||||||
|
|
||||||
__rom_region_end = .; |
|
||||||
__data_region_load_start = ALIGN(4); /* XIP imaged DATA ROM start addr */ |
|
||||||
|
|
||||||
GROUP_END(ROMABLE_REGION) |
|
||||||
|
|
||||||
GROUP_START(RAMABLE_REGION) |
|
||||||
|
|
||||||
#ifdef CONFIG_XIP |
|
||||||
/* Altera strongly recommends keeping exception entry code in RAM |
|
||||||
* even on XIP systems |
|
||||||
* |
|
||||||
* This is code not data, but we need this copied just like XIP data |
|
||||||
*/ |
|
||||||
|
|
||||||
SECTION_DATA_PROLOGUE(_EXCEPTION_SECTION_NAME,,) |
|
||||||
{ |
|
||||||
_image_ram_start = .; |
|
||||||
__data_region_start = .; |
|
||||||
|
|
||||||
KEEP(*(".exception.entry.*")) |
|
||||||
*(".exception.other.*") |
|
||||||
|
|
||||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) |
|
||||||
#endif |
|
||||||
|
|
||||||
#ifndef CONFIG_XIP |
|
||||||
_image_ram_start = .; |
|
||||||
#endif |
|
||||||
|
|
||||||
#include <zephyr/linker/common-ram.ld> |
|
||||||
|
|
||||||
SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) |
|
||||||
{ |
|
||||||
__data_start = .; |
|
||||||
*(.data) |
|
||||||
*(".data.*") |
|
||||||
|
|
||||||
/* Located in generated directory. This file is populated by the |
|
||||||
* zephyr_linker_sources() Cmake function. |
|
||||||
*/ |
|
||||||
#include <snippets-rwdata.ld> |
|
||||||
|
|
||||||
/* the Nios2 architecture only has 16-bit signed immediate offsets in |
|
||||||
* the instructions, so accessing a general address requires typically |
|
||||||
* three instructions - basically, two for the two halves of the 32-bit |
|
||||||
* address, and one to merge them - but if we can put the most commonly |
|
||||||
* accessed globals in a special 64K span of memory addressed by the GP |
|
||||||
* register, then we can access those values in a single instruction, |
|
||||||
* saving both codespace and runtime. |
|
||||||
* |
|
||||||
* Since these immediate offsets are signed, place gp 0x8000 past the |
|
||||||
* beginning of .sdata so that we can use both positive and negative |
|
||||||
* offsets. |
|
||||||
*/ |
|
||||||
#if defined(CONFIG_GP_LOCAL) || defined(CONFIG_GP_GLOBAL) |
|
||||||
_gp = ABSOLUTE(. + 0x8000); |
|
||||||
PROVIDE(gp = _gp); |
|
||||||
#endif |
|
||||||
|
|
||||||
*(.sdata .sdata.* .gnu.linkonce.s.*) |
|
||||||
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*) |
|
||||||
|
|
||||||
/* Located in generated directory. This file is populated by the |
|
||||||
* zephyr_linker_sources() Cmake function. |
|
||||||
*/ |
|
||||||
#include <snippets-ram-sections.ld> |
|
||||||
__data_end = .; |
|
||||||
|
|
||||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) |
|
||||||
__data_size = __data_end - __data_start; |
|
||||||
__data_load_start = LOADADDR(_DATA_SECTION_NAME); |
|
||||||
|
|
||||||
#include <zephyr/linker/cplusplus-ram.ld> |
|
||||||
|
|
||||||
/* Located in generated directory. This file is populated by the |
|
||||||
* zephyr_linker_sources() Cmake function. |
|
||||||
*/ |
|
||||||
#include <snippets-data-sections.ld> |
|
||||||
|
|
||||||
__data_region_end = .; |
|
||||||
|
|
||||||
SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),) |
|
||||||
{ |
|
||||||
/* |
|
||||||
* For performance, BSS section is assumed to be 4 byte aligned and |
|
||||||
* a multiple of 4 bytes |
|
||||||
*/ |
|
||||||
. = ALIGN(4); |
|
||||||
__bss_start = .; |
|
||||||
*(.sbss) |
|
||||||
*(".sbss.*") |
|
||||||
*(.bss) |
|
||||||
*(".bss.*") |
|
||||||
COMMON_SYMBOLS |
|
||||||
/* |
|
||||||
* As memory is cleared in words only, it is simpler to ensure the BSS |
|
||||||
* section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. |
|
||||||
*/ |
|
||||||
__bss_end = ALIGN(4); |
|
||||||
} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) |
|
||||||
|
|
||||||
#include <zephyr/linker/common-noinit.ld> |
|
||||||
|
|
||||||
/* Located in generated directory. This file is populated by the |
|
||||||
* zephyr_linker_sources() Cmake function. |
|
||||||
*/ |
|
||||||
#include <snippets-sections.ld> |
|
||||||
|
|
||||||
#include <zephyr/linker/ram-end.ld> |
|
||||||
|
|
||||||
GROUP_END(RAMABLE_REGION) |
|
||||||
|
|
||||||
#include <zephyr/linker/debug-sections.ld> |
|
||||||
|
|
||||||
} |
|
@ -1,328 +0,0 @@ |
|||||||
#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_NIOS2_H_ |
|
||||||
#define ZEPHYR_INCLUDE_ARCH_NIOS2_NIOS2_H_ |
|
||||||
|
|
||||||
/* SPDX-License-Identifier: Xnet */ |
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* * |
|
||||||
* License Agreement * |
|
||||||
* * |
|
||||||
* Copyright (c) 2008 Altera Corporation, San Jose, California, USA. * |
|
||||||
* All rights reserved. * |
|
||||||
* * |
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a * |
|
||||||
* copy of this software and associated documentation files (the "Software"), * |
|
||||||
* to deal in the Software without restriction, including without limitation * |
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, * |
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the * |
|
||||||
* Software is furnished to do so, subject to the following conditions: * |
|
||||||
* * |
|
||||||
* The above copyright notice and this permission notice shall be included in * |
|
||||||
* all copies or substantial portions of the Software. * |
|
||||||
* * |
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * |
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * |
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * |
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * |
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * |
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * |
|
||||||
* DEALINGS IN THE SOFTWARE. * |
|
||||||
* * |
|
||||||
* This agreement shall be governed in all respects by the laws of the State * |
|
||||||
* of California and by the laws of the United States of America. * |
|
||||||
* * |
|
||||||
******************************************************************************/ |
|
||||||
|
|
||||||
/*
|
|
||||||
* This header provides processor specific macros for accessing the Nios2 |
|
||||||
* control registers. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
extern "C" |
|
||||||
{ |
|
||||||
#endif /* __cplusplus */ |
|
||||||
|
|
||||||
/*
|
|
||||||
* Number of available IRQs in internal interrupt controller. |
|
||||||
*/ |
|
||||||
#define NIOS2_NIRQ 32 |
|
||||||
|
|
||||||
/* Size in bits of registers */ |
|
||||||
#define SYSTEM_BUS_WIDTH 32 |
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE |
|
||||||
|
|
||||||
#include <zephyr/types.h> |
|
||||||
#include <zephyr/arch/cpu.h> |
|
||||||
#include <zephyr/sys/sys_io.h> |
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions for accessing select Nios II general-purpose registers. |
|
||||||
*/ |
|
||||||
|
|
||||||
/* ET (Exception Temporary) register */ |
|
||||||
static inline uint32_t _nios2_read_et(void) |
|
||||||
{ |
|
||||||
uint32_t et; |
|
||||||
|
|
||||||
__asm__("mov %0, et" : "=r" (et)); |
|
||||||
return et; |
|
||||||
} |
|
||||||
|
|
||||||
static inline void _nios2_write_et(uint32_t et) |
|
||||||
{ |
|
||||||
__asm__ volatile("mov et, %z0" : : "rM" (et)); |
|
||||||
} |
|
||||||
|
|
||||||
static inline uint32_t _nios2_read_sp(void) |
|
||||||
{ |
|
||||||
uint32_t sp; |
|
||||||
|
|
||||||
__asm__("mov %0, sp" : "=r" (sp)); |
|
||||||
return sp; |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions for useful processor instructions. |
|
||||||
*/ |
|
||||||
static inline void z_nios2_break(void) |
|
||||||
{ |
|
||||||
__asm__ volatile("break"); |
|
||||||
} |
|
||||||
|
|
||||||
static inline void _nios2_report_stack_overflow(void) |
|
||||||
{ |
|
||||||
__asm__ volatile("break 3"); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Low-level cache management functions |
|
||||||
*/ |
|
||||||
static inline void _nios2_dcache_addr_flush(void *addr) |
|
||||||
{ |
|
||||||
__asm__ volatile ("flushda (%0)" :: "r" (addr)); |
|
||||||
} |
|
||||||
|
|
||||||
static inline void z_nios2_dcache_flush(uint32_t offset) |
|
||||||
{ |
|
||||||
__asm__ volatile ("flushd (%0)" :: "r" (offset)); |
|
||||||
} |
|
||||||
|
|
||||||
static inline void z_nios2_icache_flush(uint32_t offset) |
|
||||||
{ |
|
||||||
__asm__ volatile ("flushi %0" :: "r" (offset)); |
|
||||||
} |
|
||||||
|
|
||||||
static inline void z_nios2_pipeline_flush(void) |
|
||||||
{ |
|
||||||
__asm__ volatile ("flushp"); |
|
||||||
} |
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions for reading/writing control registers |
|
||||||
*/ |
|
||||||
|
|
||||||
enum nios2_creg { |
|
||||||
NIOS2_CR_STATUS = 0, |
|
||||||
NIOS2_CR_ESTATUS = 1, |
|
||||||
NIOS2_CR_BSTATUS = 2, |
|
||||||
NIOS2_CR_IENABLE = 3, |
|
||||||
NIOS2_CR_IPENDING = 4, |
|
||||||
NIOS2_CR_CPUID = 5, |
|
||||||
/* 6 is reserved */ |
|
||||||
NIOS2_CR_EXCEPTION = 7, |
|
||||||
NIOS2_CR_PTEADDR = 8, |
|
||||||
NIOS2_CR_TLBACC = 9, |
|
||||||
NIOS2_CR_TLBMISC = 10, |
|
||||||
NIOS2_CR_ECCINJ = 11, |
|
||||||
NIOS2_CR_BADADDR = 12, |
|
||||||
NIOS2_CR_CONFIG = 13, |
|
||||||
NIOS2_CR_MPUBASE = 14, |
|
||||||
NIOS2_CR_MPUACC = 15 |
|
||||||
}; |
|
||||||
|
|
||||||
/* XXX I would prefer to define these as static inline functions for
|
|
||||||
* type checking purposes. However if -O0 is used (i.e. CONFIG_DEBUG is on) |
|
||||||
* we get errors "Control register number must be in range 0-31 for |
|
||||||
* __builtin_rdctl" with the following code: |
|
||||||
* |
|
||||||
* static inline uint32_t z_nios2_creg_read(enum nios2_creg reg) |
|
||||||
* { |
|
||||||
* return __builtin_rdctl(reg); |
|
||||||
* } |
|
||||||
* |
|
||||||
* This compiles just fine with -Os. |
|
||||||
*/ |
|
||||||
#define z_nios2_creg_read(reg) __builtin_rdctl(reg) |
|
||||||
#define z_nios2_creg_write(reg, val) __builtin_wrctl(reg, val) |
|
||||||
|
|
||||||
#define z_nios2_get_register_address(base, regnum) \ |
|
||||||
((void *)(((uint8_t *)base) + ((regnum) * (SYSTEM_BUS_WIDTH / 8)))) |
|
||||||
|
|
||||||
static inline void _nios2_reg_write(void *base, int regnum, uint32_t data) |
|
||||||
{ |
|
||||||
sys_write32(data, |
|
||||||
(mm_reg_t)z_nios2_get_register_address(base, regnum)); |
|
||||||
} |
|
||||||
|
|
||||||
static inline uint32_t _nios2_reg_read(void *base, int regnum) |
|
||||||
{ |
|
||||||
return sys_read32((mm_reg_t)z_nios2_get_register_address(base, regnum)); |
|
||||||
} |
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */ |
|
||||||
|
|
||||||
/*
|
|
||||||
* Nios II control registers that are always present |
|
||||||
*/ |
|
||||||
#define NIOS2_STATUS status |
|
||||||
#define NIOS2_ESTATUS estatus |
|
||||||
#define NIOS2_BSTATUS bstatus |
|
||||||
#define NIOS2_IENABLE ienable |
|
||||||
#define NIOS2_IPENDING ipending |
|
||||||
#define NIOS2_CPUID cpuid |
|
||||||
|
|
||||||
/*
|
|
||||||
* Bit masks & offsets for Nios II control registers. |
|
||||||
* The presence and size of a field is sometimes dependent on the Nios II |
|
||||||
* configuration. Bit masks for every possible field and the maximum size of |
|
||||||
* that field are defined. |
|
||||||
* |
|
||||||
* All bit-masks are expressed relative to the position |
|
||||||
* of the data with a register. To read data that is LSB- |
|
||||||
* aligned, the register read data should be masked, then |
|
||||||
* right-shifted by the designated "OFST" macro value. The |
|
||||||
* opposite should be used for register writes when starting |
|
||||||
* with LSB-aligned data. |
|
||||||
*/ |
|
||||||
|
|
||||||
/* STATUS, ESTATUS, BSTATUS, and SSTATUS registers */ |
|
||||||
#define NIOS2_STATUS_PIE_MSK (0x00000001) |
|
||||||
#define NIOS2_STATUS_PIE_OFST (0) |
|
||||||
#define NIOS2_STATUS_U_MSK (0x00000002) |
|
||||||
#define NIOS2_STATUS_U_OFST (1) |
|
||||||
#define NIOS2_STATUS_EH_MSK (0x00000004) |
|
||||||
#define NIOS2_STATUS_EH_OFST (2) |
|
||||||
#define NIOS2_STATUS_IH_MSK (0x00000008) |
|
||||||
#define NIOS2_STATUS_IH_OFST (3) |
|
||||||
#define NIOS2_STATUS_IL_MSK (0x000003f0) |
|
||||||
#define NIOS2_STATUS_IL_OFST (4) |
|
||||||
#define NIOS2_STATUS_CRS_MSK (0x0000fc00) |
|
||||||
#define NIOS2_STATUS_CRS_OFST (10) |
|
||||||
#define NIOS2_STATUS_PRS_MSK (0x003f0000) |
|
||||||
#define NIOS2_STATUS_PRS_OFST (16) |
|
||||||
#define NIOS2_STATUS_NMI_MSK (0x00400000) |
|
||||||
#define NIOS2_STATUS_NMI_OFST (22) |
|
||||||
#define NIOS2_STATUS_RSIE_MSK (0x00800000) |
|
||||||
#define NIOS2_STATUS_RSIE_OFST (23) |
|
||||||
#define NIOS2_STATUS_SRS_MSK (0x80000000) |
|
||||||
#define NIOS2_STATUS_SRS_OFST (31) |
|
||||||
|
|
||||||
/* EXCEPTION register */ |
|
||||||
#define NIOS2_EXCEPTION_REG_CAUSE_MASK (0x0000007c) |
|
||||||
#define NIOS2_EXCEPTION_REG_CAUSE_OFST (2) |
|
||||||
#define NIOS2_EXCEPTION_REG_ECCFTL_MASK (0x80000000) |
|
||||||
#define NIOS2_EXCEPTION_REG_ECCFTL_OFST (31) |
|
||||||
|
|
||||||
/* PTEADDR (Page Table Entry Address) register */ |
|
||||||
#define NIOS2_PTEADDR_REG_VPN_OFST 2 |
|
||||||
#define NIOS2_PTEADDR_REG_VPN_MASK 0x3ffffc |
|
||||||
#define NIOS2_PTEADDR_REG_PTBASE_OFST 22 |
|
||||||
#define NIOS2_PTEADDR_REG_PTBASE_MASK 0xffc00000 |
|
||||||
|
|
||||||
/* TLBACC (TLB Access) register */ |
|
||||||
#define NIOS2_TLBACC_REG_PFN_OFST 0 |
|
||||||
#define NIOS2_TLBACC_REG_PFN_MASK 0xfffff |
|
||||||
#define NIOS2_TLBACC_REG_G_OFST 20 |
|
||||||
#define NIOS2_TLBACC_REG_G_MASK 0x100000 |
|
||||||
#define NIOS2_TLBACC_REG_X_OFST 21 |
|
||||||
#define NIOS2_TLBACC_REG_X_MASK 0x200000 |
|
||||||
#define NIOS2_TLBACC_REG_W_OFST 22 |
|
||||||
#define NIOS2_TLBACC_REG_W_MASK 0x400000 |
|
||||||
#define NIOS2_TLBACC_REG_R_OFST 23 |
|
||||||
#define NIOS2_TLBACC_REG_R_MASK 0x800000 |
|
||||||
#define NIOS2_TLBACC_REG_C_OFST 24 |
|
||||||
#define NIOS2_TLBACC_REG_C_MASK 0x1000000 |
|
||||||
#define NIOS2_TLBACC_REG_IG_OFST 25 |
|
||||||
#define NIOS2_TLBACC_REG_IG_MASK 0xfe000000 |
|
||||||
|
|
||||||
/* TLBMISC (TLB Miscellaneous) register */ |
|
||||||
#define NIOS2_TLBMISC_REG_D_OFST 0 |
|
||||||
#define NIOS2_TLBMISC_REG_D_MASK 0x1 |
|
||||||
#define NIOS2_TLBMISC_REG_PERM_OFST 1 |
|
||||||
#define NIOS2_TLBMISC_REG_PERM_MASK 0x2 |
|
||||||
#define NIOS2_TLBMISC_REG_BAD_OFST 2 |
|
||||||
#define NIOS2_TLBMISC_REG_BAD_MASK 0x4 |
|
||||||
#define NIOS2_TLBMISC_REG_DBL_OFST 3 |
|
||||||
#define NIOS2_TLBMISC_REG_DBL_MASK 0x8 |
|
||||||
#define NIOS2_TLBMISC_REG_PID_OFST 4 |
|
||||||
#define NIOS2_TLBMISC_REG_PID_MASK 0x3fff0 |
|
||||||
#define NIOS2_TLBMISC_REG_WE_OFST 18 |
|
||||||
#define NIOS2_TLBMISC_REG_WE_MASK 0x40000 |
|
||||||
#define NIOS2_TLBMISC_REG_RD_OFST 19 |
|
||||||
#define NIOS2_TLBMISC_REG_RD_MASK 0x80000 |
|
||||||
#define NIOS2_TLBMISC_REG_WAY_OFST 20 |
|
||||||
#define NIOS2_TLBMISC_REG_WAY_MASK 0xf00000 |
|
||||||
#define NIOS2_TLBMISC_REG_EE_OFST 24 |
|
||||||
#define NIOS2_TLBMISC_REG_EE_MASK 0x1000000 |
|
||||||
|
|
||||||
/* ECCINJ (ECC Inject) register */ |
|
||||||
#define NIOS2_ECCINJ_REG_RF_OFST 0 |
|
||||||
#define NIOS2_ECCINJ_REG_RF_MASK 0x3 |
|
||||||
#define NIOS2_ECCINJ_REG_ICTAG_OFST 2 |
|
||||||
#define NIOS2_ECCINJ_REG_ICTAG_MASK 0xc |
|
||||||
#define NIOS2_ECCINJ_REG_ICDAT_OFST 4 |
|
||||||
#define NIOS2_ECCINJ_REG_ICDAT_MASK 0x30 |
|
||||||
#define NIOS2_ECCINJ_REG_DCTAG_OFST 6 |
|
||||||
#define NIOS2_ECCINJ_REG_DCTAG_MASK 0xc0 |
|
||||||
#define NIOS2_ECCINJ_REG_DCDAT_OFST 8 |
|
||||||
#define NIOS2_ECCINJ_REG_DCDAT_MASK 0x300 |
|
||||||
#define NIOS2_ECCINJ_REG_TLB_OFST 10 |
|
||||||
#define NIOS2_ECCINJ_REG_TLB_MASK 0xc00 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM0_OFST 12 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM0_MASK 0x3000 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM1_OFST 14 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM1_MASK 0xc000 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM2_OFST 16 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM2_MASK 0x30000 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM3_OFST 18 |
|
||||||
#define NIOS2_ECCINJ_REG_DTCM3_MASK 0xc0000 |
|
||||||
|
|
||||||
/* CONFIG register */ |
|
||||||
#define NIOS2_CONFIG_REG_PE_MASK (0x00000001) |
|
||||||
#define NIOS2_CONFIG_REG_PE_OFST (0) |
|
||||||
#define NIOS2_CONFIG_REG_ANI_MASK (0x00000002) |
|
||||||
#define NIOS2_CONFIG_REG_ANI_OFST (1) |
|
||||||
#define NIOS2_CONFIG_REG_ECCEN_MASK (0x00000004) |
|
||||||
#define NIOS2_CONFIG_REG_ECCEN_OFST (2) |
|
||||||
#define NIOS2_CONFIG_REG_ECCEXC_MASK (0x00000008) |
|
||||||
#define NIOS2_CONFIG_REG_ECCEXC_OFST (3) |
|
||||||
|
|
||||||
/* MPUBASE (MPU Base Address) Register */ |
|
||||||
#define NIOS2_MPUBASE_D_MASK (0x00000001) |
|
||||||
#define NIOS2_MPUBASE_D_OFST (0) |
|
||||||
#define NIOS2_MPUBASE_INDEX_MASK (0x0000003e) |
|
||||||
#define NIOS2_MPUBASE_INDEX_OFST (1) |
|
||||||
#define NIOS2_MPUBASE_BASE_ADDR_MASK (0xffffffc0) |
|
||||||
#define NIOS2_MPUBASE_BASE_ADDR_OFST (6) |
|
||||||
|
|
||||||
/* MPUACC (MPU Access) Register */ |
|
||||||
#define NIOS2_MPUACC_LIMIT_MASK (0xffffffc0) |
|
||||||
#define NIOS2_MPUACC_LIMIT_OFST (6) |
|
||||||
#define NIOS2_MPUACC_MASK_MASK (0xffffffc0) |
|
||||||
#define NIOS2_MPUACC_MASK_OFST (6) |
|
||||||
#define NIOS2_MPUACC_C_MASK (0x00000020) |
|
||||||
#define NIOS2_MPUACC_C_OFST (5) |
|
||||||
#define NIOS2_MPUACC_PERM_MASK (0x0000001c) |
|
||||||
#define NIOS2_MPUACC_PERM_OFST (2) |
|
||||||
#define NIOS2_MPUACC_RD_MASK (0x00000002) |
|
||||||
#define NIOS2_MPUACC_RD_OFST (1) |
|
||||||
#define NIOS2_MPUACC_WR_MASK (0x00000001) |
|
||||||
#define NIOS2_MPUACC_WR_OFST (0) |
|
||||||
|
|
||||||
#ifdef __cplusplus |
|
||||||
} |
|
||||||
#endif /* __cplusplus */ |
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_NIOS2_H_ */ |
|
@ -1,64 +0,0 @@ |
|||||||
/*
|
|
||||||
* Copyright (c) 2017 Intel Corporation |
|
||||||
* |
|
||||||
* SPDX-License-Identifier: Apache-2.0 |
|
||||||
*/ |
|
||||||
|
|
||||||
/**
|
|
||||||
* @file |
|
||||||
* @brief Per-arch thread definition |
|
||||||
* |
|
||||||
* This file contains definitions for |
|
||||||
* |
|
||||||
* struct _thread_arch |
|
||||||
* struct _callee_saved |
|
||||||
* |
|
||||||
* necessary to instantiate instances of struct k_thread. |
|
||||||
*/ |
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_THREAD_H_ |
|
||||||
#define ZEPHYR_INCLUDE_ARCH_NIOS2_THREAD_H_ |
|
||||||
|
|
||||||
#ifndef _ASMLANGUAGE |
|
||||||
#include <zephyr/types.h> |
|
||||||
|
|
||||||
struct _callee_saved { |
|
||||||
/* General purpose callee-saved registers */ |
|
||||||
uint32_t r16; |
|
||||||
uint32_t r17; |
|
||||||
uint32_t r18; |
|
||||||
uint32_t r19; |
|
||||||
uint32_t r20; |
|
||||||
uint32_t r21; |
|
||||||
uint32_t r22; |
|
||||||
uint32_t r23; |
|
||||||
|
|
||||||
/* Normally used for the frame pointer but also a general purpose
|
|
||||||
* register if frame pointers omitted |
|
||||||
*/ |
|
||||||
uint32_t r28; |
|
||||||
|
|
||||||
/* Return address */ |
|
||||||
uint32_t ra; |
|
||||||
|
|
||||||
/* Stack pointer */ |
|
||||||
uint32_t sp; |
|
||||||
|
|
||||||
/* IRQ status before irq_lock() and call to z_swap() */ |
|
||||||
uint32_t key; |
|
||||||
|
|
||||||
/* Return value of z_swap() */ |
|
||||||
uint32_t retval; |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct _callee_saved _callee_saved_t; |
|
||||||
|
|
||||||
struct _thread_arch { |
|
||||||
/* nothing for now */ |
|
||||||
}; |
|
||||||
|
|
||||||
typedef struct _thread_arch _thread_arch_t; |
|
||||||
|
|
||||||
#endif /* _ASMLANGUAGE */ |
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_THREAD_H_ */ |
|
@ -1,8 +0,0 @@ |
|||||||
# Altera HAL drivers configuration |
|
||||||
|
|
||||||
# Copyright (c) 2017 Intel Corporation |
|
||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
config HAS_ALTERA_HAL |
|
||||||
bool "Altera HAL drivers support" |
|
||||||
depends on NIOS2 |
|
@ -1,106 +0,0 @@ |
|||||||
# Copyright (c) 2017 Linaro Limited. |
|
||||||
# |
|
||||||
# SPDX-License-Identifier: Apache-2.0 |
|
||||||
|
|
||||||
'''Runner for NIOS II, based on quartus-flash.py and GDB.''' |
|
||||||
|
|
||||||
from runners.core import NetworkPortHelper, RunnerCaps, ZephyrBinaryRunner |
|
||||||
|
|
||||||
|
|
||||||
class Nios2BinaryRunner(ZephyrBinaryRunner): |
|
||||||
'''Runner front-end for NIOS II.''' |
|
||||||
|
|
||||||
# From the original shell script: |
|
||||||
# |
|
||||||
# "XXX [flash] only support[s] cases where the .elf is sent |
|
||||||
# over the JTAG and the CPU directly boots from __start. CONFIG_XIP |
|
||||||
# and CONFIG_INCLUDE_RESET_VECTOR must be disabled." |
|
||||||
|
|
||||||
def __init__(self, cfg, quartus_py=None, cpu_sof=None, tui=False): |
|
||||||
super().__init__(cfg) |
|
||||||
self.hex_name = cfg.hex_file |
|
||||||
self.elf_name = cfg.elf_file |
|
||||||
self.cpu_sof = cpu_sof |
|
||||||
self.quartus_py = quartus_py |
|
||||||
self.gdb_cmd = [cfg.gdb] if cfg.gdb else None |
|
||||||
self.tui_arg = ['-tui'] if tui else [] |
|
||||||
|
|
||||||
@classmethod |
|
||||||
def name(cls): |
|
||||||
return 'nios2' |
|
||||||
|
|
||||||
@classmethod |
|
||||||
def capabilities(cls): |
|
||||||
return RunnerCaps(commands={'flash', 'debug', 'debugserver', 'attach'}) |
|
||||||
|
|
||||||
@classmethod |
|
||||||
def do_add_parser(cls, parser): |
|
||||||
# TODO merge quartus-flash.py script into this file. |
|
||||||
parser.add_argument('--quartus-flash', required=True) |
|
||||||
parser.add_argument('--cpu-sof', required=True, |
|
||||||
help='path to the CPU .sof data') |
|
||||||
parser.add_argument('--tui', default=False, action='store_true', |
|
||||||
help='if given, GDB uses -tui') |
|
||||||
|
|
||||||
@classmethod |
|
||||||
def do_create(cls, cfg, args): |
|
||||||
return Nios2BinaryRunner(cfg, |
|
||||||
quartus_py=args.quartus_flash, |
|
||||||
cpu_sof=args.cpu_sof, |
|
||||||
tui=args.tui) |
|
||||||
|
|
||||||
def do_run(self, command, **kwargs): |
|
||||||
if command == 'flash': |
|
||||||
self.flash(**kwargs) |
|
||||||
else: |
|
||||||
self.debug_debugserver(command, **kwargs) |
|
||||||
|
|
||||||
def flash(self, **kwargs): |
|
||||||
if self.quartus_py is None: |
|
||||||
raise ValueError('Cannot flash; --quartus-flash not given.') |
|
||||||
if self.cpu_sof is None: |
|
||||||
raise ValueError('Cannot flash; --cpu-sof not given.') |
|
||||||
self.ensure_output('hex') |
|
||||||
|
|
||||||
self.logger.info(f'Flashing file: {self.hex_name}') |
|
||||||
cmd = [self.quartus_py, |
|
||||||
'--sof', self.cpu_sof, |
|
||||||
'--kernel', self.hex_name] |
|
||||||
self.require(cmd[0]) |
|
||||||
self.check_call(cmd) |
|
||||||
|
|
||||||
def print_gdbserver_message(self, gdb_port): |
|
||||||
self.logger.info(f'Nios II GDB server running on port {gdb_port}') |
|
||||||
|
|
||||||
def debug_debugserver(self, command, **kwargs): |
|
||||||
# Per comments in the shell script, the NIOSII GDB server |
|
||||||
# doesn't exit gracefully, so it's better to explicitly search |
|
||||||
# for an unused port. The script picks a random value in |
|
||||||
# between 1024 and 49151, but we'll start with the |
|
||||||
# "traditional" 3333 choice. |
|
||||||
gdb_start = 3333 |
|
||||||
nh = NetworkPortHelper() |
|
||||||
gdb_port = nh.get_unused_ports([gdb_start])[0] |
|
||||||
|
|
||||||
server_cmd = (['nios2-gdb-server', |
|
||||||
'--tcpport', str(gdb_port), |
|
||||||
'--stop', '--reset-target']) |
|
||||||
self.require(server_cmd[0]) |
|
||||||
|
|
||||||
if command == 'debugserver': |
|
||||||
self.print_gdbserver_message(gdb_port) |
|
||||||
self.check_call(server_cmd) |
|
||||||
else: |
|
||||||
if self.elf_name is None: |
|
||||||
raise ValueError('Cannot debug; elf is missing') |
|
||||||
if self.gdb_cmd is None: |
|
||||||
raise ValueError('Cannot debug; no gdb specified') |
|
||||||
|
|
||||||
gdb_cmd = (self.gdb_cmd + |
|
||||||
self.tui_arg + |
|
||||||
[self.elf_name, |
|
||||||
'-ex', f'target remote :{gdb_port}']) |
|
||||||
self.require(gdb_cmd[0]) |
|
||||||
|
|
||||||
self.print_gdbserver_message(gdb_port) |
|
||||||
self.run_server_and_client(server_cmd, gdb_cmd) |
|
Loading…
Reference in new issue