From 692428396a38eca07398ef524a1b3fd56bdb7112 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Fri, 28 Oct 2011 11:50:00 +0000 Subject: [PATCH] Added the portALIGNMENT_ASSERT_pxCurrentTCB macro. Updated the TriCore port layer so its compare match setup does not effect any other compare match bits. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1629 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Source/include/FreeRTOS.h | 4 ++ Source/portable/GCC/TriCore_1782/port.c | 42 +++++++++++++++----- Source/portable/GCC/TriCore_1782/portmacro.h | 5 +++ Source/tasks.c | 2 +- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/Source/include/FreeRTOS.h b/Source/include/FreeRTOS.h index baa77afbc..4f24ac4ed 100644 --- a/Source/include/FreeRTOS.h +++ b/Source/include/FreeRTOS.h @@ -192,6 +192,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * ); #define configASSERT( x ) #endif +#ifndef portALIGNMENT_ASSERT_pxCurrentTCB + #define portALIGNMENT_ASSERT_pxCurrentTCB configASSERT +#endif + /* The timers module relies on xTaskGetSchedulerState(). */ #if configUSE_TIMERS == 1 diff --git a/Source/portable/GCC/TriCore_1782/port.c b/Source/portable/GCC/TriCore_1782/port.c index cc3345044..ab7f44a8d 100644 --- a/Source/portable/GCC/TriCore_1782/port.c +++ b/Source/portable/GCC/TriCore_1782/port.c @@ -95,7 +95,7 @@ /* * Perform any hardware configuration necessary to generate the tick interrupt. */ -void vPortSystemTickHandler( int ) __attribute__((longcall)); +static void prvSystemTickHandler( int ) __attribute__((longcall)); static void prvSetupTimerInterrupt( void ); /* @@ -107,6 +107,9 @@ static void prvPortYield( int iTrapIdentification ); /* This reference is required by the save/restore context macros. */ extern volatile unsigned long *pxCurrentTCB; +/* Precalculate the compare match value at compile time. */ +static const unsigned long ulCompareMatchValue = ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ ); + /*-----------------------------------------------------------*/ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE * pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) @@ -253,20 +256,23 @@ static void prvSetupTimerInterrupt( void ) } lock_wdtcon(); - /* Set-up the Compare value. Determine how many bits are used. */ - STM_CMCON.reg = ( 0x1fUL - __CLZ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ ) ); + /* Determine how many bits are used without changing other bits in the CMCON register. */ + STM_CMCON.reg &= ~( 0x1fUL ); + STM_CMCON.reg |= ( 0x1fUL - __CLZ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ ) ); /* Take into account the current time so a tick doesn't happen immediately. */ - STM_CMP0.reg = ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ ) + STM_TIM0.reg; + STM_CMP0.reg = ulCompareMatchValue + STM_TIM0.reg; - if( 0 != _install_int_handler( configKERNEL_INTERRUPT_PRIORITY, vPortSystemTickHandler, 0 ) ) + if( 0 != _install_int_handler( configKERNEL_INTERRUPT_PRIORITY, prvSystemTickHandler, 0 ) ) { /* Set-up the interrupt. */ STM_SRC0.reg = ( configKERNEL_INTERRUPT_PRIORITY | 0x00005000UL ); /* Enable the Interrupt. */ - STM_ISRR.reg = 0x1UL; - STM_ICR.reg = 0x1UL; + STM_ISRR.reg &= ~( 0x03UL ); + STM_ISRR.reg |= 0x1UL; + STM_ISRR.reg &= ~( 0x07UL ); + STM_ICR.reg |= 0x1UL; } else { @@ -276,7 +282,7 @@ static void prvSetupTimerInterrupt( void ) } /*-----------------------------------------------------------*/ -void vPortSystemTickHandler( int iArg ) +static void prvSystemTickHandler( int iArg ) { unsigned long ulSavedInterruptMask; @@ -286,8 +292,24 @@ unsigned long ulSavedInterruptMask; /* Clear the interrupt source. */ STM_ISRR.reg = 1UL; - /* Reload the Compare Match register for X ticks into the future. */ - STM_CMP0.reg += ( configPERIPHERAL_CLOCK_HZ / configTICK_RATE_HZ ); + /* Reload the Compare Match register for X ticks into the future. + + If critical section or interrupt nesting budgets are exceeded, then + it is possible that the calculated next compare match value is in the + past. If this occurs (unlikely), it is possible that the resulting + time slippage will exceed a single tick period. Any adverse effect of + this is time bounded by the fact that only the first n bits of the 56 bit + STM timer are being used for a compare match, so another compare match + will occur after an overflow in just those n bits (not the entire 56 bits). + As an example, if the peripheral clock is 75MHz, and the tick rate is 1KHz, + a missed tick could result in the next tick interrupt occurring within a + time that is 1.7 times the desired period. The fact that this is greater + than a single tick period is an effect of using a timer that cannot be + automatically reset, in hardware, by the occurrence of a tick interrupt. + Changing the tick source to a timer that has an automatic reset on compare + match (such as a GPTA timer) will reduce the maximum possible additional + period to exactly 1 times the desired period. */ + STM_CMP0.reg += ulCompareMatchValue; /* Kernel API calls require Critical Sections. */ ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR(); diff --git a/Source/portable/GCC/TriCore_1782/portmacro.h b/Source/portable/GCC/TriCore_1782/portmacro.h index 0f3a71e6a..a71d0e3ac 100644 --- a/Source/portable/GCC/TriCore_1782/portmacro.h +++ b/Source/portable/GCC/TriCore_1782/portmacro.h @@ -146,6 +146,10 @@ extern void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE uxSavedStatus /* Set ICR.CCPN to uxSavedInterruptStatus */ #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) vPortClearInterruptMaskFromISR( uxSavedStatusValue ) +/* As this port holds a CSA address in pxTopOfStack, the assert that checks the +pxTopOfStack alignment is removed. */ +#define portALIGNMENT_ASSERT_pxCurrentTCB ( void ) + /*---------------------------------------------------------------------------*/ /* @@ -173,6 +177,7 @@ extern void vPortClearInterruptMaskFromISR( unsigned portBASE_TYPE uxSavedStatus { \ unsigned portBASE_TYPE *pxUpperCSA = NULL; \ unsigned portBASE_TYPE xUpperCSA = 0UL; \ +extern volatile unsigned long *pxCurrentTCB; \ if ( pdTRUE == xHigherPriorityTaskWoken ) \ { \ _disable(); \ diff --git a/Source/tasks.c b/Source/tasks.c index 3a4b21d75..2d405c586 100644 --- a/Source/tasks.c +++ b/Source/tasks.c @@ -504,7 +504,7 @@ tskTCB * pxNewTCB; #endif /* Check the alignment of the initialised stack. */ - configASSERT( ( ( ( unsigned long ) pxNewTCB->pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); + portALIGNMENT_ASSERT_pxCurrentTCB( ( ( ( unsigned long ) pxNewTCB->pxTopOfStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) ); if( ( void * ) pxCreatedTask != NULL ) { -- 2.39.5