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:
Richard Barry 2013-09-01 19:53:24 +00:00
parent ed399e801e
commit 73606369c4
9 changed files with 146 additions and 102 deletions

View file

@ -198,9 +198,9 @@ void vPortExitCritical( void )
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 )
@ -209,7 +209,7 @@ unsigned long ulDummy;
*(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
}
/*-----------------------------------------------------------*/

View file

@ -64,14 +64,6 @@
#include <FreeRTOSConfig.h>
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
defined. The value zero should also ensure backward compatibility.
FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
#ifndef configKERNEL_INTERRUPT_PRIORITY
#define configKERNEL_INTERRUPT_PRIORITY 0
#endif
RSEG CODE:CODE(2)
thumb
@ -83,52 +75,53 @@ FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
PUBLIC xPortPendSVHandler
PUBLIC vPortSVCHandler
PUBLIC vPortStartFirstTask
PUBLIC ulSetInterruptMaskFromISR
PUBLIC vClearInterruptMaskFromISR
/*-----------------------------------------------------------*/
vSetMSP
msr msp, r0
bx lr
/*-----------------------------------------------------------*/
xPortPendSVHandler:
mrs r0, psp
mrs r0, psp
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
ldr r2, [r3]
ldr r2, [r3]
subs r0, r0, #32 /* Make space for the remaining low registers. */
str r0, [r2] /* Save the new top of stack. */
stmia r0!, {r4-r7} /* Store the low registers that are not saved automatically. */
mov r4, r8 /* Store the high registers. */
mov r5, r9
mov r6, r10
mov r7, r11
stmia r0!, {r4-r7}
push {r3, r14}
cpsid i
bl vTaskSwitchContext
cpsie i
mov r5, r9
mov r6, r10
mov r7, r11
stmia r0!, {r4-r7}
push {r3, r14}
cpsid i
bl vTaskSwitchContext
cpsie i
pop {r2, r3} /* lr goes in r3. r2 now holds tcb pointer. */
ldr r1, [r2]
ldr r1, [r2]
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
adds r0, r0, #16 /* Move to the high registers. */
ldmia r0!, {r4-r7} /* Pop the high registers. */
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
msr psp, r0 /* Remember the new top of stack for the task. */
subs r0, r0, #32 /* Go back for the low registers that are not automatically restored. */
ldmia r0!, {r4-r7} /* Pop low registers. */
bx r3
bx r3
/*-----------------------------------------------------------*/
@ -138,29 +131,41 @@ vPortSVCHandler;
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
adds r0, r0, #16 /* Move to the high registers. */
ldmia r0!, {r4-r7} /* Pop the high registers. */
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
msr psp, r0 /* Remember the new top of stack for the task. */
subs r0, r0, #32 /* Go back for the low registers that are not automatically restored. */
ldmia r0!, {r4-r7} /* Pop low registers. */
mov r1, r14 /* OR R14 with 0x0d. */
movs r0, #0x0d
orrs r1, r0
bx r1
movs r0, #0x0d
orrs r1, r0
bx r1
/*-----------------------------------------------------------*/
vPortStartFirstTask
movs r0, #0x00 /* Locate the top of stack. */
ldr r0, [r0]
msr msp, r0 /* Set the msp back to the start of the stack. */
/* 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. */
nop
nop
/*-----------------------------------------------------------*/
ulSetInterruptMaskFromISR
mrs r0, PRIMASK
cpsid i
bx lr
/*-----------------------------------------------------------*/
vClearInterruptMaskFromISR
msr PRIMASK, r0
bx lr
END

View file

@ -119,13 +119,15 @@ extern void vPortYield( void );
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern unsigned long ulSetInterruptMaskFromISR( void );
extern void vClearInterruptMaskFromISR( unsigned long ulMask );
#define portDISABLE_INTERRUPTS() __asm volatile( "cpsid i" )
#define portENABLE_INTERRUPTS() __asm volatile( "cpsie i" )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portENABLE_INTERRUPTS();(void)x
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x )
/*-----------------------------------------------------------*/
@ -135,6 +137,11 @@ extern void vPortExitCritical( void );
#define portNOP()
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
the source code because to do so would cause other compilers to generate
warnings. */
#pragma diag_suppress=Pa082
#ifdef __cplusplus
}
#endif