* file is weak to allow application writers to change the timer used to\r
* generate the tick interrupt.\r
*/\r
-void vPortSetupTimerInterrupt( void );\r
+void vPortSetupTimerInterrupt( void ) __attribute__(( weak ));\r
\r
/*\r
* Used to catch tasks that attempt to return from their implementing function.\r
\r
/*-----------------------------------------------------------*/\r
\r
+/* Used to program the machine timer compare register. */\r
+static uint64_t ullNextTime = 0ULL;\r
+static const uint64_t ullTimerIncrementsForOneTick = ( uint64_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );\r
+static volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCLINT_BASE_ADDRESS + 0x4000 );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
void prvTaskExitError( void )\r
{\r
volatile uint32_t ulx = 0;\r
*/\r
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
{\r
+uint32_t mstatus;\r
+const uint32_t ulMPIE_Bit = 0x80, ulMPP_Bits = 0x1800;\r
/*\r
X1 to X31 integer registers for the 'I' profile, X1 to X15 for the 'E' profile.\r
\r
x28-31 t3-6 Temporaries Caller\r
*/\r
\r
+ /* Start task with interrupt enabled. */\r
+ __asm volatile ("csrr %0, mstatus" : "=r"(mstatus));\r
+ mstatus |= ulMPIE_Bit | ulMPP_Bits;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) pxCode; /* X1 */\r
+ *pxTopOfStack = mstatus;\r
+\r
+ /* Numbers correspond to the x register number. */\r
pxTopOfStack--;\r
-// *pxTopOfStack = ( StackType_t ) 2; /* Stack pointer is handled separately. */\r
-// pxTopOfStack--;\r
-// *pxTopOfStack = ( StackType_t ) 3; /* Global pointer is not manipulated. */\r
-// pxTopOfStack--;\r
-// *pxTopOfStack = ( StackType_t ) 4; /* Thread pointer is not manipulated. */\r
-// pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 5;\r
+ *pxTopOfStack = ( StackType_t ) 31;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 6;\r
+ *pxTopOfStack = ( StackType_t ) 30;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 7;\r
+ *pxTopOfStack = ( StackType_t ) 29;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 8;\r
+ *pxTopOfStack = ( StackType_t ) 28;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 9;\r
+ *pxTopOfStack = ( StackType_t ) 27;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) pvParameters;\r
+ *pxTopOfStack = ( StackType_t ) 26;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 11;\r
+ *pxTopOfStack = ( StackType_t ) 25;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 12;\r
+ *pxTopOfStack = ( StackType_t ) 24;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 13;\r
+ *pxTopOfStack = ( StackType_t ) 23;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 14;\r
+ *pxTopOfStack = ( StackType_t ) 22;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 15;\r
+ *pxTopOfStack = ( StackType_t ) 21;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 16;\r
+ *pxTopOfStack = ( StackType_t ) 20;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 17;\r
+ *pxTopOfStack = ( StackType_t ) 19;\r
pxTopOfStack--;\r
*pxTopOfStack = ( StackType_t ) 18;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 19;\r
+ *pxTopOfStack = ( StackType_t ) 17;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 20;\r
+ *pxTopOfStack = ( StackType_t ) 16;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 21;\r
+ *pxTopOfStack = ( StackType_t ) 15;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 22;\r
+ *pxTopOfStack = ( StackType_t ) 14;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 23;\r
+ *pxTopOfStack = ( StackType_t ) 13;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 24;\r
+ *pxTopOfStack = ( StackType_t ) 12;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 25;\r
+ *pxTopOfStack = ( StackType_t ) 11;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 26;\r
+ *pxTopOfStack = ( StackType_t ) pvParameters;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 27;\r
+ *pxTopOfStack = ( StackType_t ) 9;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 28;\r
+ *pxTopOfStack = ( StackType_t ) 8;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 29;\r
+ *pxTopOfStack = ( StackType_t ) 7;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 30;\r
+ *pxTopOfStack = ( StackType_t ) 6;\r
pxTopOfStack--;\r
- *pxTopOfStack = ( StackType_t ) 31;\r
+ *pxTopOfStack = ( StackType_t ) 5;\r
+ pxTopOfStack--;\r
+// *pxTopOfStack = ( StackType_t ) 4; /* Thread pointer. */\r
+// pxTopOfStack--;\r
+// *pxTopOfStack = ( StackType_t ) 3; /* Global pointer. */\r
+// pxTopOfStack--;\r
+// *pxTopOfStack = ( StackType_t ) 2; /* Stack pointer. */\r
+// pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) prvTaskExitError;\r
+ pxTopOfStack--;\r
+ *pxTopOfStack = ( StackType_t ) pxCode;\r
\r
return pxTopOfStack;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+void vPortSetupTimerInterrupt( void )\r
+{\r
+uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;\r
+volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFFC );\r
+volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFF8 );\r
+\r
+ do\r
+ {\r
+ ulCurrentTimeHigh = *pulTimeHigh;\r
+ ulCurrentTimeLow = *pulTimeLow;\r
+ } while( ulCurrentTimeHigh != *pulTimeHigh );\r
+\r
+ ullNextTime = ( uint64_t ) ulCurrentTimeHigh;\r
+ ullNextTime <<= 32ULL;\r
+ ullNextTime |= ( uint64_t ) ulCurrentTimeLow;\r
+ ullNextTime += ullTimerIncrementsForOneTick;\r
+ *pullMachineTimerCompareRegister = ullNextTime;\r
+\r
+ /* Prepare the time to use after the next tick interrupt. */\r
+ ullNextTime += ullTimerIncrementsForOneTick;\r
+\r
+ /* Enable timer interrupt */\r
+ __asm volatile( "csrs mie, %0" :: "r"(0x80) ); /* 1<<7 for timer interrupt. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void Software_IRQHandler( void )\r
+{\r
+volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCLINT_BASE_ADDRESS;\r
+\r
+ vTaskSwitchContext();\r
+\r
+ /* Clear software interrupt. */\r
+ *( ( uint32_t * ) configCLINT_BASE_ADDRESS ) &= 0x08UL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void Timer_IRQHandler( void )\r
+{\r
+extern void vTaskSwitchContext( void );\r
+\r
+ /* Reload for the next timer interrupt. */\r
+ *pullMachineTimerCompareRegister = ullNextTime;\r
+ ullNextTime += ullTimerIncrementsForOneTick;\r
+\r
+ if( xTaskIncrementTick() != pdFALSE )\r
+ {\r
+ vTaskSwitchContext();\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
BaseType_t xPortStartScheduler( void )\r
{\r
- __asm volatile\r
- (\r
- ".extern pxCurrentTCB \r\n"\r
- "lw sp, pxCurrentTCB \r\n" /* Load pxCurrentTCB. */\r
- "lw sp, 0x00( sp ) \r\n" /* Read sp from first TCB member. */\r
- "lw x31, 0( sp ) \r\n" /* X31 */\r
- "lw x30, 4( sp ) \r\n" /* X30 */\r
- "lw x29, 8( sp ) \r\n" /* X29 */\r
- "lw x28, 12( sp ) \r\n" /* X28 */\r
- "lw x27, 16( sp ) \r\n" /* X27 */\r
- "lw x26, 20( sp ) \r\n" /* X26 */\r
- "lw x25, 24( sp ) \r\n" /* X25 */\r
- "lw x24, 28( sp ) \r\n" /* X24 */\r
- "lw x23, 32( sp ) \r\n" /* X23 */\r
- "lw x22, 36( sp ) \r\n" /* X22 */\r
- "lw x21, 40( sp ) \r\n" /* X21 */\r
- "lw x20, 44( sp ) \r\n" /* X20 */\r
- "lw x19, 48( sp ) \r\n" /* X19 */\r
- "lw x18, 52( sp ) \r\n" /* X18 */\r
- "lw x17, 56( sp ) \r\n" /* X17 */\r
- "lw x16, 60( sp ) \r\n" /* X16 */\r
- "lw x15, 64( sp ) \r\n" /* X15 */\r
- "lw x14, 68( sp ) \r\n" /* X14 */\r
- "lw x13, 72( sp ) \r\n" /* X13 */\r
- "lw x12, 76( sp ) \r\n" /* X12 */\r
- "lw x11, 80( sp ) \r\n" /* X11 */\r
- "lw x10, 84( sp ) \r\n" /* X10 */\r
- "lw x9, 88( sp ) \r\n" /* X9 */\r
- "lw x8, 92( sp ) \r\n" /* X8 */\r
- "lw x7, 96( sp ) \r\n" /* X7 */\r
- "lw x6, 100( sp ) \r\n" /* X6 */\r
- "lw x5, 104( sp ) \r\n" /* X5 */\r
- "lw x1, 108( sp ) \r\n" /* X1 */\r
- "csrs mstatus, 8 \r\n" /* Enable interrupts. */\r
- "ret "\r
- );\r
-\r
- /*Should not get here*/\r
- return pdFALSE;\r
+extern void xPortStartFirstTask( void );\r
+\r
+ #if( configASSERT_DEFINED == 1 )\r
+ {\r
+ volatile uint32_t mtvec = 0;\r
+\r
+ /* Check the least significant two bits of mtvec are 00 - indicating single\r
+ vector mode. */\r
+ __asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) );\r
+ configASSERT( ( mtvec & 0x03UL ) == 0 );\r
+ }\r
+ #endif\r
+\r
+ vPortSetupTimerInterrupt();\r
+ xPortStartFirstTask();\r
+\r
+ /* Should not get here as after calling xPortStartFirstTask() only tasks\r
+ should be executing. */\r
+ return pdFAIL;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vPortYield( void )\r
+void vPortEndScheduler( void )\r
{\r
+ /* Not implemented. */\r
+ for( ;; );\r
}\r
\r
\r
+\r
+\r