Merge remote-tracking branch 'upstream/master' into rx700v3dpfpu

This commit is contained in:
NoMaY (a user of Japan.RenesasRulz.com) 2020-08-13 13:36:30 +09:00
commit c9a41ddccc
41 changed files with 2522 additions and 613 deletions

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -68,7 +68,7 @@ BaseType_t xPortRaisePrivilege( void ) /* FREERTOS_SYSTEM_CALL */
xRunningPrivileged = portIS_PRIVILEGED(); xRunningPrivileged = portIS_PRIVILEGED();
/* If the processor is not already privileged, raise privilege. */ /* If the processor is not already privileged, raise privilege. */
if( xRunningPrivileged != pdTRUE ) if( xRunningPrivileged == pdFALSE )
{ {
portRAISE_PRIVILEGE(); portRAISE_PRIVILEGE();
} }
@ -79,7 +79,7 @@ BaseType_t xPortRaisePrivilege( void ) /* FREERTOS_SYSTEM_CALL */
void vPortResetPrivilege( BaseType_t xRunningPrivileged ) void vPortResetPrivilege( BaseType_t xRunningPrivileged )
{ {
if( xRunningPrivileged != pdTRUE ) if( xRunningPrivileged == pdFALSE )
{ {
portRESET_PRIVILEGE(); portRESET_PRIVILEGE();
} }

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -703,7 +703,7 @@ static void prvSetupMPU( void )
( portUNPRIVILEGED_FLASH_REGION ); ( portUNPRIVILEGED_FLASH_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -714,7 +714,7 @@ static void prvSetupMPU( void )
( portPRIVILEGED_FLASH_REGION ); ( portPRIVILEGED_FLASH_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -725,7 +725,7 @@ static void prvSetupMPU( void )
( portPRIVILEGED_RAM_REGION ); ( portPRIVILEGED_RAM_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -836,7 +836,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 0 ].ulRegionAttribute = xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | ( portMPU_REGION_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -849,7 +849,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 1 ].ulRegionAttribute = xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
( portMPU_REGION_PRIVILEGED_READ_WRITE ) | ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -877,7 +877,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 0 ].ulRegionAttribute = xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | /* Read and write. */ ( portMPU_REGION_READ_WRITE ) | /* Read and write. */
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | ( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
} }

View file

@ -80,6 +80,10 @@
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL ) #define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL ) #define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
/* Location of the TEX,S,C,B bits in the MPU Region Attribute and Size
* Register (RASR). */
#define portMPU_RASR_TEX_S_C_B_LOCATION ( 16UL )
#define portMPU_RASR_TEX_S_C_B_MASK ( 0x3FUL )
/* MPU settings that can be overriden in FreeRTOSConfig.h. */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */
#ifndef configTOTAL_MPU_REGIONS #ifndef configTOTAL_MPU_REGIONS
@ -87,6 +91,82 @@
#define configTOTAL_MPU_REGIONS ( 8UL ) #define configTOTAL_MPU_REGIONS ( 8UL )
#endif #endif
/*
* The TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits define the
* memory type, and where necessary the cacheable and shareable properties
* of the memory region.
*
* The TEX, C, and B bits together indicate the memory type of the region,
* and:
* - For Normal memory, the cacheable properties of the region.
* - For Device memory, whether the region is shareable.
*
* For Normal memory regions, the S bit indicates whether the region is
* shareable. For Strongly-ordered and Device memory, the S bit is ignored.
*
* See the following two tables for setting TEX, S, C and B bits for
* unprivileged flash, privileged flash and privileged RAM regions.
*
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| TEX | C | B | Memory type | Description or Normal region cacheability | Shareable? |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 0 | Strongly-ordered | Strongly ordered | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 1 | Device | Shared device | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 0 | Normal | Outer and inner write-through; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 1 | Normal | Outer and inner write-back; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 0 | Normal | Outer and inner Non-cacheable | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 0 | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 1 | Normal | Outer and inner write-back; write and read allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 0 | Device | Non-shared device | Not shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 1 | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 011 | X | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 1BB | A | A | Normal | Cached memory, with AA and BB indicating the inner and | Reserved |
| | | | | outer cacheability rules that must be exported on the | |
| | | | | bus. See the table below for the cacheability policy | |
| | | | | encoding. memory, BB=Outer policy, AA=Inner policy. | |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
+-----------------------------------------+----------------------------------------+
| AA or BB subfield of {TEX,C,B} encoding | Cacheability policy |
+-----------------------------------------+----------------------------------------+
| 00 | Non-cacheable |
+-----------------------------------------+----------------------------------------+
| 01 | Write-back, write and read allocate |
+-----------------------------------------+----------------------------------------+
| 10 | Write-through, no write allocate |
+-----------------------------------------+----------------------------------------+
| 11 | Write-back, no write allocate |
+-----------------------------------------+----------------------------------------+
*/
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for flash
* region. */
#ifndef configTEX_S_C_B_FLASH
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_FLASH ( 0x07UL )
#endif
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for RAM
* region. */
#ifndef configTEX_S_C_B_SRAM
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_SRAM ( 0x07UL )
#endif
#define portUNPRIVILEGED_FLASH_REGION ( 0UL ) #define portUNPRIVILEGED_FLASH_REGION ( 0UL )
#define portPRIVILEGED_FLASH_REGION ( 1UL ) #define portPRIVILEGED_FLASH_REGION ( 1UL )
#define portPRIVILEGED_RAM_REGION ( 2UL ) #define portPRIVILEGED_RAM_REGION ( 2UL )

View file

@ -147,6 +147,19 @@
#define portTASK_RETURN_ADDRESS prvTaskExitError #define portTASK_RETURN_ADDRESS prvTaskExitError
#endif #endif
/* Adding the necessary stuff in order to be able to determine from C code wheter or not the IRQs are enabled at the processor level (not interrupt controller level) */
#define GET_CPSR() ({u32 rval = 0U; \
__asm__ __volatile__(\
"mrs %0, cpsr\n"\
: "=r" (rval)\
);\
rval;\
})
#define CPSR_IRQ_ENABLE_MASK 0x80U
#define IS_IRQ_DISABLED() ({unsigned int val = 0; val = (GET_CPSR() & CPSR_IRQ_ENABLE_MASK) ? 1 : 0; val;})
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -468,6 +481,12 @@ void vPortClearInterruptMask( uint32_t ulNewMaskValue )
uint32_t ulPortSetInterruptMask( void ) uint32_t ulPortSetInterruptMask( void )
{ {
uint32_t ulReturn; uint32_t ulReturn;
uint32_t wasIRQDisabled;
/* We keep track of if the IRQ are enabled in the CPU (as opposed to interrupts masked in the interrupt controller, like the intend of this function).
* This is very important because when the CPU is interrupted, among other things, the hardware clears the IRQ Enable bit in the CPSR of the IRQ CPU Mode in which
* we enter. */
wasIRQDisabled = IS_IRQ_DISABLED();
/* Interrupt in the CPU must be turned off while the ICCPMR is being /* Interrupt in the CPU must be turned off while the ICCPMR is being
* updated. */ * updated. */
@ -486,6 +505,17 @@ uint32_t ulPortSetInterruptMask( void )
"isb \n"::: "memory" ); "isb \n"::: "memory" );
} }
/* Just like this function returns a value of wether or not the interrupts where masked in the interrupt controller in order to avoid race condition when
* calling its matching vPortClearInterruptMask function, we needed a 'wasIRQDisabled' variable holding the state of the IRQ Enable bit in the CPSR in order
* to leave that bit in it's original state. Like mentioned above, hardware automatically clear the IRQEnable bit upon trapping into IRQ Mode, so the programmer
* cannot make assumption about it's state. Very rare, but very important race condition is avoided with this when this function is called in an ISR. The race
* condition in question was discovered when integrating tracealyzer code. Inside the function 'void vTaskSwitchContext( void )' in tasks.c, there is a macro 'traceTASK_SWITCHED_IN();'
* which gets replaced by something when using the tracing capabilities. That macro protects some critical section with matching calls to 'ulPortSetInterruptMask'
* and 'vPortClearInterruptMask'. At the time of calling those functions, the interrupt mask is not set in the interrupt controller, thus the only protecting barrier
* against the CPU traping into recursive interrupt was the IRQ Enable bit in the CPSR. By not taking it into acount, the very code that protects the CPU against
* critical section violation just enabled it to happen : A SysTick was waiting to happen, and calling 'portCPU_IRQ_ENABLE' would enable it to occur... Thus triggering a
* switch of context while already performing a switch context. */
if(!wasIRQDisabled)
portCPU_IRQ_ENABLE(); portCPU_IRQ_ENABLE();
return ulReturn; return ulReturn;

View file

