diff options
Diffstat (limited to 'software/demo_gpio/demo_gpio.c')
-rw-r--r-- | software/demo_gpio/demo_gpio.c | 115 |
1 files changed, 62 insertions, 53 deletions
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(); |