mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2025-03-12 10:06:47 -04:00
PoC: Add example firmware with embedded that calls syscalls implemented in C
App is embedded in firmware and is loaded into app RAM when firmware starts. App continuously calls SET_LED syscalls. Simulation: `make tb_application_fpga_irqpoc_c_example`
This commit is contained in:
parent
e1d7608897
commit
2e1925555d
@ -157,6 +157,12 @@ IRQPOC_WITH_APP_OBJS = \
|
|||||||
$(P)/fw/irqpoc_with_app/main.o \
|
$(P)/fw/irqpoc_with_app/main.o \
|
||||||
$(P)/fw/irqpoc_with_app/start.o
|
$(P)/fw/irqpoc_with_app/start.o
|
||||||
|
|
||||||
|
IRQPOC_C_EXAMPLE_OBJS = \
|
||||||
|
$(P)/fw/irqpoc_c_example/main.o \
|
||||||
|
$(P)/fw/irqpoc_c_example/start.o \
|
||||||
|
$(P)/fw/tk1/led.o \
|
||||||
|
$(P)/fw/tk1/assert.o
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
# All: Complete build of HW and FW.
|
# All: Complete build of HW and FW.
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
@ -196,6 +202,7 @@ $(TESTFW_OBJS): $(FIRMWARE_DEPS)
|
|||||||
$(IRQPOC_OBJS): $(FIRMWARE_DEPS)
|
$(IRQPOC_OBJS): $(FIRMWARE_DEPS)
|
||||||
$(IRQPOC_LED_TOGGLE_OBJS): $(FIRMWARE_DEPS)
|
$(IRQPOC_LED_TOGGLE_OBJS): $(FIRMWARE_DEPS)
|
||||||
$(IRQPOC_WITH_APP_OBJS): $(FIRMWARE_DEPS)
|
$(IRQPOC_WITH_APP_OBJS): $(FIRMWARE_DEPS)
|
||||||
|
$(IRQPOC_C_EXAMPLE_OBJS): $(FIRMWARE_DEPS)
|
||||||
|
|
||||||
firmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds
|
firmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@
|
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@
|
||||||
@ -247,6 +254,9 @@ irqpoc_led_toggle.elf: $(IRQPOC_LED_TOGGLE_OBJS) $(P)/fw/tk1/firmware.lds
|
|||||||
irqpoc_with_app.elf: $(IRQPOC_WITH_APP_OBJS) $(P)/fw/tk1/firmware.lds
|
irqpoc_with_app.elf: $(IRQPOC_WITH_APP_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
$(CC) $(CFLAGS) $(IRQPOC_WITH_APP_OBJS) $(LDFLAGS) -o $@
|
$(CC) $(CFLAGS) $(IRQPOC_WITH_APP_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
irqpoc_c_example.elf: $(IRQPOC_C_EXAMPLE_OBJS) $(P)/fw/tk1/firmware.lds
|
||||||
|
$(CC) $(CFLAGS) $(IRQPOC_C_EXAMPLE_OBJS) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
# Generate a fake BRAM file that will be filled in later after place-n-route
|
# Generate a fake BRAM file that will be filled in later after place-n-route
|
||||||
bram_fw.hex:
|
bram_fw.hex:
|
||||||
$(ICESTORM_PATH)icebram -v -g 32 $(BRAM_FW_SIZE) > $@
|
$(ICESTORM_PATH)icebram -v -g 32 $(BRAM_FW_SIZE) > $@
|
||||||
@ -261,6 +271,8 @@ irqpoc.hex: irqpoc.bin
|
|||||||
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
irqpoc_with_app.hex: irqpoc_with_app.bin
|
irqpoc_with_app.hex: irqpoc_with_app.bin
|
||||||
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
|
irqpoc_c_example.hex: irqpoc_c_example.bin
|
||||||
|
python3 $(P)/tools/makehex/makehex.py $< $(BRAM_FW_SIZE) > $@
|
||||||
|
|
||||||
|
|
||||||
.PHONY: check-binary-hashes
|
.PHONY: check-binary-hashes
|
||||||
@ -485,6 +497,10 @@ tb_application_fpga_irqpoc: irqpoc.hex emptyapp tb_application_fpga
|
|||||||
tb_application_fpga_irqpoc_with_app: SIMFIRMWARE=irqpoc_with_app.hex
|
tb_application_fpga_irqpoc_with_app: SIMFIRMWARE=irqpoc_with_app.hex
|
||||||
tb_application_fpga_irqpoc_with_app: irqpoc_with_app.hex emptyapp tb_application_fpga
|
tb_application_fpga_irqpoc_with_app: irqpoc_with_app.hex emptyapp tb_application_fpga
|
||||||
|
|
||||||
|
.PHONY: tb_application_fpga_irqpoc_c_example
|
||||||
|
tb_application_fpga_irqpoc_c_example: SIMFIRMWARE=irqpoc_c_example.hex
|
||||||
|
tb_application_fpga_irqpoc_c_example: irqpoc_c_example.hex emptyapp tb_application_fpga
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------
|
#-------------------------------------------------------------------
|
||||||
# FPGA device programming.
|
# FPGA device programming.
|
||||||
@ -535,6 +551,7 @@ clean_fw:
|
|||||||
rm -f $(IRQPOC_OBJS)
|
rm -f $(IRQPOC_OBJS)
|
||||||
rm -f $(IRQPOC_LED_TOGGLE_OBJS)
|
rm -f $(IRQPOC_LED_TOGGLE_OBJS)
|
||||||
rm -f $(IRQPOC_WITH_APP_OBJS)
|
rm -f $(IRQPOC_WITH_APP_OBJS)
|
||||||
|
rm -f $(IRQPOC_C_EXAMPLE_OBJS)
|
||||||
rm -f qemu_firmware.elf
|
rm -f qemu_firmware.elf
|
||||||
.PHONY: clean_fw
|
.PHONY: clean_fw
|
||||||
|
|
||||||
|
9
hw/application_fpga/fw/irqpoc_c_example/Makefile
Normal file
9
hw/application_fpga/fw/irqpoc_c_example/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Uses ../.clang-format
|
||||||
|
FMTFILES=main.c
|
||||||
|
.PHONY: fmt
|
||||||
|
fmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 $(FMTFILES)
|
||||||
|
clang-format --verbose -i $(FMTFILES)
|
||||||
|
.PHONY: checkfmt
|
||||||
|
checkfmt:
|
||||||
|
clang-format --dry-run --ferror-limit=0 --Werror $(FMTFILES)
|
102
hw/application_fpga/fw/irqpoc_c_example/custom_ops.S
Normal file
102
hw/application_fpga/fw/irqpoc_c_example/custom_ops.S
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// This is free and unencumbered software released into the public domain.
|
||||||
|
//
|
||||||
|
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
// distribute this software, either in source code form or as a compiled
|
||||||
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
// means.
|
||||||
|
|
||||||
|
#define regnum_q0 0
|
||||||
|
#define regnum_q1 1
|
||||||
|
#define regnum_q2 2
|
||||||
|
#define regnum_q3 3
|
||||||
|
|
||||||
|
#define regnum_x0 0
|
||||||
|
#define regnum_x1 1
|
||||||
|
#define regnum_x2 2
|
||||||
|
#define regnum_x3 3
|
||||||
|
#define regnum_x4 4
|
||||||
|
#define regnum_x5 5
|
||||||
|
#define regnum_x6 6
|
||||||
|
#define regnum_x7 7
|
||||||
|
#define regnum_x8 8
|
||||||
|
#define regnum_x9 9
|
||||||
|
#define regnum_x10 10
|
||||||
|
#define regnum_x11 11
|
||||||
|
#define regnum_x12 12
|
||||||
|
#define regnum_x13 13
|
||||||
|
#define regnum_x14 14
|
||||||
|
#define regnum_x15 15
|
||||||
|
#define regnum_x16 16
|
||||||
|
#define regnum_x17 17
|
||||||
|
#define regnum_x18 18
|
||||||
|
#define regnum_x19 19
|
||||||
|
#define regnum_x20 20
|
||||||
|
#define regnum_x21 21
|
||||||
|
#define regnum_x22 22
|
||||||
|
#define regnum_x23 23
|
||||||
|
#define regnum_x24 24
|
||||||
|
#define regnum_x25 25
|
||||||
|
#define regnum_x26 26
|
||||||
|
#define regnum_x27 27
|
||||||
|
#define regnum_x28 28
|
||||||
|
#define regnum_x29 29
|
||||||
|
#define regnum_x30 30
|
||||||
|
#define regnum_x31 31
|
||||||
|
|
||||||
|
#define regnum_zero 0
|
||||||
|
#define regnum_ra 1
|
||||||
|
#define regnum_sp 2
|
||||||
|
#define regnum_gp 3
|
||||||
|
#define regnum_tp 4
|
||||||
|
#define regnum_t0 5
|
||||||
|
#define regnum_t1 6
|
||||||
|
#define regnum_t2 7
|
||||||
|
#define regnum_s0 8
|
||||||
|
#define regnum_s1 9
|
||||||
|
#define regnum_a0 10
|
||||||
|
#define regnum_a1 11
|
||||||
|
#define regnum_a2 12
|
||||||
|
#define regnum_a3 13
|
||||||
|
#define regnum_a4 14
|
||||||
|
#define regnum_a5 15
|
||||||
|
#define regnum_a6 16
|
||||||
|
#define regnum_a7 17
|
||||||
|
#define regnum_s2 18
|
||||||
|
#define regnum_s3 19
|
||||||
|
#define regnum_s4 20
|
||||||
|
#define regnum_s5 21
|
||||||
|
#define regnum_s6 22
|
||||||
|
#define regnum_s7 23
|
||||||
|
#define regnum_s8 24
|
||||||
|
#define regnum_s9 25
|
||||||
|
#define regnum_s10 26
|
||||||
|
#define regnum_s11 27
|
||||||
|
#define regnum_t3 28
|
||||||
|
#define regnum_t4 29
|
||||||
|
#define regnum_t5 30
|
||||||
|
#define regnum_t6 31
|
||||||
|
|
||||||
|
// x8 is s0 and also fp
|
||||||
|
#define regnum_fp 8
|
||||||
|
|
||||||
|
#define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
|
||||||
|
.word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
|
||||||
|
|
||||||
|
#define picorv32_getq_insn(_rd, _qs) \
|
||||||
|
r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_setq_insn(_qd, _rs) \
|
||||||
|
r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_retirq_insn() \
|
||||||
|
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_maskirq_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_waitirq_insn(_rd) \
|
||||||
|
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
||||||
|
#define picorv32_timer_insn(_rd, _rs) \
|
||||||
|
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
|
||||||
|
|
58
hw/application_fpga/fw/irqpoc_c_example/main.c
Normal file
58
hw/application_fpga/fw/irqpoc_c_example/main.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../tk1/types.h"
|
||||||
|
#include "../tk1/led.h"
|
||||||
|
#include "../tk1/assert.h"
|
||||||
|
|
||||||
|
// Proof-of-concept firmware for handling syscalls.
|
||||||
|
// This is NOT a best-practice example of secure syscall implementation.
|
||||||
|
|
||||||
|
#define SYSCALL_HI (1 << 31)
|
||||||
|
#define SYSCALL_LO 0
|
||||||
|
|
||||||
|
#define SYSCALL_HI_SET_LED (SYSCALL_HI | 10)
|
||||||
|
#define SYSCALL_LO_SET_LED (SYSCALL_LO | 10)
|
||||||
|
|
||||||
|
static void delay(int32_t count) {
|
||||||
|
volatile int32_t c = count;
|
||||||
|
while (c > 0) {
|
||||||
|
c--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t syscall_lo_handler(uint32_t syscall_nr, uint32_t arg1) {
|
||||||
|
switch (syscall_nr) {
|
||||||
|
case SYSCALL_LO_SET_LED:
|
||||||
|
set_led(arg1);
|
||||||
|
//delay(1000000);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
assert(1 == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(1 == 2);
|
||||||
|
return -1; // This should never run
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t syscall_hi_handler(uint32_t syscall_nr, uint32_t arg1) {
|
||||||
|
switch (syscall_nr) {
|
||||||
|
case SYSCALL_HI_SET_LED:
|
||||||
|
set_led(arg1);
|
||||||
|
//delay(500000);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
assert(1 == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(1 == 2);
|
||||||
|
return -1; // This should never run
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
261
hw/application_fpga/fw/irqpoc_c_example/start.S
Normal file
261
hw/application_fpga/fw/irqpoc_c_example/start.S
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022, 2023 - Tillitis AB
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This firmware copies an app from ROM to app RAM.
|
||||||
|
// The app continuosly calls the SET_LED syscalls in firmware (main.c).
|
||||||
|
//
|
||||||
|
#include "../tk1_mem.h"
|
||||||
|
#include "custom_ops.S" // PicoRV32 custom instructions
|
||||||
|
|
||||||
|
#define illegal_insn() .word 0
|
||||||
|
|
||||||
|
#define FW_SP_STORAGE (TK1_MMIO_FW_RAM_BASE + TK1_MMIO_FW_RAM_SIZE - 4)
|
||||||
|
#define FW_STACK_TOP (TK1_MMIO_FW_RAM_BASE + TK1_MMIO_FW_RAM_SIZE - 2*4)
|
||||||
|
|
||||||
|
#define LED_RED (1 << TK1_MMIO_TK1_LED_R_BIT)
|
||||||
|
#define LED_GREEN (1 << TK1_MMIO_TK1_LED_G_BIT)
|
||||||
|
#define LED_BLUE (1 << TK1_MMIO_TK1_LED_B_BIT)
|
||||||
|
|
||||||
|
.section ".text.init"
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
j init
|
||||||
|
|
||||||
|
//
|
||||||
|
// IRQ handler
|
||||||
|
//
|
||||||
|
.=0x10 // IRQ handler at fixed address 0x10
|
||||||
|
irq_handler:
|
||||||
|
// PicoRV32 stores the IRQ bitmask in x4.
|
||||||
|
// If bit 31 is 1: IRQ31 was triggered.
|
||||||
|
// If bit 30 is 1: IRQ30 was triggered.
|
||||||
|
irq_syscall_lo_check:
|
||||||
|
li t4, (1 << 30)
|
||||||
|
bne x4, t4, irq_syscall_hi_check
|
||||||
|
|
||||||
|
// Run low privilege syscall handler
|
||||||
|
call syscall_lo_handler
|
||||||
|
|
||||||
|
j irq_source_check_done
|
||||||
|
irq_syscall_hi_check:
|
||||||
|
li t4, (1 << 31)
|
||||||
|
bne x4, t4, unexpected_irq
|
||||||
|
|
||||||
|
// Save app stack pointer. App is responsible for saving the rest of
|
||||||
|
// the registers.
|
||||||
|
la t0, FW_SP_STORAGE
|
||||||
|
sw sp, 0(t0)
|
||||||
|
|
||||||
|
// Setup firmware stack pointer
|
||||||
|
la sp, FW_STACK_TOP
|
||||||
|
|
||||||
|
// Run high privilege syscall handler
|
||||||
|
call syscall_hi_handler
|
||||||
|
|
||||||
|
// Restore app stack pointer
|
||||||
|
la t0, FW_SP_STORAGE
|
||||||
|
lw sp, 0(t0)
|
||||||
|
|
||||||
|
j irq_source_check_done
|
||||||
|
unexpected_irq:
|
||||||
|
illegal_insn()
|
||||||
|
irq_source_check_done:
|
||||||
|
// Verify that interrupt return address is in app RAM
|
||||||
|
li t0, TK1_RAM_BASE // 0x40000000
|
||||||
|
blt x3, t0, x3_invalid
|
||||||
|
li t0, TK1_RAM_BASE + TK1_RAM_SIZE // 0x40020000
|
||||||
|
bge x3, t0, x3_invalid
|
||||||
|
j x3_valid
|
||||||
|
x3_invalid:
|
||||||
|
illegal_insn()
|
||||||
|
j x3_invalid
|
||||||
|
x3_valid:
|
||||||
|
|
||||||
|
// Remove data left over from the syscall handling
|
||||||
|
mv x0, zero
|
||||||
|
mv x1, zero
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler
|
||||||
|
// x3 (interrupt return address) assumed preserved
|
||||||
|
mv x4, zero
|
||||||
|
mv x5, zero
|
||||||
|
mv x6, zero
|
||||||
|
mv x7, zero
|
||||||
|
mv x8, zero
|
||||||
|
mv x9, zero
|
||||||
|
// x10 (a0) contains syscall return value. And should not be destroyed.
|
||||||
|
mv x11, zero
|
||||||
|
mv x12, zero
|
||||||
|
mv x13, zero
|
||||||
|
mv x14, zero
|
||||||
|
mv x15, zero
|
||||||
|
mv x16, zero
|
||||||
|
mv x17, zero
|
||||||
|
mv x18, zero
|
||||||
|
mv x19, zero
|
||||||
|
mv x20, zero
|
||||||
|
mv x21, zero
|
||||||
|
mv x22, zero
|
||||||
|
mv x23, zero
|
||||||
|
mv x24, zero
|
||||||
|
mv x25, zero
|
||||||
|
mv x26, zero
|
||||||
|
mv x27, zero
|
||||||
|
mv x28, zero
|
||||||
|
mv x29, zero
|
||||||
|
mv x30, zero
|
||||||
|
mv x31, zero
|
||||||
|
|
||||||
|
picorv32_retirq_insn() // Return from interrupt
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init
|
||||||
|
//
|
||||||
|
.=0x100
|
||||||
|
init:
|
||||||
|
li t0, TK1_MMIO_TK1_LED
|
||||||
|
li t1, LED_RED
|
||||||
|
sw t1, 0(t0)
|
||||||
|
|
||||||
|
// Enable IRQs
|
||||||
|
li t0, 0x3fffffff // IRQ31 & IRQ30 mask
|
||||||
|
picorv32_maskirq_insn(zero, t0) // Enable IRQs
|
||||||
|
|
||||||
|
// Copy app to App RAM
|
||||||
|
la t0, app_start
|
||||||
|
la t1, app_end
|
||||||
|
li t2, 0x40000000 // 0x40000000: App RAM
|
||||||
|
copy_app:
|
||||||
|
lw t3, 0(t0)
|
||||||
|
sw t3, 0(t2)
|
||||||
|
addi t0, t0, 4
|
||||||
|
addi t2, t2, 4
|
||||||
|
bleu t0, t1, copy_app
|
||||||
|
|
||||||
|
// Jump to app
|
||||||
|
li t2, 0x40000000 // 0x40000000: App RAM
|
||||||
|
jalr zero, 0(t2)
|
||||||
|
|
||||||
|
//
|
||||||
|
// App
|
||||||
|
//
|
||||||
|
#define APP_SYSCALL_HI (1 << 31)
|
||||||
|
#define APP_SYSCALL_LO 0
|
||||||
|
#define APP_SYSCALL_HI_SET_LED (APP_SYSCALL_HI | 10)
|
||||||
|
#define APP_SYSCALL_LO_SET_LED (APP_SYSCALL_LO | 10)
|
||||||
|
|
||||||
|
.=0x1000
|
||||||
|
app_start:
|
||||||
|
// Set stack pointer to end of app RAM
|
||||||
|
li sp, 0x4001fffc
|
||||||
|
|
||||||
|
app_loop:
|
||||||
|
li a0, APP_SYSCALL_LO_SET_LED
|
||||||
|
li a1, LED_GREEN
|
||||||
|
call app_syscall
|
||||||
|
|
||||||
|
li a0, APP_SYSCALL_LO_SET_LED
|
||||||
|
li a1, LED_BLUE
|
||||||
|
call app_syscall
|
||||||
|
|
||||||
|
li a0, APP_SYSCALL_HI_SET_LED
|
||||||
|
li a1, LED_RED | LED_GREEN
|
||||||
|
call app_syscall
|
||||||
|
|
||||||
|
li a0, APP_SYSCALL_HI_SET_LED
|
||||||
|
li a1, LED_RED | LED_BLUE
|
||||||
|
call app_syscall
|
||||||
|
|
||||||
|
j app_loop
|
||||||
|
|
||||||
|
app_syscall:
|
||||||
|
// Save registers to stack
|
||||||
|
addi sp, sp, -32*4
|
||||||
|
sw x0, 0*4(sp)
|
||||||
|
sw x1, 1*4(sp)
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||||
|
sw x3, 3*4(sp)
|
||||||
|
sw x4, 4*4(sp)
|
||||||
|
sw x5, 5*4(sp)
|
||||||
|
sw x6, 6*4(sp)
|
||||||
|
sw x7, 7*4(sp)
|
||||||
|
sw x8, 8*4(sp)
|
||||||
|
sw x9, 9*4(sp)
|
||||||
|
// x10 (a0) will contain syscall return value. And should not be saved.
|
||||||
|
sw x11, 11*4(sp)
|
||||||
|
sw x12, 12*4(sp)
|
||||||
|
sw x13, 13*4(sp)
|
||||||
|
sw x14, 14*4(sp)
|
||||||
|
sw x15, 15*4(sp)
|
||||||
|
sw x16, 16*4(sp)
|
||||||
|
sw x17, 17*4(sp)
|
||||||
|
sw x18, 18*4(sp)
|
||||||
|
sw x19, 19*4(sp)
|
||||||
|
sw x20, 20*4(sp)
|
||||||
|
sw x21, 21*4(sp)
|
||||||
|
sw x22, 22*4(sp)
|
||||||
|
sw x23, 23*4(sp)
|
||||||
|
sw x24, 24*4(sp)
|
||||||
|
sw x25, 25*4(sp)
|
||||||
|
sw x26, 26*4(sp)
|
||||||
|
sw x27, 27*4(sp)
|
||||||
|
sw x28, 28*4(sp)
|
||||||
|
sw x29, 29*4(sp)
|
||||||
|
sw x30, 30*4(sp)
|
||||||
|
sw x31, 31*4(sp)
|
||||||
|
|
||||||
|
// Raise interrupt depending on bit 31 in a0
|
||||||
|
// 0: Low privilege syscall
|
||||||
|
// 1: High privilege syscall
|
||||||
|
li t0, (1 << 31)
|
||||||
|
and t0, a0, t0
|
||||||
|
beqz t0, app_syscall_low_priv
|
||||||
|
li t1, 0xe1000000 // High privilege interrupt
|
||||||
|
sw zero, 0(t1) // Trigger interrupt
|
||||||
|
j app_syscall_restore_registers
|
||||||
|
app_syscall_low_priv:
|
||||||
|
li t1, 0xe0000000 // Low privelege interrupt
|
||||||
|
sw zero, 0(t1) // Trigger interrupt
|
||||||
|
|
||||||
|
app_syscall_restore_registers:
|
||||||
|
// Restore registers from stack
|
||||||
|
lw x0, 0*4(sp)
|
||||||
|
lw x1, 1*4(sp)
|
||||||
|
// x2 (sp) is assumed to be preserved by the interrupt handler.
|
||||||
|
lw x3, 3*4(sp)
|
||||||
|
lw x4, 4*4(sp)
|
||||||
|
lw x5, 5*4(sp)
|
||||||
|
lw x6, 6*4(sp)
|
||||||
|
lw x7, 7*4(sp)
|
||||||
|
lw x8, 8*4(sp)
|
||||||
|
lw x9, 9*4(sp)
|
||||||
|
// x10 (a0) contains syscall return value. And should not be destroyed.
|
||||||
|
lw x11, 11*4(sp)
|
||||||
|
lw x12, 12*4(sp)
|
||||||
|
lw x13, 13*4(sp)
|
||||||
|
lw x14, 14*4(sp)
|
||||||
|
lw x15, 15*4(sp)
|
||||||
|
lw x16, 16*4(sp)
|
||||||
|
lw x17, 17*4(sp)
|
||||||
|
lw x18, 18*4(sp)
|
||||||
|
lw x19, 19*4(sp)
|
||||||
|
lw x20, 20*4(sp)
|
||||||
|
lw x21, 21*4(sp)
|
||||||
|
lw x22, 22*4(sp)
|
||||||
|
lw x23, 23*4(sp)
|
||||||
|
lw x24, 24*4(sp)
|
||||||
|
lw x25, 25*4(sp)
|
||||||
|
lw x26, 26*4(sp)
|
||||||
|
lw x27, 27*4(sp)
|
||||||
|
lw x28, 28*4(sp)
|
||||||
|
lw x29, 29*4(sp)
|
||||||
|
lw x30, 30*4(sp)
|
||||||
|
lw x31, 31*4(sp)
|
||||||
|
addi sp, sp, 32*4
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
app_end:
|
||||||
|
|
@ -84,7 +84,7 @@ module tb_application_fpga_sim ();
|
|||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
initial begin
|
initial begin
|
||||||
// End simulation after XXX time units (set by timescale)
|
// End simulation after XXX time units (set by timescale)
|
||||||
#3000;
|
#14000;
|
||||||
$display("TIMEOUT");
|
$display("TIMEOUT");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user