@ -63,7 +63,6 @@ extern volatile RTOS_TCB_t *volatile pxCurrentTCB;
* *
* The interrupts will have been disabled during the call to portSAVE_CONTEXT() * The interrupts will have been disabled during the call to portSAVE_CONTEXT()
* so we need not worry about reading/writing to the stack pointer. * so we need not worry about reading/writing to the stack pointer.
*/ */
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
@ -292,7 +291,6 @@ void vPortYieldFromTick(void) __attribute__((naked));
void vPortYieldFromTick(void) void vPortYieldFromTick(void)
{ {
portSAVE_CONTEXT(); portSAVE_CONTEXT();
if (xTaskIncrementTick() != pdFALSE) { if (xTaskIncrementTick() != pdFALSE) {
vTaskSwitchContext(); vTaskSwitchContext();
} }
@ -319,7 +317,6 @@ static void prvSetupTimerInterrupt(void)
* the context is saved at the start of vPortYieldFromTick(). The tick * the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved. * count is incremented after the context is saved.
*/ */
ISR(TICK_INT_vect, ISR_NAKED) ISR(TICK_INT_vect, ISR_NAKED)
{ {
/* Clear tick interrupt flag. */ /* Clear tick interrupt flag. */
@ -329,7 +326,6 @@ ISR(TICK_INT_vect, ISR_NAKED)
asm volatile("reti"); asm volatile("reti");
} }
#else #else
/* /*
@ -337,14 +333,10 @@ ISR(TICK_INT_vect, ISR_NAKED)
* tick count. We don't need to switch context, this can only be done by * tick count. We don't need to switch context, this can only be done by
* manual calls to taskYIELD(); * manual calls to taskYIELD();
*/ */
ISR(TICK_INT_vect) ISR(TICK_INT_vect)
{ {
/* Clear tick interrupt flag. */ /* Clear tick interrupt flag. */
INT_FLAGS = INT_MASK; INT_FLAGS = INT_MASK;
xTaskIncrementTick(); xTaskIncrementTick();
} }
#endif #endif

View file

@ -6,7 +6,8 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define CLR_INT(FLAG_REG, FLAG_MASK) \ #define CLR_INT(FLAG_REG, FLAG_MASK) \
asm volatile( "push r16\n\t" \ asm volatile( \
"push r16\n\t" \
"ldi r16, %1\n\t" \ "ldi r16, %1\n\t" \
"sts %0, r16\n\t" \ "sts %0, r16\n\t" \
"pop r16\n\t" \ "pop r16\n\t" \
@ -26,11 +27,6 @@
TCB0.CTRLA = TCB_ENABLE_bm; \ TCB0.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB0.INTCTRL &= ~TCB_CAPT_bm;\
TCB0.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 1 ) #elif ( configUSE_TIMER_INSTANCE == 1 )
#define TICK_INT_vect TCB1_INT_vect #define TICK_INT_vect TCB1_INT_vect
@ -43,11 +39,6 @@
TCB1.CTRLA = TCB_ENABLE_bm; \ TCB1.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB1.INTCTRL &= ~TCB_CAPT_bm; \
TCB1.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 2 ) #elif ( configUSE_TIMER_INSTANCE == 2 )
#define TICK_INT_vect TCB2_INT_vect #define TICK_INT_vect TCB2_INT_vect
@ -60,11 +51,6 @@
TCB2.CTRLA = TCB_ENABLE_bm; \ TCB2.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB2.INTCTRL &= ~TCB_CAPT_bm; \
TCB2.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 3 ) #elif ( configUSE_TIMER_INSTANCE == 3 )
#define TICK_INT_vect TCB3_INT_vect #define TICK_INT_vect TCB3_INT_vect
@ -77,11 +63,6 @@
TCB3.CTRLA = TCB_ENABLE_bm; \ TCB3.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB3.INTCTRL &= ~TCB_CAPT_bm; \
TCB3.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 4 ) #elif ( configUSE_TIMER_INSTANCE == 4 )
#define TICK_INT_vect TCB4_INT_vect #define TICK_INT_vect TCB4_INT_vect
@ -94,20 +75,14 @@
TCB4.CTRLA = TCB_ENABLE_bm; \ TCB4.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB4.INTCTRL &= ~TCB_CAPT_bm; \
TCB4.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 5 ) #elif ( configUSE_TIMER_INSTANCE == 5 )
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ(x) (32768 * ((1.0 / x)))
#define TICK_INT_vect RTC_CNT_vect #define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS #define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm #define INT_MASK RTC_OVF_bm
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() { \ #define TICK_init() { \
while (RTC.STATUS > 0); \ while (RTC.STATUS > 0); \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
@ -115,11 +90,6 @@
RTC.INTCTRL |= 1 << RTC_OVF_bp; \ RTC.INTCTRL |= 1 << RTC_OVF_bp; \
} }
#define TICK_stop() { \
RTC.CTRLA &= ~(1 << RTC_RTCEN_bp); \
RTC.INTCTRL &= ~(1 << RTC_OVF_bp); \
}
#else #else
#undef TICK_INT_vect #undef TICK_INT_vect
#undef INT_FLAGS #undef INT_FLAGS

View file

@ -64,7 +64,6 @@ typedef uint16_t TickType_t;
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffffffffUL #define portMAX_DELAY (TickType_t)0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */

View file

@ -29,9 +29,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "porthardware.h" #include "porthardware.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"

View file

@ -6,7 +6,8 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define CLR_INT(FLAG_REG, FLAG_MASK) \ #define CLR_INT(FLAG_REG, FLAG_MASK) \
asm volatile( "push r16\n\t" \ asm volatile( \
"push r16\n\t" \
"ldi r16, %1\n\t" \ "ldi r16, %1\n\t" \
"sts %0, r16\n\t" \ "sts %0, r16\n\t" \
"pop r16\n\t" \ "pop r16\n\t" \
@ -26,11 +27,6 @@
TCB0.CTRLA = TCB_ENABLE_bm; \ TCB0.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB0.INTCTRL &= ~TCB_CAPT_bm;\
TCB0.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 1 ) #elif ( configUSE_TIMER_INSTANCE == 1 )
#define TICK_INT_vect TCB1_INT_vect #define TICK_INT_vect TCB1_INT_vect
@ -43,11 +39,6 @@
TCB1.CTRLA = TCB_ENABLE_bm; \ TCB1.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB1.INTCTRL &= ~TCB_CAPT_bm; \
TCB1.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 2 ) #elif ( configUSE_TIMER_INSTANCE == 2 )
#define TICK_INT_vect TCB2_INT_vect #define TICK_INT_vect TCB2_INT_vect
@ -60,11 +51,6 @@
TCB2.CTRLA = TCB_ENABLE_bm; \ TCB2.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB2.INTCTRL &= ~TCB_CAPT_bm; \
TCB2.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 3 ) #elif ( configUSE_TIMER_INSTANCE == 3 )
#define TICK_INT_vect TCB3_INT_vect #define TICK_INT_vect TCB3_INT_vect
@ -77,18 +63,14 @@
TCB3.CTRLA = TCB_ENABLE_bm; \ TCB3.CTRLA = TCB_ENABLE_bm; \
} }
#define TICK_stop() { \
TCB3.INTCTRL &= ~TCB_CAPT_bm; \
TCB3.CTRLA &= ~TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 4 ) #elif ( configUSE_TIMER_INSTANCE == 4 )
#define TICK_INT_vect RTC_CNT_vect #define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS #define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm #define INT_MASK RTC_OVF_bm
#define RTC_PERIOD_HZ(x) (32768 * ( (1.0 / x) ) ) /* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() { \ #define TICK_init() { \
while (RTC.STATUS > 0); \ while (RTC.STATUS > 0); \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
@ -96,16 +78,12 @@
RTC.INTCTRL |= 1 << RTC_OVF_bp; \ RTC.INTCTRL |= 1 << RTC_OVF_bp; \
} }
#define TICK_stop() { \
RTC.CTRLA &= ~(1 << RTC_RTCEN_bp); \
RTC.INTCTRL &= ~(1 << RTC_OVF_bp); \
}
#else #else
#undef TICK_INT_vect #undef TICK_INT_vect
#undef INT_FLAGS #undef INT_FLAGS
#undef INT_MASK #undef INT_MASK
#error Invalid timer setting #undef TICK_init()
#error Invalid timer setting.
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -85,7 +85,6 @@ typedef uint32_t TickType_t;
#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ) #define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ)
#define portBYTE_ALIGNMENT 1 #define portBYTE_ALIGNMENT 1
#define portNOP() asm volatile("nop"); #define portNOP() asm volatile("nop");
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Kernel utilities. */ /* Kernel utilities. */
@ -94,7 +93,6 @@ extern void vPortYield(void) __attribute__((naked));
extern void vPortYieldFromISR(void) __attribute__((naked)); extern void vPortYieldFromISR(void) __attribute__((naked));
#define portYIELD_FROM_ISR() vPortYieldFromISR() #define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
@ -106,4 +104,3 @@ extern void vPortYieldFromISR(void) __attribute__((naked));
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -96,7 +96,6 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* file is weak to allow application writers to change the timer used to * file is weak to allow application writers to change the timer used to
* generate the tick interrupt. * generate the tick interrupt.
*/ */
#pragma weak vPortSetupTimerInterrupt
void vPortSetupTimerInterrupt( void ); void vPortSetupTimerInterrupt( void );
/* /*
@ -242,7 +241,7 @@ void xPortSysTickHandler( void )
* Setup the systick timer to generate the tick interrupts at the required * Setup the systick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
void vPortSetupTimerInterrupt( void ) __weak void vPortSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if ( configUSE_TICKLESS_IDLE == 1 ) #if ( configUSE_TICKLESS_IDLE == 1 )

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -567,7 +567,7 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FU
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -542,7 +542,7 @@ static void prvSetupMPU( void )
( portUNPRIVILEGED_FLASH_REGION ); ( portUNPRIVILEGED_FLASH_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -553,7 +553,7 @@ static void prvSetupMPU( void )
( portPRIVILEGED_FLASH_REGION ); ( portPRIVILEGED_FLASH_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -564,7 +564,7 @@ static void prvSetupMPU( void )
( portPRIVILEGED_RAM_REGION ); ( portPRIVILEGED_RAM_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -633,7 +633,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 0 ].ulRegionAttribute = xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | ( portMPU_REGION_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -646,7 +646,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 1 ].ulRegionAttribute = xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
( portMPU_REGION_PRIVILEGED_READ_WRITE ) | ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -674,7 +674,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 0 ].ulRegionAttribute = xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | /* Read and write. */ ( portMPU_REGION_READ_WRITE ) | /* Read and write. */
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | ( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
} }

View file

