summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorJean-Paul Etienne <fractalclone@gmail.com>2017-01-11 00:24:30 +0100
committerAndrew Boie <andrew.p.boie@intel.com>2017-01-13 19:55:05 +0000
commit2a8cfca4cf70dcf68dc297dd95d824d64a47c755 (patch)
treeeffdc9c005b945af1b18a10d8c0ea7134b3c7e88 /arch
parentc76abeeae515b92ffcca477604199289a4c4704f (diff)
riscv32: added support for the pulpino soc
pulpino soc has custom-extended riscv ISA that is accounted for if CONFIG_RISCV_GENERIC_TOOLCHAIN is not set. (ex: bit manipulation asm opcodes) Change-Id: I4dafc4ebc2fedcc4eb6a3dedd0412816afea6004 Signed-off-by: Jean-Paul Etienne <fractalclone@gmail.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/riscv32/soc/pulpino/Kbuild7
-rw-r--r--arch/riscv32/soc/pulpino/Kconfig.defconfig87
-rw-r--r--arch/riscv32/soc/pulpino/Kconfig.soc2
-rw-r--r--arch/riscv32/soc/pulpino/Makefile20
-rw-r--r--arch/riscv32/soc/pulpino/linker.ld21
-rw-r--r--arch/riscv32/soc/pulpino/pulpino_idle.c73
-rw-r--r--arch/riscv32/soc/pulpino/pulpino_irq.c62
-rw-r--r--arch/riscv32/soc/pulpino/soc.h157
-rw-r--r--arch/riscv32/soc/pulpino/soc_irq.S124
-rw-r--r--arch/riscv32/soc/pulpino/vector.S76
10 files changed, 629 insertions, 0 deletions
diff --git a/arch/riscv32/soc/pulpino/Kbuild b/arch/riscv32/soc/pulpino/Kbuild
new file mode 100644
index 000000000..6eff8cafb
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/Kbuild
@@ -0,0 +1,7 @@
+ccflags-y +=-I$(srctree)/include
+ccflags-y +=-I$(srctree)/include/drivers
+ccflags-y +=-I$(srctree)/drivers
+
+asflags-y := ${ccflags-y}
+
+obj-y = soc_irq.o vector.o pulpino_irq.o pulpino_idle.o
diff --git a/arch/riscv32/soc/pulpino/Kconfig.defconfig b/arch/riscv32/soc/pulpino/Kconfig.defconfig
new file mode 100644
index 000000000..172ddb34e
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/Kconfig.defconfig
@@ -0,0 +1,87 @@
+if SOC_RISCV32_PULPINO
+
+config SOC
+ string
+ default "pulpino"
+
+config SYS_CLOCK_HW_CYCLES_PER_SEC
+ int
+ default 5000000
+
+config RISCV_SOC_CONTEXT_SAVE
+ bool
+ default y
+
+config RISCV_SOC_INTERRUPT_INIT
+ bool
+ default y
+
+config RISCV_HAS_CPU_IDLE
+ bool
+ default y
+
+config INCLUDE_RESET_VECTOR
+ bool
+ default y
+
+config NUM_IRQS
+ int
+ default 32
+
+config ATOMIC_OPERATIONS_C
+ bool
+ default y
+
+config ITCM_BASE_ADDRESS
+ hex
+ default 0x00000000
+
+config ITCM_SIZE
+ hex
+ default 0x8000
+
+config DTCM_BASE_ADDRESS
+ hex
+ default 0x00100000
+
+config DTCM_SIZE
+ hex
+ default 0x8000
+
+if UART_NS16550
+
+config UART_NS16550_PCI
+ bool
+ default n
+
+config UART_NS16750
+ bool
+ default y
+
+config UART_NS16550_PORT_0
+ bool
+ default y
+
+if UART_NS16550_PORT_0
+
+config UART_NS16550_PORT_0_NAME
+ string
+ default "UART_0"
+
+config UART_NS16550_PORT_0_IRQ_PRI
+ int
+ default 0
+
+config UART_NS16550_PORT_0_BAUD_RATE
+ int
+ default 115200
+
+config UART_NS16550_PORT_0_OPTIONS
+ int
+ default 0
+
+endif # UART_NS16550_PORT_0
+
+endif # UART_NS16550
+
+endif # SOC_RISCV32_PULPINO
diff --git a/arch/riscv32/soc/pulpino/Kconfig.soc b/arch/riscv32/soc/pulpino/Kconfig.soc
new file mode 100644
index 000000000..5925c2390
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/Kconfig.soc
@@ -0,0 +1,2 @@
+config SOC_RISCV32_PULPINO
+ bool "Pulpino SOC implementation"
diff --git a/arch/riscv32/soc/pulpino/Makefile b/arch/riscv32/soc/pulpino/Makefile
new file mode 100644
index 000000000..4dda17816
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/Makefile
@@ -0,0 +1,20 @@
+soc-cflags := -I/$(srctree)/arch/$(ARCH)/soc/$(SOC_PATH)/
+
+ifndef CONFIG_RISCV_GENERIC_TOOLCHAIN
+soc-cflags += -march=IMXpulpv2
+endif
+
+KERNEL_S19_NAME = $(KERNEL_NAME).s19
+
+quiet_cmd_gen_s19 = S19 $@
+ cmd_gen_s19 = \
+( \
+ $(OBJCOPY) --srec-len 1 --output-target=srec $< $@; \
+)
+
+$(KERNEL_S19_NAME): $(KERNEL_ELF_NAME)
+ $(call cmd,gen_s19)
+
+zephyr: $(KERNEL_S19_NAME)
+all: $(KERNEL_S19_NAME)
+export KERNEL_S19_NAME
diff --git a/arch/riscv32/soc/pulpino/linker.ld b/arch/riscv32/soc/pulpino/linker.ld
new file mode 100644
index 000000000..93992917c
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/linker.ld
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @brief Linker script for pulpino
+ */
+
+#include <arch/riscv32/pulpino/linker.ld>
diff --git a/arch/riscv32/soc/pulpino/pulpino_idle.c b/arch/riscv32/soc/pulpino/pulpino_idle.c
new file mode 100644
index 000000000..d95086e96
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/pulpino_idle.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <toolchain.h>
+#include <irq.h>
+#include <soc.h>
+
+#include <logging/kernel_event_logger.h>
+
+static ALWAYS_INLINE void pulpino_idle(unsigned int key)
+{
+#ifdef CONFIG_KERNEL_EVENT_LOGGER_SLEEP
+ _sys_k_event_logger_enter_sleep();
+#endif
+ /* unlock interrupts */
+ irq_unlock(key);
+
+ /* Put CPU core to sleep via SCR register */
+ PULP_SCR = 0x01;
+
+ /* Wait for interrupt */
+ SOC_WFI;
+}
+
+/**
+ *
+ * @brief Power save idle routine
+ *
+ * This function will be called by the kernel idle loop or possibly within
+ * an implementation of _sys_power_save_idle in the microkernel when the
+ * '_sys_power_save_flag' variable is non-zero.
+ *
+ * @return N/A
+ */
+void k_cpu_idle(void)
+{
+ pulpino_idle(SOC_MSTATUS_IEN);
+}
+
+/**
+ *
+ * @brief Atomically re-enable interrupts and enter low power mode
+ *
+ * INTERNAL
+ * The requirements for k_cpu_atomic_idle() are as follows:
+ * 1) The enablement of interrupts and entering a low-power mode needs to be
+ * atomic, i.e. there should be no period of time where interrupts are
+ * enabled before the processor enters a low-power mode. See the comments
+ * in k_lifo_get(), for example, of the race condition that
+ * occurs if this requirement is not met.
+ *
+ * 2) After waking up from the low-power mode, the interrupt lockout state
+ * must be restored as indicated in the 'imask' input parameter.
+ *
+ * @return N/A
+ */
+void k_cpu_atomic_idle(unsigned int key)
+{
+ pulpino_idle(key);
+}
diff --git a/arch/riscv32/soc/pulpino/pulpino_irq.c b/arch/riscv32/soc/pulpino/pulpino_irq.c
new file mode 100644
index 000000000..c49c88de6
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/pulpino_irq.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * @brief pulpino interrupt management code
+ */
+#include <irq.h>
+#include <soc.h>
+
+void _arch_irq_enable(unsigned int irq)
+{
+ int key;
+
+ key = irq_lock();
+ /*
+ * enable both IRQ and Event
+ * Event will allow system to wakeup upon an interrupt,
+ * if CPU was set to sleep
+ */
+ PULP_IER |= (1 << irq);
+ PULP_EER |= (1 << irq);
+ irq_unlock(key);
+};
+
+void _arch_irq_disable(unsigned int irq)
+{
+ int key;
+
+ key = irq_lock();
+ PULP_IER &= ~(1 << irq);
+ PULP_EER &= ~(1 << irq);
+ irq_unlock(key);
+};
+
+int _arch_irq_is_enabled(unsigned int irq)
+{
+ return !!(PULP_IER & (1 << irq));
+}
+
+#if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
+void soc_interrupt_init(void)
+{
+ /* ensure that all interrupts are disabled */
+ (void)irq_lock();
+ PULP_IER = 0;
+ PULP_EER = 0;
+}
+#endif
diff --git a/arch/riscv32/soc/pulpino/soc.h b/arch/riscv32/soc/pulpino/soc.h
new file mode 100644
index 000000000..26fd6b096
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/soc.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file SoC configuration macros for the pulpino core
+ */
+
+#ifndef __PULPINO_SOC_H_
+#define __PULPINO_SOC_H_
+
+/* CSR Registers */
+#define PULP_MESTATUS 0x7C0 /* Machine Exception Status Register */
+#define PULP_LPSTART0 0x7B0 /* Hardware Loop 0 Start Register */
+#define PULP_LPEND0 0x7B1 /* Hardware Loop 0 End Register */
+#define PULP_LPCOUNT0 0x7B2 /* Hardware Loop 0 Count Register */
+#define PULP_LPSTART1 0x7B4 /* Hardware Loop 1 Start Register */
+#define PULP_LPEND1 0x7B5 /* Hardware Loop 1 End Register */
+#define PULP_LPCOUNT1 0x7B6 /* Hardware Loop 1 Count Register */
+
+/* IRQ numbers */
+#define PULP_I2C_0_IRQ 23 /* I2C Controller */
+#define PULP_UART_0_IRQ 24 /* Uart Controller */
+#define PULP_GPIO_0_IRQ 25 /* GPIO Controller */
+#define PULP_SPI_0_IRQ 26 /* SPI Controller #0 */
+#define PULP_SPI_1_IRQ 27 /* SPI Controller #1 */
+#define PULP_TIMER_A_OVERFLOW_IRQ 28 /* Timer Overflow A */
+#define PULP_TIMER_A_CMP_IRQ 29 /* Timer Output Cmp A */
+#define PULP_TIMER_B_OVERFLOW_IRQ 30 /* Timer Overflow B */
+#define PULP_TIMER_B_CMP_IRQ 31 /* Timer Output Cmp B */
+
+/* min value to consider as IRQ in MCAUSE register */
+#define PULP_MIN_IRQ PULP_I2C_0_IRQ
+
+/* Exception numbers */
+#define PULP_ECALL_EXP 11 /* ECALL Instruction */
+
+/*
+ * SOC-specific MSTATUS related info
+ */
+/* MSTATUS register to save/restore upon interrupt/exception/context switch */
+#define SOC_MSTATUS_REG PULP_MESTATUS
+
+#define SOC_MSTATUS_IEN (1 << 0) /* Machine Interrupt Enable bit */
+
+/*
+ * Default MSTATUS register value to restore from stack
+ * upon scheduling a thread for the first time
+ */
+#define SOC_MSTATUS_DEF_RESTORE SOC_MSTATUS_IEN
+
+/* SOC-specific MCAUSE bitfields */
+#define SOC_MCAUSE_IRQ_MASK 0x1F /* Exception code Mask */
+#define SOC_MCAUSE_ECALL_EXP PULP_ECALL_EXP /* ECALL exception number */
+
+/* SOC-Specific EXIT ISR command */
+#define SOC_ERET eret
+
+/* UART configuration */
+#define UART_NS16550_PORT_0_BASE_ADDR 0x1A100000
+#define UART_NS16550_PORT_0_CLK_FREQ 2500000
+#define UART_NS16550_PORT_0_IRQ PULP_UART_0_IRQ
+
+/* GPIO configuration */
+#define PULP_GPIO_0_BASE 0x1A101000
+
+/* PAD configuration */
+#define PULP_PAD_BASE 0x1A107000
+
+/* IRQ configuration */
+#define PULP_IRQ_BASE 0x1A104000
+
+#define PULP_IER_ADDR (PULP_IRQ_BASE + 0x00) /* IRQ Enable Register */
+#define PULP_IPR_ADDR (PULP_IRQ_BASE + 0x04) /* IRQ Pending Register */
+#define PULP_ISP_ADDR (PULP_IRQ_BASE + 0x08) /* IRQ Set Pending Register */
+#define PULP_ICP_ADDR (PULP_IRQ_BASE + 0x0C) /* IRQ Clear Pending Register */
+#define PULP_EER_ADDR (PULP_IRQ_BASE + 0x10) /* Event Enable Register */
+#define PULP_EPR_ADDR (PULP_IRQ_BASE + 0x14) /* Event Pending Register */
+#define PULP_ESP_ADDR (PULP_IRQ_BASE + 0x18) /* Event Set Pending Register */
+#define PULP_ECP_ADDR (PULP_IRQ_BASE + 0x1C) /* Event Clear Pending Register */
+#define PULP_SCR_ADDR (PULP_IRQ_BASE + 0x20) /* Sleep Control Register */
+
+/* Timer configuration */
+#define PULP_TIMER_A_BASE 0x1A103000
+#define PULP_TIMER_B_BASE 0x1A103010
+
+/*
+ * Zephyr-SDK makes use a the latest generic riscv32 toolchain, which
+ * encodes the wfi opcode as 0x10500073. Pulpino does not understand
+ * this opcode and will generate a fault upon execution. Pulpino core
+ * implementation is based on a previous RISC-V ISA specification and
+ * expects the wfi opcode to be encoded as 0x10200073. In new toolchain,
+ * 0x10200073 opcode is used to represent the sret opcode. Hence,
+ * when compiled with a generic riscv32 toolchain, define wfi by sret
+ * in assembly code.
+ */
+#if defined(CONFIG_RISCV_GENERIC_TOOLCHAIN)
+#define wfi sret
+#endif
+
+#ifndef _ASMLANGUAGE
+#include <irq.h>
+
+/* Register Access MACRO */
+#define PULP_REG(x) (*((volatile unsigned int *)(x)))
+
+/* Interrupt Registers */
+#define PULP_IER PULP_REG(PULP_IER_ADDR)
+#define PULP_IPR PULP_REG(PULP_IPR_ADDR)
+#define PULP_ISP PULP_REG(PULP_ISP_ADDR)
+#define PULP_ICP PULP_REG(PULP_ICP_ADDR)
+#define PULP_EER PULP_REG(PULP_EER_ADDR)
+#define PULP_EPR PULP_REG(PULP_EPR_ADDR)
+#define PULP_ESP PULP_REG(PULP_ESP_ADDR)
+#define PULP_ECP PULP_REG(PULP_ECP_ADDR)
+#define PULP_SCR PULP_REG(PULP_SCR_ADDR)
+
+/* PAD MUX register */
+#define PULP_PADMUX PULP_REG(PULP_PAD_BASE)
+
+#define PULP_PAD_SPI 0
+#define PULP_PAD_GPIO 1
+#define PULP_PAD_MASK 1
+
+#if defined(CONFIG_RISCV_SOC_INTERRUPT_INIT)
+void soc_interrupt_init(void);
+#endif
+
+/*
+ * when a generic riscv32 toolchain is used replaced wfi by sret
+ * in inline assembly. Explanation given above.
+ */
+#if defined(CONFIG_RISCV_GENERIC_TOOLCHAIN)
+#define SOC_WFI __asm__ volatile("sret")
+#else
+#define SOC_WFI __asm__ volatile("wfi")
+#endif
+
+/* lib-c hooks required RAM defined variables */
+#define RISCV_RAM_BASE CONFIG_DTCM_BASE_ADDRESS
+#define RISCV_RAM_SIZE CONFIG_DTCM_SIZE
+
+#endif /* !_ASMLANGUAGE */
+
+#endif /* __PULPINO_SOC_H_ */
diff --git a/arch/riscv32/soc/pulpino/soc_irq.S b/arch/riscv32/soc/pulpino/soc_irq.S
new file mode 100644
index 000000000..a5a7579fd
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/soc_irq.S
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _ASMLANGUAGE
+
+#include <kernel_structs.h>
+#include <offsets.h>
+#include <toolchain.h>
+#include <sections.h>
+#include <soc.h>
+
+/* exports */
+GTEXT(__soc_save_context)
+GTEXT(__soc_restore_context)
+GTEXT(__soc_is_irq)
+GTEXT(__soc_handle_irq)
+GTEXT(__soc_irq_unlock)
+
+/* Use ABI name of registers for the sake of simplicity */
+
+/*
+ * Pulpino core has hardware loops registers that need to be saved
+ * prior to handling an interrupt/exception.
+ *
+ * NOTE: Stack space allocation is not needed here, as already allocated at
+ * architecture level with __NANO_ESF_SIZEOF value (including space for the
+ * pulpino-specific registers)
+ */
+SECTION_FUNC(exception.other, __soc_save_context)
+ /* Save hardware loop registers to stack */
+ csrr t0, PULP_LPSTART0
+ csrr t1, PULP_LPEND0
+ csrr t2, PULP_LPCOUNT0
+ sw t0, __NANO_ESF_lpstart0_OFFSET(sp)
+ sw t1, __NANO_ESF_lpend0_OFFSET(sp)
+ sw t2, __NANO_ESF_lpcount0_OFFSET(sp)
+ csrr t0, PULP_LPSTART1
+ csrr t1, PULP_LPEND1
+ csrr t2, PULP_LPCOUNT1
+ sw t0, __NANO_ESF_lpstart1_OFFSET(sp)
+ sw t1, __NANO_ESF_lpend1_OFFSET(sp)
+ sw t2, __NANO_ESF_lpcount1_OFFSET(sp)
+
+ /* Return */
+ jalr x0, ra
+
+
+SECTION_FUNC(exception.other, __soc_restore_context)
+ /* Restore hardloop registers from stack */
+ lw t0, __NANO_ESF_lpstart0_OFFSET(sp)
+ lw t1, __NANO_ESF_lpend0_OFFSET(sp)
+ lw t2, __NANO_ESF_lpcount0_OFFSET(sp)
+ csrw PULP_LPSTART0, t0
+ csrw PULP_LPEND0, t1
+ csrw PULP_LPCOUNT0, t2
+ lw t0, __NANO_ESF_lpstart1_OFFSET(sp)
+ lw t1, __NANO_ESF_lpend1_OFFSET(sp)
+ lw t2, __NANO_ESF_lpcount1_OFFSET(sp)
+ csrw PULP_LPSTART1, t0
+ csrw PULP_LPEND1, t1
+ csrw PULP_LPCOUNT1, t2
+
+ /* Return */
+ jalr x0, ra
+
+
+/*
+ * SOC-specific function to handle pending IRQ number generating the interrupt.
+ *
+ * The pulpino core has:
+ * 1) an ICP register, which is used to clear the pending
+ * IRQ number upon an interrupt.
+ * 2) an ECP register, which is used to clear the pending IRQ number
+ * that has woken up the CPU from sleep state.
+ *
+ * Exception number is given as parameter via register a0.
+ */
+SECTION_FUNC(exception.other, __soc_handle_irq)
+ /* Clear exception number from the Interrupt pending register */
+ li t1, PULP_ICP_ADDR
+ li t2, 1
+ sll t3, t2, a0
+ sw t3, 0x00(t1)
+
+ /* Clear exception number from the Event pending register */
+ li t1, PULP_ECP_ADDR
+ sw t3, 0x00(t1)
+
+ /* Return */
+ jalr x0, ra
+
+
+/*
+ * SOC-specific function to determine if the exception is the result of a
+ * an interrupt or an exception
+ * return 1 (interrupt) or 0 (exception)
+ */
+SECTION_FUNC(exception.other, __soc_is_irq)
+ /* Get exception number from the mcause CSR register. */
+ csrr t0, mcause
+ andi t0, t0, SOC_MCAUSE_IRQ_MASK
+
+ /* if IRQ number < PULP_MIN_IRQ, not interrupt */
+ li t1, PULP_MIN_IRQ
+ addi a0, x0, 0
+ blt t0, t1, not_interrupt
+ addi a0, a0, 1
+
+not_interrupt:
+ /* return */
+ jalr x0, ra
diff --git a/arch/riscv32/soc/pulpino/vector.S b/arch/riscv32/soc/pulpino/vector.S
new file mode 100644
index 000000000..2de5ccb41
--- /dev/null
+++ b/arch/riscv32/soc/pulpino/vector.S
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016 Jean-Paul Etienne <fractalclone@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _ASMLANGUAGE
+
+#include <toolchain.h>
+
+/* imports */
+GTEXT(__reset)
+GTEXT(__irq_wrapper)
+
+/*
+ * following pulpino datasheet, addr 0x00000000 - 0x00000058 are not used
+ * in IVT. Hence, set them to nop.
+ *
+ * Call __irq_wrapper to handle all interrupts/exceptions/faults/ECALL
+ *
+ * ECALL is used to handle context switching of threads, as well as
+ * IRQ offloading (when enabled).
+ *
+ * Interrupt Line 23: I2C IRQ 0x0000005C
+ * Interrupt Line 24: UART IRQ 0x00000060
+ * Interrupt Line 25: GPIO IRQ 0x00000064
+ * Interrupt Line 26: SPI Master 0 0x00000068
+ * Interrupt Line 27: SPI Master 1 0x0000006C
+ * Interrupt Line 28: Timer A Overflow 0x00000070
+ * Interrupt Line 29: Timer A Output Cmp 0x00000074
+ * Interrupt Line 30: Timer B Overflow 0x00000078
+ * Interrupt Line 31: Timer B Output Cmp 0x0000007C
+ *
+ * RESET 0x00000080 - call __reset
+
+ * Illegal Instruction Exception 0x00000084
+ * ECALL Instruction 0x00000088
+ * Invalid Memory Access 0x0000008C
+ */
+SECTION_FUNC(vectors, vinit)
+ .option norvc;
+
+ /* nop addr 0x00000000 - 0x00000058 */
+ .org 0x00
+ .rept 23
+ nop
+ .endr
+
+ /* Call __irq_wrapper for all interrupts */
+ .org 0x5C
+ .rept 9
+ jal x0, __irq_wrapper
+ .endr
+
+ /* Call __reset for reset vector */
+ .org 0x80
+ jal x0, __reset
+
+ /* Illegal instruction */
+ jal x0, __irq_wrapper
+
+ /* ECALL (system call) */
+ jal x0, __irq_wrapper
+
+ /* Invalid memory access */
+ jal x0, __irq_wrapper