42
42
#include <xintc_i.h>
43
43
#include <xil_exception.h>
44
44
#include <microblaze_exceptions_g.h>
45
+ #include <microblaze_instructions.h>
45
46
46
47
/* Tasks are started with a critical section nesting of 0 - however, prior to
47
48
* the scheduler being commenced interrupts should not be enabled, so the critical
58
59
* given to the FSR register when the initial context is set up for a task being
59
60
* created. */
60
61
#define portINITIAL_FSR ( 0U )
62
+ /*
63
+ * Global counter used for calculation of run time statistics of tasks.
64
+ * Defined only when the relevant option is turned on
65
+ */
66
+ #if (configGENERATE_RUN_TIME_STATS == 1 )
67
+ volatile uint32_t ulHighFrequencyTimerTicks ;
68
+ #endif
61
69
62
70
/*-----------------------------------------------------------*/
63
71
@@ -116,10 +124,11 @@ static XIntc xInterruptControllerInstance;
116
124
void * pvParameters )
117
125
#endif
118
126
{
119
- extern void * _SDA2_BASE_ ;
120
- extern void * _SDA_BASE_ ;
121
- const uint32_t ulR2 = ( uint32_t ) & _SDA2_BASE_ ;
122
- const uint32_t ulR13 = ( uint32_t ) & _SDA_BASE_ ;
127
+ extern void * _SDA2_BASE_ ;
128
+ extern void * _SDA_BASE_ ;
129
+ const UINTPTR ulR2 = ( UINTPTR ) & _SDA2_BASE_ ;
130
+ const UINTPTR ulR13 = ( UINTPTR ) & _SDA_BASE_ ;
131
+
123
132
extern void _start1 ( void );
124
133
125
134
/* Place a few bytes of known values on the bottom of the stack.
@@ -255,8 +264,8 @@ static XIntc xInterruptControllerInstance;
255
264
256
265
BaseType_t xPortStartScheduler ( void )
257
266
{
258
- extern void ( vPortStartFirstTask )( void );
259
- extern uint32_t _stack [];
267
+ extern void ( vPortStartFirstTask )( void );
268
+ extern UINTPTR _stack [];
260
269
261
270
/* Setup the hardware to generate the tick. Interrupts are disabled when
262
271
* this function is called.
@@ -270,7 +279,7 @@ BaseType_t xPortStartScheduler( void )
270
279
vApplicationSetupTimerInterrupt ();
271
280
272
281
/* Reuse the stack from main() as the stack for the interrupts/exceptions. */
273
- pulISRStack = ( uint32_t * ) _stack ;
282
+ pulISRStack = ( UINTPTR * ) _stack ;
274
283
275
284
/* Ensure there is enough space for the functions called from the interrupt
276
285
* service routines to write back into the stack frame of the caller. */
@@ -304,13 +313,18 @@ void vPortYield( void )
304
313
* not interrupted by the tick ISR. It is not a problem to do this as
305
314
* each task maintains its own interrupt status. */
306
315
portENTER_CRITICAL ();
307
- {
308
- /* Jump directly to the yield function to ensure there is no
309
- * compiler generated prologue code. */
310
- asm volatile ( "bralid r14, VPortYieldASM \n\t" \
311
- "or r0, r0, r0 \n\t" );
312
- }
313
- portEXIT_CRITICAL ();
316
+ {
317
+ /* Jump directly to the yield function to ensure there is no
318
+ * compiler generated prologue code. */
319
+ #ifdef __arch64__
320
+ asm volatile ( "brealid r14, VPortYieldASM \n\t" \
321
+ "or r0, r0, r0 \n\t" );
322
+ #else
323
+ asm volatile ( "bralid r14, VPortYieldASM \n\t" \
324
+ "or r0, r0, r0 \n\t" );
325
+ #endif
326
+ }
327
+ portEXIT_CRITICAL ();
314
328
}
315
329
/*-----------------------------------------------------------*/
316
330
@@ -434,22 +448,34 @@ void vPortTickISR( void * pvUnused )
434
448
{
435
449
extern void vApplicationClearTimerInterrupt ( void );
436
450
437
- /* Ensure the unused parameter does not generate a compiler warning. */
438
- ( void ) pvUnused ;
439
-
440
- /* This port uses an application defined callback function to clear the tick
441
- * interrupt because the kernel will run on lots of different MicroBlaze and
442
- * FPGA configurations - not all of which will have the same timer peripherals
443
- * defined or available. An example definition of
444
- * vApplicationClearTimerInterrupt() is provided in the official demo
445
- * application that accompanies this port . */
446
- vApplicationClearTimerInterrupt ();
447
-
448
- /* Increment the RTOS tick - this might cause a task to unblock. */
449
- if ( xTaskIncrementTick () != pdFALSE )
451
+ /* Ensure the unused parameter does not generate a compiler warning. */
452
+ ( void ) pvUnused ;
453
+
454
+ /* The Xilinx implementation of generating run time task stats uses the same timer used for generating
455
+ * FreeRTOS ticks. In case user decides to generate run time stats the tick handler is called more
456
+ * frequently (10 times faster). The timer ick handler uses logic to handle the same. It handles
457
+ * the FreeRTOS tick once per 10 interrupts.
458
+ * For handling generation of run time stats, it increments a pre-defined counter every time the
459
+ * interrupt handler executes . */
460
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
461
+ ulHighFrequencyTimerTicks ++ ;
462
+ if (!( ulHighFrequencyTimerTicks % 10 ))
463
+ #endif
450
464
{
451
- /* Force vTaskSwitchContext() to be called as the interrupt exits. */
452
- ulTaskSwitchRequested = 1 ;
465
+ /* This port uses an application defined callback function to clear the tick
466
+ * interrupt because the kernel will run on lots of different MicroBlaze and
467
+ * FPGA configurations - not all of which will have the same timer peripherals
468
+ * defined or available. An example definition of
469
+ * vApplicationClearTimerInterrupt() is provided in the official demo
470
+ * application that accompanies this port. */
471
+ vApplicationClearTimerInterrupt ();
472
+
473
+ /* Increment the RTOS tick - this might cause a task to unblock. */
474
+ if ( xTaskIncrementTick () != pdFALSE )
475
+ {
476
+ /* Force vTaskSwitchContext() to be called as the interrupt exits. */
477
+ ulTaskSwitchRequested = 1 ;
478
+ }
453
479
}
454
480
}
455
481
/*-----------------------------------------------------------*/
@@ -495,4 +521,25 @@ static int32_t prvInitialiseInterruptController( void )
495
521
496
522
return lStatus ;
497
523
}
524
+
525
+ #if ( configGENERATE_RUN_TIME_STATS == 1 )
526
+ /*
527
+ * For Xilinx implementation this is a dummy function that does a redundant operation
528
+ * of zeroing out the global counter.
529
+ * It is called by FreeRTOS kernel.
530
+ */
531
+ void xCONFIGURE_TIMER_FOR_RUN_TIME_STATS (void )
532
+ {
533
+ ulHighFrequencyTimerTicks = 0 ;
534
+ }
535
+ /*
536
+ * For Xilinx implementation this function returns the global counter used for
537
+ * run time task stats calculation.
538
+ * It is called by FreeRTOS kernel task handling logic.
539
+ */
540
+ uint32_t xGET_RUN_TIME_COUNTER_VALUE (void )
541
+ {
542
+ return ulHighFrequencyTimerTicks ;
543
+ }
544
+ #endif
498
545
/*-----------------------------------------------------------*/
0 commit comments