@ -83,6 +83,10 @@
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL ) #define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL ) #define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
/* Location of the TEX,S,C,B bits in the MPU Region Attribute and Size
* Register (RASR). */
#define portMPU_RASR_TEX_S_C_B_LOCATION ( 16UL )
#define portMPU_RASR_TEX_S_C_B_MASK ( 0x3FUL )
/* MPU settings that can be overriden in FreeRTOSConfig.h. */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */
#ifndef configTOTAL_MPU_REGIONS #ifndef configTOTAL_MPU_REGIONS
@ -90,6 +94,82 @@
#define configTOTAL_MPU_REGIONS ( 8UL ) #define configTOTAL_MPU_REGIONS ( 8UL )
#endif #endif
/*
* The TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits define the
* memory type, and where necessary the cacheable and shareable properties
* of the memory region.
*
* The TEX, C, and B bits together indicate the memory type of the region,
* and:
* - For Normal memory, the cacheable properties of the region.
* - For Device memory, whether the region is shareable.
*
* For Normal memory regions, the S bit indicates whether the region is
* shareable. For Strongly-ordered and Device memory, the S bit is ignored.
*
* See the following two tables for setting TEX, S, C and B bits for
* unprivileged flash, privileged flash and privileged RAM regions.
*
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| TEX | C | B | Memory type | Description or Normal region cacheability | Shareable? |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 0 | Strongly-ordered | Strongly ordered | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 1 | Device | Shared device | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 0 | Normal | Outer and inner write-through; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 1 | Normal | Outer and inner write-back; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 0 | Normal | Outer and inner Non-cacheable | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 0 | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 1 | Normal | Outer and inner write-back; write and read allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 0 | Device | Non-shared device | Not shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 1 | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 011 | X | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 1BB | A | A | Normal | Cached memory, with AA and BB indicating the inner and | Reserved |
| | | | | outer cacheability rules that must be exported on the | |
| | | | | bus. See the table below for the cacheability policy | |
| | | | | encoding. memory, BB=Outer policy, AA=Inner policy. | |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
+-----------------------------------------+----------------------------------------+
| AA or BB subfield of {TEX,C,B} encoding | Cacheability policy |
+-----------------------------------------+----------------------------------------+
| 00 | Non-cacheable |
+-----------------------------------------+----------------------------------------+
| 01 | Write-back, write and read allocate |
+-----------------------------------------+----------------------------------------+
| 10 | Write-through, no write allocate |
+-----------------------------------------+----------------------------------------+
| 11 | Write-back, no write allocate |
+-----------------------------------------+----------------------------------------+
*/
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for flash
* region. */
#ifndef configTEX_S_C_B_FLASH
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_FLASH ( 0x07UL )
#endif
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for RAM
* region. */
#ifndef configTEX_S_C_B_SRAM
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_SRAM ( 0x07UL )
#endif
#define portUNPRIVILEGED_FLASH_REGION ( 0UL ) #define portUNPRIVILEGED_FLASH_REGION ( 0UL )
#define portPRIVILEGED_FLASH_REGION ( 1UL ) #define portPRIVILEGED_FLASH_REGION ( 1UL )
#define portPRIVILEGED_RAM_REGION ( 2UL ) #define portPRIVILEGED_RAM_REGION ( 2UL )

View file

@ -0,0 +1,293 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#include <stdlib.h>
#include "porthardware.h"
#include "FreeRTOS.h"
#include "task.h"
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the AVR port.
*----------------------------------------------------------*/
/* Start tasks with interrupts enables. */
#define portFLAGS_INT_ENABLED ((StackType_t) 0x80)
/*-----------------------------------------------------------*/
#define portBYTES_USED_BY_RETURN_ADDRESS 2
#define portNO_CRITICAL_NESTING ( ( UBaseType_t ) 0 )
/* Stores the critical section nesting. This must not be initialised to 0.
It will be initialised when a task starts. */
UBaseType_t uxCriticalNesting = 0x50;
/*
* Setup timer to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt(void);
/*
* The IAR compiler does not have full support for inline assembler, so
* these are defined in the portmacro assembler file.
*/
extern void vPortYieldFromTick( void );
extern void vPortStart( void );
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
{
uint16_t usAddress;
StackType_t *pxTopOfHardwareStack;
/* Simulate how the stack would look after a call to vPortYield(). */
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* The IAR compiler requires two stacks per task. First there is the
hardware call stack which uses the AVR stack pointer. Second there is the
software stack (local variables, parameter passing, etc.) which uses the
AVR Y register.
This function places both stacks within the memory block passed in as the
first parameter. The hardware stack is placed at the bottom of the memory
block. A gap is then left for the hardware stack to grow. Next the software
stack is placed. The amount of space between the software and hardware
stacks is defined by configCALL_STACK_SIZE.
The first part of the stack is the hardware stack. Place the start
address of the task on the hardware stack. */
/* Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging. */
//*pxTopOfStack = 0x11;
//pxTopOfStack--;
//*pxTopOfStack = 0x22;
//pxTopOfStack--;
//*pxTopOfStack = 0x33;
//pxTopOfStack--;
/* Remember where the top of the hardware stack is - this is required
below. */
pxTopOfHardwareStack = pxTopOfStack;
usAddress = ( uint16_t ) pxCode;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
/* Leave enough space for the hardware stack before starting the software
stack. The '- 2' is because we have already used two spaces for the
address of the start of the task. */
pxTopOfStack -= ( configCALL_STACK_SIZE - 2 );
/* Next simulate the stack as if after a call to portSAVE_CONTEXT().
portSAVE_CONTEXT places the flags on the stack immediately after r0
to ensure the interrupts get disabled as soon as possible, and so ensuring
the stack use is minimal should a context switch interrupt occur. */
*pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */
pxTopOfStack--;
/* Next place the address of the hardware stack. This is required so
the AVR stack pointer can be restored to point to the hardware stack. */
pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS;
usAddress = ( uint16_t ) pxTopOfHardwareStack;
/* SPL */
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
/* SPH */
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
/* Now the remaining registers. */
*pxTopOfStack = ( StackType_t ) 0x01; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x13; /* R13 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x14; /* R14 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x15; /* R15 */
pxTopOfStack--;
/* Place the parameter on the stack in the expected location. */
usAddress = (uint16_t) pvParameters;
*pxTopOfStack = (StackType_t) (usAddress & (uint16_t) 0x00ff);
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = (StackType_t) (usAddress & (uint16_t) 0x00ff);
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x18; /* R18 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x19; /* R19 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x20; /* R20 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x21; /* R21 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22; /* R22 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x23; /* R23 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x24; /* R24 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x25; /* R25 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x26; /* R26 X */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x27; /* R27 */
pxTopOfStack--;
/* The Y register is not stored as it is used as the software stack and
gets saved into the task control block. */
*pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x031; /* R31 */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING; /* Critical nesting is zero when the task starts. */
/*lint +e950 +e611 +e923 */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler(void)
{
/* Setup the hardware to generate the tick. */
prvSetupTimerInterrupt();
/* Restore the context of the first task that is going to run.
Normally we would just call portRESTORE_CONTEXT() here, but as the IAR
compiler does not fully support inline assembler we have to make a call.*/
vPortStart();
/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler(void)
{
/* vPortEndScheduler is not implemented in this port. */
}
/*-----------------------------------------------------------*/
/*
* Setup timer to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt(void)
{
TICK_init();
}
/*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 1
/*
* Tick ISR for preemptive scheduler. We can use a naked attribute as
* the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved.
*/
__task void TICK_INT(void)
{
vPortYieldFromTick();
asm("reti");
}
#else
/*
* Tick ISR for the cooperative scheduler. All this does is increment the
* tick count. We don't need to switch context, this can only be done by
* manual calls to taskYIELD();
*/
__interrupt void TICK_INT(void)
{
/* Clear tick interrupt flag. */
INT_FLAGS = INT_MASK;
xTaskIncrementTick();
}
#endif
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
uxCriticalNesting--;
if( uxCriticalNesting == portNO_CRITICAL_NESTING )
{
portENABLE_INTERRUPTS();
}
}

View file

@ -0,0 +1,94 @@
#ifndef PORTHARDWARE_H
#define PORTHARDWARE_H
#include <ioavr.h>
#include "FreeRTOSConfig.h"
/*-----------------------------------------------------------*/
#if ( configUSE_TIMER_INSTANCE == 0 )
#define TICK_INT_vect TCB0_INT_vect
#define INT_FLAGS TCB0_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB0.INTCTRL = TCB_CAPT_bm; \
TCB0.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 1 )
#define TICK_INT_vect TCB1_INT_vect
#define INT_FLAGS TCB1_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB1.INTCTRL = TCB_CAPT_bm; \
TCB1.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 2 )
#define TICK_INT_vect TCB2_INT_vect
#define INT_FLAGS TCB2_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB2.INTCTRL = TCB_CAPT_bm; \
TCB2.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 3 )
#define TICK_INT_vect TCB3_INT_vect
#define INT_FLAGS TCB3_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB3.INTCTRL = TCB_CAPT_bm; \
TCB3.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 4 )
#define TICK_INT_vect TCB4_INT_vect
#define INT_FLAGS TCB4_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB4.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB4.INTCTRL = TCB_CAPT_bm; \
TCB4.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 5 )
#define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() { \
while (RTC.STATUS > 0); \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \
RTC.INTCTRL |= 1 << RTC_OVF_bp; \
}
#else
#undef TICK_INT_vect
#undef INT_FLAGS
#undef INT_MASK
#undef TICK_init()
#error Invalid timer setting.
#endif
/*-----------------------------------------------------------*/
#endif /* PORTHARDWARE_H */

View file

