summaryrefslogtreecommitdiff
path: root/software
diff options
context:
space:
mode:
Diffstat (limited to 'software')
-rw-r--r--software/clic_interrupts/Makefile8
-rw-r--r--software/clic_interrupts/clic.c231
-rw-r--r--software/clic_vectored/Makefile10
-rw-r--r--software/clic_vectored/clic_vectored.c197
4 files changed, 207 insertions, 239 deletions
diff --git a/software/clic_interrupts/Makefile b/software/clic_interrupts/Makefile
deleted file mode 100644
index 502534d..0000000
--- a/software/clic_interrupts/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-TARGET = clic_interrupts
-CFLAGS += -O2 -fno-builtin-printf -DUSE_CLIC -DUSE_LOCAL_ISR
-
-BSP_BASE = ../../bsp
-
-C_SRCS += clic.c
-
-include $(BSP_BASE)/env/common.mk
diff --git a/software/clic_interrupts/clic.c b/software/clic_interrupts/clic.c
deleted file mode 100644
index ccf98b2..0000000
--- a/software/clic_interrupts/clic.c
+++ /dev/null
@@ -1,231 +0,0 @@
-// See LICENSE for license details.
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "platform.h"
-#include <string.h>
-#include "encoding.h"
-#include <unistd.h>
-#include "sifive/devices/clic.h"
-
-#ifndef _SIFIVE_COREPLEXIP_ARTY_H
-#error 'local_interrupts' demo only supported for Coreplex IP Eval Kits
-#endif
-
-// Global Variable used to show
-// software interrupts.
-volatile uint32_t g_debouncing;
-
-void debounce();
-
-static void clic_enable(int offset) __attribute__((noinline));
-static void clic_enable(int offset)
-{
- CLIC_REG8(CLIC_INTCFG + offset) = 0xff;
- CLIC_REG8(CLIC_INTIE + offset) = 1;
-}
-
-static void clic_disable(int offset) __attribute__((noinline));
-static void clic_disable(int offset)
-{
- CLIC_REG8(CLIC_INTCFG + offset) = 0xff;
- CLIC_REG8(CLIC_INTIE + offset) = 0;
-}
-
-// Structures for registering different interrupt handlers
-// for different parts of the application.
-typedef void (*interrupt_function_ptr_t) (void);
-
-// This function enables some of the local interrupts sources
-// used in this demo -- just those for the buttons and
-// Switch 3.
-
-void enable_local_interrupts(){
- clic_enable(IRQ_M_LOCAL + LOCAL_INT_SW_3);
- clic_enable(IRQ_M_LOCAL + LOCAL_INT_BTN_0);
- clic_enable(IRQ_M_LOCAL + LOCAL_INT_BTN_1);
- clic_enable(IRQ_M_LOCAL + LOCAL_INT_BTN_2);
- clic_enable(IRQ_M_LOCAL + LOCAL_INT_BTN_3);
-}
-
-void disable_local_interrupts() {
- clic_disable(IRQ_M_LOCAL + LOCAL_INT_SW_3);
- clic_disable(IRQ_M_LOCAL + LOCAL_INT_BTN_0);
- clic_disable(IRQ_M_LOCAL + LOCAL_INT_BTN_1);
- clic_disable(IRQ_M_LOCAL + LOCAL_INT_BTN_2);
- clic_disable(IRQ_M_LOCAL + LOCAL_INT_BTN_3);
-}
-
-/*Entry Point for Machine Software Interrupt Handler*/
-void msi_isr() {
- const char msi_msg[] = " Debouncing: (this message due to Software Interrupt)\n\n";
- write (STDOUT_FILENO, msi_msg, strlen(msi_msg));
-
- //clear the SW interrupt
- CLIC_REG(CLIC_MSIP) = 0;
-}
-
-/*Entry Point for Machine Timer Interrupt Handler*/
-void mti_isr(){
- const char mti_msg[] = " Timer interrupt, done debouncing.\n\n";
- write (STDOUT_FILENO, mti_msg, strlen(mti_msg));
-
- // Disable the timer interrupt. The Debounce logic sets it.
- clic_disable(IRQ_M_TIMER);
-
- // Enable all the local interrupts
- enable_local_interrupts();
-}
-
-const char * instructions_msg = " \
-\n\
- SiFive, Inc\n\
- E21 Core IP Eval Kit 'clic_interrupts' demo.\n\
-\n\
-The Buttons 0-3 and Switch 3 are enabled as local\n\
-interrupts sources. A .5 s 'debounce' timer is used \n\
-between these interrupts. Software interrupts are\n\
-used to print a message while debouncing.\n\
-Note the priority of the interrupts sources.\n\
-\n";
-
-void print_instructions() {
-
- write (STDERR_FILENO, instructions_msg, strlen(instructions_msg));
-
-}
-
-void button_0_isr(void) {
-
- // Toggle Red LED
- const char button_0_msg[] = "Button 0 was pressed. Toggle Red.\n";
- write (STDOUT_FILENO, button_0_msg, strlen(button_0_msg));
- GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << RED_LED_OFFSET);
- debounce();
-};
-
-void button_1_isr(void) {
-
- // Toggle Green LED
- const char button_1_msg[] = "Button 1 was pressed. Toggle Green.\n";
- write (STDOUT_FILENO, button_1_msg, strlen(button_1_msg));
- GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << GREEN_LED_OFFSET);
- debounce();
-};
-
-
-void button_2_isr(void) {
-
- // Toggle Blue LED
- const char button_2_msg[] = "Button 2 was pressed. Toggle Blue.\n";
- write (STDOUT_FILENO, button_2_msg, strlen(button_2_msg));
- GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << BLUE_LED_OFFSET);
- debounce();
-
-};
-
-void button_3_isr(void) {
- const char button_3_msg[] = "Button 3 was pressed! (No LEDs change).\n";
- write (STDOUT_FILENO, button_3_msg, strlen(button_3_msg));
- debounce();
-}
-
-void switch_3_isr(void) {
- const char sw_3_msg[] = "Switch 3 is on! But buttons have higher priority.\n";
- write (STDOUT_FILENO, sw_3_msg, strlen(sw_3_msg));
- debounce();
-}
-
-void debounce(int local_interrupt_num) {
- // Disable the most recent interrupt.
- // Don't enable it again until the timer goes off,
- // in .5 second.
-
- // Set the machine timer to go off in .5 seconds.
- // If the timer was already set to go off, this "cancels"
- // the current one.
-
- volatile uint64_t * mtime = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIME);
- volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
- uint64_t now = *mtime;
- uint64_t then = now + .5*RTC_FREQ;
- *mtimecmp = then;
-
- disable_local_interrupts();
- g_debouncing = 1;
-
- // Enable the Machine-Timer bit in MIE
- clic_enable(IRQ_M_TIMER);
-}
-
-// See bsp/env/<BOARD>/init.c for how this
-// interrupt vector is used.
-
-interrupt_function_ptr_t localISR[32];
-
-static void unmapped_interrupt(void) {
- printf("unmapped interrupt");
- asm volatile ("1: j 1b" ::: "memory");
-}
-
-int main(int argc, char **argv)
-{
- // Configure LEDs as outputs.
- GPIO_REG(GPIO_INPUT_EN) &= ~((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET) | (0x1 << BLUE_LED_OFFSET)) ;
- GPIO_REG(GPIO_OUTPUT_EN) |= ((0x1<< RED_LED_OFFSET)| (0x1<< GREEN_LED_OFFSET) | (0x1 << BLUE_LED_OFFSET)) ;
- GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << BLUE_LED_OFFSET) ;
- GPIO_REG(GPIO_OUTPUT_VAL) &= ~((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET)) ;
-
- // The Buttons and Switches which are used as local interrupt sources
- // do not go through the GPIO peripheral, so they do not need to
- // be configured as inputs.
-
- // Disable the timer & local interrupts until setup is done (they're
- // not reset by default)
-
- // Unconfigure the CLIC before doing anything
- for (int i = 0; i < 1024; ++i)
- CLIC_REG8(CLIC_INTIE + i) = 0;
-
- // Write down the software interrupt pending bit, as we shouldn't start out
- // by debouncing anything at all.
- CLIC_REG(CLIC_MSIP) = 0;
-
- for (int isr = 0; isr < 32; isr++)
- localISR[isr] = &unmapped_interrupt;
-
- localISR[IRQ_M_SOFT] = msi_isr;
- localISR[IRQ_M_TIMER] = mti_isr;
- localISR[IRQ_M_LOCAL + LOCAL_INT_SW_3] = switch_3_isr;
- localISR[IRQ_M_LOCAL + LOCAL_INT_BTN_0] = button_0_isr;
- localISR[IRQ_M_LOCAL + LOCAL_INT_BTN_1] = button_1_isr;
- localISR[IRQ_M_LOCAL + LOCAL_INT_BTN_2] = button_2_isr;
- localISR[IRQ_M_LOCAL + LOCAL_INT_BTN_3] = button_3_isr;
-
- // Set up the CLIC interrupt mechanism
- CLIC_REG(CLIC_CFG) = 4<<1; // nmBits=0; nlBits=4; nvBits=0
-
- print_instructions();
-
- enable_local_interrupts();
-
- g_debouncing = 0;
-
- // Enable SW interrupts as well in this demo.
- clic_enable(IRQ_M_SOFT);
-
- // Enable all global interrupts
- set_csr(mstatus, MSTATUS_MIE);
-
- volatile int foo = 1;
- while(foo){
- if (g_debouncing){
- //Trigger a SW interrupt
- CLIC_REG(CLIC_MSIP) = 1;
- g_debouncing = 0;
- }
- }
-
- return 0;
-
-}
diff --git a/software/clic_vectored/Makefile b/software/clic_vectored/Makefile
new file mode 100644
index 0000000..d6e2342
--- /dev/null
+++ b/software/clic_vectored/Makefile
@@ -0,0 +1,10 @@
+TARGET = clic_vectored
+CFLAGS += -Og -fno-builtin-printf
+
+BSP_BASE = ../../bsp
+
+C_SRCS += clic_vectored.c
+
+C_SRCS += $(BSP_BASE)/drivers/clic/clic_driver.c
+
+include $(BSP_BASE)/env/common.mk
diff --git a/software/clic_vectored/clic_vectored.c b/software/clic_vectored/clic_vectored.c
new file mode 100644
index 0000000..37ea723
--- /dev/null
+++ b/software/clic_vectored/clic_vectored.c
@@ -0,0 +1,197 @@
+// See LICENSE for license details.
+#include <stdio.h>
+#include <stdlib.h>
+#include "platform.h"
+#include <string.h>
+#include "encoding.h"
+#include <unistd.h>
+#include "sifive/devices/clic.h"
+#include "clic/clic_driver.h"
+#include "sifive/devices/clint.h"
+
+#ifndef _SIFIVE_COREPLEXIP_ARTY_H
+#error 'local_interrupts' demo only supported for Core IP Eval Kits
+#endif
+
+// Global Variable used to show
+// software interrupts.
+volatile uint32_t g_debouncing;
+
+// vector table defined in init.c
+typedef void (*interrupt_function_ptr_t) (void);
+extern interrupt_function_ptr_t localISR[CLIC_NUM_INTERRUPTS];
+extern void default_handler(void);
+
+//clic data structure
+clic_instance_t clic;
+
+const char * instructions_msg = " \
+\n\
+ SiFive, Inc\n\
+\n\
+ 5555555555555555555555555\n\
+ 5555 5555\n\
+ 5555 5555\n\
+ 5555 5555\n\
+ 5555 5555555555555555555555\n\
+ 5555 555555555555555555555555\n\
+ 5555 5555\n\
+ 5555 5555\n\
+ 5555 5555\n\
+5555555555555555555555555555 55555\n\
+ 55555 555555555 55555\n\
+ 55555 55555 55555\n\
+ 55555 5 55555\n\
+ 55555 55555\n\
+ 55555 55555\n\
+ 55555 55555\n\
+ 55555 55555\n\
+ 55555 55555\n\
+ 555555555\n\
+ 55555\n\
+ 5\n\
+\n\
+E2 Core IP Eval Kit 'clic_vectored' demo.\n\
+This demo uses buttons 0, 1, and 2 on the\n\
+Arty board to trigger vectored clic interrupts.\n\
+The higher the button number, the higher the\n\
+interupt priority. Button 0's handler runs for\n\
+10 seconds, button 1's for 5, and button 2's for 1.\n\
+Preemption is enabled so that higher priority\n\
+interrupts can be triggered while in low priority\n\
+handlers. The demo also uses the CLIC's software\n\
+interrupt to pend a lower priority interrupt from\n\
+button 2's handler.\n\
+\n\
+Note the buttons are wired directly into the local\n\
+interrupts, so a given interrupt will stay asserted\n\
+as long as the button is being pushed.\n\
+\n\
+This demo works for both the E20 and E21 FPGA\n\
+as long as CLIC_CONFIG_BITS matches the desired\n\
+core.\n\
+\n";
+
+void print_instructions() {
+ write (STDERR_FILENO, instructions_msg, strlen(instructions_msg));
+}
+
+
+//busy wait for the specified time
+void wait_ms(uint64_t ms) {
+ static const uint64_t ms_tick = RTC_FREQ/1000;
+ volatile uint64_t * mtime = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIME);
+ uint64_t then = (ms_tick * ms) + *mtime;
+ while(*mtime<then);
+}
+
+void button_0_isr(void) __attribute__((interrupt("SiFive-CLIC-preemptible")));
+void button_0_isr(void) {
+ // Toggle Red LED
+ uint8_t level = clic_get_int_level(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_0));
+ printf("Button 0 was pressed, interrupt level %d. Toggle Red.\n", level);
+ GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << RED_LED_OFFSET);
+ wait_ms(10000);
+ GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << RED_LED_OFFSET);
+}
+
+void button_0_setup(void) {
+ clic_install_handler(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_0), button_0_isr);
+ clic_set_int_level(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_0), 1);
+ clic_enable_interrupt(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_0));
+}
+
+void button_1_isr(void) __attribute__((interrupt("SiFive-CLIC-preemptible")));
+void button_1_isr(void) {
+ // Toggle Red LED
+ uint8_t level = clic_get_int_level(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_1));
+ printf("Button 1 was pressed, interrupt level %d. Toggle Blue.\n", level);
+ GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << BLUE_LED_OFFSET);
+ wait_ms(5000);
+ GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << BLUE_LED_OFFSET);
+}
+
+void button_1_setup(void) {
+ clic_install_handler(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_1), button_1_isr);
+ clic_set_int_level(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_1), 2);
+ clic_enable_interrupt(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_1));
+}
+
+void button_2_isr(void) __attribute__((interrupt("SiFive-CLIC-preemptible")));
+void button_2_isr(void) {
+ // Toggle Red LED
+ uint8_t level = clic_get_int_level(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_2));
+ printf("Button 2 was pressed, interrupt level %d. Pending CSIPID and toggle Green.\n", level);
+ GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << GREEN_LED_OFFSET);
+ //pend a software interrupt
+ clic_set_pending(&clic, CSIPID);
+ wait_ms(1000);
+ GPIO_REG(GPIO_OUTPUT_VAL) = GPIO_REG(GPIO_OUTPUT_VAL) ^ (0x1 << GREEN_LED_OFFSET);
+}
+
+void button_2_setup(void) {
+ clic_install_handler(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_2), button_2_isr);
+ clic_set_int_level(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_2), 3);
+ clic_enable_interrupt(&clic, (LOCALINTIDBASE + LOCAL_INT_BTN_2));
+}
+
+/*Entry Point for Machine Software Interrupt Handler*/
+uint32_t COUNT;
+void csip_isr()__attribute((interrupt));
+void csip_isr() {
+ //clear the SW interrupt
+ CLIC0_REG8(CLIC_INTIP + CSIPID) = 0;
+ COUNT++;
+}
+
+void csip_setup(void) {
+ clic_install_handler(&clic, CSIPID, csip_isr);
+ clic_set_int_level(&clic, CSIPID, 1);
+ clic_enable_interrupt(&clic, CSIPID);
+}
+
+void config_gpio() {
+ // Configure LEDs as outputs.
+ GPIO_REG(GPIO_INPUT_EN) &= ~((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET) | (0x1 << BLUE_LED_OFFSET)) ;
+ GPIO_REG(GPIO_OUTPUT_EN) |= ((0x1<< RED_LED_OFFSET)| (0x1<< GREEN_LED_OFFSET) | (0x1 << BLUE_LED_OFFSET)) ;
+ GPIO_REG(GPIO_OUTPUT_VAL) &= ((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET)| (0x1 << BLUE_LED_OFFSET)) ;
+}
+
+int main(int argc, char **argv)
+{
+ clear_csr(mstatus, MSTATUS_MIE);
+ clear_csr(mie, IRQ_M_SOFT);
+ clear_csr(mie, IRQ_M_TIMER);
+
+ //initialize clic registers and vector table
+ clic_init(&clic, CLIC_HART0_ADDR,
+ (interrupt_function_ptr_t*)localISR,
+ default_handler,
+ CLIC_NUM_INTERRUPTS,
+ CLIC_CONFIG_BITS);
+
+ //use all 4 config bits for levels, no shv
+ clic_set_cliccfg(&clic, (CLIC_CONFIG_BITS<<1));
+
+ //initialize gpio and buttons.
+ //each button registers an interrupt handler
+ config_gpio();
+ button_0_setup();
+ button_1_setup();
+ button_2_setup();
+ csip_setup();
+
+ // Enable all global interrupts
+ set_csr(mstatus, MSTATUS_MIE);
+ print_instructions();
+
+ while(1) {
+ wait_ms(10000);
+ printf("Count=%d\n", COUNT);
+ //Trigger a SW interrupt
+ clic_set_pending(&clic, CSIPID);
+ }
+
+ return 0;
+
+}