]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/RISC-V-Qemu-sifive_e-FreedomStudio/main.c
First task running in RISC-V-Qemu-sifive_e-FreedomStudio demo.
[freertos] / FreeRTOS / Demo / RISC-V-Qemu-sifive_e-FreedomStudio / main.c
index 649218528de93fa4ec8ef39760412297bf9612a5..a33a716a6755815a1e4b349a8a69d07ecec6aa2e 100644 (file)
@@ -30,247 +30,99 @@ void vApplicationIdleHook( void );
 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
+void vRegTest1Task( void *pvParameters );\r
+void vRegTest2Task( void *pvParameters );\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
+const char * const pcStartMessage = "FreeRTOS demo\r\n";\r
+volatile uint32_t ulRegTest1LoopCounter = 0, ulRegTest2LoopCounter = 0;\r
+static void prvCheckTask( void *pvParameters );\r
 plic_instance_t g_plic;\r
+uint32_t bitbang_mask = 0;\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
-\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
+int main( void )\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
+       /* For Bit-banging with Atomics demo. */\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
+//     xTaskCreate( vRegTest1Task, "RegTest1", 1000, NULL, tskIDLE_PRIORITY, NULL );\r
+//     xTaskCreate( vRegTest2Task, "RegTest2", 1000, NULL, tskIDLE_PRIORITY, NULL );\r
+       xTaskCreate( prvCheckTask, "Check", 1000, NULL, configMAX_PRIORITIES - 1, NULL );\r
+\r
+       vTaskStartScheduler();\r
 }\r
+/*-----------------------------------------------------------*/\r
 \r
-int main(int argc, char **argv)\r
+static void prvCheckTask( void *pvParameters )\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
+const char *pcMessage = "PASS\r\n";\r
+const TickType_t xCheckPeriod = pdMS_TO_TICKS( 3000UL );\r
+uint32_t ulLastRegTest1LoopCounter = 0, ulLastRegTest2LoopCounter = 0;\r
+volatile uintptr_t mstatus;\r
+\r
+volatile uint32_t ulx;\r
+__asm volatile ("csrr %0, mstatus" : "=r"(mstatus));\r
+portENABLE_INTERRUPTS();\r
+__asm volatile ("csrr %0, mstatus" : "=r"(mstatus));\r
+for( ;; )\r
+{\r
+//     for( ulx = 0; ulx < 0xffff; ulx++ ) __asm volatile( "NOP" );\r
+//     vPortSetupTimerInterrupt();\r
+       vTaskDelay( xCheckPeriod );\r
+       write( STDOUT_FILENO, "Blip\r\n", strlen( "Blip\r\n" ) );\r
+}\r
+#if 0\r
+       for( ;; )\r
+       {\r
+               vTaskDelay( xCheckPeriod );\r
+\r
+               if( ulLastRegTest1LoopCounter == ulRegTest1LoopCounter )\r
+               {\r
+                       /* The RegTest1 loop counter is no longer incrementing, indicating\r
+                       the task failed its self check. */\r
+                       pcMessage = "FAIL: RegTest1\r\n";\r
+               }\r
+               else\r
+               {\r
+                       ulLastRegTest1LoopCounter = ulRegTest1LoopCounter;\r
+               }\r
+\r
+               if( ulLastRegTest2LoopCounter == ulRegTest2LoopCounter )\r
+               {\r
+                       /* The RegTest1 loop counter is no longer incrementing, indicating\r
+                       the task failed its self check. */\r
+                       pcMessage = "FAIL: RegTest2\r\n";\r
+               }\r
+               else\r
+               {\r
+                       ulLastRegTest2LoopCounter = ulRegTest2LoopCounter;\r
+               }\r
+\r
+               vUARTWriteString( pcMessage );\r
+       }\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
 }\r
+/*-----------------------------------------------------------*/\r
 \r
 void vApplicationMallocFailedHook( void )\r
 {\r
@@ -316,11 +168,35 @@ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#define mainINTERRUPT_BIT_SET 0x80000000UL\r
+#define mainENVIRONMENT_CALL   11UL\r
+#define mainEXTERNAL_INTERRRUPT ( mainINTERRUPT_BIT_SET | 11UL )\r
+#define mainTIMER_INTERRUPT            ( mainINTERRUPT_BIT_SET | 7UL )\r
+#define mainSOFTWARE_INTERRUPT ( mainINTERRUPT_BIT_SET | 3UL )\r
 \r
+extern void Timer_IRQHandler( void );\r
 \r
-void trap_entry( void )\r
+uint32_t ulPortTrapHandler( uint32_t mcause, uint32_t mepc )\r
 {\r
-#warning Dummy until kernel code is incldued.\r
+       if( mcause == mainENVIRONMENT_CALL )\r
+       {\r
+               vTaskSwitchContext();\r
+\r
+               /* Ensure not to return to the instruction that generated the exception. */\r
+               mepc += 4;\r
+       }\r
+       else if( mcause == mainEXTERNAL_INTERRRUPT )\r
+       {\r
+               for( ;; );\r
+       }\r
+       else if( mcause == mainTIMER_INTERRUPT )\r
+       {\r
+               Timer_IRQHandler();\r
+       }\r
+       else if( mcause == mainSOFTWARE_INTERRUPT )\r
+       {\r
+               for( ;; );\r
+       }\r
+\r
+       return mepc;\r
 }\r
-\r
-\r