@ -0,0 +1,105 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT int
#define portSTACK_TYPE uint8_t
#define portBASE_TYPE char
#define portPOINTER_SIZE_TYPE uint16_t
typedef portSTACK_TYPE StackType_t;
typedef signed char BaseType_t;
typedef unsigned char UBaseType_t;
#if (configUSE_16_BIT_TICKS == 1)
typedef uint16_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm( "cli" )
#define portENABLE_INTERRUPTS() asm( "sei" )
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH (-1)
#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ)
#define portBYTE_ALIGNMENT 1
#define portNOP() asm( "nop" )
/*-----------------------------------------------------------*/
/* Kernel utilities. */
extern void vPortYield(void);
#define portYIELD() vPortYield()
extern void vPortYieldFromISR(void);
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -0,0 +1,254 @@
;/*
; * FreeRTOS Kernel V10.3.1
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
; *
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
; * this software and associated documentation files (the "Software"), to deal in
; * the Software without restriction, including without limitation the rights to
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
; * the Software, and to permit persons to whom the Software is furnished to do so,
; * subject to the following conditions:
; *
; * The above copyright notice and this permission notice shall be included in all
; * copies or substantial portions of the Software.
; *
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
; *
; * http://www.FreeRTOS.org
; * http://aws.amazon.com/freertos
; *
; * 1 tab == 4 spaces!
; */
#include "porthardware.h"
; Declare all extern symbols here - including any ISRs that are referenced in
; the vector table.
; ISR functions
; -------------
EXTERN TICK_INT
; Functions used by scheduler
; ---------------------------
EXTERN vTaskSwitchContext
EXTERN pxCurrentTCB
EXTERN xTaskIncrementTick
EXTERN uxCriticalNesting
; Functions implemented in this file
; ----------------------------------
PUBLIC vPortYield
PUBLIC vPortYieldFromTick
PUBLIC vPortYieldFromISR
PUBLIC vPortStart
; Interrupt vector table.
; -----------------------
;
; For simplicity the RTOS tick interrupt routine uses the __task keyword.
; As the IAR compiler does not permit a function to be declared using both
; __task and __interrupt, the use of __task necessitates that the interrupt
; vector table be setup manually.
;
; To write an ISR, implement the ISR function using the __interrupt keyword
; but do not install the interrupt using the "#pragma vector=ABC" method.
; Instead manually place the name of the ISR in the vector table using an
; ORG and jmp instruction as demonstrated below.
; You will also have to add an EXTERN statement at the top of the file.
ASEG
ORG TICK_INT_vect ; Vector address
jmp TICK_INT ; ISR
RSEG CODE
CLR_INT MACRO FLAG_REG, FLAG_MASK
st -y, r16
ldi r16, FLAG_MASK
sts FLAG_REG, r16
ld r16, y+
ENDM
; Saving and Restoring a Task Context and Task Switching
; ------------------------------------------------------
;
; The IAR compiler does not fully support inline assembler, so saving and
; restoring a task context has to be written in an asm file.
;
; vPortYield() and vPortYieldFromTick() are usually written in C. Doing
; so in this case would required calls to be made to portSAVE_CONTEXT() and
; portRESTORE_CONTEXT(). This is dis-advantageous as the context switch
; function would require two extra jump and return instructions over the
; WinAVR equivalent.
;
; To avoid this I have opted to implement both vPortYield() and
; vPortYieldFromTick() in this assembly file. For convenience
; portSAVE_CONTEXT and portRESTORE_CONTEXT are implemented as macros.
portSAVE_CONTEXT MACRO
st -y, r0 ; First save the r0 register - we need to use this.
in r0, SREG ; Obtain the SREG value so we can disable interrupts...
cli ; ... as soon as possible.
st -y, r0 ; Store the SREG as it was before we disabled interrupts.
in r0, RAMPZ
st -y, r0
in r0, SPL ; Next store the hardware stack pointer. The IAR...
st -y, r0 ; ... compiler uses the hardware stack as a call stack ...
in r0, SPH ; ... only.
st -y, r0
st -y, r1 ; Now store the rest of the registers. Dont store the ...
st -y, r2 ; ... the Y register here as it is used as the software
st -y, r3 ; stack pointer and will get saved into the TCB.
st -y, r4
st -y, r5
st -y, r6
st -y, r7
st -y, r8
st -y, r9
st -y, r10
st -y, r11
st -y, r12
st -y, r13
st -y, r14
st -y, r15
st -y, r16
st -y, r17
st -y, r18
st -y, r19
st -y, r20
st -y, r21
st -y, r22
st -y, r23
st -y, r24
st -y, r25
st -y, r26
st -y, r27
st -y, r30
st -y, r31
lds r0, uxCriticalNesting
st -y, r0 ; Store the critical nesting counter.
lds r26, pxCurrentTCB ; Finally save the software stack pointer (Y ...
lds r27, pxCurrentTCB + 1 ; ... register) into the TCB.
st x+, r28
st x+, r29
ENDM
portRESTORE_CONTEXT MACRO
lds r26, pxCurrentTCB
lds r27, pxCurrentTCB + 1 ; Restore the software stack pointer from ...
ld r28, x+ ; the TCB into the software stack pointer (...
ld r29, x+ ; ... the Y register).
ld r0, y+
sts uxCriticalNesting, r0
ld r31, y+ ; Restore the registers down to R0. The Y
ld r30, y+ ; register is missing from this list as it
ld r27, y+ ; has already been restored.
ld r26, y+
ld r25, y+
ld r24, y+
ld r23, y+
ld r22, y+
ld r21, y+
ld r20, y+
ld r19, y+
ld r18, y+
ld r17, y+
ld r16, y+
ld r15, y+
ld r14, y+
ld r13, y+
ld r12, y+
ld r11, y+
ld r10, y+
ld r9, y+
ld r8, y+
ld r7, y+
ld r6, y+
ld r5, y+
ld r4, y+
ld r3, y+
ld r2, y+
ld r1, y+
ld r0, y+ ; The next thing on the stack is the ...
out SPH, r0 ; ... hardware stack pointer.
ld r0, y+
out SPL, r0
ld r0, y+
out RAMPZ, r0
ld r0, y+ ; Next there is the SREG register.
out SREG, r0
ld r0, y+ ; Finally we have finished with r0, so restore r0.
ENDM
; vPortYield(), vPortYieldFromTick() and vPortYieldFromISR()
; -------------------------------------
;
; Manual and preemptive context switch functions respectively.
; The IAR compiler does not fully support inline assembler,
; so these are implemented here rather than the more usually
; place of within port.c.
vPortYield:
portSAVE_CONTEXT ; Save the context of the current task.
call vTaskSwitchContext ; Call the scheduler.
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
ret ; ... scheduler decided should run.
vPortYieldFromTick:
CLR_INT INT_FLAGS, INT_MASK ; Clear tick interrupt flag
portSAVE_CONTEXT ; Save the context of the current task.
call xTaskIncrementTick ; Call the timer tick function.
tst r16
breq SkipTaskSwitch
call vTaskSwitchContext ; Call the scheduler.
SkipTaskSwitch:
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
reti ; ... scheduler decided should run.
vPortYieldFromISR:
portSAVE_CONTEXT ; Save the context of the current task.
call vTaskSwitchContext ; Call the scheduler.
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
reti ; ... scheduler decided should run.
; vPortStart()
; ------------
;
; Again due to the lack of inline assembler, this is required
; to get access to the portRESTORE_CONTEXT macro.
vPortStart:
portRESTORE_CONTEXT
ret
; Just a filler for unused interrupt vectors.
vNoISR:
reti
END

View file

