summaryrefslogtreecommitdiff
path: root/software/demo_gpio
diff options
context:
space:
mode:
authorMegan Wachs <megan@sifive.com>2016-11-30 10:55:18 -0800
committerGitHub <noreply@github.com>2016-11-30 10:55:18 -0800
commitae5f878d6acadabaa671a7a30b87e16eb1d718a7 (patch)
tree20749a4e80815136d2129486b25202427b9ea30b /software/demo_gpio
parente12b0338d24597f12263322216fbe4e6c6b8e12a (diff)
Bump Everything to Match new Freedom Repo (#8)
* Bump tool versions * Use version of OpenOCD which can load programs into flash * Bump OpenOCD to Handle ISSI Flash Programming * Update Header files * add initial support for hifive1 * add dhrystone * add clock helper functions * add openocd cfg file * Demo_GPIO checkpoint -- compiles and runs but no blinky LEDs * Remove riscv-tests submodule * Remove FPGA files, as they are no longer relevant to this Repository * Add openocd_upload script * Add Pinmux Mappings Adding the pinmux mappings to the Platform Header * Add IOF Mappings to platform header * Re-order the IOF Mapping declarations * Add more useful things to platform headers * Get GPIO Demo working again (except interrupts aren't working) * Update README with more OS packages needed A bare ubuntu-16.04.1-server installation could not run `make tools` without these packages. * bump openocd to get SCKDIV fix * Remove duplicated help text for run_debug target * Add package to README that is needed for openocd build Without this package I was seeing two different failures like below when running `make tools`. /home/scottj/freedom-e-sdk/openocd/configure: line 4533: syntax error near unexpected token `0.23' /home/scottj/freedom-e-sdk/openocd/configure: line 4533: `PKG_PROG_PKG_CONFIG(0.23)' Makefile:70: recipe for target '/home/scottj/freedom-e-sdk/toolchain/bin/openocd' failed make: *** [/home/scottj/freedom-e-sdk/toolchain/bin/openocd] Error 2 ... or ... + autoconf configure.ac:12: error: possibly undefined macro: AC_MSG_WARN If this token and others are legitimate, please use m4_pattern_allow. See the Autoconf documentation. configure.ac:240: error: possibly undefined macro: AC_MSG_NOTICE configure.ac:342: error: possibly undefined macro: AC_DEFINE Makefile:70: recipe for target '/home/scottj/freedom-e-sdk/toolchain/bin/openocd' failed make: *** [/home/scottj/freedom-e-sdk/toolchain/bin/openocd] Error 1 * Bump OpenOCD to not overwrite SCKDIV when flashing * Roll back CoreMark
Diffstat (limited to 'software/demo_gpio')
-rw-r--r--software/demo_gpio/Makefile14
-rw-r--r--software/demo_gpio/demo_gpio.c115
-rw-r--r--software/demo_gpio/plic_driver.c127
3 files changed, 195 insertions, 61 deletions
diff --git a/software/demo_gpio/Makefile b/software/demo_gpio/Makefile
index 5f201a2..0a0b148 100644
--- a/software/demo_gpio/Makefile
+++ b/software/demo_gpio/Makefile
@@ -1,9 +1,7 @@
-#See LICENSE for license details.
+TARGET = demo_gpio
+C_SRCS += demo_gpio.c
+C_SRCS += plic_driver.c
+CFLAGS += -fno-builtin-printf -DUSE_PLIC -DUSE_M_TIME
-TARGET=demo_gpio
-CFLAGS += -g
-CDEFINES += -DUSE_PLIC -DUSE_M_TIME
-
-SWDIR = ../
-
-include $(SWDIR)/shared/Makefile.shared
+BSP_BASE = ../../bsp
+include $(BSP_BASE)/env/common.mk
diff --git a/software/demo_gpio/demo_gpio.c b/software/demo_gpio/demo_gpio.c
index 3b0b6f5..c977281 100644
--- a/software/demo_gpio/demo_gpio.c
+++ b/software/demo_gpio/demo_gpio.c
@@ -1,10 +1,14 @@
// See LICENSE for license details.
#include <stdio.h>
-
-#include "shared.h"
-#include "plic.h"
+#include <stdlib.h>
+#include "platform.h"
#include <string.h>
+#include "plic_driver.h"
+#include "encoding.h"
+#include <unistd.h>
+
+#define RTC_FREQUENCY 32768
void reset_demo (void);
@@ -14,19 +18,19 @@ typedef void (*function_ptr_t) (void);
void no_interrupt_handler (void) {};
-function_ptr_t g_ext_interrupt_handlers[9];
+function_ptr_t g_ext_interrupt_handlers[PLIC_NUM_INTERRUPTS];
-function_ptr_t g_m_timer_interrupt_handler = no_interrupt_handler;
// Instance data for the PLIC.
plic_instance_t g_plic;
// Simple variables for LEDs, buttons, etc.
-volatile unsigned int* g_outputs = (unsigned int *) (GPIO_BASE_ADDR + GPIO_OUT_OFFSET);
-volatile unsigned int* g_inputs = (unsigned int *) (GPIO_BASE_ADDR + GPIO_IN_OFFSET);
-volatile unsigned int* g_tristates = (unsigned int *) (GPIO_BASE_ADDR + GPIO_TRI_OFFSET);
-
+volatile unsigned int* g_output_vals = (unsigned int *) (GPIO_BASE_ADDR + GPIO_OUTPUT_VAL);
+volatile unsigned int* g_input_vals = (unsigned int *) (GPIO_BASE_ADDR + GPIO_INPUT_VAL);
+volatile unsigned int* g_output_en = (unsigned int *) (GPIO_BASE_ADDR + GPIO_OUTPUT_EN);
+volatile unsigned int* g_pullup_en = (unsigned int *) (GPIO_BASE_ADDR + GPIO_PULLUP_EN);
+volatile unsigned int* g_input_en = (unsigned int *) (GPIO_BASE_ADDR + GPIO_INPUT_EN);
/*Entry Point for PLIC Interrupt Handler*/
void handle_m_ext_interrupt(){
@@ -35,7 +39,7 @@ void handle_m_ext_interrupt(){
g_ext_interrupt_handlers[int_num]();
}
else {
- _exit(1 + (uintptr_t) int_num);
+ exit(1 + (uintptr_t) int_num);
}
PLIC_complete_interrupt(&g_plic, int_num);
}
@@ -49,31 +53,25 @@ void handle_m_time_interrupt(){
// Reset the timer for 3s in the future.
// This also clears the existing timer interrupt.
- volatile uint64_t * mtime = (uint64_t*) MTIME_ADDR;
- volatile uint64_t * mtimecmp = (uint64_t*) MTIMECMP_BASE_ADDR;
+ volatile uint64_t * mtime = (uint64_t*) (CLINT_BASE_ADDR + CLINT_MTIME);
+ volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_BASE_ADDR + CLINT_MTIMECMP);
uint64_t now = *mtime;
- uint64_t then = now + 3 * CLOCK_FREQUENCY / RTC_PRESCALER;
+ uint64_t then = now + 3 * RTC_FREQUENCY;
*mtimecmp = then;
// read the current value of the LEDS and invert them.
- uint32_t leds = *g_outputs;
-
- *g_outputs = (~leds) & ((0xF << RED_LEDS_OFFSET) |
- (0xF << GREEN_LEDS_OFFSET) |
- (0xF << BLUE_LEDS_OFFSET));
+ uint32_t leds = *g_output_vals;
+
+ *g_output_vals ^= ((0x1 << RED_LED_OFFSET) |
+ (0x1 << GREEN_LED_OFFSET) |
+ (0x1 << BLUE_LED_OFFSET));
-
// Re-enable the timer interrupt.
set_csr(mie, MIP_MTIP);
-
+
}
-/*Entry Point for Machine Timer Interrupt Handler*/
-void handle_m_timer_interrupt(){
- g_m_timer_interrupt_handler();
-}
-
const char * instructions_msg = " \
\n\
SIFIVE, INC.\n\
@@ -112,8 +110,10 @@ void print_instructions() {
void button_0_handler(void) {
- // Rainbow LEDs!
- * g_outputs = (0x9 << RED_LEDS_OFFSET) | (0xA << GREEN_LEDS_OFFSET) | (0xC << BLUE_LEDS_OFFSET);
+ // All LEDS on
+ * g_output_vals = (0x1 << RED_LED_OFFSET) |
+ (0x1 << GREEN_LED_OFFSET) |
+ (0x1 << BLUE_LED_OFFSET);
};
@@ -122,30 +122,31 @@ void reset_demo (){
// Disable the machine & timer interrupts until setup is done.
- clear_csr(mie, MIP_MEIP);
- clear_csr(mie, MIP_MTIP);
+ clear_csr(mie, MIP_MEIP);
+ clear_csr(mie, MIP_MTIP);
+
+ for (int ii = 0; ii < PLIC_NUM_INTERRUPTS; ii ++){
+ g_ext_interrupt_handlers[ii] = no_interrupt_handler;
+ }
+
+#ifdef HAS_BOARD_BUTTONS
+ g_ext_interrupt_handlers[INT_DEVICE_BUTTON_0] = button_0_handler;
+#endif
- g_ext_interrupt_handlers[INT_DEVICE_BUTTON_0] = button_0_handler;
- g_ext_interrupt_handlers[INT_DEVICE_BUTTON_1] = no_interrupt_handler;
- g_ext_interrupt_handlers[INT_DEVICE_BUTTON_2] = no_interrupt_handler;
- g_ext_interrupt_handlers[INT_DEVICE_BUTTON_3] = no_interrupt_handler;
- g_ext_interrupt_handlers[INT_DEVICE_JA_7] = no_interrupt_handler;
- g_ext_interrupt_handlers[INT_DEVICE_JA_8] = no_interrupt_handler;
- g_ext_interrupt_handlers[INT_DEVICE_JA_9] = no_interrupt_handler;
- g_ext_interrupt_handlers[INT_DEVICE_JA_10] = no_interrupt_handler;
-
- print_instructions();
+ print_instructions();
- PLIC_enable_interrupt (&g_plic, INT_DEVICE_BUTTON_0);
-
+#ifdef HAS_BOARD_BUTTONS
+ PLIC_enable_interrupt (&g_plic, INT_DEVICE_BUTTON_0);
+#endif
+
// Set the machine timer to go off in 3 seconds.
// The
- volatile uint64_t * mtime = (uint64_t*) MTIME_ADDR;
- volatile uint64_t * mtimecmp = (uint64_t*) MTIMECMP_BASE_ADDR;
+ volatile uint64_t * mtime = (uint64_t*) (CLINT_BASE_ADDR + CLINT_MTIME);
+ volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_BASE_ADDR + CLINT_MTIMECMP);
uint64_t now = *mtime;
- uint64_t then = now + 3*CLOCK_FREQUENCY / RTC_PRESCALER;
+ uint64_t then = now + 3*RTC_FREQUENCY;
*mtimecmp = then;
-
+
// Enable the Machine-External bit in MIE
set_csr(mie, MIP_MEIP);
@@ -154,24 +155,32 @@ void reset_demo (){
// Enable interrupts in general.
set_csr(mstatus, MSTATUS_MIE);
-
}
int main(int argc, char **argv)
{
- // Set up the GPIOs such that the inputs' tristate are set.
- // The boot ROM actually does this, but still good.
+ // Set up the GPIOs such that the LED GPIO
+ // can be used as both Inputs and Outputs.
+
+#ifdef HAS_BOARD_BUTTONS
+ * g_output_en &= ~((0x1 << BUTTON_0_OFFSET) | (0x1 << BUTTON_1_OFFSET) | (0x2 << BUTTON_2_OFFSET));
+ * g_pullup_en &= ~((0x1 << BUTTON_0_OFFSET) | (0x1 << BUTTON_1_OFFSET) | (0x2 << BUTTON_2_OFFSET));
+ * g_input_en |= ((0x1 << BUTTON_0_OFFSET) | (0x1 << BUTTON_1_OFFSET) | (0x2 << BUTTON_2_OFFSET));
+#endif
- * g_tristates = (0xF << BUTTONS_OFFSET) | (0xF << SWITCHES_OFFSET) | (0xF << JA_IN_OFFSET);
-
- * g_outputs = (0xF << RED_LEDS_OFFSET);
-
+ * g_input_en &= ~((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET) | (0x1 << BLUE_LED_OFFSET)) ;
+ * g_output_en |= ((0x1<< RED_LED_OFFSET)| (0x1<< GREEN_LED_OFFSET) | (0x1 << BLUE_LED_OFFSET)) ;
+ * g_output_vals|= (0x1 << BLUE_LED_OFFSET) ;
+ * g_output_vals &= ~((0x1<< RED_LED_OFFSET)| (0x1<< GREEN_LED_OFFSET)) ;
/**************************************************************************
* Set up the PLIC
*
*************************************************************************/
- PLIC_init(&g_plic, PLIC_BASE_ADDR, PLIC_NUM_SOURCES, PLIC_NUM_PRIORITIES);
+ PLIC_init(&g_plic,
+ PLIC_BASE_ADDR,
+ PLIC_NUM_INTERRUPTS,
+ PLIC_NUM_PRIORITIES);
reset_demo();
diff --git a/software/demo_gpio/plic_driver.c b/software/demo_gpio/plic_driver.c
new file mode 100644
index 0000000..01b7e6e
--- /dev/null
+++ b/software/demo_gpio/plic_driver.c
@@ -0,0 +1,127 @@
+// See LICENSE for license details.
+
+#include "sifive/devices/plic.h"
+#include "plic_driver.h"
+#include "platform.h"
+#include "encoding.h"
+#include <string.h>
+
+
+// Note that there are no assertions or bounds checking on these
+// parameter values.
+
+void volatile_memzero(uint8_t * base, unsigned int size)
+{
+ volatile uint8_t * ptr;
+ for (ptr = base; ptr < (base + size); ptr++){
+ *ptr = 0;
+ }
+}
+
+void PLIC_init (
+ plic_instance_t * this_plic,
+ uintptr_t base_addr,
+ uint32_t num_sources,
+ uint32_t num_priorities
+ )
+{
+
+ this_plic->base_addr = base_addr;
+ this_plic->num_sources = num_sources;
+ this_plic->num_priorities = num_priorities;
+
+ // Disable all interrupts (don't assume that these registers are reset).
+ unsigned long hart_id = read_csr(mhartid);
+ volatile_memzero((uint8_t*) (this_plic->base_addr +
+ PLIC_ENABLE_OFFSET +
+ (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET)),
+ (num_sources + 8) / 8);
+
+ // Set all priorities to 0 (equal priority -- don't assume that these are reset).
+ volatile_memzero ((uint8_t *)(this_plic->base_addr +
+ PLIC_PRIORITY_OFFSET),
+ (num_sources + 1) << PLIC_PRIORITY_SHIFT_PER_SOURCE);
+
+ // Set the threshold to 0.
+ volatile plic_threshold* threshold = (plic_threshold*)
+ (this_plic->base_addr +
+ PLIC_THRESHOLD_OFFSET +
+ (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
+
+ *threshold = 0;
+
+}
+
+void PLIC_set_threshold (plic_instance_t * this_plic,
+ plic_threshold threshold){
+
+ unsigned long hart_id = read_csr(mhartid);
+ volatile plic_threshold* threshold_ptr = (plic_threshold*) (this_plic->base_addr +
+ PLIC_THRESHOLD_OFFSET +
+ (hart_id << PLIC_THRESHOLD_SHIFT_PER_TARGET));
+
+ *threshold_ptr = threshold;
+
+}
+
+
+void PLIC_enable_interrupt (plic_instance_t * this_plic, plic_source source){
+
+ unsigned long hart_id = read_csr(mhartid);
+ volatile uint8_t * current_ptr = (volatile uint8_t *)(this_plic->base_addr +
+ PLIC_ENABLE_OFFSET +
+ (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
+ (source >> 3));
+ uint8_t current = *current_ptr;
+ current = current | ( 1 << (source & 0x7));
+ *current_ptr = current;
+
+}
+
+void PLIC_disable_interrupt (plic_instance_t * this_plic, plic_source source){
+
+ unsigned long hart_id = read_csr(mhartid);
+ volatile uint8_t * current_ptr = (volatile uint8_t *) (this_plic->base_addr +
+ PLIC_ENABLE_OFFSET +
+ (hart_id << PLIC_ENABLE_SHIFT_PER_TARGET) +
+ (source >> 3));
+ uint8_t current = *current_ptr;
+ current = current & ~(( 1 << (source & 0x7)));
+ *current_ptr = current;
+
+}
+
+void PLIC_set_priority (plic_instance_t * this_plic, plic_source source, plic_priority priority){
+
+ if (this_plic->num_priorities > 0) {
+ volatile plic_priority * priority_ptr = (volatile plic_priority *)
+ (this_plic->base_addr +
+ PLIC_PRIORITY_OFFSET +
+ (source << PLIC_PRIORITY_SHIFT_PER_SOURCE));
+ *priority_ptr = priority;
+ }
+}
+
+plic_source PLIC_claim_interrupt(plic_instance_t * this_plic){
+
+ unsigned long hart_id = read_csr(mhartid);
+
+ volatile plic_source * claim_addr = (volatile plic_source * )
+ (this_plic->base_addr +
+ PLIC_CLAIM_OFFSET +
+ (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
+
+ return *claim_addr;
+
+}
+
+void PLIC_complete_interrupt(plic_instance_t * this_plic, plic_source source){
+
+ unsigned long hart_id = read_csr(mhartid);
+ volatile plic_source * claim_addr = (volatile plic_source *) (this_plic->base_addr +
+ PLIC_CLAIM_OFFSET +
+ (hart_id << PLIC_CLAIM_SHIFT_PER_TARGET));
+ *claim_addr = source;
+
+}
+