\r
/* Used to program the machine timer compare register. */\r
static uint64_t ullNextTime = 0ULL;\r
-static volatile uint64_t * const pullMachineTimerCompareRegister = ( volatile uint64_t * const ) ( configCTRL_BASE + 0x4000 );\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
*/\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 = mstatus;\r
+\r
+ /* Numbers correspond to the x register number. */\r
pxTopOfStack--;\r
*pxTopOfStack = ( StackType_t ) 31;\r
pxTopOfStack--;\r
void vPortSetupTimerInterrupt( void )\r
{\r
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;\r
-volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCTRL_BASE + 0xBFF8 );\r
-volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCTRL_BASE + 0xBFFc );\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
ullNextTime = ( uint64_t ) ulCurrentTimeHigh;\r
ullNextTime <<= 32ULL;\r
ullNextTime |= ( uint64_t ) ulCurrentTimeLow;\r
- ullNextTime += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );\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) );\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 * ) configCTRL_BASE;\r
+volatile uint32_t * const ulSoftInterrupt = ( uint32_t * ) configCLINT_BASE_ADDRESS;\r
\r
vTaskSwitchContext();\r
\r
/* Clear software interrupt. */\r
- *ulSoftInterrupt = 0UL;\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
+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 vPortEndScheduler( void )\r
+{\r
+ /* Not implemented. */\r
+ for( ;; );\r
+}\r
+\r
+\r
+\r
\r