@ -0,0 +1,291 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#include <stdlib.h>
#include "porthardware.h"
#include "FreeRTOS.h"
#include "task.h"
/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the AVR port.
*----------------------------------------------------------*/
/* Start tasks with interrupts enables. */
#define portFLAGS_INT_ENABLED ((StackType_t) 0x80)
/*-----------------------------------------------------------*/
#define portBYTES_USED_BY_RETURN_ADDRESS 2
#define portNO_CRITICAL_NESTING ( ( UBaseType_t ) 0 )
/* Stores the critical section nesting. This must not be initialised to 0.
It will be initialised when a task starts. */
UBaseType_t uxCriticalNesting = 0x50;
/*
* Setup timer to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt(void);
/*
* The IAR compiler does not have full support for inline assembler, so
* these are defined in the portmacro assembler file.
*/
extern void vPortYieldFromTick( void );
extern void vPortStart( void );
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
{
uint16_t usAddress;
StackType_t *pxTopOfHardwareStack;
/* Simulate how the stack would look after a call to vPortYield(). */
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* The IAR compiler requires two stacks per task. First there is the
hardware call stack which uses the AVR stack pointer. Second there is the
software stack (local variables, parameter passing, etc.) which uses the
AVR Y register.
This function places both stacks within the memory block passed in as the
first parameter. The hardware stack is placed at the bottom of the memory
block. A gap is then left for the hardware stack to grow. Next the software
stack is placed. The amount of space between the software and hardware
stacks is defined by configCALL_STACK_SIZE.
The first part of the stack is the hardware stack. Place the start
address of the task on the hardware stack. */
/* Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging. */
//*pxTopOfStack = 0x11;
//pxTopOfStack--;
//*pxTopOfStack = 0x22;
//pxTopOfStack--;
//*pxTopOfStack = 0x33;
//pxTopOfStack--;
/* Remember where the top of the hardware stack is - this is required
below. */
pxTopOfHardwareStack = pxTopOfStack;
usAddress = ( uint16_t ) pxCode;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
/* Leave enough space for the hardware stack before starting the software
stack. The '- 2' is because we have already used two spaces for the
address of the start of the task. */
pxTopOfStack -= ( configCALL_STACK_SIZE - 2 );
/* Next simulate the stack as if after a call to portSAVE_CONTEXT().
portSAVE_CONTEXT places the flags on the stack immediately after r0
to ensure the interrupts get disabled as soon as possible, and so ensuring
the stack use is minimal should a context switch interrupt occur. */
*pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED;
pxTopOfStack--;
/* Next place the address of the hardware stack. This is required so
the AVR stack pointer can be restored to point to the hardware stack. */
pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS;
usAddress = ( uint16_t ) pxTopOfHardwareStack;
/* SPL */
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
/* SPH */
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
/* Now the remaining registers. */
*pxTopOfStack = ( StackType_t ) 0x01; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x13; /* R13 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x14; /* R14 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x15; /* R15 */
pxTopOfStack--;
/* Place the parameter on the stack in the expected location. */
usAddress = (uint16_t) pvParameters;
*pxTopOfStack = (StackType_t) (usAddress & (uint16_t) 0x00ff);
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = (StackType_t) (usAddress & (uint16_t) 0x00ff);
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x18; /* R18 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x19; /* R19 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x20; /* R20 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x21; /* R21 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22; /* R22 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x23; /* R23 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x24; /* R24 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x25; /* R25 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x26; /* R26 X */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x27; /* R27 */
pxTopOfStack--;
/* The Y register is not stored as it is used as the software stack and
gets saved into the task control block. */
*pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x031; /* R31 */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING; /* Critical nesting is zero when the task starts. */
/*lint +e950 +e611 +e923 */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler(void)
{
/* Setup the hardware to generate the tick. */
prvSetupTimerInterrupt();
/* Restore the context of the first task that is going to run.
Normally we would just call portRESTORE_CONTEXT() here, but as the IAR
compiler does not fully support inline assembler we have to make a call.*/
vPortStart();
/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler(void)
{
/* vPortEndScheduler is not implemented in this port. */
}
/*-----------------------------------------------------------*/
/*
* Setup timer to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt(void)
{
TICK_init();
}
/*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 1
/*
* Tick ISR for preemptive scheduler. We can use a naked attribute as
* the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved.
*/
__task void TICK_INT(void)
{
vPortYieldFromTick();
asm("reti");
}
#else
/*
* Tick ISR for the cooperative scheduler. All this does is increment the
* tick count. We don't need to switch context, this can only be done by
* manual calls to taskYIELD();
*/
__interrupt void TICK_INT(void)
{
/* Clear tick interrupt flag. */
INT_FLAGS = INT_MASK;
xTaskIncrementTick();
}
#endif
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
uxCriticalNesting--;
if( uxCriticalNesting == portNO_CRITICAL_NESTING )
{
portENABLE_INTERRUPTS();
}
}

View file

@ -0,0 +1,82 @@
#ifndef PORTHARDWARE_H
#define PORTHARDWARE_H
#include <ioavr.h>
#include "FreeRTOSConfig.h"
/*-----------------------------------------------------------*/
#if ( configUSE_TIMER_INSTANCE == 0 )
#define TICK_INT_vect TCB0_INT_vect
#define INT_FLAGS TCB0_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB0.INTCTRL = TCB_CAPT_bm; \
TCB0.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 1 )
#define TICK_INT_vect TCB1_INT_vect
#define INT_FLAGS TCB1_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB1.INTCTRL = TCB_CAPT_bm; \
TCB1.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 2 )
#define TICK_INT_vect TCB2_INT_vect
#define INT_FLAGS TCB2_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB2.INTCTRL = TCB_CAPT_bm; \
TCB2.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 3 )
#define TICK_INT_vect TCB3_INT_vect
#define INT_FLAGS TCB3_INTFLAGS
#define INT_MASK TCB_CAPT_bm
#define TICK_init() { \
TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \
TCB3.INTCTRL = TCB_CAPT_bm; \
TCB3.CTRLA = TCB_ENABLE_bm; \
}
#elif ( configUSE_TIMER_INSTANCE == 4 )
#define TICK_INT_vect RTC_CNT_vect
#define INT_FLAGS RTC_INTFLAGS
#define INT_MASK RTC_OVF_bm
/* Hertz to period for RTC setup */
#define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) )
#define TICK_init() { \
while (RTC.STATUS > 0); \
RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \
RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \
RTC.INTCTRL |= 1 << RTC_OVF_bp; \
}
#else
#undef TICK_INT_vect
#undef INT_FLAGS
#undef INT_MASK
#undef TICK_init()
#error Invalid timer setting.
#endif
/*-----------------------------------------------------------*/
#endif /* PORTHARDWARE_H */

View file

@ -0,0 +1,105 @@
/*
* FreeRTOS Kernel V10.0.0
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. If you wish to use our Amazon
* FreeRTOS name, please do so in a fair use way that does not cause confusion.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
#ifdef __cplusplus
extern "C" {
#endif
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT int
#define portSTACK_TYPE uint8_t
#define portBASE_TYPE char
#define portPOINTER_SIZE_TYPE uint16_t
typedef portSTACK_TYPE StackType_t;
typedef signed char BaseType_t;
typedef unsigned char UBaseType_t;
#if (configUSE_16_BIT_TICKS == 1)
typedef uint16_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffff
#else
typedef uint32_t TickType_t;
#define portMAX_DELAY (TickType_t)0xffffffffUL
#endif
/*-----------------------------------------------------------*/
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm( "cli" )
#define portENABLE_INTERRUPTS() asm( "sei" )
/*-----------------------------------------------------------*/
/* Architecture specifics. */
#define portSTACK_GROWTH (-1)
#define portTICK_PERIOD_MS ((TickType_t)1000 / configTICK_RATE_HZ)
#define portBYTE_ALIGNMENT 1
#define portNOP() asm( "nop" )
/*-----------------------------------------------------------*/
/* Kernel utilities. */
extern void vPortYield(void);
#define portYIELD() vPortYield()
extern void vPortYieldFromISR(void);
#define portYIELD_FROM_ISR() vPortYieldFromISR()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
#ifdef __cplusplus
}
#endif
#endif /* PORTMACRO_H */

View file

@ -0,0 +1,248 @@
;/*
; * FreeRTOS Kernel V10.3.1
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
; *
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
; * this software and associated documentation files (the "Software"), to deal in
; * the Software without restriction, including without limitation the rights to
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
; * the Software, and to permit persons to whom the Software is furnished to do so,
; * subject to the following conditions:
; *
; * The above copyright notice and this permission notice shall be included in all
; * copies or substantial portions of the Software.
; *
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
; *
; * http://www.FreeRTOS.org
; * http://aws.amazon.com/freertos
; *
; * 1 tab == 4 spaces!
; */
#include "porthardware.h"
; Declare all extern symbols here - including any ISRs that are referenced in
; the vector table.
; ISR functions
; -------------
EXTERN TICK_INT
; Functions used by scheduler
; ---------------------------
EXTERN vTaskSwitchContext
EXTERN pxCurrentTCB
EXTERN xTaskIncrementTick
EXTERN uxCriticalNesting
; Functions implemented in this file
; ----------------------------------
PUBLIC vPortYield
PUBLIC vPortYieldFromTick
PUBLIC vPortYieldFromISR
PUBLIC vPortStart
; Interrupt vector table.
; -----------------------
;
; For simplicity the RTOS tick interrupt routine uses the __task keyword.
; As the IAR compiler does not permit a function to be declared using both
; __task and __interrupt, the use of __task necessitates that the interrupt
; vector table be setup manually.
;
; To write an ISR, implement the ISR function using the __interrupt keyword
; but do not install the interrupt using the "#pragma vector=ABC" method.
; Instead manually place the name of the ISR in the vector table using an
; ORG and jmp instruction as demonstrated below.
; You will also have to add an EXTERN statement at the top of the file.
ASEG
ORG TICK_INT_vect ; Vector address
jmp TICK_INT ; ISR
RSEG CODE
CLR_INT MACRO FLAG_REG, FLAG_MASK
st -y, r16
ldi r16, FLAG_MASK
sts FLAG_REG, r16
ld r16, y+
ENDM
; Saving and Restoring a Task Context and Task Switching
; ------------------------------------------------------
;
; The IAR compiler does not fully support inline assembler, so saving and
; restoring a task context has to be written in an asm file.
;
; vPortYield() and vPortYieldFromTick() are usually written in C. Doing
; so in this case would required calls to be made to portSAVE_CONTEXT() and
; portRESTORE_CONTEXT(). This is dis-advantageous as the context switch
; function would require two extra jump and return instructions over the
; WinAVR equivalent.
;
; To avoid this I have opted to implement both vPortYield() and
; vPortYieldFromTick() in this assembly file. For convenience
; portSAVE_CONTEXT and portRESTORE_CONTEXT are implemented as macros.
portSAVE_CONTEXT MACRO
st -y, r0 ; First save the r0 register - we need to use this.
in r0, SREG ; Obtain the SREG value so we can disable interrupts...
cli ; ... as soon as possible.
st -y, r0 ; Store the SREG as it was before we disabled interrupts.
in r0, SPL ; Next store the hardware stack pointer. The IAR...
st -y, r0 ; ... compiler uses the hardware stack as a call stack ...
in r0, SPH ; ... only.
st -y, r0
st -y, r1 ; Now store the rest of the registers. Dont store the ...
st -y, r2 ; ... the Y register here as it is used as the software
st -y, r3 ; stack pointer and will get saved into the TCB.
st -y, r4
st -y, r5
st -y, r6
st -y, r7
st -y, r8
st -y, r9
st -y, r10
st -y, r11
st -y, r12
st -y, r13
st -y, r14
st -y, r15
st -y, r16
st -y, r17
st -y, r18
st -y, r19
st -y, r20
st -y, r21
st -y, r22
st -y, r23
st -y, r24
st -y, r25
st -y, r26
st -y, r27
st -y, r30
st -y, r31
lds r0, uxCriticalNesting
st -y, r0 ; Store the critical nesting counter.
lds r26, pxCurrentTCB ; Finally save the software stack pointer (Y ...
lds r27, pxCurrentTCB + 1 ; ... register) into the TCB.
st x+, r28
st x+, r29
ENDM
portRESTORE_CONTEXT MACRO
lds r26, pxCurrentTCB
lds r27, pxCurrentTCB + 1 ; Restore the software stack pointer from ...
ld r28, x+ ; the TCB into the software stack pointer (...
ld r29, x+ ; ... the Y register).
ld r0, y+
sts uxCriticalNesting, r0
ld r31, y+ ; Restore the registers down to R0. The Y
ld r30, y+ ; register is missing from this list as it
ld r27, y+ ; has already been restored.
ld r26, y+
ld r25, y+
ld r24, y+
ld r23, y+
ld r22, y+
ld r21, y+
ld r20, y+
ld r19, y+
ld r18, y+
ld r17, y+
ld r16, y+
ld r15, y+
ld r14, y+
ld r13, y+
ld r12, y+
ld r11, y+
ld r10, y+
ld r9, y+
ld r8, y+
ld r7, y+
ld r6, y+
ld r5, y+
ld r4, y+
ld r3, y+
ld r2, y+
ld r1, y+
ld r0, y+ ; The next thing on the stack is the ...
out SPH, r0 ; ... hardware stack pointer.
ld r0, y+
out SPL, r0
ld r0, y+ ; Next there is the SREG register.
out SREG, r0
ld r0, y+ ; Finally we have finished with r0, so restore r0.
ENDM
; vPortYield(), vPortYieldFromTick() and vPortYieldFromISR()
; -------------------------------------
;
; Manual and preemptive context switch functions respectively.
; The IAR compiler does not fully support inline assembler,
; so these are implemented here rather than the more usually
; place of within port.c.
vPortYield:
portSAVE_CONTEXT ; Save the context of the current task.
call vTaskSwitchContext ; Call the scheduler.
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
ret ; ... scheduler decided should run.
vPortYieldFromTick:
CLR_INT INT_FLAGS, INT_MASK ; Clear tick interrupt flag
portSAVE_CONTEXT ; Save the context of the current task.
call xTaskIncrementTick ; Call the timer tick function.
tst r16
breq SkipTaskSwitch
call vTaskSwitchContext ; Call the scheduler.
SkipTaskSwitch:
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
reti ; ... scheduler decided should run.
vPortYieldFromISR:
portSAVE_CONTEXT ; Save the context of the current task.
call vTaskSwitchContext ; Call the scheduler.
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
reti ; ... scheduler decided should run.
; vPortStart()
; ------------
;
; Again due to the lack of inline assembler, this is required
; to get access to the portRESTORE_CONTEXT macro.
vPortStart:
portRESTORE_CONTEXT
ret
; Just a filler for unused interrupt vectors.
vNoISR:
reti
END

