From ae5f878d6acadabaa671a7a30b87e16eb1d718a7 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Wed, 30 Nov 2016 10:55:18 -0800 Subject: 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 --- software/demo_gpio/Makefile | 14 ++--- software/demo_gpio/demo_gpio.c | 115 +++++++++++++++++++---------------- software/demo_gpio/plic_driver.c | 127 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+), 61 deletions(-) create mode 100644 software/demo_gpio/plic_driver.c (limited to 'software/demo_gpio') 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 - -#include "shared.h" -#include "plic.h" +#include +#include "platform.h" #include +#include "plic_driver.h" +#include "encoding.h" +#include + +#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 + + +// 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; + +} + -- cgit v1.2.3