X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=FreeRTOS%2FDemo%2FRISC-V-Qemu-sifive_e-FreedomStudio%2Fmain.c;h=07912293e2e09061bc8bc1ea630e3d169cc6cc5e;hb=213b15149ddbb511e587ec60de3e2283c41d8a28;hp=649218528de93fa4ec8ef39760412297bf9612a5;hpb=3e52b83195faca538486ea84619ef1e61130493b;p=freertos diff --git a/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/main.c b/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/main.c index 649218528..07912293e 100644 --- a/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/main.c +++ b/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/main.c @@ -1,276 +1,125 @@ -// See LICENSE for license details. +/* + * FreeRTOS Kernel V10.2.1 + * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ +/* FreeRTOS kernel includes. */ #include #include -#include -#include -#include "platform.h" -#include -#include "plic/plic_driver.h" -#include "encoding.h" -#include -#include "stdatomic.h" - +/****************************************************************************** + * This project provides two demo applications. A simple blinky style project, + * and a more comprehensive test and demo application. The + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to + * select between the two. The simply blinky demo is implemented and described + * in main_blinky.c. The more comprehensive test and demo application is + * implemented and described in main_full.c. + * + * This file implements the code that is not demo specific, including the + * hardware setup and standard FreeRTOS hook functions. + * + * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON + * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO + * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT! + * + * + * NOTE 1: + * + * This project has only been tested in the QEMU emulation of the HiFive board + * from SiFive. + * + * Start QEMU using the following command line: + * + * [your_path_1]\qemu-system-riscv32 -kernel [your_path_2]\FreeRTOS\Demo\RISC-V-Qemu-sifive_e-FreedomStudio\Debug\RTOSDemo.elf -S -s -machine sifive_e + * + * Where [your_path_1] must be replaced with the correct path to your QEMU + * installation and the elf file generated by this project respectively. + * + * + * NOTE 2: + * + * Start GDB using the following command line (this can be entered in the + * Eclipse Debug Launch Configuration dialogue): + * + * riscv64-unknown-elf-gdb.exe -iex "set mem inaccessible-by-default off" -iex "set arch riscv:rv32" -iex "set riscv use_compressed_breakpoint off" + * + * + * Note 3: + * + * Status information is sent to the QEMU serial console. + */ +/* Set mainCREATE_SIMPLE_BLINKY_DEMO_ONLY to one to run the simple blinky demo, +or 0 to run the more comprehensive test and demo application. */ +#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0 /* - * FreeRTOS hook for when malloc fails, enable in FreeRTOSConfig. + * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. + * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. */ -void vApplicationMallocFailedHook( void ); +#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 + extern void main_blinky( void ); +#else + extern void main_full( void ); +#endif /* #if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */ /* - * FreeRTOS hook for when FreeRtos is idling, enable in FreeRTOSConfig. + * Prototypes for the standard FreeRTOS callback/hook functions implemented + * within this file. See https://www.freertos.org/a00016.html */ +void vApplicationMallocFailedHook( void ); void vApplicationIdleHook( void ); +void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); +void vApplicationTickHook( void ); /* - * FreeRTOS hook for when a stack overflow occurs, enable in FreeRTOSConfig. + * Very simply polling write to the UART. The full demo only writes single + * characters at a time so as not to disrupt the timing of the test and demo + * tasks. */ -void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); - - -void reset_demo (void); - -// Structures for registering different interrupt handlers -// for different parts of the application. -typedef void (*function_ptr_t) (void); - -void no_interrupt_handler (void) {}; - -function_ptr_t g_ext_interrupt_handlers[PLIC_NUM_INTERRUPTS]; - - -// Instance data for the PLIC. - -plic_instance_t g_plic; - - -/*Entry Point for PLIC Interrupt Handler*/ -void handle_m_ext_interrupt(){ - plic_source int_num = PLIC_claim_interrupt(&g_plic); - if ((int_num >=1 ) && (int_num < PLIC_NUM_INTERRUPTS)) { - g_ext_interrupt_handlers[int_num](); - } - else { - exit(1 + (uintptr_t) int_num); - } - PLIC_complete_interrupt(&g_plic, int_num); -} - - -/*Entry Point for Machine Timer Interrupt Handler*/ -void handle_m_time_interrupt(){ - - clear_csr(mie, MIP_MTIP); - - // Reset the timer for 3s in the future. - // This also clears the existing timer interrupt. - - 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 + 2 * RTC_FREQ; - *mtimecmp = then; - - // read the current value of the LEDS and invert them. - uint32_t leds = GPIO_REG(GPIO_OUTPUT_VAL); - - GPIO_REG(GPIO_OUTPUT_VAL) ^= ((0x1 << RED_LED_OFFSET) | - (0x1 << GREEN_LED_OFFSET) | - (0x1 << BLUE_LED_OFFSET)); - - // Re-enable the timer interrupt. - set_csr(mie, MIP_MTIP); - -} - - -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\ -SiFive E-Series Software Development Kit 'demo_gpio' program.\n\ -Every 2 second, the Timer Interrupt will invert the LEDs.\n\ -(Arty Dev Kit Only): Press Buttons 0, 1, 2 to Set the LEDs.\n\ -Pin 19 (HiFive1) or A5 (Arty Dev Kit) is being bit-banged\n\ -for GPIO speed demonstration.\n\ -\n\ - "; - -void print_instructions() { - - write (STDOUT_FILENO, instructions_msg, strlen(instructions_msg)); - -} - -#ifdef HAS_BOARD_BUTTONS -void button_0_handler(void) { - - // Red LED on - GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << RED_LED_OFFSET); - - // Clear the GPIO Pending interrupt by writing 1. - GPIO_REG(GPIO_RISE_IP) = (0x1 << BUTTON_0_OFFSET); - -}; - -void button_1_handler(void) { - - // Green LED On - GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << GREEN_LED_OFFSET); - - // Clear the GPIO Pending interrupt by writing 1. - GPIO_REG(GPIO_RISE_IP) = (0x1 << BUTTON_1_OFFSET); +void vSendString( const char * pcString ); -}; - - -void button_2_handler(void) { - - // Blue LED On - GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << BLUE_LED_OFFSET); - - GPIO_REG(GPIO_RISE_IP) = (0x1 << BUTTON_2_OFFSET); - -}; -#endif - -void reset_demo (){ - - // Disable the machine & timer interrupts until setup is done. - - 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; - g_ext_interrupt_handlers[INT_DEVICE_BUTTON_1] = button_1_handler; - g_ext_interrupt_handlers[INT_DEVICE_BUTTON_2] = button_2_handler; -#endif - - print_instructions(); - -#ifdef HAS_BOARD_BUTTONS - - // Have to enable the interrupt both at the GPIO level, - // and at the PLIC level. - PLIC_enable_interrupt (&g_plic, INT_DEVICE_BUTTON_0); - PLIC_enable_interrupt (&g_plic, INT_DEVICE_BUTTON_1); - PLIC_enable_interrupt (&g_plic, INT_DEVICE_BUTTON_2); - - // Priority must be set > 0 to trigger the interrupt. - PLIC_set_priority(&g_plic, INT_DEVICE_BUTTON_0, 1); - PLIC_set_priority(&g_plic, INT_DEVICE_BUTTON_1, 1); - PLIC_set_priority(&g_plic, INT_DEVICE_BUTTON_2, 1); - - GPIO_REG(GPIO_RISE_IE) |= (1 << BUTTON_0_OFFSET); - GPIO_REG(GPIO_RISE_IE) |= (1 << BUTTON_1_OFFSET); - GPIO_REG(GPIO_RISE_IE) |= (1 << BUTTON_2_OFFSET); - -#endif - - // Set the machine timer to go off in 3 seconds. - // The - 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 + 2*RTC_FREQ; - *mtimecmp = then; - - // Enable the Machine-External bit in MIE - set_csr(mie, MIP_MEIP); - - // Enable the Machine-Timer bit in MIE - set_csr(mie, MIP_MTIP); - - // Enable interrupts in general. - set_csr(mstatus, MSTATUS_MIE); -} +/*-----------------------------------------------------------*/ -int main(int argc, char **argv) +int main( void ) { - // Set up the GPIOs such that the LED GPIO - // can be used as both Inputs and Outputs. - - -#ifdef HAS_BOARD_BUTTONS - GPIO_REG(GPIO_OUTPUT_EN) &= ~((0x1 << BUTTON_0_OFFSET) | (0x1 << BUTTON_1_OFFSET) | (0x1 << BUTTON_2_OFFSET)); - GPIO_REG(GPIO_PULLUP_EN) &= ~((0x1 << BUTTON_0_OFFSET) | (0x1 << BUTTON_1_OFFSET) | (0x1 << BUTTON_2_OFFSET)); - GPIO_REG(GPIO_INPUT_EN) |= ((0x1 << BUTTON_0_OFFSET) | (0x1 << BUTTON_1_OFFSET) | (0x1 << BUTTON_2_OFFSET)); -#endif - - 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)) ; - - - // For Bit-banging with Atomics demo. - - uint32_t bitbang_mask = 0; -#ifdef _SIFIVE_HIFIVE1_H - bitbang_mask = (1 << PIN_19_OFFSET); -#else -#ifdef _SIFIVE_COREPLEXIP_ARTY_H - bitbang_mask = (0x1 << JA_0_OFFSET); -#endif -#endif - - GPIO_REG(GPIO_OUTPUT_EN) |= bitbang_mask; - - /************************************************************************** - * Set up the PLIC - * - *************************************************************************/ - PLIC_init(&g_plic, - PLIC_CTRL_ADDR, - PLIC_NUM_INTERRUPTS, - PLIC_NUM_PRIORITIES); - - reset_demo(); - - /************************************************************************** - * Demonstrate fast GPIO bit-banging. - * One can bang it faster than this if you know - * the entire OUTPUT_VAL that you want to write, but - * Atomics give a quick way to control a single bit. - *************************************************************************/ - // For Bit-banging with Atomics demo. - - while (1){ - atomic_fetch_xor_explicit(&GPIO_REG(GPIO_OUTPUT_VAL), bitbang_mask, memory_order_relaxed); - } - - return 0; - + vSendString( "Starting" ); + + /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top + of this file. */ + #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) + { + main_blinky(); + } + #else + { + main_full(); + } + #endif } +/*-----------------------------------------------------------*/ void vApplicationMallocFailedHook( void ) { @@ -316,11 +165,37 @@ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ) } /*-----------------------------------------------------------*/ +void vApplicationTickHook( void ) +{ + /* The tests in the full demo expect some interaction with interrupts. */ + #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) + { + extern void vFullDemoTickHook( void ); + vFullDemoTickHook(); + } + #endif +} +/*-----------------------------------------------------------*/ - -void trap_entry( void ) +void vAssertCalled( void ) { -#warning Dummy until kernel code is incldued. +volatile uint32_t ulSetTo1ToExitFunction = 0; + + taskDISABLE_INTERRUPTS(); + while( ulSetTo1ToExitFunction != 1 ) + { + __asm volatile( "NOP" ); + } } +/*-----------------------------------------------------------*/ +void vSendString( const char * pcString ) +{ + while( *pcString != 0x00 ) + { + while( UART0_REG( UART_REG_TXFIFO ) & 0x80000000 ); + UART0_REG( UART_REG_TXFIFO ) = *pcString; + *pcString++; + } +}