mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-19 09:38:32 -04:00
Make Cortex-M0 set/clear interrupt flag from ISR functions nestable.
Don't reset the stack location when starting the scheduler in Cortex-M0 ports as the vector offset register is not implemented and XMC1000 devices have their application vector address somewhere other than 0x00.
This commit is contained in:
parent
ed399e801e
commit
73606369c4
9 changed files with 146 additions and 102 deletions
|
@ -108,7 +108,7 @@ void vPortSVCHandler( void );
|
|||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
static void vPortStartFirstTask( void );
|
||||
static void prvPortStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -137,11 +137,11 @@ __asm void vPortSVCHandler( void )
|
|||
|
||||
PRESERVE8
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Restore the context. */
|
||||
ldr r1, [r3] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
|
||||
ldr r3, =pxCurrentTCB /* Obtain location of pxCurrentTCB. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
adds r0, #16 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Pop the high registers. */
|
||||
adds r0, #16 /* Pop the high registers. */
|
||||
ldmia r0!, {r4-r7}
|
||||
mov r8, r4
|
||||
mov r9, r5
|
||||
mov r10, r6
|
||||
|
@ -155,20 +155,20 @@ __asm void vPortSVCHandler( void )
|
|||
movs r0, #0x0d
|
||||
orrs r1, r0
|
||||
bx r1
|
||||
nop
|
||||
ALIGN
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__asm void vPortStartFirstTask( void )
|
||||
__asm void prvPortStartFirstTask( void )
|
||||
{
|
||||
PRESERVE8
|
||||
|
||||
movs r0, #0x00 /* Locate the top of stack. */
|
||||
ldr r0, [r0]
|
||||
msr msp, r0 /* Set the msp back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
svc 0 /* System call to start first task. */
|
||||
nop
|
||||
|
||||
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
|
||||
table offset register that can be used to locate the initial stack value.
|
||||
Not all M0 parts have the application vector table at address 0. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
svc 0 /* System call to start first task. */
|
||||
ALIGN
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
@ -189,7 +189,7 @@ portBASE_TYPE xPortStartScheduler( void )
|
|||
uxCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
prvPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
|
@ -234,6 +234,21 @@ void vPortExitCritical( void )
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__asm unsigned long ulSetInterruptMaskFromISR( void )
|
||||
{
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__asm void vClearInterruptMaskFromISR( unsigned long ulMask )
|
||||
{
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__asm void xPortPendSVHandler( void )
|
||||
{
|
||||
extern vTaskSwitchContext
|
||||
|
@ -276,14 +291,15 @@ __asm void xPortPendSVHandler( void )
|
|||
ldmia r0!, {r4-r7} /* Pop low registers. */
|
||||
|
||||
bx r3
|
||||
ALIGN
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
unsigned long ulDummy;
|
||||
unsigned long ulPreviousMask;
|
||||
|
||||
ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
|
@ -292,7 +308,7 @@ unsigned long ulDummy;
|
|||
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -114,16 +114,16 @@ extern void vPortYield( void );
|
|||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portSET_INTERRUPT_MASK() __disable_irq()
|
||||
#define portCLEAR_INTERRUPT_MASK() __enable_irq()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
|
||||
#define portDISABLE_INTERRUPTS() portSET_INTERRUPT_MASK()
|
||||
#define portENABLE_INTERRUPTS() portCLEAR_INTERRUPT_MASK()
|
||||
extern unsigned long ulSetInterruptMaskFromISR( void );
|
||||
extern void vClearInterruptMaskFromISR( unsigned long ulMask );
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x )
|
||||
#define portDISABLE_INTERRUPTS() __disable_irq()
|
||||
#define portENABLE_INTERRUPTS() __enable_irq()
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue