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