View file

@ -690,7 +690,7 @@ static void prvSetupMPU( void )
( portUNPRIVILEGED_FLASH_REGION ); ( portUNPRIVILEGED_FLASH_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -701,7 +701,7 @@ static void prvSetupMPU( void )
( portPRIVILEGED_FLASH_REGION ); ( portPRIVILEGED_FLASH_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -712,7 +712,7 @@ static void prvSetupMPU( void )
( portPRIVILEGED_RAM_REGION ); ( portPRIVILEGED_RAM_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -807,7 +807,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 0 ].ulRegionAttribute = xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | ( portMPU_REGION_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -820,7 +820,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 1 ].ulRegionAttribute = xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
( portMPU_REGION_PRIVILEGED_READ_WRITE ) | ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
@ -848,7 +848,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
xMPUSettings->xRegion[ 0 ].ulRegionAttribute = xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | /* Read and write. */ ( portMPU_REGION_READ_WRITE ) | /* Read and write. */
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | ( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) | ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( portMPU_REGION_ENABLE ); ( portMPU_REGION_ENABLE );
} }

View file

@ -80,6 +80,10 @@
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL ) #define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL ) #define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL ) #define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
/* Location of the TEX,S,C,B bits in the MPU Region Attribute and Size
* Register (RASR). */
#define portMPU_RASR_TEX_S_C_B_LOCATION ( 16UL )
#define portMPU_RASR_TEX_S_C_B_MASK ( 0x3FUL )
/* MPU settings that can be overriden in FreeRTOSConfig.h. */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */
#ifndef configTOTAL_MPU_REGIONS #ifndef configTOTAL_MPU_REGIONS
@ -87,6 +91,82 @@
#define configTOTAL_MPU_REGIONS ( 8UL ) #define configTOTAL_MPU_REGIONS ( 8UL )
#endif #endif
/*
* The TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits define the
* memory type, and where necessary the cacheable and shareable properties
* of the memory region.
*
* The TEX, C, and B bits together indicate the memory type of the region,
* and:
* - For Normal memory, the cacheable properties of the region.
* - For Device memory, whether the region is shareable.
*
* For Normal memory regions, the S bit indicates whether the region is
* shareable. For Strongly-ordered and Device memory, the S bit is ignored.
*
* See the following two tables for setting TEX, S, C and B bits for
* unprivileged flash, privileged flash and privileged RAM regions.
*
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| TEX | C | B | Memory type | Description or Normal region cacheability | Shareable? |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 0 | Strongly-ordered | Strongly ordered | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 0 | 1 | Device | Shared device | Shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 0 | Normal | Outer and inner write-through; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 000 | 1 | 1 | Normal | Outer and inner write-back; no write allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 0 | Normal | Outer and inner Non-cacheable | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 0 | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 001 | 1 | 1 | Normal | Outer and inner write-back; write and read allocate | S bit |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 0 | Device | Non-shared device | Not shareable |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 0 | 1 | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 010 | 1 | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 011 | X | X | Reserved | Reserved | Reserved |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
| 1BB | A | A | Normal | Cached memory, with AA and BB indicating the inner and | Reserved |
| | | | | outer cacheability rules that must be exported on the | |
| | | | | bus. See the table below for the cacheability policy | |
| | | | | encoding. memory, BB=Outer policy, AA=Inner policy. | |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
+-----------------------------------------+----------------------------------------+
| AA or BB subfield of {TEX,C,B} encoding | Cacheability policy |
+-----------------------------------------+----------------------------------------+
| 00 | Non-cacheable |
+-----------------------------------------+----------------------------------------+
| 01 | Write-back, write and read allocate |
+-----------------------------------------+----------------------------------------+
| 10 | Write-through, no write allocate |
+-----------------------------------------+----------------------------------------+
| 11 | Write-back, no write allocate |
+-----------------------------------------+----------------------------------------+
*/
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for Flash
* region. */
#ifndef configTEX_S_C_B_FLASH
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_FLASH ( 0x07UL )
#endif
/* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for SRAM
* region. */
#ifndef configTEX_S_C_B_SRAM
/* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */
#define configTEX_S_C_B_SRAM ( 0x07UL )
#endif
#define portUNPRIVILEGED_FLASH_REGION ( 0UL ) #define portUNPRIVILEGED_FLASH_REGION ( 0UL )
#define portPRIVILEGED_FLASH_REGION ( 1UL ) #define portPRIVILEGED_FLASH_REGION ( 1UL )
#define portPRIVILEGED_RAM_REGION ( 2UL ) #define portPRIVILEGED_RAM_REGION ( 2UL )

View file

