+
diff --git a/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/FreeRTOSConfig.h
index 74858e462..c9e825c50 100644
--- a/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/FreeRTOSConfig.h
+++ b/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/FreeRTOSConfig.h
@@ -71,6 +71,7 @@
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
+#include "platform.h"
/*-----------------------------------------------------------
* Application specific definitions.
@@ -84,7 +85,7 @@
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
-#define configCTRL_BASE 0x2000000
+#define configCLINT_BASE_ADDRESS CLINT_CTRL_ADDR
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
@@ -92,7 +93,7 @@
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMAX_PRIORITIES ( 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 512 )
-#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 8 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
diff --git a/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/full_demo/RegTest.S b/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/full_demo/RegTest.S
new file mode 100644
index 000000000..e4d87147b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/full_demo/RegTest.S
@@ -0,0 +1,255 @@
+/*
+ * FreeRTOS Kernel V10.1.1
+ * Copyright (C) 2018 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!
+ */
+
+ .extern ulRegTest1LoopCounter
+ .extern ulRegTest2LoopCounter
+
+ .global vRegTest1Task
+ .global vRegTest2Task
+
+/*-----------------------------------------------------------*/
+
+vRegTest1Task:
+
+ /* Fill the core registers with known values. */
+ li x5, 0x5
+ li x6, 0x6
+ li x7, 0x7
+ li x8, 0x8
+ li x9, 0x9
+ li x10, 0xa
+ li x11, 0xb
+ li x12, 0xc
+ li x13, 0xd
+ li x14, 0xe
+ li x15, 0xf
+ li x16, 0x10
+ li x17, 0x11
+ li x18, 0x12
+ li x19, 0x13
+ li x20, 0x14
+ li x21, 0x15
+ li x22, 0x16
+ li x23, 0x17
+ li x24, 0x18
+ li x25, 0x19
+ li x26, 0x1a
+ li x27, 0x1b
+ li x28, 0x1c
+ li x29, 0x1d
+ li x30, 0x1e
+
+reg1_loop:
+
+ /* Check each register still contains the expected known value.
+ vRegTest1Implementation uses x31 as the temporary, vRegTest2Implementation
+ uses x5 as the temporary. */
+ li x31, 0x5
+ bne x31, x5, reg1_error_loop
+ li x31, 0x6
+ bne x31, x6, reg1_error_loop
+ li x31, 0x7
+ bne x31, x7, reg1_error_loop
+ li x31, 0x8
+ bne x31, x8, reg1_error_loop
+ li x31, 0x9
+ bne x31, x9, reg1_error_loop
+ li x31, 0xa
+ bne x31, x10, reg1_error_loop
+ li x31, 0xb
+ bne x31, x11, reg1_error_loop
+ li x31, 0xc
+ bne x31, x12, reg1_error_loop
+ li x31, 0xd
+ bne x31, x13, reg1_error_loop
+ li x31, 0xe
+ bne x31, x14, reg1_error_loop
+ li x31, 0xf
+ bne x31, x15, reg1_error_loop
+ li x31, 0x10
+ bne x31, x16, reg1_error_loop
+ li x31, 0x11
+ bne x31, x17, reg1_error_loop
+ li x31, 0x12
+ bne x31, x18, reg1_error_loop
+ li x31, 0x13
+ bne x31, x19, reg1_error_loop
+ li x31, 0x14
+ bne x31, x20, reg1_error_loop
+ li x31, 0x15
+ bne x31, x21, reg1_error_loop
+ li x31, 0x16
+ bne x31, x22, reg1_error_loop
+ li x31, 0x17
+ bne x31, x23, reg1_error_loop
+ li x31, 0x18
+ bne x31, x24, reg1_error_loop
+ li x31, 0x19
+ bne x31, x25, reg1_error_loop
+ li x31, 0x1a
+ bne x31, x26, reg1_error_loop
+ li x31, 0x1b
+ bne x31, x27, reg1_error_loop
+ li x31, 0x1c
+ bne x31, x28, reg1_error_loop
+ li x31, 0x1d
+ bne x31, x29, reg1_error_loop
+ li x31, 0x1e
+ bne x31, x30, reg1_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ lw x31, ulRegTest1LoopCounterConst
+ lw x30, 0(x31)
+ addi x30, x30, 1
+ sw x30, 0(x31)
+
+ /* Restore clobbered register reading for next loop. */
+ li x30, 0x1e
+
+ /* Yield to increase code coverage. */
+ ecall
+
+ /* Start again. */
+ jal reg1_loop
+
+reg1_error_loop:
+ /* Jump here if a register contains an uxpected value. This stops the loop
+ counter being incremented so the check task knows an error was found. */
+ jal reg1_error_loop
+
+ulRegTest1LoopCounterConst: .word ulRegTest1LoopCounter
+
+/*-----------------------------------------------------------*/
+
+vRegTest2Task:
+
+ /* Fill the core registers with known values. */
+ li x6, 0x61
+ li x7, 0x71
+ li x8, 0x81
+ li x9, 0x91
+ li x10, 0xa1
+ li x11, 0xb1
+ li x12, 0xc1
+ li x13, 0xd1
+ li x14, 0xe1
+ li x15, 0xf1
+ li x16, 0x20
+ li x17, 0x21
+ li x18, 0x22
+ li x19, 0x23
+ li x20, 0x24
+ li x21, 0x25
+ li x22, 0x26
+ li x23, 0x27
+ li x24, 0x28
+ li x25, 0x29
+ li x26, 0x2a
+ li x27, 0x2b
+ li x28, 0x2c
+ li x29, 0x2d
+ li x30, 0x2e
+ li x31, 0x2f
+
+Reg2_loop:
+
+ /* Check each register still contains the expected known value.
+ vRegTest2Implementation uses x5 as the temporary, vRegTest1Implementation
+ uses x31 as the temporary. */
+ li x5, 0x61
+ bne x5, x6, reg2_error_loop
+ li x5, 0x71
+ bne x5, x7, reg2_error_loop
+ li x5, 0x81
+ bne x5, x8, reg2_error_loop
+ li x5, 0x91
+ bne x5, x9, reg2_error_loop
+ li x5, 0xa1
+ bne x5, x10, reg2_error_loop
+ li x5, 0xb1
+ bne x5, x11, reg2_error_loop
+ li x5, 0xc1
+ bne x5, x12, reg2_error_loop
+ li x5, 0xd1
+ bne x5, x13, reg2_error_loop
+ li x5, 0xe1
+ bne x5, x14, reg2_error_loop
+ li x5, 0xf1
+ bne x5, x15, reg2_error_loop
+ li x5, 0x20
+ bne x5, x16, reg2_error_loop
+ li x5, 0x21
+ bne x5, x17, reg2_error_loop
+ li x5, 0x22
+ bne x5, x18, reg2_error_loop
+ li x5, 0x23
+ bne x5, x19, reg2_error_loop
+ li x5, 0x24
+ bne x5, x20, reg2_error_loop
+ li x5, 0x25
+ bne x5, x21, reg2_error_loop
+ li x5, 0x26
+ bne x5, x22, reg2_error_loop
+ li x5, 0x27
+ bne x5, x23, reg2_error_loop
+ li x5, 0x28
+ bne x5, x24, reg2_error_loop
+ li x5, 0x29
+ bne x5, x25, reg2_error_loop
+ li x5, 0x2a
+ bne x5, x26, reg2_error_loop
+ li x5, 0x2b
+ bne x5, x27, reg2_error_loop
+ li x5, 0x2c
+ bne x5, x28, reg2_error_loop
+ li x5, 0x2d
+ bne x5, x29, reg2_error_loop
+ li x5, 0x2e
+ bne x5, x30, reg2_error_loop
+ li x5, 0x2f
+ bne x5, x31, reg2_error_loop
+
+ /* Everything passed, increment the loop counter. */
+ lw x5, ulRegTest2LoopCounterConst
+ lw x6, 0(x5)
+ addi x6, x6, 1
+ sw x6, 0(x5)
+
+ /* Restore clobbered register reading for next loop. */
+ li x6, 0x61
+
+ /* Start again. */
+ jal Reg2_loop
+
+reg2_error_loop:
+ /* Jump here if a register contains an uxpected value. This stops the loop
+ counter being incremented so the check task knows an error was found. */
+ jal reg2_error_loop
+
+ulRegTest2LoopCounterConst: .word ulRegTest2LoopCounter
+
+
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..a33a716a6 100644
--- a/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/main.c
+++ b/FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/main.c
@@ -30,247 +30,99 @@ void vApplicationIdleHook( void );
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 vRegTest1Task( void *pvParameters );
+void vRegTest2Task( void *pvParameters );
-void no_interrupt_handler (void) {};
-
-function_ptr_t g_ext_interrupt_handlers[PLIC_NUM_INTERRUPTS];
-
-
-// Instance data for the PLIC.
+const char * const pcStartMessage = "FreeRTOS demo\r\n";
+volatile uint32_t ulRegTest1LoopCounter = 0, ulRegTest2LoopCounter = 0;
+static void prvCheckTask( void *pvParameters );
plic_instance_t g_plic;
+uint32_t bitbang_mask = 0;
-
-/*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 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( void )
+{
+ #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. */
+ #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;
+
+// xTaskCreate( vRegTest1Task, "RegTest1", 1000, NULL, tskIDLE_PRIORITY, NULL );
+// xTaskCreate( vRegTest2Task, "RegTest2", 1000, NULL, tskIDLE_PRIORITY, NULL );
+ xTaskCreate( prvCheckTask, "Check", 1000, NULL, configMAX_PRIORITIES - 1, NULL );
+
+ vTaskStartScheduler();
}
+/*-----------------------------------------------------------*/
-int main(int argc, char **argv)
+static void prvCheckTask( void *pvParameters )
{
- // 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
+const char *pcMessage = "PASS\r\n";
+const TickType_t xCheckPeriod = pdMS_TO_TICKS( 3000UL );
+uint32_t ulLastRegTest1LoopCounter = 0, ulLastRegTest2LoopCounter = 0;
+volatile uintptr_t mstatus;
+
+volatile uint32_t ulx;
+__asm volatile ("csrr %0, mstatus" : "=r"(mstatus));
+portENABLE_INTERRUPTS();
+__asm volatile ("csrr %0, mstatus" : "=r"(mstatus));
+for( ;; )
+{
+// for( ulx = 0; ulx < 0xffff; ulx++ ) __asm volatile( "NOP" );
+// vPortSetupTimerInterrupt();
+ vTaskDelay( xCheckPeriod );
+ write( STDOUT_FILENO, "Blip\r\n", strlen( "Blip\r\n" ) );
+}
+#if 0
+ for( ;; )
+ {
+ vTaskDelay( xCheckPeriod );
+
+ if( ulLastRegTest1LoopCounter == ulRegTest1LoopCounter )
+ {
+ /* The RegTest1 loop counter is no longer incrementing, indicating
+ the task failed its self check. */
+ pcMessage = "FAIL: RegTest1\r\n";
+ }
+ else
+ {
+ ulLastRegTest1LoopCounter = ulRegTest1LoopCounter;
+ }
+
+ if( ulLastRegTest2LoopCounter == ulRegTest2LoopCounter )
+ {
+ /* The RegTest1 loop counter is no longer incrementing, indicating
+ the task failed its self check. */
+ pcMessage = "FAIL: RegTest2\r\n";
+ }
+ else
+ {
+ ulLastRegTest2LoopCounter = ulRegTest2LoopCounter;
+ }
+
+ vUARTWriteString( pcMessage );
+ }
#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;
-
}
+/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook( void )
{
@@ -316,11 +168,35 @@ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
}
/*-----------------------------------------------------------*/
+#define mainINTERRUPT_BIT_SET 0x80000000UL
+#define mainENVIRONMENT_CALL 11UL
+#define mainEXTERNAL_INTERRRUPT ( mainINTERRUPT_BIT_SET | 11UL )
+#define mainTIMER_INTERRUPT ( mainINTERRUPT_BIT_SET | 7UL )
+#define mainSOFTWARE_INTERRUPT ( mainINTERRUPT_BIT_SET | 3UL )
+extern void Timer_IRQHandler( void );
-void trap_entry( void )
+uint32_t ulPortTrapHandler( uint32_t mcause, uint32_t mepc )
{
-#warning Dummy until kernel code is incldued.
+ if( mcause == mainENVIRONMENT_CALL )
+ {
+ vTaskSwitchContext();
+
+ /* Ensure not to return to the instruction that generated the exception. */
+ mepc += 4;
+ }
+ else if( mcause == mainEXTERNAL_INTERRRUPT )
+ {
+ for( ;; );
+ }
+ else if( mcause == mainTIMER_INTERRUPT )
+ {
+ Timer_IRQHandler();
+ }
+ else if( mcause == mainSOFTWARE_INTERRUPT )
+ {
+ for( ;; );
+ }
+
+ return mepc;
}
-
-
diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h
index 446f6fa88..9d0b52052 100644
--- a/FreeRTOS/Source/include/task.h
+++ b/FreeRTOS/Source/include/task.h
@@ -376,9 +376,9 @@ is used in assert() statements. */
* memory to be allocated dynamically.
*
* @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will
- * be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer
- * are NULL then the task will not be created and
- * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
+ * be created and a handle to the created task is returned. If either
+ * pxStackBuffer or pxTaskBuffer are NULL then the task will not be created and
+ * NULL is returned.
*
* Example usage:
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
index 2a0686b80..2754cb40e 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/port.c
@@ -51,7 +51,7 @@ static void prvTaskExitError( void );
/* Used to program the machine timer compare register. */
static uint64_t ullNextTime = 0ULL;
static const uint64_t ullTimerIncrementsForOneTick = ( uint64_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
-static volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCTRL_BASE + 0x4000 );
+static volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCLINT_BASE_ADDRESS + 0x4000 );
/*-----------------------------------------------------------*/
@@ -175,8 +175,8 @@ const uint32_t ulMPIE_Bit = 0x80, ulMPP_Bits = 0x1800;
void vPortSetupTimerInterrupt( void )
{
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
-volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCTRL_BASE + 0xBFFC );
-volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCTRL_BASE + 0xBFF8 );
+volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFFC );
+volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFF8 );
do
{
@@ -200,12 +200,12 @@ volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCTR
void Software_IRQHandler( void )
{
-volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCTRL_BASE;
+volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCLINT_BASE_ADDRESS;
vTaskSwitchContext();
/* Clear software interrupt. */
- *( ( uint32_t * ) configCTRL_BASE ) &= 0x08UL;
+ *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) &= 0x08UL;
}
/*-----------------------------------------------------------*/
@@ -246,6 +246,14 @@ extern void xPortStartFirstTask( void );
should be executing. */
return pdFAIL;
}
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+ /* Not implemented. */
+ for( ;; );
+}
+
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
index 4a128cb32..8ffd3a434 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portASM.S
@@ -41,13 +41,16 @@
.global xPortStartFirstTask
.global vPortTrapHandler
.extern pxCurrentTCB
-.extern handle_trap
+.extern ulPortTrapHandler
/*-----------------------------------------------------------*/
.align 8
xPortStartFirstTask:
+ la t0, vPortTrapHandler
+ csrw mtvec, t0
+
lw sp, pxCurrentTCB /* Load pxCurrentTCB. */
lw sp, 0( sp ) /* Read sp from first TCB member. */
@@ -127,7 +130,7 @@ vPortTrapHandler:
csrr a1, mepc
mv a2, sp
/*_RB_ Does stack need aligning here? */
- jal handle_trap
+ jal ulPortTrapHandler
csrw mepc, a0
/* Save exception return address. */
sw a0, 0( sp )
diff --git a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h
index d1df6815a..72b8b8392 100644
--- a/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h
+++ b/FreeRTOS/Source/portable/GCC/RISC-V-RV32/portmacro.h
@@ -70,7 +70,7 @@ not need to be guarded with a critical section. */
/* Scheduler utilities. */
-#define portYIELD() __asm volatile( "ecall" ); // software interrupt alternative *( ( uint32_t * ) configCTRL_BASE ) |= 0x08UL
+#define portYIELD() __asm volatile( "ecall" ); // software interrupt alternative *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) |= 0x08UL
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYield()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c
index 0c395d790..faf46713e 100644
--- a/FreeRTOS/Source/tasks.c
+++ b/FreeRTOS/Source/tasks.c
@@ -2937,28 +2937,28 @@ void vTaskSwitchContext( void )
#if ( configGENERATE_RUN_TIME_STATS == 1 )
{
- #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
- portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
- #else
- ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
- #endif
+ #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
+ portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime );
+ #else
+ ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE();
+ #endif
- /* Add the amount of time the task has been running to the
- accumulated time so far. The time the task started running was
- stored in ulTaskSwitchedInTime. Note that there is no overflow
- protection here so count values are only valid until the timer
- overflows. The guard against negative values is to protect
- against suspect run time stat counter implementations - which
- are provided by the application, not the kernel. */
- if( ulTotalRunTime > ulTaskSwitchedInTime )
- {
- pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
- ulTaskSwitchedInTime = ulTotalRunTime;
+ /* Add the amount of time the task has been running to the
+ accumulated time so far. The time the task started running was
+ stored in ulTaskSwitchedInTime. Note that there is no overflow
+ protection here so count values are only valid until the timer
+ overflows. The guard against negative values is to protect
+ against suspect run time stat counter implementations - which
+ are provided by the application, not the kernel. */
+ if( ulTotalRunTime > ulTaskSwitchedInTime )
+ {
+ pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime );
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
+ }
+ ulTaskSwitchedInTime = ulTotalRunTime;
}
#endif /* configGENERATE_RUN_TIME_STATS */