summaryrefslogtreecommitdiff
path: root/software/demo_gpio/demo_gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'software/demo_gpio/demo_gpio.c')
-rw-r--r--software/demo_gpio/demo_gpio.c115
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();