@ -305,12 +305,32 @@
uint32_t compare, uint32_t compare,
uint32_t * set ) uint32_t * set )
{ {
#if ( XCHAL_HAVE_S32C1I > 0 )
__asm__ __volatile__ ( __asm__ __volatile__ (
"WSR %2,SCOMPARE1 \n" "WSR %2,SCOMPARE1 \n"
"S32C1I %0, %1, 0 \n" "S32C1I %0, %1, 0 \n"
: "=r" ( *set ) : "=r" ( *set )
: "r" ( addr ), "r" ( compare ), "0" ( *set ) : "r" ( addr ), "r" ( compare ), "0" ( *set )
); );
#else
/* No S32C1I, so do this by disabling and re-enabling interrupts (slower) */
uint32_t intlevel, old_value;
__asm__ __volatile__ ( "rsil %0, " XTSTR( XCHAL_EXCM_LEVEL ) "\n"
: "=r" ( intlevel ) );
old_value = *addr;
if( old_value == compare )
{
*addr = *set;
}
__asm__ __volatile__ ( "memw \n"
"wsr %0, ps\n"
: : "r" ( intlevel ) );
*set = old_value;
#endif /* if ( XCHAL_HAVE_S32C1I > 0 ) */
} }
void uxPortCompareSetExtram( volatile uint32_t * addr, void uxPortCompareSetExtram( volatile uint32_t * addr,
@ -407,13 +427,6 @@
#define xPortGetFreeHeapSize esp_get_free_heap_size #define xPortGetFreeHeapSize esp_get_free_heap_size
#define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size #define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size
/*
* Send an interrupt to another core in order to make the task running
* on it yield for a higher-priority task.
*/
void vPortYieldOtherCore( BaseType_t coreid ) PRIVILEGED_FUNCTION;
/* /*
* Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack

View file

@ -96,17 +96,23 @@
#include "xtensa_rtos.h" #include "xtensa_rtos.h"
#include "rom/ets_sys.h" #if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#endif
#include "soc/cpu.h" #include "soc/cpu.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
#include "esp_panic.h" #include "esp_private/panic_reason.h"
#include "esp_debug_helpers.h"
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "esp_crosscore_int.h" #include "esp_private/crosscore_int.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_log.h"
/* Defined in portasm.h */ /* Defined in portasm.h */
extern void _frxt_tick_timer_init( void ); extern void _frxt_tick_timer_init( void );
@ -132,6 +138,19 @@ unsigned port_interruptNesting[ portNUM_PROCESSORS ] = { 0 }; /* Interrupt nest
/* User exception dispatcher when exiting */ /* User exception dispatcher when exiting */
void _xt_user_exit( void ); void _xt_user_exit( void );
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
/* Wrapper to allow task functions to return (increases stack overhead by 16 bytes) */
static void vPortTaskWrapper( TaskFunction_t pxCode,
void * pvParameters )
{
pxCode( pvParameters );
/*FreeRTOS tasks should not return. Log the task name and abort. */
char * pcTaskName = pcTaskGetTaskName( NULL );
ESP_LOGE( "FreeRTOS", "FreeRTOS Task \"%s\" should not return, Aborting now!", pcTaskName );
abort();
}
#endif /* if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER */
/* /*
* Stack initialization * Stack initialization
*/ */
@ -165,7 +184,11 @@ void _xt_user_exit( void );
frame = ( XtExcFrame * ) sp; frame = ( XtExcFrame * ) sp;
/* Explicitly initialize certain saved registers */ /* Explicitly initialize certain saved registers */
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
frame->pc = ( UBaseType_t ) vPortTaskWrapper; /* task wrapper */
#else
frame->pc = ( UBaseType_t ) pxCode; /* task entrypoint */ frame->pc = ( UBaseType_t ) pxCode; /* task entrypoint */
#endif
frame->a0 = 0; /* to terminate GDB backtrace */ frame->a0 = 0; /* to terminate GDB backtrace */
frame->a1 = ( UBaseType_t ) sp + XT_STK_FRMSZ; /* physical top of stack frame */ frame->a1 = ( UBaseType_t ) sp + XT_STK_FRMSZ; /* physical top of stack frame */
frame->exit = ( UBaseType_t ) _xt_user_exit; /* user exception exit dispatcher */ frame->exit = ( UBaseType_t ) _xt_user_exit; /* user exception exit dispatcher */
@ -173,13 +196,23 @@ void _xt_user_exit( void );
/* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */ /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
/* Also set entry point argument parameter. */ /* Also set entry point argument parameter. */
#ifdef __XTENSA_CALL0_ABI__ #ifdef __XTENSA_CALL0_ABI__
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
frame->a2 = ( UBaseType_t ) pxCode;
frame->a3 = ( UBaseType_t ) pvParameters;
#else
frame->a2 = ( UBaseType_t ) pvParameters; frame->a2 = ( UBaseType_t ) pvParameters;
#endif
frame->ps = PS_UM | PS_EXCM; frame->ps = PS_UM | PS_EXCM;
#else #else
/* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */ /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
frame->a6 = ( UBaseType_t ) pxCode;
frame->a7 = ( UBaseType_t ) pvParameters;
#else
frame->a6 = ( UBaseType_t ) pvParameters; frame->a6 = ( UBaseType_t ) pvParameters;
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC( 1 );
#endif #endif
frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC( 1 );
#endif /* ifdef __XTENSA_CALL0_ABI__ */
#ifdef XT_USE_SWPRI #ifdef XT_USE_SWPRI
/* Set the initial virtual priority mask value to all 1's. */ /* Set the initial virtual priority mask value to all 1's. */

View file

@ -138,8 +138,24 @@ _frxt_int_enter:
mull a2, a4, a2 mull a2, a4, a2
add a1, a1, a2 /* for current proc */ add a1, a1, a2 /* for current proc */
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
#if XCHAL_CP_NUM > 0
rsr a3, CPENABLE /* Restore thread scope CPENABLE */
addi sp, sp,-4 /* ISR will manage FPU coprocessor by forcing */
s32i a3, a1, 0 /* its trigger */
#endif
#endif
.Lnested: .Lnested:
1: 1:
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
#if XCHAL_CP_NUM > 0
movi a3, 0 /* whilst ISRs pending keep CPENABLE exception active */
wsr a3, CPENABLE
rsync
#endif
#endif
mov a0, a12 /* restore return addr and return */ mov a0, a12 /* restore return addr and return */
ret ret
@ -176,6 +192,15 @@ _frxt_int_exit:
s32i a2, a3, 0 /* save nesting count */ s32i a2, a3, 0 /* save nesting count */
bnez a2, .Lnesting /* !=0 after decr so still nested */ bnez a2, .Lnesting /* !=0 after decr so still nested */
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
#if XCHAL_CP_NUM > 0
l32i a3, sp, 0 /* Grab last CPENABLE before leave ISR */
addi sp, sp, 4
wsr a3, CPENABLE
rsync /* ensure CPENABLE was modified */
#endif
#endif
movi a2, pxCurrentTCB movi a2, pxCurrentTCB
addx4 a2, a4, a2 addx4 a2, a4, a2
l32i a2, a2, 0 /* a2 = current TCB */ l32i a2, a2, 0 /* a2 = current TCB */
@ -642,7 +667,6 @@ _frxt_task_coproc_state:
addx4 a15, a3, a15 addx4 a15, a3, a15
l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */ l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */
beqz a15, 2f beqz a15, 2f
l32i a15, a15, CP_TOPOFSTACK_OFFS l32i a15, a15, CP_TOPOFSTACK_OFFS
ret ret

View file

@ -34,7 +34,11 @@
#endif #endif
#include "xtensa_rtos.h" #include "xtensa_rtos.h"
#include "esp_clk.h" #if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#endif
#ifdef XT_RTOS_TIMER_INT #ifdef XT_RTOS_TIMER_INT

View file

@ -34,7 +34,11 @@
#include "freertos/xtensa_api.h" #include "freertos/xtensa_api.h"
#include "freertos/portable.h" #include "freertos/portable.h"
#include "rom/ets_sys.h" #if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#endif
#if XCHAL_HAVE_EXCEPTIONS #if XCHAL_HAVE_EXCEPTIONS

View file

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
#include "xtensa_rtos.h" #include "xtensa_rtos.h"
#include "esp_panic.h" #include "esp_private/panic_reason.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "soc/soc.h" #include "soc/soc.h"

View file

@ -91,10 +91,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************************/ *******************************************************************************/
#include "xtensa_rtos.h" #include "xtensa_rtos.h"
#include "esp_panic.h" #include "esp_private/panic_reason.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "soc/soc.h" #include "soc/soc.h"
#include "soc/dport_reg.h"
/* /*
Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used. Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
@ -103,7 +102,25 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3 #define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3
.extern pxCurrentTCB .extern pxCurrentTCB
/* Enable stack backtrace across exception/interrupt - see below */ /*
--------------------------------------------------------------------------------
In order for backtracing to be able to trace from the pre-exception stack
across to the exception stack (including nested interrupts), we need to create
a pseudo base-save area to make it appear like the exception dispatcher was
triggered by a CALL4 from the pre-exception code. In reality, the exception
dispatcher uses the same window as pre-exception code, and only CALL0s are
used within the exception dispatcher.
To create the pseudo base-save area, we need to store a copy of the pre-exception's
base save area (a0 to a4) below the exception dispatcher's SP. EXCSAVE_x will
be used to store a copy of the SP that points to the interrupted code's exception
frame just in case the exception dispatcher's SP does not point to the exception
frame (which is the case when switching from task to interrupt stack).
Clearing the pseudo base-save area is uncessary as the interrupt dispatcher
will restore the current SP to that of the pre-exception SP.
--------------------------------------------------------------------------------
*/
#ifdef CONFIG_FREERTOS_INTERRUPT_BACKTRACE #ifdef CONFIG_FREERTOS_INTERRUPT_BACKTRACE
#define XT_DEBUG_BACKTRACE 1 #define XT_DEBUG_BACKTRACE 1
#endif #endif
@ -202,9 +219,22 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/* This bit of code provides a nice debug backtrace in the debugger. /* This bit of code provides a nice debug backtrace in the debugger.
It does take a few more instructions, so undef XT_DEBUG_BACKTRACE It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
if you want to save the cycles. if you want to save the cycles.
At this point, the exception frame should have been allocated and filled,
and current sp points to the interrupt stack (for non-nested interrupt)
or below the allocated exception frame (for nested interrupts). Copy the
pre-exception's base save area below the current SP.
*/ */
#ifdef XT_DEBUG_BACKTRACE #ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__ #ifndef __XTENSA_CALL0_ABI__
rsr a0, EXCSAVE_1 + \level - 1 /* Get exception frame pointer stored in EXCSAVE_x */
l32i a3, a0, XT_STK_A0 /* Copy pre-exception a0 (return address) */
s32e a3, a1, -16
l32i a3, a0, XT_STK_A1 /* Copy pre-exception a1 (stack pointer) */
s32e a3, a1, -12
/* Backtracing only needs a0 and a1, no need to create full base save area.
Also need to change current frame's return address to point to pre-exception's
last run instruction.
*/
rsr a0, EPC_1 + \level - 1 /* return address */ rsr a0, EPC_1 + \level - 1 /* return address */
movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */ movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */
or a0, a0, a4 /* set top 2 bits */ or a0, a0, a4 /* set top 2 bits */
@ -698,8 +728,16 @@ _xt_user_exc:
#endif #endif
wsr a0, PS wsr a0, PS
/*
Create pseudo base save area. At this point, sp is still pointing to the
allocated and filled exception stack frame.
*/
#ifdef XT_DEBUG_BACKTRACE #ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__ #ifndef __XTENSA_CALL0_ABI__
l32i a3, sp, XT_STK_A0 /* Copy pre-exception a0 (return address) */
s32e a3, sp, -16
l32i a3, sp, XT_STK_A1 /* Copy pre-exception a1 (stack pointer) */
s32e a3, sp, -12
rsr a0, EPC_1 /* return address for debug backtrace */ rsr a0, EPC_1 /* return address for debug backtrace */
movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */ movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */
rsync /* wait for WSR.PS to complete */ rsync /* wait for WSR.PS to complete */
@ -945,7 +983,12 @@ _xt_coproc_exc:
/* Get co-processor state save area of new owner thread. */ /* Get co-processor state save area of new owner thread. */
call0 XT_RTOS_CP_STATE /* a15 = new owner's save area */ call0 XT_RTOS_CP_STATE /* a15 = new owner's save area */
beqz a15, .L_goto_invalid /* not in a thread (invalid) */
#ifndef CONFIG_FREERTOS_FPU_IN_ISR
beqz a15, .L_goto_invalid
#endif
/*When FPU in ISR is enabled we could deal with zeroed a15 */
/* Enable the co-processor's bit in CPENABLE. */ /* Enable the co-processor's bit in CPENABLE. */
movi a0, _xt_coproc_mask movi a0, _xt_coproc_mask
@ -987,7 +1030,13 @@ locking.
rsync /* ensure wsr.CPENABLE is complete */ rsync /* ensure wsr.CPENABLE is complete */
/* Only need to context switch if new owner != old owner. */ /* Only need to context switch if new owner != old owner. */
/* If float is necessary on ISR, we need to remove this check */
/* below, because on restoring from ISR we may have new == old condition used
* to force cp restore to next thread
*/
#ifndef CONFIG_FREERTOS_FPU_IN_ISR
beq a15, a2, .L_goto_done /* new owner == old, we're done */ beq a15, a2, .L_goto_done /* new owner == old, we're done */
#endif
/* If no old owner then nothing to save. */ /* If no old owner then nothing to save. */
beqz a2, .L_check_new beqz a2, .L_check_new
@ -1029,6 +1078,7 @@ locking.
.L_check_new: .L_check_new:
/* Check if any state has to be restored for new owner. */ /* Check if any state has to be restored for new owner. */
/* NOTE: a15 = new owner's save area, cannot be zero when we get here. */ /* NOTE: a15 = new owner's save area, cannot be zero when we get here. */
beqz a15, .L_xt_coproc_done
l16ui a3, a15, XT_CPSTORED /* a3 = new owner's CPSTORED */ l16ui a3, a15, XT_CPSTORED /* a3 = new owner's CPSTORED */
movi a4, _xt_coproc_sa_offset movi a4, _xt_coproc_sa_offset
@ -1114,6 +1164,16 @@ _xt_lowint1:
movi a0, _xt_user_exit /* save exit point for dispatch */ movi a0, _xt_user_exit /* save exit point for dispatch */
s32i a0, sp, XT_STK_EXIT s32i a0, sp, XT_STK_EXIT
/* EXCSAVE_1 should now be free to use. Use it to keep a copy of the
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
#ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__
mov a0, sp
wsr a0, EXCSAVE_1
#endif
#endif
/* Save rest of interrupt context and enter RTOS. */ /* Save rest of interrupt context and enter RTOS. */
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
@ -1194,6 +1254,16 @@ _xt_medint2:
movi a0, _xt_medint2_exit /* save exit point for dispatch */ movi a0, _xt_medint2_exit /* save exit point for dispatch */
s32i a0, sp, XT_STK_EXIT s32i a0, sp, XT_STK_EXIT
/* EXCSAVE_2 should now be free to use. Use it to keep a copy of the
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
#ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__
mov a0, sp
wsr a0, EXCSAVE_2
#endif
#endif
/* Save rest of interrupt context and enter RTOS. */ /* Save rest of interrupt context and enter RTOS. */
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
@ -1265,6 +1335,16 @@ _xt_medint3:
movi a0, _xt_medint3_exit /* save exit point for dispatch */ movi a0, _xt_medint3_exit /* save exit point for dispatch */
s32i a0, sp, XT_STK_EXIT s32i a0, sp, XT_STK_EXIT
/* EXCSAVE_3 should now be free to use. Use it to keep a copy of the
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
#ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__
mov a0, sp
wsr a0, EXCSAVE_3
#endif
#endif
/* Save rest of interrupt context and enter RTOS. */ /* Save rest of interrupt context and enter RTOS. */
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
@ -1335,6 +1415,16 @@ _xt_medint4:
movi a0, _xt_medint4_exit /* save exit point for dispatch */ movi a0, _xt_medint4_exit /* save exit point for dispatch */
s32i a0, sp, XT_STK_EXIT s32i a0, sp, XT_STK_EXIT
/* EXCSAVE_4 should now be free to use. Use it to keep a copy of the
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
#ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__
mov a0, sp
wsr a0, EXCSAVE_4
#endif
#endif
/* Save rest of interrupt context and enter RTOS. */ /* Save rest of interrupt context and enter RTOS. */
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
@ -1405,6 +1495,15 @@ _xt_medint5:
movi a0, _xt_medint5_exit /* save exit point for dispatch */ movi a0, _xt_medint5_exit /* save exit point for dispatch */
s32i a0, sp, XT_STK_EXIT s32i a0, sp, XT_STK_EXIT
/* EXCSAVE_5 should now be free to use. Use it to keep a copy of the
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
#ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__
mov a0, sp
wsr a0, EXCSAVE_5
#endif
#endif
/* Save rest of interrupt context and enter RTOS. */ /* Save rest of interrupt context and enter RTOS. */
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
@ -1475,6 +1574,15 @@ _xt_medint6:
movi a0, _xt_medint6_exit /* save exit point for dispatch */ movi a0, _xt_medint6_exit /* save exit point for dispatch */
s32i a0, sp, XT_STK_EXIT s32i a0, sp, XT_STK_EXIT
/* EXCSAVE_6 should now be free to use. Use it to keep a copy of the
current stack pointer that points to the exception frame (XT_STK_FRAME).*/
#ifdef XT_DEBUG_BACKTRACE
#ifndef __XTENSA_CALL0_ABI__
mov a0, sp
wsr a0, EXCSAVE_6
#endif
#endif
/* Save rest of interrupt context and enter RTOS. */ /* Save rest of interrupt context and enter RTOS. */
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */

View file

@ -519,6 +519,10 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
size_t xRequiredSpace = xDataLengthBytes; size_t xRequiredSpace = xDataLengthBytes;
TimeOut_t xTimeOut; TimeOut_t xTimeOut;
/* Having a 'isFeasible' variable allows to respect the convention that there is only a return statement at the end. Othewise, return
* could be done as soon as we realise the send cannot happen. We will let the call to 'prvWriteMessageToBuffer' dealing with this scenario. */
BaseType_t xIsFeasible;
configASSERT( pvTxData ); configASSERT( pvTxData );
configASSERT( pxStreamBuffer ); configASSERT( pxStreamBuffer );
@ -532,13 +536,56 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
/* Overflow? */ /* Overflow? */
configASSERT( xRequiredSpace > xDataLengthBytes ); configASSERT( xRequiredSpace > xDataLengthBytes );
/* In the case of the message buffer, one has to be able to write the complete message as opposed to
* a stream buffer for semantic reasons. Check if it is physically possible to write the message given
* the length of the buffer. */
if(xRequiredSpace > pxStreamBuffer->xLength)
{
/* The message could never be written because it is greater than the buffer length.
* By setting xIsFeasable to FALSE, we skip over the following do..while loop, thus avoiding
* a deadlock. The call to 'prvWriteMessageToBuffer' toward the end of this function with
* xRequiredSpace greater than xSpace will suffice in not writing anything to the internal buffer.
* Now, the function will return 0 because the message could not be written. Should an error code be
* returned instead ??? In my opinion, probably.. But the return type doesn't allow for negative
* values to be returned. A confusion could exist to the caller. Returning 0 because a timeout occurred
* and a subsequent send attempts could eventually succeed, and returning 0 because a write could never
* happen because of the size are two scenarios to me :/ */
xIsFeasible = pdFALSE;
} }
else else
{ {
mtCOVERAGE_TEST_MARKER(); /* It is possible to write the message completely in the buffer. This is the intended route.
* Let's continue with the regular timeout logic. */
xIsFeasible = pdTRUE;
}
}
else
{
/* In the case of the stream buffer, not being able to completely write the message in the buffer
* is an acceptable scenario, but it has to be dealt with properly */
if(xRequiredSpace > pxStreamBuffer->xLength)
{
/* Not enough buffer space. We will attempt to write as much as we can in this run
* so that the caller can send the remaining in subsequent calls. We avoid a deadlock by
* offering the possibility to take the 'else' branch in the 'if( xSpace < xRequiredSpace )'
* condition inside the following do..while loop */
xRequiredSpace = pxStreamBuffer->xLength;
/* TODO FIXME: Is there a check we should do with the xTriggerLevelBytes value ? */
/* With the adjustment to 'xRequiredSpace', the deadlock is avoided, thus it's now feasible. */
xIsFeasible = pdTRUE;
}
else
{
/* It is possible to write the message completely in the buffer. */
xIsFeasible = pdTRUE;
}
} }
if( xTicksToWait != ( TickType_t ) 0 ) /* Added check against xIsFeasible. If it's not feasible, don't even wait for notification, let the call to 'prvWriteMessageToBuffer' do nothing and return 0 */
if( xTicksToWait != ( TickType_t ) 0 && xIsFeasible == pdTRUE )
{ {
vTaskSetTimeOutState( &xTimeOut ); vTaskSetTimeOutState( &xTimeOut );

View file

@ -3309,7 +3309,7 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut )
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
TickType_t * const pxTicksToWait ) TickType_t * const pxTicksToWait )
{ {
BaseType_t xReturn; BaseType_t xReturn;
configASSERT( pxTimeOut ); configASSERT( pxTimeOut );
configASSERT( pxTicksToWait ); configASSERT( pxTicksToWait );
@ -3320,7 +3320,7 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
const TickType_t xConstTickCount = xTickCount; const TickType_t xConstTickCount = xTickCount;
const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering; const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering;
#if ( INCLUDE_xTaskAbortDelay == 1 ) #if( INCLUDE_xTaskAbortDelay == 1 )
if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE ) if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE )
{ {
/* The delay was aborted, which is not the same as a time out, /* The delay was aborted, which is not the same as a time out,
@ -3350,6 +3350,7 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
* around and gone past again. This passed since vTaskSetTimeout() * around and gone past again. This passed since vTaskSetTimeout()
* was called. */ * was called. */
xReturn = pdTRUE; xReturn = pdTRUE;
*pxTicksToWait = ( TickType_t ) 0;
} }
else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */ else if( xElapsedTime < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */
{ {
@ -3360,7 +3361,7 @@ BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
} }
else else
{ {
*pxTicksToWait = 0; *pxTicksToWait = ( TickType_t ) 0;
xReturn = pdTRUE; xReturn = pdTRUE;
} }
} }
@ -5245,7 +5246,7 @@ TickType_t uxTaskResetEventItemValue( void )
{ {
/* Return the notification as it was before the bits were cleared, /* Return the notification as it was before the bits were cleared,
* then clear the bit mask. */ * then clear the bit mask. */
ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToClear ]; ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear; pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();